From 037099f50dbae37ab5a7aae6b54fec7f931d25f0 Mon Sep 17 00:00:00 2001 From: CleverMouse Date: Fri, 14 Oct 2011 21:38:50 +0000 Subject: [PATCH] Style corrected for new rules, no semantic changes git-svn-id: svn://kolibrios.org@2288 a494cfbc-eb01-0410-851d-a64ba20cac60 --- kernel/trunk/blkdev/cd_drv.inc | 1860 +-- kernel/trunk/blkdev/cdrom.inc | 542 +- kernel/trunk/blkdev/disk.inc | 2516 ++-- kernel/trunk/blkdev/disk_cache.inc | 1184 +- kernel/trunk/blkdev/fdc.inc | 142 +- kernel/trunk/blkdev/flp_drv.inc | 1256 +- kernel/trunk/blkdev/hd_drv.inc | 1894 +-- kernel/trunk/blkdev/ide_cache.inc | 1844 +-- kernel/trunk/blkdev/rd.inc | 4545 +++---- kernel/trunk/blkdev/rdsave.inc | 60 +- kernel/trunk/boot/bootcode.inc | 2747 ++--- kernel/trunk/boot/booteng.inc | 202 +- kernel/trunk/boot/bootet.inc | 202 +- kernel/trunk/boot/bootge.inc | 202 +- kernel/trunk/boot/bootru.inc | 202 +- kernel/trunk/boot/bootstr.inc | 125 +- kernel/trunk/boot/bootvesa.inc | 1589 +-- kernel/trunk/boot/et.inc | 32 +- kernel/trunk/boot/parsers.inc | 340 +- kernel/trunk/boot/preboot.inc | 83 +- kernel/trunk/boot/rdload.inc | 250 +- kernel/trunk/boot/ru.inc | 204 +- kernel/trunk/boot/shutdown.inc | 424 +- kernel/trunk/bootloader/boot_fat12.asm | 420 +- .../extended_primary_loader/after_win/fat.inc | 1018 +- .../after_win/kordldr.win.asm | 1845 +-- .../after_win/ntfs.inc | 1174 +- .../extended_primary_loader/cdfs/bootsect.asm | 2048 ++-- .../fat1x/bootsect.asm | 784 +- .../fat1x/kordldr.f1x.asm | 1377 +-- .../fat32/bootsect.asm | 716 +- .../fat32/kordldr.f32.asm | 1346 +- kernel/trunk/bootloader/floppy1440.inc | 38 +- kernel/trunk/bootloader/floppy1680.inc | 38 +- kernel/trunk/bootloader/floppy1743.inc | 38 +- kernel/trunk/bootloader/floppy2880.inc | 38 +- kernel/trunk/bus/pci/PCIe.inc | 238 +- kernel/trunk/bus/pci/pci16.inc | 102 +- kernel/trunk/bus/pci/pci32.inc | 1314 +- kernel/trunk/const.inc | 1564 +-- kernel/trunk/core/apic.inc | 834 +- kernel/trunk/core/conf_lib.inc | 595 +- kernel/trunk/core/debug.inc | 864 +- kernel/trunk/core/dll.inc | 2894 ++--- kernel/trunk/core/export.inc | 79 +- kernel/trunk/core/exports.inc | 362 +- kernel/trunk/core/ext_lib.inc | 653 +- kernel/trunk/core/fpu.inc | 366 +- kernel/trunk/core/heap.inc | 2948 ++--- kernel/trunk/core/irq.inc | 458 +- kernel/trunk/core/malloc.inc | 2084 ++-- kernel/trunk/core/memory.inc | 3086 ++--- kernel/trunk/core/peload.inc | 664 +- kernel/trunk/core/sched.inc | 808 +- kernel/trunk/core/string.inc | 376 +- kernel/trunk/core/sync.inc | 238 +- kernel/trunk/core/sys32.inc | 1392 +-- kernel/trunk/core/syscall.inc | 400 +- kernel/trunk/core/taskman.inc | 2322 ++-- kernel/trunk/core/test_malloc.asm | 446 +- kernel/trunk/core/timers.inc | 410 +- kernel/trunk/core/v86.inc | 1863 +-- kernel/trunk/data16.inc | 181 +- kernel/trunk/data32.inc | 9 +- kernel/trunk/detect/biosdisk.inc | 162 +- kernel/trunk/detect/biosmem.inc | 86 +- kernel/trunk/detect/dev_fd.inc | 74 +- kernel/trunk/detect/dev_hdcd.inc | 779 +- kernel/trunk/detect/disks.inc | 30 +- kernel/trunk/detect/getcache.inc | 424 +- kernel/trunk/detect/sear_par.inc | 306 +- kernel/trunk/drivers/apm.asm | 638 +- kernel/trunk/drivers/codec.inc | 652 +- kernel/trunk/drivers/com_mouse.asm | 764 +- kernel/trunk/drivers/emu10k1x.asm | 1376 +-- kernel/trunk/drivers/ensoniq.asm | 2354 ++-- kernel/trunk/drivers/fm801.asm | 1107 +- kernel/trunk/drivers/imports.inc | 190 +- kernel/trunk/drivers/infinity.asm | 2870 ++--- kernel/trunk/drivers/main.inc | 346 +- kernel/trunk/drivers/mix_mmx.inc | 494 +- kernel/trunk/drivers/mix_sse2.inc | 290 +- kernel/trunk/drivers/mixer.asm | 2532 ++-- kernel/trunk/drivers/proc32.inc | 536 +- kernel/trunk/drivers/sb16/CONFIG.INC | 100 +- kernel/trunk/drivers/sb16/SB16.INC | 594 +- kernel/trunk/drivers/sb16/sb16.asm | 793 +- kernel/trunk/drivers/sceletone.asm | 346 +- kernel/trunk/drivers/sis.asm | 2614 ++-- kernel/trunk/drivers/sound.asm | 3014 ++--- kernel/trunk/drivers/uart.asm | 1952 +-- kernel/trunk/drivers/usb/urb.inc | 230 +- kernel/trunk/drivers/usb/usb.asm | 870 +- kernel/trunk/drivers/vidintel.asm | 930 +- kernel/trunk/drivers/vt823x.asm | 2562 ++-- kernel/trunk/fdo.inc | 881 +- kernel/trunk/fs/ext2.inc | 346 +- kernel/trunk/fs/fat12.inc | 4544 +++---- kernel/trunk/fs/fat32.inc | 5875 ++++----- kernel/trunk/fs/fs.inc | 1598 +-- kernel/trunk/fs/fs_lfn.inc | 2298 ++-- kernel/trunk/fs/iso9660.inc | 1522 +-- kernel/trunk/fs/ntfs.inc | 3644 +++--- kernel/trunk/fs/parse_fn.inc | 472 +- kernel/trunk/fs/part_set.inc | 1001 +- kernel/trunk/gui/button.inc | 50 +- kernel/trunk/gui/event.inc | 1007 +- kernel/trunk/gui/font.inc | 264 +- kernel/trunk/gui/mouse.inc | 39 +- kernel/trunk/gui/mousepointer.inc | 500 +- kernel/trunk/gui/skincode.inc | 922 +- kernel/trunk/gui/skindata.inc | 128 +- kernel/trunk/gui/window.inc | 235 +- kernel/trunk/hid/keyboard.inc | 814 +- kernel/trunk/hid/mousedrv.inc | 911 +- kernel/trunk/hid/set_dtc.inc | 406 +- kernel/trunk/imports.inc | 54 +- kernel/trunk/init.inc | 1107 +- kernel/trunk/kernel.asm | 10185 ++++++++-------- kernel/trunk/kglobals.inc | 138 +- kernel/trunk/macros.inc | 276 +- kernel/trunk/memmap.inc | 528 +- kernel/trunk/network/eth_drv/arp.inc | 1113 +- .../trunk/network/eth_drv/drivers/3c59x.inc | 4782 ++++---- .../network/eth_drv/drivers/forcedeth.inc | 3924 +++--- .../trunk/network/eth_drv/drivers/i8255x.inc | 1554 +-- .../trunk/network/eth_drv/drivers/pcnet32.inc | 1696 +-- .../trunk/network/eth_drv/drivers/r6040.inc | 1626 +-- .../trunk/network/eth_drv/drivers/rtl8029.inc | 1935 +-- .../trunk/network/eth_drv/drivers/rtl8139.inc | 1245 +- .../trunk/network/eth_drv/drivers/rtl8169.inc | 2458 ++-- .../trunk/network/eth_drv/drivers/sis900.inc | 2324 ++-- kernel/trunk/network/eth_drv/ethernet.inc | 1030 +- kernel/trunk/network/eth_drv/pci.inc | 702 +- kernel/trunk/network/icmp.inc | 386 +- kernel/trunk/network/ip.inc | 488 +- kernel/trunk/network/queue.inc | 458 +- kernel/trunk/network/socket.inc | 2253 ++-- kernel/trunk/network/stack.inc | 1820 +-- kernel/trunk/network/tcp.inc | 2348 ++-- kernel/trunk/network/udp.inc | 310 +- kernel/trunk/proc32.inc | 542 +- .../sec_loader/trunk/boot/after_win/fat.inc | 1018 +- .../trunk/boot/after_win/kordldr.win.asm | 1845 +-- .../sec_loader/trunk/boot/after_win/ntfs.inc | 1174 +- .../sec_loader/trunk/boot/cdfs/bootsect.asm | 2048 ++-- .../sec_loader/trunk/boot/fat1x/bootsect.asm | 784 +- .../trunk/boot/fat1x/kordldr.f1x.asm | 1335 +- .../sec_loader/trunk/boot/fat32/bootsect.asm | 716 +- .../trunk/boot/fat32/kordldr.f32.asm | 1344 +- .../trunk/sec_loader/trunk/boot/mkfloppy.inc | 181 +- kernel/trunk/sec_loader/trunk/boot_st.inc | 136 +- kernel/trunk/sec_loader/trunk/debug_msg.inc | 154 +- .../sec_loader/trunk/kolibri_ldm/booteng.inc | 196 +- .../sec_loader/trunk/kolibri_ldm/bootet.inc | 238 +- .../sec_loader/trunk/kolibri_ldm/bootge.inc | 236 +- .../sec_loader/trunk/kolibri_ldm/bootru.inc | 174 +- .../sec_loader/trunk/kolibri_ldm/bootstr.inc | 111 +- .../sec_loader/trunk/kolibri_ldm/bootvesa.inc | 1516 +-- .../trunk/sec_loader/trunk/kolibri_ldm/et.inc | 28 +- .../trunk/kolibri_ldm/kolibri_ldm.asm | 1623 +-- .../sec_loader/trunk/kolibri_ldm/macros.inc | 172 +- .../sec_loader/trunk/kolibri_ldm/preboot.inc | 72 +- .../sec_loader/trunk/kolibri_ldm/rdload.inc | 246 +- .../trunk/sec_loader/trunk/kolibri_ldm/ru.inc | 200 +- .../sec_loader/trunk/kolibri_ldm/shutdown.inc | 414 +- kernel/trunk/sec_loader/trunk/listing.inc | 1270 +- kernel/trunk/sec_loader/trunk/loader.asm | 634 +- kernel/trunk/sec_loader/trunk/parse.inc | 236 +- kernel/trunk/sec_loader/trunk/parse_any.inc | 1369 +-- kernel/trunk/sec_loader/trunk/parse_dat.inc | 112 +- .../trunk/sec_loader/trunk/parse_def_sect.inc | 4215 +++---- kernel/trunk/sec_loader/trunk/parse_err.inc | 132 +- .../trunk/sec_loader/trunk/parse_loader.inc | 667 +- kernel/trunk/sec_loader/trunk/sl_equ.inc | 196 +- kernel/trunk/sec_loader/trunk/sl_proc.inc | 1052 +- kernel/trunk/skin/default.asm | 76 +- kernel/trunk/skin/me_skin.inc | 484 +- kernel/trunk/sound/playnote.inc | 332 +- kernel/trunk/unpacker.inc | 1055 +- kernel/trunk/video/blitter.inc | 568 +- kernel/trunk/video/cursors.inc | 1612 +-- kernel/trunk/video/vesa12.inc | 2008 +-- kernel/trunk/video/vesa20.inc | 2300 ++-- kernel/trunk/video/vga.inc | 900 +- 185 files changed, 99632 insertions(+), 99176 deletions(-) diff --git a/kernel/trunk/blkdev/cd_drv.inc b/kernel/trunk/blkdev/cd_drv.inc index bcc184d52..1a81fc941 100644 --- a/kernel/trunk/blkdev/cd_drv.inc +++ b/kernel/trunk/blkdev/cd_drv.inc @@ -1,929 +1,931 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;********************************************************** -; Непосредственная работа с устройством СD (ATAPI) -;********************************************************** -; Автор части исходного текста Кулаков Владимир Геннадьевич -; Адаптация, доработка и разработка Mario79, - -; Максимальное количество повторений операции чтения -MaxRetr equ 10 -; Предельное время ожидания готовности к приему команды -; (в тиках) -BSYWaitTime equ 1000 ;2 -NoTickWaitTime equ 0xfffff -CDBlockSize equ 2048 -;******************************************** -;* ЧТЕНИЕ СЕКТОРА С ПОВТОРАМИ * -;* Многократное повторение чтения при сбоях * -;******************************************** -ReadCDWRetr: -;----------------------------------------------------------- -; input : eax = block to read -; ebx = destination -;----------------------------------------------------------- - pushad - mov eax,[CDSectorAddress] - mov ebx,[CDDataBuf_pointer] - call cd_calculate_cache - xor edi,edi - add esi,8 - inc edi -.hdreadcache: -; cmp dword [esi+4],0 ; empty -; je .nohdcache - cmp [esi],eax ; correct sector - je .yeshdcache -.nohdcache: - add esi,8 - inc edi - dec ecx - jnz .hdreadcache - call find_empty_slot_CD_cache ; ret in edi - - push edi - push eax - call cd_calculate_cache_2 - shl edi,11 - add edi,eax - mov [CDDataBuf_pointer],edi - pop eax - pop edi - - call ReadCDWRetr_1 - cmp [DevErrorCode],0 - jne .exit - - mov [CDDataBuf_pointer],ebx - call cd_calculate_cache_1 - lea esi,[edi*8+esi] - mov [esi],eax ; sector number -; mov dword [esi+4],1 ; hd read - mark as same as in hd -.yeshdcache: - mov esi,edi - shl esi,11 ;9 - push eax - call cd_calculate_cache_2 - add esi,eax - pop eax - mov edi,ebx ;[CDDataBuf_pointer] - mov ecx,512 ;/4 - cld - rep movsd ; move data -.exit: - popad - ret - -ReadCDWRetr_1: - pushad - -; Цикл, пока команда не выполнена успешно или не -; исчерпано количество попыток - mov ECX,MaxRetr -@@NextRetr: -; Подать команду -;************************************************* -;* ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА * -;* Считываются данные пользователя, информация * -;* субканала и контрольная информация * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале; * -;* CDSectorAddress - адрес считываемого сектора. * -;* Данные считывается в массив CDDataBuf. * -;************************************************* -;ReadCD: - push ecx -; pusha -; Задать размер сектора -; mov [CDBlockSize],2048 ;2352 -; Очистить буфер пакетной команды - call clear_packet_buffer -; Сформировать пакетную команду для считывания -; сектора данных -; Задать код команды Read CD - mov [PacketCommand],byte 0x28 ;0xBE -; Задать адрес сектора - mov AX,word [CDSectorAddress+2] - xchg AL,AH - mov word [PacketCommand+2],AX - mov AX,word [CDSectorAddress] - xchg AL,AH - mov word [PacketCommand+4],AX -; mov eax,[CDSectorAddress] -; mov [PacketCommand+2],eax -; Задать количество считываемых секторов - mov [PacketCommand+8],byte 1 -; Задать считывание данных в полном объеме -; mov [PacketCommand+9],byte 0xF8 -; Подать команду - call SendPacketDatCommand - pop ecx -; ret - -; cmp [DevErrorCode],0 - test eax,eax - jz @@End_4 - - or ecx,ecx ;{SPraid.simba} (for cd load) - jz @@End_4 - dec ecx - - cmp [timer_ticks_enable],0 - jne @f - mov eax,NoTickWaitTime -.wait: - dec eax -; test eax,eax - jz @@NextRetr - jmp .wait -@@: -; Задержка на 2,5 секунды -; mov EAX,[timer_ticks] -; add EAX,50 ;250 -;@@Wait: -; call change_task -; cmp EAX,[timer_ticks] -; ja @@Wait - loop @@NextRetr -@@End_4: - mov dword [DevErrorCode],eax - popad - ret - - -; Универсальные процедуры, обеспечивающие выполнение -; пакетных команд в режиме PIO - -; Максимально допустимое время ожидания реакции -; устройства на пакетную команду (в тиках) - -MaxCDWaitTime equ 1000 ;200 ;10 секунд -uglobal -; Область памяти для формирования пакетной команды -PacketCommand: rb 12 ;DB 12 DUP (?) -; Область памяти для приема данных от дисковода -;CDDataBuf DB 4096 DUP (0) -; Размер принимаемого блока данных в байтах -;CDBlockSize DW ? -; Адрес считываемого сектора данных -CDSectorAddress: DD ? -; Время начала очередной операции с диском -TickCounter_1 DD 0 -; Время начала ожидания готовности устройства -WURStartTime DD 0 -; указатель буфера для считывания -CDDataBuf_pointer dd 0 -endg -;**************************************************** -;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, * -;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ * -;* РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале; * -;* PacketCommand - 12-байтный командный пакет; * -;* CDBlockSize - размер принимаемого блока данных. * -; return eax DevErrorCode -;**************************************************** -SendPacketDatCommand: - xor eax,eax -; mov byte [DevErrorCode],al -; Задать режим CHS - mov byte [ATAAddressMode],al -; Послать ATA-команду передачи пакетной команды - mov byte [ATAFeatures],al - mov byte [ATASectorCount],al - mov byte [ATASectorNumber],al - ; Загрузить размер передаваемого блока - mov [ATAHead],al -; mov AX,[CDBlockSize] - mov [ATACylinder],CDBlockSize - mov [ATACommand],0A0h - call SendCommandToHDD_1 - test eax,eax -; cmp [DevErrorCode],0 ;проверить код ошибки - jnz @@End_8 ;закончить, сохранив код ошибки - -; Ожидание готовности дисковода к приему -; пакетной команды - mov DX,[ATABasePortAddr] - add DX,7 ;порт 1х7h - mov ecx,NoTickWaitTime -@@WaitDevice0: - cmp [timer_ticks_enable],0 - jne @f - dec ecx -; test ecx,ecx - jz @@Err1_1 - jmp .test -@@: - call change_task - ; Проверить время выполнения команды - mov EAX,[timer_ticks] - sub EAX,[TickCounter_1] - cmp EAX,BSYWaitTime - ja @@Err1_1 ;ошибка тайм-аута - ; Проверить готовность -.test: - in AL,DX - test AL,80h ;состояние сигнала BSY - jnz @@WaitDevice0 - test AL,1 ;состояние сигнала ERR - jnz @@Err6 - test AL,08h ;состояние сигнала DRQ - jz @@WaitDevice0 -; Послать пакетную команду - cli - mov DX,[ATABasePortAddr] - mov AX,[PacketCommand] - out DX,AX - mov AX,[PacketCommand+2] - out DX,AX - mov AX,[PacketCommand+4] - out DX,AX - mov AX,[PacketCommand+6] - out DX,AX - mov AX,[PacketCommand+8] - out DX,AX - mov AX,[PacketCommand+10] - out DX,AX - sti -; Ожидание готовности данных - mov DX,[ATABasePortAddr] - add DX,7 ;порт 1х7h - mov ecx,NoTickWaitTime -@@WaitDevice1: - cmp [timer_ticks_enable],0 - jne @f - dec ecx -; test ecx,ecx - jz @@Err1_1 - jmp .test_1 -@@: - call change_task - ; Проверить время выполнения команды - mov EAX,[timer_ticks] - sub EAX,[TickCounter_1] - cmp EAX,MaxCDWaitTime - ja @@Err1_1 ;ошибка тайм-аута - ; Проверить готовность -.test_1: - in AL,DX - test AL,80h ;состояние сигнала BSY - jnz @@WaitDevice1 - test AL,1 ;состояние сигнала ERR - jnz @@Err6_temp - test AL,08h ;состояние сигнала DRQ - jz @@WaitDevice1 -; Принять блок данных от контроллера - mov EDI,[CDDataBuf_pointer] ;0x7000 ;CDDataBuf - ; Загрузить адрес регистра данных контроллера - mov DX,[ATABasePortAddr] ;порт 1x0h - ; Загрузить в счетчик размер блока в байтах - xor ecx,ecx - mov CX,CDBlockSize - ; Вычислить размер блока в 16-разрядных словах - shr CX,1 ;разделить размер блока на 2 - ; Принять блок данных - cli - cld - rep insw - sti -; Успешное завершение приема данных -@@End_8: - xor eax,eax - ret - -; Записать код ошибки -@@Err1_1: - xor eax,eax - inc eax - ret -; mov [DevErrorCode],1 -; ret -@@Err6_temp: - mov eax,7 - ret -; mov [DevErrorCode],7 -; ret -@@Err6: - mov eax,6 - ret -; mov [DevErrorCode],6 -;@@End_8: -; ret - - - -;*********************************************** -;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, * -;* НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ * -;* Входные параметры передаются через * -;* глобальные перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале; * -;* PacketCommand - 12-байтный командный пакет. * -;*********************************************** -SendPacketNoDatCommand: - pushad - xor eax,eax -; mov byte [DevErrorCode],al -; Задать режим CHS - mov byte [ATAAddressMode],al -; Послать ATA-команду передачи пакетной команды - mov byte [ATAFeatures],al - mov byte [ATASectorCount],al - mov byte [ATASectorNumber],al - mov word [ATACylinder],ax - mov byte [ATAHead],al - mov [ATACommand],0A0h - call SendCommandToHDD_1 -; cmp [DevErrorCode],0 ;проверить код ошибки - test eax,eax - jnz @@End_9 ;закончить, сохранив код ошибки -; Ожидание готовности дисковода к приему -; пакетной команды - mov DX,[ATABasePortAddr] - add DX,7 ;порт 1х7h -@@WaitDevice0_1: - call change_task - ; Проверить время ожидания - mov EAX,[timer_ticks] - sub EAX,[TickCounter_1] - cmp EAX,BSYWaitTime - ja @@Err1_3 ;ошибка тайм-аута - ; Проверить готовность - in AL,DX - test AL,80h ;состояние сигнала BSY - jnz @@WaitDevice0_1 - test AL,1 ;состояние сигнала ERR - jnz @@Err6_1 - test AL,08h ;состояние сигнала DRQ - jz @@WaitDevice0_1 -; Послать пакетную команду -; cli - mov DX,[ATABasePortAddr] - mov AX,word [PacketCommand] - out DX,AX - mov AX,word [PacketCommand+2] - out DX,AX - mov AX,word [PacketCommand+4] - out DX,AX - mov AX,word [PacketCommand+6] - out DX,AX - mov AX,word [PacketCommand+8] - out DX,AX - mov AX,word [PacketCommand+10] - out DX,AX -; sti - cmp [ignore_CD_eject_wait],1 - je @@clear_DEC -; Ожидание подтверждения приема команды - mov DX,[ATABasePortAddr] - add DX,7 ;порт 1х7h -@@WaitDevice1_1: - call change_task - ; Проверить время выполнения команды - mov EAX,[timer_ticks] - sub EAX,[TickCounter_1] - cmp EAX,MaxCDWaitTime - ja @@Err1_3 ;ошибка тайм-аута - ; Ожидать освобождения устройства - in AL,DX - test AL,80h ;состояние сигнала BSY - jnz @@WaitDevice1_1 - test AL,1 ;состояние сигнала ERR - jnz @@Err6_1 - test AL,40h ;состояние сигнала DRDY - jz @@WaitDevice1_1 -@@clear_DEC: - and [DevErrorCode],0 - popad - ret -; Записать код ошибки -@@Err1_3: - xor eax,eax - inc eax - jmp @@End_9 -@@Err6_1: - mov eax,6 -@@End_9: - mov [DevErrorCode],eax - popad - ret - -;**************************************************** -;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ * -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала (1 или 2); * -;* DiskNumber - номер диска (0 или 1); * -;* ATAFeatures - "особенности"; * -;* ATASectorCount - количество секторов; * -;* ATASectorNumber - номер начального сектора; * -;* ATACylinder - номер начального цилиндра; * -;* ATAHead - номер начальной головки; * -;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); * -;* ATACommand - код команды. * -;* После успешного выполнения функции: * -;* в ATABasePortAddr - базовый адрес HDD; * -;* в DevErrorCode - ноль. * -;* При возникновении ошибки в DevErrorCode будет * -;* возвращен код ошибки в eax * -;**************************************************** -SendCommandToHDD_1: -; pushad -; mov [DevErrorCode],0 not need -; Проверить значение кода режима - cmp [ATAAddressMode],1 - ja @@Err2_4 -; Проверить корректность номера канала - mov BX,[ChannelNumber] - cmp BX,1 - jb @@Err3_4 - cmp BX,2 - ja @@Err3_4 -; Установить базовый адрес - dec BX - shl BX,1 - movzx ebx,bx - mov AX,[ebx+StandardATABases] - mov [ATABasePortAddr],AX -; Ожидание готовности HDD к приему команды - ; Выбрать нужный диск - mov DX,[ATABasePortAddr] - add DX,6 ;адрес регистра головок - mov AL,[DiskNumber] - cmp AL,1 ;проверить номера диска - ja @@Err4_4 - shl AL,4 - or AL,10100000b - out DX,AL - ; Ожидать, пока диск не будет готов - inc DX - mov eax,[timer_ticks] - mov [TickCounter_1],eax - mov ecx,NoTickWaitTime -@@WaitHDReady_2: - cmp [timer_ticks_enable],0 - jne @f - dec ecx -; test ecx,ecx - jz @@Err1_4 - jmp .test -@@: - call change_task - ; Проверить время ожидания - mov eax,[timer_ticks] - sub eax,[TickCounter_1] - cmp eax,BSYWaitTime ;300 ;ожидать 3 сек. - ja @@Err1_4 ;ошибка тайм-аута - ; Прочитать регистр состояния -.test: - in AL,DX - ; Проверить состояние сигнала BSY - test AL,80h - jnz @@WaitHDReady_2 - ; Проверить состояние сигнала DRQ - test AL,08h - jnz @@WaitHDReady_2 - -; Загрузить команду в регистры контроллера - cli - mov DX,[ATABasePortAddr] - inc DX ;регистр "особенностей" - mov AL,[ATAFeatures] - out DX,AL - inc DX ;счетчик секторов - mov AL,[ATASectorCount] - out DX,AL - inc DX ;регистр номера сектора - mov AL,[ATASectorNumber] - out DX,AL - inc DX ;номер цилиндра (младший байт) - mov AX,[ATACylinder] - out DX,AL - inc DX ;номер цилиндра (старший байт) - mov AL,AH - out DX,AL - inc DX ;номер головки/номер диска - mov AL,[DiskNumber] - shl AL,4 - cmp [ATAHead],0Fh ;проверить номер головки - ja @@Err5_4 - or AL,[ATAHead] - or AL,10100000b - mov AH,[ATAAddressMode] - shl AH,6 - or AL,AH - out DX,AL -; Послать команду - mov AL,[ATACommand] - inc DX ;регистр команд - out DX,AL - sti -; Сбросить признак ошибки -; mov [DevErrorCode],0 -@@End_10: - xor eax,eax - ret -; Записать код ошибки -@@Err1_4: - xor eax,eax - inc eax -; mov [DevErrorCode],1 - ret -@@Err2_4: - mov eax,2 -; mov [DevErrorCode],2 - ret -@@Err3_4: - mov eax,3 -; mov [DevErrorCode],3 - ret -@@Err4_4: - mov eax,4 -; mov [DevErrorCode],4 - ret -@@Err5_4: - mov eax,5 -; mov [DevErrorCode],5 -; Завершение работы программы - ret -; sti -; popad - -;************************************************* -;* ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -WaitUnitReady: - pusha -; Запомнить время начала операции - mov EAX,[timer_ticks] - mov [WURStartTime],EAX -; Очистить буфер пакетной команды - call clear_packet_buffer -; Сформировать команду TEST UNIT READY - mov [PacketCommand],word 00h -; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА - mov ecx,NoTickWaitTime -@@SendCommand: - ; Подать команду проверки готовности - call SendPacketNoDatCommand - cmp [timer_ticks_enable],0 - jne @f - cmp [DevErrorCode],0 - je @@End_11 - dec ecx -; cmp ecx,0 - jz .Error - jmp @@SendCommand -@@: - call change_task - ; Проверить код ошибки - cmp [DevErrorCode],0 - je @@End_11 - ; Проверить время ожидания готовности - mov EAX,[timer_ticks] - sub EAX,[WURStartTime] - cmp EAX,MaxCDWaitTime - jb @@SendCommand -.Error: - ; Ошибка тайм-аута - mov [DevErrorCode],1 -@@End_11: - popa - ret - -;************************************************* -;* ЗАПРЕТИТЬ СМЕНУ ДИСКА * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -prevent_medium_removal: - pusha -; Очистить буфер пакетной команды - call clear_packet_buffer -; Задать код команды - mov [PacketCommand],byte 0x1E -; Задать код запрета - mov [PacketCommand+4],byte 11b -; Подать команду - call SendPacketNoDatCommand - mov eax,ATAPI_IDE0_lock - add eax,[cdpos] - dec eax - mov [eax],byte 1 - popa - ret - -;************************************************* -;* РАЗРЕШИТЬ СМЕНУ ДИСКА * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -allow_medium_removal: - pusha -; Очистить буфер пакетной команды - call clear_packet_buffer -; Задать код команды - mov [PacketCommand],byte 0x1E -; Задать код запрета - mov [PacketCommand+4],byte 00b -; Подать команду - call SendPacketNoDatCommand - mov eax,ATAPI_IDE0_lock - add eax,[cdpos] - dec eax - mov [eax],byte 0 - popa - ret - -;************************************************* -;* ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -LoadMedium: - pusha -; Очистить буфер пакетной команды - call clear_packet_buffer -; Сформировать команду START/STOP UNIT - ; Задать код команды - mov [PacketCommand],word 1Bh - ; Задать операцию загрузки носителя - mov [PacketCommand+4],word 00000011b -; Подать команду - call SendPacketNoDatCommand - popa - ret - -;************************************************* -;* ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -EjectMedium: - pusha -; Очистить буфер пакетной команды - call clear_packet_buffer -; Сформировать команду START/STOP UNIT - ; Задать код команды - mov [PacketCommand],word 1Bh - ; Задать операцию извлечения носителя - mov [PacketCommand+4],word 00000010b -; Подать команду - call SendPacketNoDatCommand - popa - ret - -;************************************************* -;* Проверить событие нажатия кнопки извлечения * -;* диска * -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -align 4 -check_ATAPI_device_event: - pusha - mov eax,[timer_ticks] - sub eax,[timer_ATAPI_check] - cmp eax,100 - jb .end_1 - mov al,[DRIVE_DATA+1] - and al,11b - cmp al,10b - jz .ide3 -.ide2_1: - mov al,[DRIVE_DATA+1] - and al,1100b - cmp al,1000b - jz .ide2 -.ide1_1: - mov al,[DRIVE_DATA+1] - and al,110000b - cmp al,100000b - jz .ide1 -.ide0_1: - mov al,[DRIVE_DATA+1] - and al,11000000b - cmp al,10000000b - jz .ide0 -.end: - - sti - mov eax,[timer_ticks] - mov [timer_ATAPI_check],eax -.end_1: - popa - ret - -.ide3: - cli - cmp [ATAPI_IDE3_lock],1 - jne .ide2_1 - cmp [IDE_Channel_2],0 - jne .ide1_1 - cmp [cd_status],0 - jne .end - mov [IDE_Channel_2],1 - call reserve_ok2 - mov [ChannelNumber],2 - mov [DiskNumber],1 - mov [cdpos],4 - call GetEvent_StatusNotification - cmp [CDDataBuf+4],byte 1 - je .eject_ide3 - call syscall_cdaudio.free - jmp .ide2_1 -.eject_ide3: - call .eject - call syscall_cdaudio.free - jmp .ide2_1 - -.ide2: - cli - cmp [ATAPI_IDE2_lock],1 - jne .ide1_1 - cmp [IDE_Channel_2],0 - jne .ide1_1 - cmp [cd_status],0 - jne .end - mov [IDE_Channel_2],1 - call reserve_ok2 - mov [ChannelNumber],2 - mov [DiskNumber],0 - mov [cdpos],3 - call GetEvent_StatusNotification - cmp [CDDataBuf+4],byte 1 - je .eject_ide2 - call syscall_cdaudio.free - jmp .ide1_1 -.eject_ide2: - call .eject - call syscall_cdaudio.free - jmp .ide1_1 - -.ide1: - cli - cmp [ATAPI_IDE1_lock],1 - jne .ide0_1 - cmp [IDE_Channel_1],0 - jne .end - cmp [cd_status],0 - jne .end - mov [IDE_Channel_1],1 - call reserve_ok2 - mov [ChannelNumber],1 - mov [DiskNumber],1 - mov [cdpos],2 - call GetEvent_StatusNotification - cmp [CDDataBuf+4],byte 1 - je .eject_ide1 - call syscall_cdaudio.free - jmp .ide0_1 -.eject_ide1: - call .eject - call syscall_cdaudio.free - jmp .ide0_1 - -.ide0: - cli - cmp [ATAPI_IDE0_lock],1 - jne .end - cmp [IDE_Channel_1],0 - jne .end - cmp [cd_status],0 - jne .end - mov [IDE_Channel_1],1 - call reserve_ok2 - mov [ChannelNumber],1 - mov [DiskNumber],0 - mov [cdpos],1 - call GetEvent_StatusNotification - cmp [CDDataBuf+4],byte 1 - je .eject_ide0 - call syscall_cdaudio.free - jmp .end -.eject_ide0: - call .eject - call syscall_cdaudio.free - jmp .end - -.eject: - call clear_CD_cache - call allow_medium_removal - mov [ignore_CD_eject_wait],1 - call EjectMedium - mov [ignore_CD_eject_wait],0 - ret -iglobal -timer_ATAPI_check dd 0 -ATAPI_IDE0_lock db 0 -ATAPI_IDE1_lock db 0 -ATAPI_IDE2_lock db 0 -ATAPI_IDE3_lock db 0 -ignore_CD_eject_wait db 0 -endg -;************************************************* -;* Получить сообщение о событии или состоянии * -;* устройства * -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -GetEvent_StatusNotification: - pusha - mov [CDDataBuf_pointer],CDDataBuf -; Очистить буфер пакетной команды - call clear_packet_buffer -; Задать код команды - mov [PacketCommand],byte 4Ah - mov [PacketCommand+1],byte 00000001b -; Задать запрос класса сообщений - mov [PacketCommand+4],byte 00010000b -; Размер выделенной области - mov [PacketCommand+7],byte 8h - mov [PacketCommand+8],byte 0h -; Подать команду - call SendPacketDatCommand - popa - ret - -;************************************************* -; прочитать информацию из TOC -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -Read_TOC: - pusha - mov [CDDataBuf_pointer],CDDataBuf -; Очистить буфер пакетной команды - call clear_packet_buffer -; Сформировать пакетную команду для считывания -; сектора данных - mov [PacketCommand],byte 0x43 - ; Задать формат - mov [PacketCommand+2],byte 1 -; Размер выделенной области - mov [PacketCommand+7],byte 0xFF - mov [PacketCommand+8],byte 0h -; Подать команду - call SendPacketDatCommand - popa - ret - -;************************************************* -;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ * -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;************************************************* -;ReadCapacity: -; pusha -;; Очистить буфер пакетной команды -; call clear_packet_buffer -;; Задать размер буфера в байтах -; mov [CDBlockSize],8 -;; Сформировать команду READ CAPACITY -; mov [PacketCommand],word 25h -;; Подать команду -; call SendPacketDatCommand -; popa -; ret - -clear_packet_buffer: -; Очистить буфер пакетной команды - and [PacketCommand],dword 0 - and [PacketCommand+4],dword 0 - and [PacketCommand+8],dword 0 - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;********************************************************** +; Непосредственная работа с устройством СD (ATAPI) +;********************************************************** +; Автор части исходного текста Кулаков Владимир Геннадьевич +; Адаптация, доработка и разработка Mario79, + +; Максимальное количество повторений операции чтения +MaxRetr equ 10 +; Предельное время ожидания готовности к приему команды +; (в тиках) +BSYWaitTime equ 1000 ;2 +NoTickWaitTime equ 0xfffff +CDBlockSize equ 2048 +;******************************************** +;* ЧТЕНИЕ СЕКТОРА С ПОВТОРАМИ * +;* Многократное повторение чтения при сбоях * +;******************************************** +ReadCDWRetr: +;----------------------------------------------------------- +; input : eax = block to read +; ebx = destination +;----------------------------------------------------------- + pushad + mov eax, [CDSectorAddress] + mov ebx, [CDDataBuf_pointer] + call cd_calculate_cache + xor edi, edi + add esi, 8 + inc edi +.hdreadcache: +; cmp dword [esi+4],0 ; empty +; je .nohdcache + cmp [esi], eax ; correct sector + je .yeshdcache +.nohdcache: + add esi, 8 + inc edi + dec ecx + jnz .hdreadcache + call find_empty_slot_CD_cache ; ret in edi + + push edi + push eax + call cd_calculate_cache_2 + shl edi, 11 + add edi, eax + mov [CDDataBuf_pointer], edi + pop eax + pop edi + + call ReadCDWRetr_1 + cmp [DevErrorCode], 0 + jne .exit + + mov [CDDataBuf_pointer], ebx + call cd_calculate_cache_1 + lea esi, [edi*8+esi] + mov [esi], eax ; sector number +; mov dword [esi+4],1 ; hd read - mark as same as in hd +.yeshdcache: + mov esi, edi + shl esi, 11;9 + push eax + call cd_calculate_cache_2 + add esi, eax + pop eax + mov edi, ebx;[CDDataBuf_pointer] + mov ecx, 512;/4 + cld + rep movsd ; move data +.exit: + popad + ret + +ReadCDWRetr_1: + pushad + +; Цикл, пока команда не выполнена успешно или не +; исчерпано количество попыток + mov ECX, MaxRetr +@@NextRetr: +; Подать команду +;************************************************* +;* ПОЛНОЕ ЧТЕНИЕ СЕКТОРА КОМПАКТ-ДИСКА * +;* Считываются данные пользователя, информация * +;* субканала и контрольная информация * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале; * +;* CDSectorAddress - адрес считываемого сектора. * +;* Данные считывается в массив CDDataBuf. * +;************************************************* +;ReadCD: + push ecx +; pusha +; Задать размер сектора +; mov [CDBlockSize],2048 ;2352 +; Очистить буфер пакетной команды + call clear_packet_buffer +; Сформировать пакетную команду для считывания +; сектора данных +; Задать код команды Read CD + mov [PacketCommand], byte 0x28;0xBE +; Задать адрес сектора + mov AX, word [CDSectorAddress+2] + xchg AL, AH + mov word [PacketCommand+2], AX + mov AX, word [CDSectorAddress] + xchg AL, AH + mov word [PacketCommand+4], AX +; mov eax,[CDSectorAddress] +; mov [PacketCommand+2],eax +; Задать количество считываемых секторов + mov [PacketCommand+8], byte 1 +; Задать считывание данных в полном объеме +; mov [PacketCommand+9],byte 0xF8 +; Подать команду + call SendPacketDatCommand + pop ecx +; ret + +; cmp [DevErrorCode],0 + test eax, eax + jz @@End_4 + + or ecx, ecx ;{SPraid.simba} (for cd load) + jz @@End_4 + dec ecx + + cmp [timer_ticks_enable], 0 + jne @f + mov eax, NoTickWaitTime +.wait: + dec eax +; test eax,eax + jz @@NextRetr + jmp .wait +@@: +; Задержка на 2,5 секунды +; mov EAX,[timer_ticks] +; add EAX,50 ;250 +;@@Wait: +; call change_task +; cmp EAX,[timer_ticks] +; ja @@Wait + loop @@NextRetr +@@End_4: + mov dword [DevErrorCode], eax + popad + ret + + +; Универсальные процедуры, обеспечивающие выполнение +; пакетных команд в режиме PIO + +; Максимально допустимое время ожидания реакции +; устройства на пакетную команду (в тиках) + +MaxCDWaitTime equ 1000 ;200 ;10 секунд +uglobal +; Область памяти для формирования пакетной команды +PacketCommand: + rb 12 ;DB 12 DUP (?) +; Область памяти для приема данных от дисковода +;CDDataBuf DB 4096 DUP (0) +; Размер принимаемого блока данных в байтах +;CDBlockSize DW ? +; Адрес считываемого сектора данных +CDSectorAddress: + DD ? +; Время начала очередной операции с диском +TickCounter_1 DD 0 +; Время начала ожидания готовности устройства +WURStartTime DD 0 +; указатель буфера для считывания +CDDataBuf_pointer dd 0 +endg +;**************************************************** +;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, * +;* ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧУ ОДНОГО СЕКТОРА ДАННЫХ * +;* РАЗМЕРОМ 2048 БАЙТ ОТ УСТРОЙСТВА К ХОСТУ * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале; * +;* PacketCommand - 12-байтный командный пакет; * +;* CDBlockSize - размер принимаемого блока данных. * +; return eax DevErrorCode +;**************************************************** +SendPacketDatCommand: + xor eax, eax +; mov byte [DevErrorCode],al +; Задать режим CHS + mov byte [ATAAddressMode], al +; Послать ATA-команду передачи пакетной команды + mov byte [ATAFeatures], al + mov byte [ATASectorCount], al + mov byte [ATASectorNumber], al + ; Загрузить размер передаваемого блока + mov [ATAHead], al +; mov AX,[CDBlockSize] + mov [ATACylinder], CDBlockSize + mov [ATACommand], 0A0h + call SendCommandToHDD_1 + test eax, eax +; cmp [DevErrorCode],0 ;проверить код ошибки + jnz @@End_8 ;закончить, сохранив код ошибки + +; Ожидание готовности дисковода к приему +; пакетной команды + mov DX, [ATABasePortAddr] + add DX, 7 ;порт 1х7h + mov ecx, NoTickWaitTime +@@WaitDevice0: + cmp [timer_ticks_enable], 0 + jne @f + dec ecx +; test ecx,ecx + jz @@Err1_1 + jmp .test +@@: + call change_task + ; Проверить время выполнения команды + mov EAX, [timer_ticks] + sub EAX, [TickCounter_1] + cmp EAX, BSYWaitTime + ja @@Err1_1 ;ошибка тайм-аута + ; Проверить готовность +.test: + in AL, DX + test AL, 80h ;состояние сигнала BSY + jnz @@WaitDevice0 + test AL, 1 ;состояние сигнала ERR + jnz @@Err6 + test AL, 08h ;состояние сигнала DRQ + jz @@WaitDevice0 +; Послать пакетную команду + cli + mov DX, [ATABasePortAddr] + mov AX, [PacketCommand] + out DX, AX + mov AX, [PacketCommand+2] + out DX, AX + mov AX, [PacketCommand+4] + out DX, AX + mov AX, [PacketCommand+6] + out DX, AX + mov AX, [PacketCommand+8] + out DX, AX + mov AX, [PacketCommand+10] + out DX, AX + sti +; Ожидание готовности данных + mov DX, [ATABasePortAddr] + add DX, 7 ;порт 1х7h + mov ecx, NoTickWaitTime +@@WaitDevice1: + cmp [timer_ticks_enable], 0 + jne @f + dec ecx +; test ecx,ecx + jz @@Err1_1 + jmp .test_1 +@@: + call change_task + ; Проверить время выполнения команды + mov EAX, [timer_ticks] + sub EAX, [TickCounter_1] + cmp EAX, MaxCDWaitTime + ja @@Err1_1 ;ошибка тайм-аута + ; Проверить готовность +.test_1: + in AL, DX + test AL, 80h ;состояние сигнала BSY + jnz @@WaitDevice1 + test AL, 1 ;состояние сигнала ERR + jnz @@Err6_temp + test AL, 08h ;состояние сигнала DRQ + jz @@WaitDevice1 +; Принять блок данных от контроллера + mov EDI, [CDDataBuf_pointer];0x7000 ;CDDataBuf + ; Загрузить адрес регистра данных контроллера + mov DX, [ATABasePortAddr];порт 1x0h + ; Загрузить в счетчик размер блока в байтах + xor ecx, ecx + mov CX, CDBlockSize + ; Вычислить размер блока в 16-разрядных словах + shr CX, 1;разделить размер блока на 2 + ; Принять блок данных + cli + cld + rep insw + sti +; Успешное завершение приема данных +@@End_8: + xor eax, eax + ret + +; Записать код ошибки +@@Err1_1: + xor eax, eax + inc eax + ret +; mov [DevErrorCode],1 +; ret +@@Err6_temp: + mov eax, 7 + ret +; mov [DevErrorCode],7 +; ret +@@Err6: + mov eax, 6 + ret +; mov [DevErrorCode],6 +;@@End_8: +; ret + + + +;*********************************************** +;* ПОСЛАТЬ УСТРОЙСТВУ ATAPI ПАКЕТНУЮ КОМАНДУ, * +;* НЕ ПРЕДУСМАТРИВАЮЩУЮ ПЕРЕДАЧИ ДАННЫХ * +;* Входные параметры передаются через * +;* глобальные перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале; * +;* PacketCommand - 12-байтный командный пакет. * +;*********************************************** +SendPacketNoDatCommand: + pushad + xor eax, eax +; mov byte [DevErrorCode],al +; Задать режим CHS + mov byte [ATAAddressMode], al +; Послать ATA-команду передачи пакетной команды + mov byte [ATAFeatures], al + mov byte [ATASectorCount], al + mov byte [ATASectorNumber], al + mov word [ATACylinder], ax + mov byte [ATAHead], al + mov [ATACommand], 0A0h + call SendCommandToHDD_1 +; cmp [DevErrorCode],0 ;проверить код ошибки + test eax, eax + jnz @@End_9 ;закончить, сохранив код ошибки +; Ожидание готовности дисковода к приему +; пакетной команды + mov DX, [ATABasePortAddr] + add DX, 7 ;порт 1х7h +@@WaitDevice0_1: + call change_task + ; Проверить время ожидания + mov EAX, [timer_ticks] + sub EAX, [TickCounter_1] + cmp EAX, BSYWaitTime + ja @@Err1_3 ;ошибка тайм-аута + ; Проверить готовность + in AL, DX + test AL, 80h ;состояние сигнала BSY + jnz @@WaitDevice0_1 + test AL, 1 ;состояние сигнала ERR + jnz @@Err6_1 + test AL, 08h ;состояние сигнала DRQ + jz @@WaitDevice0_1 +; Послать пакетную команду +; cli + mov DX, [ATABasePortAddr] + mov AX, word [PacketCommand] + out DX, AX + mov AX, word [PacketCommand+2] + out DX, AX + mov AX, word [PacketCommand+4] + out DX, AX + mov AX, word [PacketCommand+6] + out DX, AX + mov AX, word [PacketCommand+8] + out DX, AX + mov AX, word [PacketCommand+10] + out DX, AX +; sti + cmp [ignore_CD_eject_wait], 1 + je @@clear_DEC +; Ожидание подтверждения приема команды + mov DX, [ATABasePortAddr] + add DX, 7 ;порт 1х7h +@@WaitDevice1_1: + call change_task + ; Проверить время выполнения команды + mov EAX, [timer_ticks] + sub EAX, [TickCounter_1] + cmp EAX, MaxCDWaitTime + ja @@Err1_3 ;ошибка тайм-аута + ; Ожидать освобождения устройства + in AL, DX + test AL, 80h ;состояние сигнала BSY + jnz @@WaitDevice1_1 + test AL, 1 ;состояние сигнала ERR + jnz @@Err6_1 + test AL, 40h ;состояние сигнала DRDY + jz @@WaitDevice1_1 +@@clear_DEC: + and [DevErrorCode], 0 + popad + ret +; Записать код ошибки +@@Err1_3: + xor eax, eax + inc eax + jmp @@End_9 +@@Err6_1: + mov eax, 6 +@@End_9: + mov [DevErrorCode], eax + popad + ret + +;**************************************************** +;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ * +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала (1 или 2); * +;* DiskNumber - номер диска (0 или 1); * +;* ATAFeatures - "особенности"; * +;* ATASectorCount - количество секторов; * +;* ATASectorNumber - номер начального сектора; * +;* ATACylinder - номер начального цилиндра; * +;* ATAHead - номер начальной головки; * +;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); * +;* ATACommand - код команды. * +;* После успешного выполнения функции: * +;* в ATABasePortAddr - базовый адрес HDD; * +;* в DevErrorCode - ноль. * +;* При возникновении ошибки в DevErrorCode будет * +;* возвращен код ошибки в eax * +;**************************************************** +SendCommandToHDD_1: +; pushad +; mov [DevErrorCode],0 not need +; Проверить значение кода режима + cmp [ATAAddressMode], 1 + ja @@Err2_4 +; Проверить корректность номера канала + mov BX, [ChannelNumber] + cmp BX, 1 + jb @@Err3_4 + cmp BX, 2 + ja @@Err3_4 +; Установить базовый адрес + dec BX + shl BX, 1 + movzx ebx, bx + mov AX, [ebx+StandardATABases] + mov [ATABasePortAddr], AX +; Ожидание готовности HDD к приему команды + ; Выбрать нужный диск + mov DX, [ATABasePortAddr] + add DX, 6 ;адрес регистра головок + mov AL, [DiskNumber] + cmp AL, 1 ;проверить номера диска + ja @@Err4_4 + shl AL, 4 + or AL, 10100000b + out DX, AL + ; Ожидать, пока диск не будет готов + inc DX + mov eax, [timer_ticks] + mov [TickCounter_1], eax + mov ecx, NoTickWaitTime +@@WaitHDReady_2: + cmp [timer_ticks_enable], 0 + jne @f + dec ecx +; test ecx,ecx + jz @@Err1_4 + jmp .test +@@: + call change_task + ; Проверить время ожидания + mov eax, [timer_ticks] + sub eax, [TickCounter_1] + cmp eax, BSYWaitTime;300 ;ожидать 3 сек. + ja @@Err1_4 ;ошибка тайм-аута + ; Прочитать регистр состояния +.test: + in AL, DX + ; Проверить состояние сигнала BSY + test AL, 80h + jnz @@WaitHDReady_2 + ; Проверить состояние сигнала DRQ + test AL, 08h + jnz @@WaitHDReady_2 + +; Загрузить команду в регистры контроллера + cli + mov DX, [ATABasePortAddr] + inc DX ;регистр "особенностей" + mov AL, [ATAFeatures] + out DX, AL + inc DX ;счетчик секторов + mov AL, [ATASectorCount] + out DX, AL + inc DX ;регистр номера сектора + mov AL, [ATASectorNumber] + out DX, AL + inc DX ;номер цилиндра (младший байт) + mov AX, [ATACylinder] + out DX, AL + inc DX ;номер цилиндра (старший байт) + mov AL, AH + out DX, AL + inc DX ;номер головки/номер диска + mov AL, [DiskNumber] + shl AL, 4 + cmp [ATAHead], 0Fh;проверить номер головки + ja @@Err5_4 + or AL, [ATAHead] + or AL, 10100000b + mov AH, [ATAAddressMode] + shl AH, 6 + or AL, AH + out DX, AL +; Послать команду + mov AL, [ATACommand] + inc DX ;регистр команд + out DX, AL + sti +; Сбросить признак ошибки +; mov [DevErrorCode],0 +@@End_10: + xor eax, eax + ret +; Записать код ошибки +@@Err1_4: + xor eax, eax + inc eax +; mov [DevErrorCode],1 + ret +@@Err2_4: + mov eax, 2 +; mov [DevErrorCode],2 + ret +@@Err3_4: + mov eax, 3 +; mov [DevErrorCode],3 + ret +@@Err4_4: + mov eax, 4 +; mov [DevErrorCode],4 + ret +@@Err5_4: + mov eax, 5 +; mov [DevErrorCode],5 +; Завершение работы программы + ret +; sti +; popad + +;************************************************* +;* ОЖИДАНИЕ ГОТОВНОСТИ УСТРОЙСТВА К РАБОТЕ * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +WaitUnitReady: + pusha +; Запомнить время начала операции + mov EAX, [timer_ticks] + mov [WURStartTime], EAX +; Очистить буфер пакетной команды + call clear_packet_buffer +; Сформировать команду TEST UNIT READY + mov [PacketCommand], word 00h +; ЦИКЛ ОЖИДАНИЯ ГОТОВНОСТИ УСТРОЙСТВА + mov ecx, NoTickWaitTime +@@SendCommand: + ; Подать команду проверки готовности + call SendPacketNoDatCommand + cmp [timer_ticks_enable], 0 + jne @f + cmp [DevErrorCode], 0 + je @@End_11 + dec ecx +; cmp ecx,0 + jz .Error + jmp @@SendCommand +@@: + call change_task + ; Проверить код ошибки + cmp [DevErrorCode], 0 + je @@End_11 + ; Проверить время ожидания готовности + mov EAX, [timer_ticks] + sub EAX, [WURStartTime] + cmp EAX, MaxCDWaitTime + jb @@SendCommand +.Error: + ; Ошибка тайм-аута + mov [DevErrorCode], 1 +@@End_11: + popa + ret + +;************************************************* +;* ЗАПРЕТИТЬ СМЕНУ ДИСКА * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +prevent_medium_removal: + pusha +; Очистить буфер пакетной команды + call clear_packet_buffer +; Задать код команды + mov [PacketCommand], byte 0x1E +; Задать код запрета + mov [PacketCommand+4], byte 11b +; Подать команду + call SendPacketNoDatCommand + mov eax, ATAPI_IDE0_lock + add eax, [cdpos] + dec eax + mov [eax], byte 1 + popa + ret + +;************************************************* +;* РАЗРЕШИТЬ СМЕНУ ДИСКА * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +allow_medium_removal: + pusha +; Очистить буфер пакетной команды + call clear_packet_buffer +; Задать код команды + mov [PacketCommand], byte 0x1E +; Задать код запрета + mov [PacketCommand+4], byte 00b +; Подать команду + call SendPacketNoDatCommand + mov eax, ATAPI_IDE0_lock + add eax, [cdpos] + dec eax + mov [eax], byte 0 + popa + ret + +;************************************************* +;* ЗАГРУЗИТЬ НОСИТЕЛЬ В ДИСКОВОД * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +LoadMedium: + pusha +; Очистить буфер пакетной команды + call clear_packet_buffer +; Сформировать команду START/STOP UNIT + ; Задать код команды + mov [PacketCommand], word 1Bh + ; Задать операцию загрузки носителя + mov [PacketCommand+4], word 00000011b +; Подать команду + call SendPacketNoDatCommand + popa + ret + +;************************************************* +;* ИЗВЛЕЧЬ НОСИТЕЛЬ ИЗ ДИСКОВОДА * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +EjectMedium: + pusha +; Очистить буфер пакетной команды + call clear_packet_buffer +; Сформировать команду START/STOP UNIT + ; Задать код команды + mov [PacketCommand], word 1Bh + ; Задать операцию извлечения носителя + mov [PacketCommand+4], word 00000010b +; Подать команду + call SendPacketNoDatCommand + popa + ret + +;************************************************* +;* Проверить событие нажатия кнопки извлечения * +;* диска * +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +align 4 +check_ATAPI_device_event: + pusha + mov eax, [timer_ticks] + sub eax, [timer_ATAPI_check] + cmp eax, 100 + jb .end_1 + mov al, [DRIVE_DATA+1] + and al, 11b + cmp al, 10b + jz .ide3 +.ide2_1: + mov al, [DRIVE_DATA+1] + and al, 1100b + cmp al, 1000b + jz .ide2 +.ide1_1: + mov al, [DRIVE_DATA+1] + and al, 110000b + cmp al, 100000b + jz .ide1 +.ide0_1: + mov al, [DRIVE_DATA+1] + and al, 11000000b + cmp al, 10000000b + jz .ide0 +.end: + + sti + mov eax, [timer_ticks] + mov [timer_ATAPI_check], eax +.end_1: + popa + ret + +.ide3: + cli + cmp [ATAPI_IDE3_lock], 1 + jne .ide2_1 + cmp [IDE_Channel_2], 0 + jne .ide1_1 + cmp [cd_status], 0 + jne .end + mov [IDE_Channel_2], 1 + call reserve_ok2 + mov [ChannelNumber], 2 + mov [DiskNumber], 1 + mov [cdpos], 4 + call GetEvent_StatusNotification + cmp [CDDataBuf+4], byte 1 + je .eject_ide3 + call syscall_cdaudio.free + jmp .ide2_1 +.eject_ide3: + call .eject + call syscall_cdaudio.free + jmp .ide2_1 + +.ide2: + cli + cmp [ATAPI_IDE2_lock], 1 + jne .ide1_1 + cmp [IDE_Channel_2], 0 + jne .ide1_1 + cmp [cd_status], 0 + jne .end + mov [IDE_Channel_2], 1 + call reserve_ok2 + mov [ChannelNumber], 2 + mov [DiskNumber], 0 + mov [cdpos], 3 + call GetEvent_StatusNotification + cmp [CDDataBuf+4], byte 1 + je .eject_ide2 + call syscall_cdaudio.free + jmp .ide1_1 +.eject_ide2: + call .eject + call syscall_cdaudio.free + jmp .ide1_1 + +.ide1: + cli + cmp [ATAPI_IDE1_lock], 1 + jne .ide0_1 + cmp [IDE_Channel_1], 0 + jne .end + cmp [cd_status], 0 + jne .end + mov [IDE_Channel_1], 1 + call reserve_ok2 + mov [ChannelNumber], 1 + mov [DiskNumber], 1 + mov [cdpos], 2 + call GetEvent_StatusNotification + cmp [CDDataBuf+4], byte 1 + je .eject_ide1 + call syscall_cdaudio.free + jmp .ide0_1 +.eject_ide1: + call .eject + call syscall_cdaudio.free + jmp .ide0_1 + +.ide0: + cli + cmp [ATAPI_IDE0_lock], 1 + jne .end + cmp [IDE_Channel_1], 0 + jne .end + cmp [cd_status], 0 + jne .end + mov [IDE_Channel_1], 1 + call reserve_ok2 + mov [ChannelNumber], 1 + mov [DiskNumber], 0 + mov [cdpos], 1 + call GetEvent_StatusNotification + cmp [CDDataBuf+4], byte 1 + je .eject_ide0 + call syscall_cdaudio.free + jmp .end +.eject_ide0: + call .eject + call syscall_cdaudio.free + jmp .end + +.eject: + call clear_CD_cache + call allow_medium_removal + mov [ignore_CD_eject_wait], 1 + call EjectMedium + mov [ignore_CD_eject_wait], 0 + ret +iglobal +timer_ATAPI_check dd 0 +ATAPI_IDE0_lock db 0 +ATAPI_IDE1_lock db 0 +ATAPI_IDE2_lock db 0 +ATAPI_IDE3_lock db 0 +ignore_CD_eject_wait db 0 +endg +;************************************************* +;* Получить сообщение о событии или состоянии * +;* устройства * +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +GetEvent_StatusNotification: + pusha + mov [CDDataBuf_pointer], CDDataBuf +; Очистить буфер пакетной команды + call clear_packet_buffer +; Задать код команды + mov [PacketCommand], byte 4Ah + mov [PacketCommand+1], byte 00000001b +; Задать запрос класса сообщений + mov [PacketCommand+4], byte 00010000b +; Размер выделенной области + mov [PacketCommand+7], byte 8h + mov [PacketCommand+8], byte 0h +; Подать команду + call SendPacketDatCommand + popa + ret + +;************************************************* +; прочитать информацию из TOC +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +Read_TOC: + pusha + mov [CDDataBuf_pointer], CDDataBuf +; Очистить буфер пакетной команды + call clear_packet_buffer +; Сформировать пакетную команду для считывания +; сектора данных + mov [PacketCommand], byte 0x43 + ; Задать формат + mov [PacketCommand+2], byte 1 +; Размер выделенной области + mov [PacketCommand+7], byte 0xFF + mov [PacketCommand+8], byte 0h +; Подать команду + call SendPacketDatCommand + popa + ret + +;************************************************* +;* ОПРЕДЕЛИТЬ ОБЩЕЕ КОЛИЧЕСТВО СЕКТОРОВ НА ДИСКЕ * +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;************************************************* +;ReadCapacity: +; pusha +;; Очистить буфер пакетной команды +; call clear_packet_buffer +;; Задать размер буфера в байтах +; mov [CDBlockSize],8 +;; Сформировать команду READ CAPACITY +; mov [PacketCommand],word 25h +;; Подать команду +; call SendPacketDatCommand +; popa +; ret + +clear_packet_buffer: +; Очистить буфер пакетной команды + and [PacketCommand], dword 0 + and [PacketCommand+4], dword 0 + and [PacketCommand+8], dword 0 + ret diff --git a/kernel/trunk/blkdev/cdrom.inc b/kernel/trunk/blkdev/cdrom.inc index d7a937066..860a2879e 100644 --- a/kernel/trunk/blkdev/cdrom.inc +++ b/kernel/trunk/blkdev/cdrom.inc @@ -1,271 +1,271 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -sys_cd_audio: - - cmp word [cdbase],word 0 - jnz @f - mov eax,1 - ret - @@: - - ; eax=1 cdplay at ebx 0x00FFSSMM - ; eax=2 get tracklist size of ecx to [ebx] - ; eax=3 stop/pause playing - - cmp eax,1 - jnz nocdp - call sys_cdplay - ret - nocdp: - - cmp eax,2 - jnz nocdtl - mov edi,[TASK_BASE] - add edi,TASKDATA.mem_start - add ebx,[edi] - call sys_cdtracklist - ret - nocdtl: - - cmp eax,3 - jnz nocdpause - call sys_cdpause - ret - nocdpause: - - mov eax,0xffffff01 - ret - - - -sys_cd_atapi_command: - - pushad - - mov dx,word [cdbase] - add dx,6 - mov ax,word [cdid] - out dx,al - mov esi,10 - call delay_ms - mov dx,word [cdbase] - add dx,7 - in al,dx - and al,0x80 - cmp al,0 - jnz res - jmp cdl6 - res: - mov dx,word [cdbase] - add dx,7 - mov al,0x8 - out dx,al - mov dx,word [cdbase] - add dx,0x206 - mov al,0xe - out dx,al - mov esi,1 - call delay_ms - mov dx,word [cdbase] - add dx,0x206 - mov al,0x8 - out dx,al - mov esi,30 - call delay_ms - xor cx,cx - cdl5: - inc cx - cmp cx,10 - jz cdl6 - mov dx,word [cdbase] - add dx,7 - in al,dx - and al,0x88 - cmp al,0x00 - jz cdl5 - mov esi,100 - call delay_ms - jmp cdl5 - cdl6: - mov dx,word [cdbase] - add dx,4 - mov al,0 - out dx,al - mov dx,word [cdbase] - add dx,5 - mov al,0 - out dx,al - mov dx,word [cdbase] - add dx,7 - mov al,0xec - out dx,al - mov esi,5 - call delay_ms - mov dx,word [cdbase] - add dx,1 - mov al,0 - out dx,al - add dx,1 - mov al,0 - out dx,al - add dx,1 - mov al,0 - out dx,al - add dx,1 - mov al,0 - out dx,al - add dx,1 - mov al,128 - out dx,al - add dx,2 - mov al,0xa0 - out dx,al - xor cx,cx - mov dx,word [cdbase] - add dx,7 - cdl1: - inc cx - cmp cx,100 - jz cdl2 - in al,dx - and ax,0x88 - cmp al,0x8 - jz cdl2 - mov esi,2 - call delay_ms - jmp cdl1 - cdl2: - - popad - ret - - -sys_cdplay: - - mov ax,5 - push ax - push ebx - cdplay: - call sys_cd_atapi_command - cli - mov dx,word [cdbase] - mov ax,0x0047 - out dx,ax - mov al,1 - mov ah,[esp+0] ; min xx - out dx,ax - mov ax,[esp+1] ; fr sec - out dx,ax - mov ax,256+99 - out dx,ax - mov ax,0x0001 - out dx,ax - mov ax,0x0000 - out dx,ax - mov esi,10 - call delay_ms - sti - add dx,7 - in al,dx - test al,1 - jz cdplayok - mov ax,[esp+4] - dec ax - mov [esp+4],ax - cmp ax,0 - jz cdplayfail - jmp cdplay - cdplayfail: - cdplayok: - pop ebx - pop ax - xor eax, eax - ret - - -sys_cdtracklist: - - push ebx - tcdplay: - call sys_cd_atapi_command - mov dx,word [cdbase] - mov ax,0x43+2*256 - out dx,ax - mov ax,0x0 - out dx,ax - mov ax,0x0 - out dx,ax - mov ax,0x0 - out dx,ax - mov ax,200 - out dx,ax - mov ax,0x0 - out dx,ax - in al,dx - mov cx,1000 - mov dx,word [cdbase] - add dx,7 - cld - cdtrnwewait: - mov esi,10 - call delay_ms - in al,dx - and al,128 - cmp al,0 - jz cdtrl1 - loop cdtrnwewait - cdtrl1: - ; read the result - mov ecx,[esp+0] - mov dx,word [cdbase] - cdtrread: - add dx,7 - in al,dx - and al,8 - cmp al,8 - jnz cdtrdone - sub dx,7 - in ax,dx - mov [ecx],ax - add ecx,2 - jmp cdtrread - cdtrdone: - pop ecx - xor eax, eax - ret - - -sys_cdpause: - - call sys_cd_atapi_command - - mov dx,word [cdbase] - mov ax,0x004B - out dx,ax - mov ax,0 - out dx,ax - mov ax,0 - out dx,ax - mov ax,0 - out dx,ax - mov ax,0 - out dx,ax - mov ax,0 - out dx,ax - - mov esi,10 - call delay_ms - add dx,7 - in al,dx - - xor eax, eax - ret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +sys_cd_audio: + + cmp word [cdbase], word 0 + jnz @f + mov eax, 1 + ret + @@: + + ; eax=1 cdplay at ebx 0x00FFSSMM + ; eax=2 get tracklist size of ecx to [ebx] + ; eax=3 stop/pause playing + + cmp eax, 1 + jnz nocdp + call sys_cdplay + ret + nocdp: + + cmp eax, 2 + jnz nocdtl + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add ebx, [edi] + call sys_cdtracklist + ret + nocdtl: + + cmp eax, 3 + jnz nocdpause + call sys_cdpause + ret + nocdpause: + + mov eax, 0xffffff01 + ret + + + +sys_cd_atapi_command: + + pushad + + mov dx, word [cdbase] + add dx, 6 + mov ax, word [cdid] + out dx, al + mov esi, 10 + call delay_ms + mov dx, word [cdbase] + add dx, 7 + in al, dx + and al, 0x80 + cmp al, 0 + jnz res + jmp cdl6 + res: + mov dx, word [cdbase] + add dx, 7 + mov al, 0x8 + out dx, al + mov dx, word [cdbase] + add dx, 0x206 + mov al, 0xe + out dx, al + mov esi, 1 + call delay_ms + mov dx, word [cdbase] + add dx, 0x206 + mov al, 0x8 + out dx, al + mov esi, 30 + call delay_ms + xor cx, cx + cdl5: + inc cx + cmp cx, 10 + jz cdl6 + mov dx, word [cdbase] + add dx, 7 + in al, dx + and al, 0x88 + cmp al, 0x00 + jz cdl5 + mov esi, 100 + call delay_ms + jmp cdl5 + cdl6: + mov dx, word [cdbase] + add dx, 4 + mov al, 0 + out dx, al + mov dx, word [cdbase] + add dx, 5 + mov al, 0 + out dx, al + mov dx, word [cdbase] + add dx, 7 + mov al, 0xec + out dx, al + mov esi, 5 + call delay_ms + mov dx, word [cdbase] + add dx, 1 + mov al, 0 + out dx, al + add dx, 1 + mov al, 0 + out dx, al + add dx, 1 + mov al, 0 + out dx, al + add dx, 1 + mov al, 0 + out dx, al + add dx, 1 + mov al, 128 + out dx, al + add dx, 2 + mov al, 0xa0 + out dx, al + xor cx, cx + mov dx, word [cdbase] + add dx, 7 + cdl1: + inc cx + cmp cx, 100 + jz cdl2 + in al, dx + and ax, 0x88 + cmp al, 0x8 + jz cdl2 + mov esi, 2 + call delay_ms + jmp cdl1 + cdl2: + + popad + ret + + +sys_cdplay: + + mov ax, 5 + push ax + push ebx + cdplay: + call sys_cd_atapi_command + cli + mov dx, word [cdbase] + mov ax, 0x0047 + out dx, ax + mov al, 1 + mov ah, [esp+0]; min xx + out dx, ax + mov ax, [esp+1]; fr sec + out dx, ax + mov ax, 256+99 + out dx, ax + mov ax, 0x0001 + out dx, ax + mov ax, 0x0000 + out dx, ax + mov esi, 10 + call delay_ms + sti + add dx, 7 + in al, dx + test al, 1 + jz cdplayok + mov ax, [esp+4] + dec ax + mov [esp+4], ax + cmp ax, 0 + jz cdplayfail + jmp cdplay + cdplayfail: + cdplayok: + pop ebx + pop ax + xor eax, eax + ret + + +sys_cdtracklist: + + push ebx + tcdplay: + call sys_cd_atapi_command + mov dx, word [cdbase] + mov ax, 0x43+2*256 + out dx, ax + mov ax, 0x0 + out dx, ax + mov ax, 0x0 + out dx, ax + mov ax, 0x0 + out dx, ax + mov ax, 200 + out dx, ax + mov ax, 0x0 + out dx, ax + in al, dx + mov cx, 1000 + mov dx, word [cdbase] + add dx, 7 + cld + cdtrnwewait: + mov esi, 10 + call delay_ms + in al, dx + and al, 128 + cmp al, 0 + jz cdtrl1 + loop cdtrnwewait + cdtrl1: + ; read the result + mov ecx, [esp+0] + mov dx, word [cdbase] + cdtrread: + add dx, 7 + in al, dx + and al, 8 + cmp al, 8 + jnz cdtrdone + sub dx, 7 + in ax, dx + mov [ecx], ax + add ecx, 2 + jmp cdtrread + cdtrdone: + pop ecx + xor eax, eax + ret + + +sys_cdpause: + + call sys_cd_atapi_command + + mov dx, word [cdbase] + mov ax, 0x004B + out dx, ax + mov ax, 0 + out dx, ax + mov ax, 0 + out dx, ax + mov ax, 0 + out dx, ax + mov ax, 0 + out dx, ax + mov ax, 0 + out dx, ax + + mov esi, 10 + call delay_ms + add dx, 7 + in al, dx + + xor eax, eax + ret + diff --git a/kernel/trunk/blkdev/disk.inc b/kernel/trunk/blkdev/disk.inc index 76406d17b..d50631b11 100644 --- a/kernel/trunk/blkdev/disk.inc +++ b/kernel/trunk/blkdev/disk.inc @@ -1,1258 +1,1258 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; ============================================================================= -; ================================= Constants ================================= -; ============================================================================= -; Error codes for callback functions. -DISK_STATUS_OK = 0 ; success -DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable -DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters -DISK_STATUS_NO_MEDIA = 2 ; no media present -DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data -; Driver flags. Represent bits in DISK.DriverFlags. -DISK_NO_INSERT_NOTIFICATION = 1 -; Media flags. Represent bits in DISKMEDIAINFO.Flags. -DISK_MEDIA_READONLY = 1 - -; If too many partitions are detected,there is probably an error on the disk. -; 256 partitions should be enough for any reasonable use. -; Also, the same number is limiting the number of MBRs to process; if -; too many MBRs are visible,there probably is a loop in the MBR structure. -MAX_NUM_PARTITIONS = 256 - -; ============================================================================= -; ================================ Structures ================================= -; ============================================================================= -; This structure defines all callback functions for working with the physical -; device. They are implemented by a driver. Objects with this structure reside -; in a driver. -struct DISKFUNC -.strucsize dd ? -; Size of the structure. This field is intended for possible extensions of -; this structure. If a new function is added to this structure and a driver -; implements an old version, the caller can detect this by checking .strucsize, -; so the driver remains compatible. -.close dd ? -; The pointer to the function which frees all driver-specific resources for -; the disk. -; Optional, may be NULL. -; void close(void* userdata); -.closemedia dd ? -; The pointer to the function which informs the driver that the kernel has -; finished all processing with the current media. If media is removed, the -; driver should decline all requests to that media with DISK_STATUS_NO_MEDIA, -; even if new media is inserted, until this function is called. If media is -; removed, a new call to 'disk_media_changed' is not allowed until this -; function is called. -; Optional, may be NULL (if media is not removable). -; void closemedia(void* userdata); -.querymedia dd ? -; The pointer to the function which determines capabilities of the media. -; int querymedia(void* userdata, DISKMEDIAINFO* info); -; Return value: one of DISK_STATUS_* -.read dd ? -; The pointer to the function which reads data from the device. -; int read(void* userdata, void* buffer, __int64 startsector, int* numsectors); -; input: *numsectors = number of sectors to read -; output: *numsectors = number of sectors which were successfully read -; Return value: one of DISK_STATUS_* -.write dd ? -; The pointer to the function which writes data to the device. -; Optional, may be NULL. -; int write(void* userdata, void* buffer, __int64 startsector, int* numsectors); -; input: *numsectors = number of sectors to write -; output: *numsectors = number of sectors which were successfully written -; Return value: one of DISK_STATUS_* -.flush dd ? -; The pointer to the function which flushes the internal device cache. -; Optional, may be NULL. -; int flush(void* userdata); -; Return value: one of DISK_STATUS_* -; Note that read/write are called by the cache manager, so a driver should not -; create a software cache. This function is implemented for flushing a hardware -; cache, if it exists. -.adjust_cache_size dd ? -; The pointer to the function which returns the cache size for this device. -; Optional, may be NULL. -; unsigned int adjust_cache_size(unsigned int suggested_size); -; Return value: 0 = disable cache, otherwise = used cache size in bytes. -ends - -; This structure holds information on a medium. -; Objects with this structure are allocated by the kernel as a part of the DISK -; structure and are filled by a driver in the 'querymedia' callback. -struct DISKMEDIAINFO -.Flags dd ? -; Combination of DISK_MEDIA_* bits. -.SectorSize dd ? -; Size of the sector. -.Capacity dq ? -; Size of the media in sectors. -ends - -; This structure represents the disk cache. To follow the old implementation, -; there are two distinct caches for a disk, one for "system" data,and the other -; for "application" data. -struct DISKCACHE -.Lock MUTEX -; Lock to protect the cache. -; The following fields are inherited from data32.inc:cache_ideX. -.pointer rd 1 -.data_size rd 1 ; not use -.data rd 1 -.sad_size rd 1 -.search_start rd 1 -ends - -; This structure represents a disk device and its media for the kernel. -; This structure is allocated by the kernel in the 'disk_add' function, -; freed in the 'disk_dereference' function. -struct DISK -; Fields of disk object -.Next dd ? -.Prev dd ? -; All disk devices are linked in one list with these two fields. -; Head of the list is the 'disk_list' variable. -.Functions dd ? -; Pointer to the 'DISKFUNC' structure with driver functions. -.Name dd ? -; Pointer to the string used for accesses through the global filesystem. -.UserData dd ? -; This field is passed to all callback functions so a driver can decide which -; physical device is addressed. -.DriverFlags dd ? -; Bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit is defined. -; If it is set, the driver will never issue 'disk_media_changed' notification -; with argument set to true, so the kernel must try to detect media during -; requests from the file system. -.RefCount dd ? -; Count of active references to this structure. One reference is kept during -; the lifetime of the structure between 'disk_add' and 'disk_del'. -; Another reference is taken during any filesystem operation for this disk. -; One reference is added if media is inserted. -; The structure is destroyed when the reference count decrements to zero: -; this usually occurs in 'disk_del', but can be delayed to the end of last -; filesystem operation, if one is active. -.MediaLock MUTEX -; Lock to protect the MEDIA structure. See the description after -; 'disk_list_mutex' for the locking strategy. -; Fields of media object -.MediaInserted db ? -; 0 if media is not inserted, nonzero otherwise. -.MediaUsed db ? -; 0 if media fields are not used, nonzero otherwise. If .MediaRefCount is -; nonzero, this field is nonzero too; however, when .MediaRefCount goes -; to zero, there is some time interval during which media object is still used. - align 4 -; The following fields are not valid unless either .MediaInserted is nonzero -; or they are accessed from a code which has obtained the reference when -; .MediaInserted was nonzero. -.MediaRefCount dd ? -; Count of active references to the media object. One reference is kept during -; the lifetime of the media between two calls to 'disk_media_changed'. -; Another reference is taken during any filesystem operation for this media. -; The callback 'closemedia' is called when the reference count decrements to -; zero: this usually occurs in 'disk_media_changed', but can be delayed to the -; end of the last filesystem operation, if one is active. -.MediaInfo DISKMEDIAINFO -; This field keeps information on the current media. -.NumPartitions dd ? -; Number of partitions on this media. -.Partitions dd ? -; Pointer to array of .NumPartitions pointers to PARTITION structures. -.cache_size dd ? -; inherited from cache_ideX_size -.SysCache DISKCACHE -.AppCache DISKCACHE -; Two caches for the disk. -ends - -; This structure represents one partition for the kernel. This is a base -; template, the actual contents after common fields is determined by the -; file system code for this partition. -struct PARTITION -.FirstSector dq ? -; First sector of the partition. -.Length dq ? -; Length of the partition in sectors. -.Disk dd ? -; Pointer to parent DISK structure. -.FSUserFunctions dd ? -; Handlers for the sysfunction 70h. This field is a pointer to the following -; array. The first dword is a number of supported subfunctions, other dwords -; point to handlers of corresponding subfunctions. -; This field is 0 if file system is not recognized. -; ...fs-specific data may follow... -ends - -; This is an external structure, it represents an entry in the partition table. -struct PARTITION_TABLE_ENTRY -.Bootable db ? -; 80h = bootable partition, 0 = non-bootable partition, other values = invalid -.FirstHead db ? -.FirstSector db ? -.FirstTrack db ? -; Coordinates of first sector in CHS. -.Type db ? -; Partition type, one of predefined constants. 0 = empty, several types denote -; extended partition (see process_partition_table_entry), we are not interested -; in other values. -.LastHead db ? -.LastSector db ? -.LastTrack db ? -; Coordinates of last sector in CHS. -.FirstAbsSector dd ? -; Coordinate of first sector in LBA. -.Length dd ? -; Length of the partition in sectors. -ends - -; ============================================================================= -; ================================ Global data ================================ -; ============================================================================= -iglobal -; The pseudo-item for the list of all DISK structures. -; Initialized to the empty list. -disk_list: - dd disk_list - dd disk_list -endg -uglobal -; This mutex guards all operations with the global list of DISK structures. -disk_list_mutex MUTEX -; * There are two dependent objects, a disk and a media. In the simplest case, -; disk and media are both non-removable. However, in the general case both -; can be removed at any time, simultaneously or only media,and this makes things -; complicated. -; * For efficiency, both disk and media objects are located in the one -; structure named DISK. However, logically they are different. -; * The following operations use data of disk object: adding (disk_add); -; deleting (disk_del); filesystem (fs_lfn which eventually calls -; dyndisk_handler or dyndisk_enum_root). -; * The following operations use data of media object: adding/removing -; (disk_media_changed); filesystem (fs_lfn which eventually calls -; dyndisk_handler; dyndisk_enum_root doesn't work with media). -; * Notifications disk_add, disk_media_changed, disk_del are synchronized -; between themselves, this is a requirement for the driver. However, file -; system operations are asynchronous, can be issued at any time by any -; thread. -; * We must prevent a situation when a filesystem operation thinks that the -; object is still valid but in fact the notification has destroyed the -; object. So we keep a reference counter for both disk and media and destroy -; the object when this counter goes to zero. -; * The driver must know when it is safe to free driver-allocated resources. -; The object can be alive even after death notification has completed. -; We use special callbacks to satisfy both assertions: 'close' for the disk -; and 'closemedia' for the media. The destruction of the object includes -; calling the corresponding callback. -; * Each filesystem operation keeps one reference for the disk and one -; reference for the media. Notification disk_del forces notification on the -; media death, so the reference counter for the disk is always not less than -; the reference counter for the media. -; * Two operations "get the object" and "increment the reference counter" can -; not be done simultaneously. We use a mutex to guard the consistency here. -; It must be a part of the container for the object, so that this mutex can -; be acquired as a part of getting the object from the container. The -; container for disk object is the global list, and this list is guarded by -; 'disk_list_mutex'. The container for media object is the disk object, and -; the corresponding mutex is DISK.MediaLock. -; * Notifications do not change the data of objects, they can only remove -; objects. Thus we don't need another synchronization at this level. If two -; filesystem operations are referencing the same filesystem data, this is -; better resolved at the level of the filesystem. -endg - -iglobal -; The function 'disk_scan_partitions' needs three 512-byte buffers for -; MBR, bootsector and fs-temporary sector data. It can not use the static -; buffers always, since it can be called for two or more disks in parallel. -; However, this case is not typical. We reserve three static 512-byte buffers -; and a flag that these buffers are currently used. If 'disk_scan_partitions' -; detects that the buffers are currently used, it allocates buffers from the -; heap. -; The flag is implemented as a global dword variable. When the static buffers -; are not used, the value is -1. When the static buffers are used, the value -; is normally 0 and temporarily can become greater. The function increments -; this value. If the resulting value is zero, it uses the buffers and -; decrements the value when the job is done. Otherwise, it immediately -; decrements the value and uses buffers from the heap, allocated in the -; beginning and freed in the end. -partition_buffer_users dd -1 -endg -uglobal -; The static buffers for MBR, bootsector and fs-temporary sector data. -align 16 -mbr_buffer rb 512 -bootsect_buffer rb 512 -fs_tmp_buffer rb 512 -endg - -iglobal -; This is the array of default implementations of driver callbacks. -; Same as DRIVERFUNC structure except for the first field; all functions must -; have the default implementations. -align 4 -disk_default_callbacks: - dd disk_default_close - dd disk_default_closemedia - dd disk_default_querymedia - dd disk_default_read - dd disk_default_write - dd disk_default_flush - dd disk_default_adjust_cache_size -endg - -; ============================================================================= -; ================================= Functions ================================= -; ============================================================================= - -; This function registers a disk device. -; This includes: -; - allocating an internal structure describing this device; -; - registering this structure in the global filesystem. -; The function initializes the disk as if there is no media. If a media is -; present, the function 'disk_media_changed' should be called after this -; function succeeds. -; Parameters: -; [esp+4] = pointer to DISKFUNC structure with the callbacks -; [esp+8] = pointer to name (ASCIIZ string) -; [esp+12] = userdata to be passed to the callbacks as is. -; [esp+16] = flags, bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit -; is defined. -; Return value: -; NULL = operation has failed -; non-NULL = handle of the disk. This handle can be used -; in the operations with other Disk* functions. -; The handle is the pointer to the internal structure DISK. -disk_add: - push ebx esi ; save used registers to be stdcall -; 1. Allocate the DISK structure. -; 1a. Call the heap manager. - push sizeof.DISK - pop eax - call malloc -; 1b. Check the result. If allocation failed, return (go to 9) with eax = 0. - test eax, eax - jz .nothing -; 2. Copy the disk name to the DISK structure. -; 2a. Get length of the name, including the terminating zero. - mov ebx, [esp+8+8] ; ebx = pointer to name - push eax ; save allocated pointer to DISK - xor eax, eax ; the argument of malloc() is in eax -@@: - inc eax - cmp byte [ebx+eax-1], 0 - jnz @b -; 2b. Call the heap manager. - call malloc -; 2c. Check the result. If allocation failed, go to 7. - pop esi ; restore allocated pointer to DISK - test eax, eax - jz .free -; 2d. Store the allocated pointer to the DISK structure. - mov [esi+DISK.Name], eax -; 2e. Copy the name. -@@: - mov dl, [ebx] - mov [eax], dl - inc ebx - inc eax - test dl, dl - jnz @b -; 3. Copy other arguments of the function to the DISK structure. - mov eax, [esp+4+8] - mov [esi+DISK.Functions], eax - mov eax, [esp+12+8] - mov [esi+DISK.UserData], eax - mov eax, [esp+16+8] - mov [esi+DISK.DriverFlags], eax -; 4. Initialize other fields of the DISK structure. -; Media is not inserted, reference counter is 1. - lea ecx, [esi+DISK.MediaLock] - call mutex_init - xor eax, eax - mov dword [esi+DISK.MediaInserted], eax - inc eax - mov [esi+DISK.RefCount], eax -; The DISK structure is initialized. -; 5. Insert the new structure to the global list. -; 5a. Acquire the mutex. - mov ecx, disk_list_mutex - call mutex_lock -; 5b. Insert item to the tail of double-linked list. - mov edx, disk_list - list_add_tail esi, edx ;esi= new edx= list head -; 5c. Release the mutex. - call mutex_unlock -; 6. Return with eax = pointer to DISK. - xchg eax, esi - jmp .nothing -.free: -; Memory allocation for DISK structure succeeded, but for disk name failed. -; 7. Free the DISK structure. - xchg eax, esi - call free -; 8. Return with eax = 0. - xor eax, eax -.nothing: -; 9. Return. - pop esi ebx ; restore used registers to be stdcall - ret 16 ; purge 4 dword arguments to be stdcall - -; This function deletes a disk device from the global filesystem. -; This includes: -; - removing a media including all partitions; -; - deleting this structure from the global filesystem; -; - dereferencing the DISK structure and possibly destroying it. -; Parameters: -; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. -; Return value: none. -disk_del: - push esi ; save used registers to be stdcall -; 1. Force media to be removed. If the media is already removed, the -; call does nothing. - mov esi, [esp+4+8] ; esi = handle of the disk - stdcall disk_media_changed, esi, 0 -; 2. Delete the structure from the global list. -; 2a. Acquire the mutex. - mov ecx, disk_list_mutex - call mutex_lock -; 2b. Delete item from double-linked list. - mov eax, [esi+DISK.Next] - mov edx, [esi+DISK.Prev] - mov [eax+DISK.Prev], edx - mov [edx+DISK.Next], eax -; 2c. Release the mutex. - call mutex_unlock -; 3. The structure still has one reference created in disk_add. Remove this -; reference. If there are no other references, disk_dereference will free the -; structure. - call disk_dereference -; 4. Return. - pop esi ; restore used registers to be stdcall - ret 4 ; purge 1 dword argument to be stdcall - -; This is an internal function which removes a previously obtained reference -; to the disk. If this is the last reference, this function lets the driver -; finalize all associated data, and afterwards frees the DISK structure. -; esi = pointer to DISK structure -disk_dereference: -; 1. Decrement reference counter. Use atomic operation to correctly handle -; possible simultaneous calls. -lock dec [esi+DISK.RefCount] -; 2. If the result is nonzero, there are other references, so nothing to do. -; In this case, return (go to 4). - jnz .nothing -; 3. If we are here, we just removed the last reference and must destroy the -; disk object. -; 3a. Call the driver. - mov al, DISKFUNC.close - stdcall disk_call_driver -; 3b. Free the structure. - xchg eax, esi - call free -; 4. Return. -.nothing: - ret - -; This is an internal function which removes a previously obtained reference -; to the media. If this is the last reference, this function calls 'closemedia' -; callback to signal the driver that the processing has finished and it is safe -; to inform about a new media. -; esi = pointer to DISK structure -disk_media_dereference: -; 1. Decrement reference counter. Use atomic operation to correctly handle -; possible simultaneous calls. -lock dec [esi+DISK.MediaRefCount] -; 2. If the result is nonzero, there are other references, so nothing to do. -; In this case, return (go to 4). - jnz .nothing -; 3. If we are here, we just removed the last reference and must destroy the -; media object. -; Note that the same place inside the DISK structure is reused for all media -; objects, so we must guarantee that reusing does not happen while freeing. -; Reusing is only possible when someone processes a new media. There are two -; mutually exclusive variants: -; * driver issues media insert notifications (DISK_NO_INSERT_NOTIFICATION bit -; in DISK.DriverFlags is not set). In this case, we require from the driver -; that such notification (except for the first one) can occur only after a -; call to 'closemedia' callback. -; * driver does not issue media insert notifications. In this case, the kernel -; itself must sometimes check whether media is inserted. We have the flag -; DISK.MediaUsed, visible to the kernel. This flag signals to the other parts -; of kernel that the way is free. -; In the first case other parts of the kernel do not use DISK.MediaUsed, so it -; does not matter when this flag is cleared. In the second case this flag must -; be cleared after all other actions, including call to 'closemedia'. -; 3a. Free all partitions. - push esi edi - mov edi, [esi+DISK.NumPartitions] - mov esi, [esi+DISK.Partitions] - test edi, edi - jz .nofree -.freeloop: - lodsd - call free - dec edi - jnz .freeloop -.nofree: - pop edi esi -; 3b. Free the cache. - call disk_free_cache -; 3c. Call the driver. - mov al, DISKFUNC.closemedia - stdcall disk_call_driver -; 3d. Clear the flag. - mov [esi+DISK.MediaUsed], 0 -.nothing: - ret - -; This function is called by the driver and informs the kernel that the media -; has changed. If the media is non-removable, it is called exactly once -; immediately after 'disk_add' and once from 'disk_del'. -; Parameters: -; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. -; [esp+8] = new status of the media: zero = no media, nonzero = media inserted. -disk_media_changed: - push ebx esi edi ; save used registers to be stdcall -; 1. Remove the existing media, if it is present. - mov esi, [esp+4+12] ; esi = pointer to DISK -; 1a. Check whether it is present. Since DISK.MediaInserted is changed only -; in this function and calls to this function are synchronized, no lock is -; required for checking. - cmp [esi+DISK.MediaInserted], 0 - jz .noremove -; We really need to remove the media. -; 1b. Acquire mutex. - lea ecx, [esi+DISK.MediaLock] - call mutex_lock -; 1c. Clear the flag. - mov [esi+DISK.MediaInserted], 0 -; 1d. Release mutex. - call mutex_unlock -; 1e. Remove the "lifetime" reference and possibly destroy the structure. - call disk_media_dereference -.noremove: -; 2. Test whether there is new media. - cmp dword [esp+8+12], 0 - jz .noinsert -; Yep, there is. -; 3. Process the new media. We assume that all media fields are available to -; use, see comments in 'disk_media_dereference' (this covers using by previous -; media referencers) and note that calls to this function are synchronized -; (this covers using by new media referencers). -; 3a. Call the 'querymedia' callback. -; .Flags are set to zero for possible future extensions. - lea edx, [esi+DISK.MediaInfo] - and [edx+DISKMEDIAINFO.Flags], 0 - mov al, DISKFUNC.querymedia - stdcall disk_call_driver, edx -; 3b. Check the result of the callback. Abort if it failed. - test eax, eax - jnz .noinsert -; 3c. Allocate the cache unless disabled by the driver. Abort if failed. - call disk_init_cache - test al, al - jz .noinsert -; 3d. Acquire the lifetime reference for the media object. - inc [esi+DISK.MediaRefCount] -; 3e. Scan for partitions. Ignore result; the list of partitions is valid even -; on errors. - call disk_scan_partitions -; 3f. Media is inserted and available for use. - inc [esi+DISK.MediaInserted] -.noinsert: -; 4. Return. - pop edi esi ebx ; restore used registers to be stdcall - ret 8 ; purge 2 dword arguments to be stdcall - -; This function is a thunk for all functions of a disk driver. -; It checks whether the referenced function is implemented in the driver. -; If so, this function jumps to the function in the driver. -; Otherwise, it jumps to the default implementation. -; al = offset of function in the DISKFUNC structure; -; esi = pointer to the DISK structure; -; stack is the same as for the corresponding function except that the -; first parameter (void* userdata) is prepended automatically. -disk_call_driver: - movzx eax, al ; eax = offset of function in the DISKFUNC structure -; 1. Prepend the first argument to the stack. - pop ecx ; ecx = return address - push [esi+DISK.UserData] ; add argument - push ecx ; save return address -; 2. Check that the required function is inside the table. If not, go to 5. - mov ecx, [esi+DISK.Functions] - cmp eax, [ecx+DISKFUNC.strucsize] - jae .default -; 3. Check that the required function is implemented. If not, go to 5. - mov ecx, [ecx+eax] - test ecx, ecx - jz .default -; 4. Jump to the required function. - jmp ecx -.default: -; 5. Driver does not implement the required function; use default implementation. - jmp dword [disk_default_callbacks+eax-4] - -; The default implementation of DISKFUNC.querymedia. -disk_default_querymedia: - push DISK_STATUS_INVALID_CALL - pop eax - ret 8 - -; The default implementation of DISKFUNC.read and DISKFUNC.write. -disk_default_read: -disk_default_write: - push DISK_STATUS_INVALID_CALL - pop eax - ret 20 - -; The default implementation of DISKFUNC.close, DISKFUNC.closemedia and -; DISKFUNC.flush. -disk_default_close: -disk_default_closemedia: -disk_default_flush: - xor eax, eax - ret 4 - -; The default implementation of DISKFUNC.adjust_cache_size. -disk_default_adjust_cache_size: - mov eax, [esp+4] - ret 4 - -; This is an internal function called from 'disk_media_changed' when a new media -; is detected. It creates the list of partitions for the media. -; If media is not partitioned, then the list consists of one partition which -; covers all the media. -; esi = pointer to the DISK structure. -disk_scan_partitions: -; 1. Initialize .NumPartitions and .Partitions fields as zeros: empty list. - and [esi+DISK.NumPartitions], 0 - and [esi+DISK.Partitions], 0 -; 2. Currently we can work only with 512-bytes sectors. Check this restriction. -; The only exception is 2048-bytes CD/DVD, but they are not supported yet by -; this code. - cmp [esi+DISK.MediaInfo.SectorSize], 512 - jz .doscan - DEBUGF 1,'K : sector size is %d, only 512 is supported\n',[esi+DISK.MediaInfo.SectorSize] - ret -.doscan: -; 3. Acquire the buffer for MBR and bootsector tests. See the comment before -; the 'partition_buffer_users' variable. - mov ebx, mbr_buffer ; assume the global buffer is free -lock inc [partition_buffer_users] - jz .buffer_acquired ; yes, it is free -lock dec [partition_buffer_users] ; no, we must allocate - stdcall kernel_alloc, 512*3 - test eax, eax - jz .nothing - xchg eax, ebx -.buffer_acquired: -; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no -; more than MAX_NUM_PARTITION times. -; 4. Prepare things for the loop. -; ebp will hold the sector number for current MBR/EBR. -; [esp] will hold the sector number for current extended partition, if there -; is one. -; [esp+4] will hold the counter that prevents long loops. - push ebp ; save ebp - push MAX_NUM_PARTITIONS ; the counter of max MBRs to process - xor ebp, ebp ; start from sector zero - push ebp ; no extended partition yet -.new_mbr: -; 5. Read the current sector. -; Note that 'read' callback operates with 64-bit sector numbers, so we must -; push additional zero as a high dword of sector number. - mov al, DISKFUNC.read - push 1 - stdcall disk_call_driver, ebx, ebp, 0, esp - pop ecx -; 6. If the read has failed, abort the loop. - dec ecx - jnz .mbr_failed -; 7. Check the MBR/EBR signature. If it is wrong, abort the loop. -; Soon we will access the partition table which starts at ebx+0x1BE, -; so we can fill its address right now. If we do it now, then the addressing -; [ecx+0x40] is shorter than [ebx+0x1fe]: one-byte offset vs 4-bytes offset. - lea ecx, [ebx+0x1be] ; ecx -> partition table - cmp word [ecx+0x40], 0xaa55 - jnz .mbr_failed -; 8. The MBR is treated differently from EBRs. For MBR we additionally need to -; execute step 9 and possibly step 10. - test ebp, ebp - jnz .mbr -; The partition table can be present or not present. In the first case, we just -; read the MBR. In the second case, we just read the bootsector for a -; filesystem. -; The following algorithm is used to distinguish between these cases. -; A. If at least one entry of the partition table is invalid, this is -; a bootsector. See the description of 'is_partition_table_entry' for -; definition of validity. -; B. If all entries are empty (filesystem type field is zero) and the first -; byte is jmp opcode (0EBh or 0E9h), this is a bootsector which happens to -; have zeros in the place of partition table. -; C. Otherwise, this is an MBR. -; 9. Test for MBR vs bootsector. -; 9a. Check entries. If any is invalid, go to 10 (rule A). - call is_partition_table_entry - jc .notmbr - add ecx, 10h - call is_partition_table_entry - jc .notmbr - add ecx, 10h - call is_partition_table_entry - jc .notmbr - add ecx, 10h - call is_partition_table_entry - jc .notmbr -; 9b. Check types of the entries. If at least one is nonzero, go to 11 (rule C). - mov al, [ecx-30h+PARTITION_TABLE_ENTRY.Type] - or al, [ecx-20h+PARTITION_TABLE_ENTRY.Type] - or al, [ecx-10h+PARTITION_TABLE_ENTRY.Type] - or al, [ecx+PARTITION_TABLE_ENTRY.Type] - jnz .mbr -; 9c. Empty partition table or bootsector with many zeroes? (rule B) - cmp byte [ebx], 0EBh - jz .notmbr - cmp byte [ebx], 0E9h - jnz .mbr -.notmbr: -; 10. This is not an MBR. The media is not partitioned. Create one partition -; which covers all the media and abort the loop. - stdcall disk_add_partition, 0, 0, \ - dword [esi+DISK.MediaInfo.Capacity], dword [esi+DISK.MediaInfo.Capacity+4] - jmp .done -.mbr: -; 11. Process all entries of the new MBR/EBR - lea ecx, [ebx+0x1be] ; ecx -> partition table - push 0 ; assume no extended partition - call process_partition_table_entry - add ecx, 10h - call process_partition_table_entry - add ecx, 10h - call process_partition_table_entry - add ecx, 10h - call process_partition_table_entry - pop ebp -; 12. Test whether we found a new EBR and should continue the loop. -; 12a. If there was no next EBR, return. - test ebp, ebp - jz .done -; Ok, we have EBR. -; 12b. EBRs addresses are relative to the start of extended partition. -; For simplicity, just abort if an 32-bit overflow occurs; large disks -; are most likely partitioned with GPT, not MBR scheme, since the precise -; calculation here would increase limit just twice at the price of big -; compatibility problems. - pop eax ; load extended partition - add ebp, eax - jc .mbr_failed -; 12c. If extended partition has not yet started, start it. - test eax, eax - jnz @f - mov eax, ebp -@@: -; 12c. If the limit is not exceeded, continue the loop. - dec dword [esp] - push eax ; store extended partition - jnz .new_mbr -.mbr_failed: -.done: -; 13. Cleanup after the loop. - pop eax ; not important anymore - pop eax ; not important anymore - pop ebp ; restore ebp -; 14. Release the buffer. -; 14a. Test whether it is the global buffer or we have allocated it. - cmp ebx, mbr_buffer - jz .release_partition_buffer -; 14b. If we have allocated it, free it. - xchg eax, ebx - call free - jmp .nothing -; 14c. Otherwise, release reference. -.release_partition_buffer: -lock dec [partition_buffer_users] -.nothing: -; 15. Return. - ret - -; This is an internal function called from disk_scan_partitions. It checks -; whether the entry pointed to by ecx is a valid entry of partition table. -; The entry is valid if the first byte is 0 or 80h, the first sector plus the -; length is less than twice the size of media. Multiplication by two is -; required since the size mentioned in the partition table can be slightly -; greater than the real size. -is_partition_table_entry: -; 1. Check .Bootable field. - mov al, [ecx+PARTITION_TABLE_ENTRY.Bootable] - and al, 7Fh - jnz .invalid -; 3. Calculate first sector + length. Note that .FirstAbsSector is relative -; to the MBR/EBR, so the real sum is ebp + .FirstAbsSector + .Length. - mov eax, ebp - xor edx, edx - add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] - adc edx, 0 - add eax, [ecx+PARTITION_TABLE_ENTRY.Length] - adc edx, 0 -; 4. Divide by two. - shr edx, 1 - rcr eax, 1 -; 5. Compare with capacity. If the subtraction (edx:eax) - .Capacity does not -; overflow, this is bad. - sub eax, dword [esi+DISK.MediaInfo.Capacity] - sbb edx, dword [esi+DISK.MediaInfo.Capacity+4] - jnc .invalid -.valid: -; 5. Return success: CF is cleared. - clc - ret -.invalid: -; 6. Return fail: CF is set. - stc - ret - -; This is an internal function called from disk_scan_partitions. It processes -; the entry pointed to by ecx. -; * If the entry is invalid, just ignore this entry. -; * If the type is zero, just ignore this entry. -; * If the type is one of types for extended partition, store the address -; of this partition as the new MBR in [esp+4]. -; * Otherwise, add the partition to the list of partitions for this disk. -; We don't use the type from the entry to identify the file system; -; fs-specific checks do this more reliably. -process_partition_table_entry: -; 1. Check for valid entry. If invalid, return (go to 5). - call is_partition_table_entry - jc .nothing -; 2. Check for empty entry. If invalid, return (go to 5). - mov al, [ecx+PARTITION_TABLE_ENTRY.Type] - test al, al - jz .nothing -; 3. Check for extended partition. If extended, go to 6. -irp type,\ - 0x05,\ ; DOS: extended partition - 0x0f,\ ; WIN95: extended partition, LBA-mapped - 0xc5,\ ; DRDOS/secured: extended partition - 0xd5 ; Old Multiuser DOS secured: extended partition -{ - cmp al, type - jz .extended -} -; 4. If we are here, that is a normal partition. Add it to the list. -; Note that the first sector is relative to MBR/EBR. - mov eax, ebp - xor edx, edx - add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] - adc edx, 0 - push ecx - stdcall disk_add_partition, eax, edx, \ - [ecx+PARTITION_TABLE_ENTRY.Length], 0 - pop ecx -.nothing: -; 5. Return. - ret -.extended: -; 6. If we are here, that is an extended partition. Store the address. - mov eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] - mov [esp+4], eax - ret - -; This is an internal function called from disk_scan_partitions and -; process_partition_table_entry. It adds one partition to the list of -; partitions for the media. -proc disk_add_partition stdcall uses ebx edi, start:qword, length:qword -; 1. Check that this partition will not exceed the limit on total number. - cmp [esi+DISK.NumPartitions], MAX_NUM_PARTITIONS - jae .nothing -; 2. Check that this partition does not overlap with any already registered -; partition. Since any file system assumes that the disk data will not change -; outside of its control, such overlap could be destructive. -; Since the number of partitions is usually very small and is guaranteed not -; to be large, the simple linear search is sufficient. -; 2a. Prepare the loop: edi will point to the current item of .Partitions -; array, ecx will be the current item, ebx will hold number of items left. - mov edi, [esi+DISK.Partitions] - mov ebx, [esi+DISK.NumPartitions] - test ebx, ebx - jz .partitionok -.scan_existing: -; 2b. Get the next partition. - mov ecx, [edi] - add edi, 4 -; The range [.FirstSector, .FirstSector+.Length) must be either entirely to -; the left of [start, start+length) or entirely to the right. -; 2c. Subtract .FirstSector - start. The possible overflow distinguish between -; cases "to the left" (2e) and "to the right" (2d). - mov eax, dword [ecx+PARTITION.FirstSector] - mov edx, dword [ecx+PARTITION.FirstSector+4] - sub eax, dword [start] - sbb edx, dword [start+4] - jb .less -; 2d. .FirstSector is greater than or equal to start. Check that .FirstSector -; is greater than or equal to start+length; the subtraction -; (.FirstSector-start) - length must not cause overflow. Go to 2g if life is -; good or to 2f in the other case. - sub eax, dword [length] - sbb edx, dword [length+4] - jb .overlap - jmp .next_existing -.less: -; 2e. .FirstSector is less than start. Check that .FirstSector+.Length is less -; than or equal to start. If the addition (.FirstSector-start) + .Length does -; not cause overflow, then .FirstSector + .Length is strictly less than start; -; since the equality is also valid, use decrement preliminarily. Go to 2g or -; 2f depending on the overflow. - sub eax, 1 - sbb edx, 0 - add eax, dword [ecx+PARTITION.Length] - adc edx, dword [ecx+PARTITION.Length+4] - jnc .next_existing -.overlap: -; 2f. The partition overlaps with previously registered partition. Say warning -; and return with nothing done. - dbgstr 'two partitions overlap, ignoring the last one' - jmp .nothing -.next_existing: -; 2g. The partition does not overlap with the current partition. Continue the -; loop. - dec ebx - jnz .scan_existing -.partitionok: -; 3. The partition has passed tests. Reallocate the partitions array for a new -; entry. -; 3a. Call the allocator. - mov eax, [esi+DISK.NumPartitions] - inc eax ; one more entry - shl eax, 2 ; each entry is dword - call malloc -; 3b. Test the result. If failed, return with nothing done. - test eax, eax - jz .nothing -; 3c. Copy the old array to the new array. - mov edi, eax - push esi - mov ecx, [esi+DISK.NumPartitions] - mov esi, [esi+DISK.Partitions] - rep movsd - pop esi -; 3d. Set the field in the DISK structure to the new array. - xchg [esi+DISK.Partitions], eax -; 3e. Free the old array. - call free -; 4. Recognize the file system. -; 4a. Call the filesystem recognizer. It will allocate the PARTITION structure -; with possible filesystem-specific fields. - call disk_detect_partition -; 4b. Check return value. If zero, return with list not changed; so far only -; the array was reallocated, this is ok for other code. - test eax, eax - jz .nothing -; 5. Insert the new partition to the list. - stosd - inc [esi+DISK.NumPartitions] -; 6. Return. -.nothing: - ret -endp - -; This is an internal function called from disk_add_partition. -; It tries to recognize the file system on the partition and allocates the -; corresponding PARTITION structure with filesystem-specific fields. -disk_detect_partition: -; This function inherits the stack frame from disk_add_partition. In stdcall -; with ebp-based frame arguments start from ebp+8, since [ebp]=saved ebp -; and [ebp+4]=return address. -virtual at ebp+8 -.start dq ? -.length dq ? -end virtual -; Currently no file systems are supported, so just allocate the PARTITION -; structure without extra fields. -; 1. Allocate and check result. - push sizeof.PARTITION - pop eax - call malloc - test eax, eax - jz .nothing -; 2. Fill the common fields: copy .start and .length. - mov edx, dword [.start] - mov dword [eax+PARTITION.FirstSector], edx - mov edx, dword [.start+4] - mov dword [eax+PARTITION.FirstSector+4], edx - mov edx, dword [.length] - mov dword [eax+PARTITION.Length], edx - mov edx, dword [.length+4] - mov dword [eax+PARTITION.Length+4], edx -.nothing: -; 3. Return with eax = pointer to PARTITION or NULL. - ret - -; This function is called from file_system_lfn. -; This handler gets the control each time when fn 70 is called -; with unknown item of root subdirectory. -; in: esi -> name -; ebp = 0 or rest of name relative to esi -; out: if the handler processes path, it must not return in file_system_lfn, -; but instead pop return address and return directly to the caller -; otherwise simply return -dyndisk_handler: - push ebx edi ; save registers used in file_system_lfn -; 1. Acquire the mutex. - mov ecx, disk_list_mutex - call mutex_lock -; 2. Loop over the list of DISK structures. -; 2a. Initialize. - mov ebx, disk_list -.scan: -; 2b. Get the next item. - mov ebx, [ebx+DISK.Next] -; 2c. Check whether the list is done. If so, go to 3. - cmp ebx, disk_list - jz .notfound -; 2d. Compare names. If names match, go to 5. - mov edi, [ebx+DISK.Name] - push esi -@@: -; esi points to the name from fs operation; it is terminated by zero or slash. - lodsb - test al, al - jz .eoin_dec - cmp al, '/' - jz .eoin -; edi points to the disk name. - inc edi -; edi points to lowercase name, this is a requirement for the driver. -; Characters at esi can have any register. Lowercase the current character. -; This lowercasing works for latin letters and digits; since the disk name -; should not contain other symbols, this is ok. - or al, 20h - cmp al, [edi-1] - jz @b -.wrongname: -; 2f. Names don't match. Continue the loop. - pop esi - jmp .scan -.notfound: -; The loop is done and no name matches. -; 3. Release the mutex. - call mutex_unlock -; 4. Return normally. - pop edi ebx ; restore registers used in file_system_lfn - ret -; part of 2d: the name matches partially, but we must check that this is full -; equality. -.eoin_dec: - dec esi -.eoin: - cmp byte [edi], 0 - jnz .wrongname -; We found the addressed DISK structure. -; 5. Reference the disk. -lock inc [ebx+DISK.RefCount] -; 6. Now we are sure that the DISK structure is not going to die at least -; while we are working with it, so release the global mutex. - call mutex_unlock -; 7. Acquire the mutex for media object. - pop edi ; restore edi - lea ecx, [ebx+DISK.MediaLock] - call mutex_lock -; 8. Get the media object. If it is not NULL, reference it. - xor edx, edx - cmp [ebx+DISK.MediaInserted], dl - jz @f - mov edx, ebx - inc [ebx+DISK.MediaRefCount] -@@: -; 9. Now we are sure that the media object, if it exists, is not going to die -; at least while we are working with it, so release the mutex for media object. - call mutex_unlock - mov ecx, ebx - pop ebx eax ; restore ebx, pop return address -; 10. Check whether the fs operation wants to enumerate partitions (go to 11) -; or work with some concrete partition (go to 12). - cmp byte [esi], 0 - jnz .haspartition -; 11. The fs operation wants to enumerate partitions. -; 11a. Only "list directory" operation is applicable to / path. Check -; the operation code. If wrong, go to 13. - cmp dword [ebx], 1 - jnz .access_denied -; 11b. If the media is inserted, use 'fs_dyndisk_next' as an enumeration -; procedure. Otherwise, use 'fs_dyndisk_next_nomedia'. - mov esi, fs_dyndisk_next_nomedia - test edx, edx - jz @f - mov esi, fs_dyndisk_next -@@: -; 11c. Let the procedure from fs_lfn.inc do the job. - jmp file_system_lfn.maindir_noesi -.haspartition: -; 12. The fs operation has specified some partition. -; 12a. Store parameters for callback functions. - push edx - push ecx -; 12b. Store callback functions. - push dyndisk_cleanup - push fs_dyndisk - mov edi, esp -; 12c. Let the procedure from fs_lfn.inc do the job. - jmp file_system_lfn.found2 -.access_denied: -; 13. Fail the operation with the appropriate code. - mov dword [esp+32], ERROR_ACCESS_DENIED -.cleanup: -; 14. Cleanup. - mov esi, ecx ; disk*dereference assume that esi points to DISK -.cleanup_esi: - test edx, edx ; if there are no media, we didn't reference it - jz @f - call disk_media_dereference -@@: - call disk_dereference -; 15. Return. - ret - -; This is a callback for cleaning up things called from file_system_lfn.found2. -dyndisk_cleanup: - mov esi, [edi+8] - mov edx, [edi+12] - jmp dyndisk_handler.cleanup_esi - -; This is a callback for enumerating partitions called from -; file_system_lfn.maindir in the case of inserted media. -; It just increments eax until DISK.NumPartitions reached and then -; cleans up. -fs_dyndisk_next: - cmp eax, [ecx+DISK.NumPartitions] - jae .nomore - inc eax - clc - ret -.nomore: - pusha - mov esi, ecx - call disk_media_dereference - call disk_dereference - popa - stc - ret - -; This is a callback for enumerating partitions called from -; file_system_lfn.maindir in the case of missing media. -; In this case we create one pseudo-partition. -fs_dyndisk_next_nomedia: - cmp eax, 1 - jae .nomore - inc eax - clc - ret -.nomore: - pusha - mov esi, ecx - call disk_dereference - popa - stc - ret - -; This is a callback for doing real work with selected partition. -; Currently this is just placeholder, since no file systems are supported. -; edi = esp -> {dd fs_dyndisk, dd dyndisk_cleanup, dd pointer to DISK, dd media object} -; ecx = partition number, esi+ebp = ASCIIZ name -fs_dyndisk: - dec ecx ; convert to zero-based partition index - pop edx edx edx eax ; edx = pointer to DISK, eax = NULL or edx - test eax, eax - jz .nomedia -.main: - cmp ecx, [edx+DISK.NumPartitions] - jae .notfound - mov dword [esp+32], ERROR_UNKNOWN_FS -.cleanup: - mov esi, edx - call disk_media_dereference - call disk_dereference - ret -.notfound: - mov dword [esp+32], ERROR_FILE_NOT_FOUND - jmp .cleanup -.nomedia: - test ecx, ecx - jnz .notfound - test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION - jz .deverror -; if the driver does not support insert notifications and we are the only fs -; operation with this disk, issue the fake insert notification; if media is -; still not inserted, 'disk_media_changed' will detect this and do nothing -;;; push ebx - lea ecx, [edx+DISK.MediaLock] - call mutex_lock - cmp [edx+DISK.MediaRefCount], 1 - jnz .noluck - call mutex_unlock - push edx - stdcall disk_media_changed, edx, 1 - pop edx - lea ecx, [edx+DISK.MediaLock] - call mutex_lock - cmp [edx+DISK.MediaInserted], 0 - jz .noluck -lock inc [edx+DISK.MediaRefCount] - call mutex_unlock - xor ecx, ecx - jmp .main -.noluck: - call mutex_unlock -.deverror: - mov dword [esp+32], ERROR_DEVICE - mov esi, edx - call disk_dereference - ret - -; This function is called from file_system_lfn. -; This handler is called when virtual root is enumerated -; and must return all items which can be handled by this. -; It is called several times, first time with eax=0 -; in: eax = 0 for first call, previously returned value for subsequent calls -; out: eax = 0 => no more items -; eax != 0 => buffer pointed to by edi contains name of item -dyndisk_enum_root: - push edx ; save register used in file_system_lfn - mov ecx, disk_list_mutex ; it will be useful -; 1. If this is the first call, acquire the mutex and initialize. - test eax, eax - jnz .notfirst - call mutex_lock - mov eax, disk_list -.notfirst: -; 2. Get next item. - mov eax, [eax+DISK.Next] -; 3. If there are no more items, go to 6. - cmp eax, disk_list - jz .last -; 4. Copy name from the DISK structure to edi. - push eax esi - mov esi, [eax+DISK.Name] -@@: - lodsb - stosb - test al, al - jnz @b - pop esi eax -; 5. Return with eax = item. - pop edx ; restore register used in file_system_lfn - ret -.last: -; 6. Release the mutex and return with eax = 0. - call mutex_unlock - xor eax, eax - pop edx ; restore register used in file_system_lfn - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; ============================================================================= +; ================================= Constants ================================= +; ============================================================================= +; Error codes for callback functions. +DISK_STATUS_OK = 0 ; success +DISK_STATUS_GENERAL_ERROR = -1; if no other code is suitable +DISK_STATUS_INVALID_CALL = 1 ; invalid input parameters +DISK_STATUS_NO_MEDIA = 2 ; no media present +DISK_STATUS_END_OF_MEDIA = 3 ; end of media while reading/writing data +; Driver flags. Represent bits in DISK.DriverFlags. +DISK_NO_INSERT_NOTIFICATION = 1 +; Media flags. Represent bits in DISKMEDIAINFO.Flags. +DISK_MEDIA_READONLY = 1 + +; If too many partitions are detected,there is probably an error on the disk. +; 256 partitions should be enough for any reasonable use. +; Also, the same number is limiting the number of MBRs to process; if +; too many MBRs are visible,there probably is a loop in the MBR structure. +MAX_NUM_PARTITIONS = 256 + +; ============================================================================= +; ================================ Structures ================================= +; ============================================================================= +; This structure defines all callback functions for working with the physical +; device. They are implemented by a driver. Objects with this structure reside +; in a driver. +struct DISKFUNC +.strucsize dd ? +; Size of the structure. This field is intended for possible extensions of +; this structure. If a new function is added to this structure and a driver +; implements an old version, the caller can detect this by checking .strucsize, +; so the driver remains compatible. +.close dd ? +; The pointer to the function which frees all driver-specific resources for +; the disk. +; Optional, may be NULL. +; void close(void* userdata); +.closemedia dd ? +; The pointer to the function which informs the driver that the kernel has +; finished all processing with the current media. If media is removed, the +; driver should decline all requests to that media with DISK_STATUS_NO_MEDIA, +; even if new media is inserted, until this function is called. If media is +; removed, a new call to 'disk_media_changed' is not allowed until this +; function is called. +; Optional, may be NULL (if media is not removable). +; void closemedia(void* userdata); +.querymedia dd ? +; The pointer to the function which determines capabilities of the media. +; int querymedia(void* userdata, DISKMEDIAINFO* info); +; Return value: one of DISK_STATUS_* +.read dd ? +; The pointer to the function which reads data from the device. +; int read(void* userdata, void* buffer, __int64 startsector, int* numsectors); +; input: *numsectors = number of sectors to read +; output: *numsectors = number of sectors which were successfully read +; Return value: one of DISK_STATUS_* +.write dd ? +; The pointer to the function which writes data to the device. +; Optional, may be NULL. +; int write(void* userdata, void* buffer, __int64 startsector, int* numsectors); +; input: *numsectors = number of sectors to write +; output: *numsectors = number of sectors which were successfully written +; Return value: one of DISK_STATUS_* +.flush dd ? +; The pointer to the function which flushes the internal device cache. +; Optional, may be NULL. +; int flush(void* userdata); +; Return value: one of DISK_STATUS_* +; Note that read/write are called by the cache manager, so a driver should not +; create a software cache. This function is implemented for flushing a hardware +; cache, if it exists. +.adjust_cache_size dd ? +; The pointer to the function which returns the cache size for this device. +; Optional, may be NULL. +; unsigned int adjust_cache_size(unsigned int suggested_size); +; Return value: 0 = disable cache, otherwise = used cache size in bytes. +ends + +; This structure holds information on a medium. +; Objects with this structure are allocated by the kernel as a part of the DISK +; structure and are filled by a driver in the 'querymedia' callback. +struct DISKMEDIAINFO +.Flags dd ? +; Combination of DISK_MEDIA_* bits. +.SectorSize dd ? +; Size of the sector. +.Capacity dq ? +; Size of the media in sectors. +ends + +; This structure represents the disk cache. To follow the old implementation, +; there are two distinct caches for a disk, one for "system" data,and the other +; for "application" data. +struct DISKCACHE +.Lock MUTEX +; Lock to protect the cache. +; The following fields are inherited from data32.inc:cache_ideX. +.pointer rd 1 +.data_size rd 1 ; not use +.data rd 1 +.sad_size rd 1 +.search_start rd 1 +ends + +; This structure represents a disk device and its media for the kernel. +; This structure is allocated by the kernel in the 'disk_add' function, +; freed in the 'disk_dereference' function. +struct DISK +; Fields of disk object +.Next dd ? +.Prev dd ? +; All disk devices are linked in one list with these two fields. +; Head of the list is the 'disk_list' variable. +.Functions dd ? +; Pointer to the 'DISKFUNC' structure with driver functions. +.Name dd ? +; Pointer to the string used for accesses through the global filesystem. +.UserData dd ? +; This field is passed to all callback functions so a driver can decide which +; physical device is addressed. +.DriverFlags dd ? +; Bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit is defined. +; If it is set, the driver will never issue 'disk_media_changed' notification +; with argument set to true, so the kernel must try to detect media during +; requests from the file system. +.RefCount dd ? +; Count of active references to this structure. One reference is kept during +; the lifetime of the structure between 'disk_add' and 'disk_del'. +; Another reference is taken during any filesystem operation for this disk. +; One reference is added if media is inserted. +; The structure is destroyed when the reference count decrements to zero: +; this usually occurs in 'disk_del', but can be delayed to the end of last +; filesystem operation, if one is active. +.MediaLock MUTEX +; Lock to protect the MEDIA structure. See the description after +; 'disk_list_mutex' for the locking strategy. +; Fields of media object +.MediaInserted db ? +; 0 if media is not inserted, nonzero otherwise. +.MediaUsed db ? +; 0 if media fields are not used, nonzero otherwise. If .MediaRefCount is +; nonzero, this field is nonzero too; however, when .MediaRefCount goes +; to zero, there is some time interval during which media object is still used. + align 4 +; The following fields are not valid unless either .MediaInserted is nonzero +; or they are accessed from a code which has obtained the reference when +; .MediaInserted was nonzero. +.MediaRefCount dd ? +; Count of active references to the media object. One reference is kept during +; the lifetime of the media between two calls to 'disk_media_changed'. +; Another reference is taken during any filesystem operation for this media. +; The callback 'closemedia' is called when the reference count decrements to +; zero: this usually occurs in 'disk_media_changed', but can be delayed to the +; end of the last filesystem operation, if one is active. +.MediaInfo DISKMEDIAINFO +; This field keeps information on the current media. +.NumPartitions dd ? +; Number of partitions on this media. +.Partitions dd ? +; Pointer to array of .NumPartitions pointers to PARTITION structures. +.cache_size dd ? +; inherited from cache_ideX_size +.SysCache DISKCACHE +.AppCache DISKCACHE +; Two caches for the disk. +ends + +; This structure represents one partition for the kernel. This is a base +; template, the actual contents after common fields is determined by the +; file system code for this partition. +struct PARTITION +.FirstSector dq ? +; First sector of the partition. +.Length dq ? +; Length of the partition in sectors. +.Disk dd ? +; Pointer to parent DISK structure. +.FSUserFunctions dd ? +; Handlers for the sysfunction 70h. This field is a pointer to the following +; array. The first dword is a number of supported subfunctions, other dwords +; point to handlers of corresponding subfunctions. +; This field is 0 if file system is not recognized. +; ...fs-specific data may follow... +ends + +; This is an external structure, it represents an entry in the partition table. +struct PARTITION_TABLE_ENTRY +.Bootable db ? +; 80h = bootable partition, 0 = non-bootable partition, other values = invalid +.FirstHead db ? +.FirstSector db ? +.FirstTrack db ? +; Coordinates of first sector in CHS. +.Type db ? +; Partition type, one of predefined constants. 0 = empty, several types denote +; extended partition (see process_partition_table_entry), we are not interested +; in other values. +.LastHead db ? +.LastSector db ? +.LastTrack db ? +; Coordinates of last sector in CHS. +.FirstAbsSector dd ? +; Coordinate of first sector in LBA. +.Length dd ? +; Length of the partition in sectors. +ends + +; ============================================================================= +; ================================ Global data ================================ +; ============================================================================= +iglobal +; The pseudo-item for the list of all DISK structures. +; Initialized to the empty list. +disk_list: + dd disk_list + dd disk_list +endg +uglobal +; This mutex guards all operations with the global list of DISK structures. +disk_list_mutex MUTEX +; * There are two dependent objects, a disk and a media. In the simplest case, +; disk and media are both non-removable. However, in the general case both +; can be removed at any time, simultaneously or only media,and this makes things +; complicated. +; * For efficiency, both disk and media objects are located in the one +; structure named DISK. However, logically they are different. +; * The following operations use data of disk object: adding (disk_add); +; deleting (disk_del); filesystem (fs_lfn which eventually calls +; dyndisk_handler or dyndisk_enum_root). +; * The following operations use data of media object: adding/removing +; (disk_media_changed); filesystem (fs_lfn which eventually calls +; dyndisk_handler; dyndisk_enum_root doesn't work with media). +; * Notifications disk_add, disk_media_changed, disk_del are synchronized +; between themselves, this is a requirement for the driver. However, file +; system operations are asynchronous, can be issued at any time by any +; thread. +; * We must prevent a situation when a filesystem operation thinks that the +; object is still valid but in fact the notification has destroyed the +; object. So we keep a reference counter for both disk and media and destroy +; the object when this counter goes to zero. +; * The driver must know when it is safe to free driver-allocated resources. +; The object can be alive even after death notification has completed. +; We use special callbacks to satisfy both assertions: 'close' for the disk +; and 'closemedia' for the media. The destruction of the object includes +; calling the corresponding callback. +; * Each filesystem operation keeps one reference for the disk and one +; reference for the media. Notification disk_del forces notification on the +; media death, so the reference counter for the disk is always not less than +; the reference counter for the media. +; * Two operations "get the object" and "increment the reference counter" can +; not be done simultaneously. We use a mutex to guard the consistency here. +; It must be a part of the container for the object, so that this mutex can +; be acquired as a part of getting the object from the container. The +; container for disk object is the global list, and this list is guarded by +; 'disk_list_mutex'. The container for media object is the disk object, and +; the corresponding mutex is DISK.MediaLock. +; * Notifications do not change the data of objects, they can only remove +; objects. Thus we don't need another synchronization at this level. If two +; filesystem operations are referencing the same filesystem data, this is +; better resolved at the level of the filesystem. +endg + +iglobal +; The function 'disk_scan_partitions' needs three 512-byte buffers for +; MBR, bootsector and fs-temporary sector data. It can not use the static +; buffers always, since it can be called for two or more disks in parallel. +; However, this case is not typical. We reserve three static 512-byte buffers +; and a flag that these buffers are currently used. If 'disk_scan_partitions' +; detects that the buffers are currently used, it allocates buffers from the +; heap. +; The flag is implemented as a global dword variable. When the static buffers +; are not used, the value is -1. When the static buffers are used, the value +; is normally 0 and temporarily can become greater. The function increments +; this value. If the resulting value is zero, it uses the buffers and +; decrements the value when the job is done. Otherwise, it immediately +; decrements the value and uses buffers from the heap, allocated in the +; beginning and freed in the end. +partition_buffer_users dd -1 +endg +uglobal +; The static buffers for MBR, bootsector and fs-temporary sector data. +align 16 +mbr_buffer rb 512 +bootsect_buffer rb 512 +fs_tmp_buffer rb 512 +endg + +iglobal +; This is the array of default implementations of driver callbacks. +; Same as DRIVERFUNC structure except for the first field; all functions must +; have the default implementations. +align 4 +disk_default_callbacks: + dd disk_default_close + dd disk_default_closemedia + dd disk_default_querymedia + dd disk_default_read + dd disk_default_write + dd disk_default_flush + dd disk_default_adjust_cache_size +endg + +; ============================================================================= +; ================================= Functions ================================= +; ============================================================================= + +; This function registers a disk device. +; This includes: +; - allocating an internal structure describing this device; +; - registering this structure in the global filesystem. +; The function initializes the disk as if there is no media. If a media is +; present, the function 'disk_media_changed' should be called after this +; function succeeds. +; Parameters: +; [esp+4] = pointer to DISKFUNC structure with the callbacks +; [esp+8] = pointer to name (ASCIIZ string) +; [esp+12] = userdata to be passed to the callbacks as is. +; [esp+16] = flags, bitfield. Currently only DISK_NO_INSERT_NOTIFICATION bit +; is defined. +; Return value: +; NULL = operation has failed +; non-NULL = handle of the disk. This handle can be used +; in the operations with other Disk* functions. +; The handle is the pointer to the internal structure DISK. +disk_add: + push ebx esi ; save used registers to be stdcall +; 1. Allocate the DISK structure. +; 1a. Call the heap manager. + push sizeof.DISK + pop eax + call malloc +; 1b. Check the result. If allocation failed, return (go to 9) with eax = 0. + test eax, eax + jz .nothing +; 2. Copy the disk name to the DISK structure. +; 2a. Get length of the name, including the terminating zero. + mov ebx, [esp+8+8] ; ebx = pointer to name + push eax ; save allocated pointer to DISK + xor eax, eax ; the argument of malloc() is in eax +@@: + inc eax + cmp byte [ebx+eax-1], 0 + jnz @b +; 2b. Call the heap manager. + call malloc +; 2c. Check the result. If allocation failed, go to 7. + pop esi ; restore allocated pointer to DISK + test eax, eax + jz .free +; 2d. Store the allocated pointer to the DISK structure. + mov [esi+DISK.Name], eax +; 2e. Copy the name. +@@: + mov dl, [ebx] + mov [eax], dl + inc ebx + inc eax + test dl, dl + jnz @b +; 3. Copy other arguments of the function to the DISK structure. + mov eax, [esp+4+8] + mov [esi+DISK.Functions], eax + mov eax, [esp+12+8] + mov [esi+DISK.UserData], eax + mov eax, [esp+16+8] + mov [esi+DISK.DriverFlags], eax +; 4. Initialize other fields of the DISK structure. +; Media is not inserted, reference counter is 1. + lea ecx, [esi+DISK.MediaLock] + call mutex_init + xor eax, eax + mov dword [esi+DISK.MediaInserted], eax + inc eax + mov [esi+DISK.RefCount], eax +; The DISK structure is initialized. +; 5. Insert the new structure to the global list. +; 5a. Acquire the mutex. + mov ecx, disk_list_mutex + call mutex_lock +; 5b. Insert item to the tail of double-linked list. + mov edx, disk_list + list_add_tail esi, edx ;esi= new edx= list head +; 5c. Release the mutex. + call mutex_unlock +; 6. Return with eax = pointer to DISK. + xchg eax, esi + jmp .nothing +.free: +; Memory allocation for DISK structure succeeded, but for disk name failed. +; 7. Free the DISK structure. + xchg eax, esi + call free +; 8. Return with eax = 0. + xor eax, eax +.nothing: +; 9. Return. + pop esi ebx ; restore used registers to be stdcall + ret 16 ; purge 4 dword arguments to be stdcall + +; This function deletes a disk device from the global filesystem. +; This includes: +; - removing a media including all partitions; +; - deleting this structure from the global filesystem; +; - dereferencing the DISK structure and possibly destroying it. +; Parameters: +; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. +; Return value: none. +disk_del: + push esi ; save used registers to be stdcall +; 1. Force media to be removed. If the media is already removed, the +; call does nothing. + mov esi, [esp+4+8] ; esi = handle of the disk + stdcall disk_media_changed, esi, 0 +; 2. Delete the structure from the global list. +; 2a. Acquire the mutex. + mov ecx, disk_list_mutex + call mutex_lock +; 2b. Delete item from double-linked list. + mov eax, [esi+DISK.Next] + mov edx, [esi+DISK.Prev] + mov [eax+DISK.Prev], edx + mov [edx+DISK.Next], eax +; 2c. Release the mutex. + call mutex_unlock +; 3. The structure still has one reference created in disk_add. Remove this +; reference. If there are no other references, disk_dereference will free the +; structure. + call disk_dereference +; 4. Return. + pop esi ; restore used registers to be stdcall + ret 4 ; purge 1 dword argument to be stdcall + +; This is an internal function which removes a previously obtained reference +; to the disk. If this is the last reference, this function lets the driver +; finalize all associated data, and afterwards frees the DISK structure. +; esi = pointer to DISK structure +disk_dereference: +; 1. Decrement reference counter. Use atomic operation to correctly handle +; possible simultaneous calls. + lock dec [esi+DISK.RefCount] +; 2. If the result is nonzero, there are other references, so nothing to do. +; In this case, return (go to 4). + jnz .nothing +; 3. If we are here, we just removed the last reference and must destroy the +; disk object. +; 3a. Call the driver. + mov al, DISKFUNC.close + stdcall disk_call_driver +; 3b. Free the structure. + xchg eax, esi + call free +; 4. Return. +.nothing: + ret + +; This is an internal function which removes a previously obtained reference +; to the media. If this is the last reference, this function calls 'closemedia' +; callback to signal the driver that the processing has finished and it is safe +; to inform about a new media. +; esi = pointer to DISK structure +disk_media_dereference: +; 1. Decrement reference counter. Use atomic operation to correctly handle +; possible simultaneous calls. + lock dec [esi+DISK.MediaRefCount] +; 2. If the result is nonzero, there are other references, so nothing to do. +; In this case, return (go to 4). + jnz .nothing +; 3. If we are here, we just removed the last reference and must destroy the +; media object. +; Note that the same place inside the DISK structure is reused for all media +; objects, so we must guarantee that reusing does not happen while freeing. +; Reusing is only possible when someone processes a new media. There are two +; mutually exclusive variants: +; * driver issues media insert notifications (DISK_NO_INSERT_NOTIFICATION bit +; in DISK.DriverFlags is not set). In this case, we require from the driver +; that such notification (except for the first one) can occur only after a +; call to 'closemedia' callback. +; * driver does not issue media insert notifications. In this case, the kernel +; itself must sometimes check whether media is inserted. We have the flag +; DISK.MediaUsed, visible to the kernel. This flag signals to the other parts +; of kernel that the way is free. +; In the first case other parts of the kernel do not use DISK.MediaUsed, so it +; does not matter when this flag is cleared. In the second case this flag must +; be cleared after all other actions, including call to 'closemedia'. +; 3a. Free all partitions. + push esi edi + mov edi, [esi+DISK.NumPartitions] + mov esi, [esi+DISK.Partitions] + test edi, edi + jz .nofree +.freeloop: + lodsd + call free + dec edi + jnz .freeloop +.nofree: + pop edi esi +; 3b. Free the cache. + call disk_free_cache +; 3c. Call the driver. + mov al, DISKFUNC.closemedia + stdcall disk_call_driver +; 3d. Clear the flag. + mov [esi+DISK.MediaUsed], 0 +.nothing: + ret + +; This function is called by the driver and informs the kernel that the media +; has changed. If the media is non-removable, it is called exactly once +; immediately after 'disk_add' and once from 'disk_del'. +; Parameters: +; [esp+4] = handle of the disk, i.e. the pointer to the DISK structure. +; [esp+8] = new status of the media: zero = no media, nonzero = media inserted. +disk_media_changed: + push ebx esi edi ; save used registers to be stdcall +; 1. Remove the existing media, if it is present. + mov esi, [esp+4+12] ; esi = pointer to DISK +; 1a. Check whether it is present. Since DISK.MediaInserted is changed only +; in this function and calls to this function are synchronized, no lock is +; required for checking. + cmp [esi+DISK.MediaInserted], 0 + jz .noremove +; We really need to remove the media. +; 1b. Acquire mutex. + lea ecx, [esi+DISK.MediaLock] + call mutex_lock +; 1c. Clear the flag. + mov [esi+DISK.MediaInserted], 0 +; 1d. Release mutex. + call mutex_unlock +; 1e. Remove the "lifetime" reference and possibly destroy the structure. + call disk_media_dereference +.noremove: +; 2. Test whether there is new media. + cmp dword [esp+8+12], 0 + jz .noinsert +; Yep, there is. +; 3. Process the new media. We assume that all media fields are available to +; use, see comments in 'disk_media_dereference' (this covers using by previous +; media referencers) and note that calls to this function are synchronized +; (this covers using by new media referencers). +; 3a. Call the 'querymedia' callback. +; .Flags are set to zero for possible future extensions. + lea edx, [esi+DISK.MediaInfo] + and [edx+DISKMEDIAINFO.Flags], 0 + mov al, DISKFUNC.querymedia + stdcall disk_call_driver, edx +; 3b. Check the result of the callback. Abort if it failed. + test eax, eax + jnz .noinsert +; 3c. Allocate the cache unless disabled by the driver. Abort if failed. + call disk_init_cache + test al, al + jz .noinsert +; 3d. Acquire the lifetime reference for the media object. + inc [esi+DISK.MediaRefCount] +; 3e. Scan for partitions. Ignore result; the list of partitions is valid even +; on errors. + call disk_scan_partitions +; 3f. Media is inserted and available for use. + inc [esi+DISK.MediaInserted] +.noinsert: +; 4. Return. + pop edi esi ebx ; restore used registers to be stdcall + ret 8 ; purge 2 dword arguments to be stdcall + +; This function is a thunk for all functions of a disk driver. +; It checks whether the referenced function is implemented in the driver. +; If so, this function jumps to the function in the driver. +; Otherwise, it jumps to the default implementation. +; al = offset of function in the DISKFUNC structure; +; esi = pointer to the DISK structure; +; stack is the same as for the corresponding function except that the +; first parameter (void* userdata) is prepended automatically. +disk_call_driver: + movzx eax, al ; eax = offset of function in the DISKFUNC structure +; 1. Prepend the first argument to the stack. + pop ecx ; ecx = return address + push [esi+DISK.UserData] ; add argument + push ecx ; save return address +; 2. Check that the required function is inside the table. If not, go to 5. + mov ecx, [esi+DISK.Functions] + cmp eax, [ecx+DISKFUNC.strucsize] + jae .default +; 3. Check that the required function is implemented. If not, go to 5. + mov ecx, [ecx+eax] + test ecx, ecx + jz .default +; 4. Jump to the required function. + jmp ecx +.default: +; 5. Driver does not implement the required function; use default implementation. + jmp dword [disk_default_callbacks+eax-4] + +; The default implementation of DISKFUNC.querymedia. +disk_default_querymedia: + push DISK_STATUS_INVALID_CALL + pop eax + ret 8 + +; The default implementation of DISKFUNC.read and DISKFUNC.write. +disk_default_read: +disk_default_write: + push DISK_STATUS_INVALID_CALL + pop eax + ret 20 + +; The default implementation of DISKFUNC.close, DISKFUNC.closemedia and +; DISKFUNC.flush. +disk_default_close: +disk_default_closemedia: +disk_default_flush: + xor eax, eax + ret 4 + +; The default implementation of DISKFUNC.adjust_cache_size. +disk_default_adjust_cache_size: + mov eax, [esp+4] + ret 4 + +; This is an internal function called from 'disk_media_changed' when a new media +; is detected. It creates the list of partitions for the media. +; If media is not partitioned, then the list consists of one partition which +; covers all the media. +; esi = pointer to the DISK structure. +disk_scan_partitions: +; 1. Initialize .NumPartitions and .Partitions fields as zeros: empty list. + and [esi+DISK.NumPartitions], 0 + and [esi+DISK.Partitions], 0 +; 2. Currently we can work only with 512-bytes sectors. Check this restriction. +; The only exception is 2048-bytes CD/DVD, but they are not supported yet by +; this code. + cmp [esi+DISK.MediaInfo.SectorSize], 512 + jz .doscan + DEBUGF 1,'K : sector size is %d, only 512 is supported\n',[esi+DISK.MediaInfo.SectorSize] + ret +.doscan: +; 3. Acquire the buffer for MBR and bootsector tests. See the comment before +; the 'partition_buffer_users' variable. + mov ebx, mbr_buffer ; assume the global buffer is free + lock inc [partition_buffer_users] + jz .buffer_acquired ; yes, it is free + lock dec [partition_buffer_users] ; no, we must allocate + stdcall kernel_alloc, 512*3 + test eax, eax + jz .nothing + xchg eax, ebx +.buffer_acquired: +; MBR/EBRs are organized in the chain. We use a loop over MBR/EBRs, but no +; more than MAX_NUM_PARTITION times. +; 4. Prepare things for the loop. +; ebp will hold the sector number for current MBR/EBR. +; [esp] will hold the sector number for current extended partition, if there +; is one. +; [esp+4] will hold the counter that prevents long loops. + push ebp ; save ebp + push MAX_NUM_PARTITIONS ; the counter of max MBRs to process + xor ebp, ebp ; start from sector zero + push ebp ; no extended partition yet +.new_mbr: +; 5. Read the current sector. +; Note that 'read' callback operates with 64-bit sector numbers, so we must +; push additional zero as a high dword of sector number. + mov al, DISKFUNC.read + push 1 + stdcall disk_call_driver, ebx, ebp, 0, esp + pop ecx +; 6. If the read has failed, abort the loop. + dec ecx + jnz .mbr_failed +; 7. Check the MBR/EBR signature. If it is wrong, abort the loop. +; Soon we will access the partition table which starts at ebx+0x1BE, +; so we can fill its address right now. If we do it now, then the addressing +; [ecx+0x40] is shorter than [ebx+0x1fe]: one-byte offset vs 4-bytes offset. + lea ecx, [ebx+0x1be] ; ecx -> partition table + cmp word [ecx+0x40], 0xaa55 + jnz .mbr_failed +; 8. The MBR is treated differently from EBRs. For MBR we additionally need to +; execute step 9 and possibly step 10. + test ebp, ebp + jnz .mbr +; The partition table can be present or not present. In the first case, we just +; read the MBR. In the second case, we just read the bootsector for a +; filesystem. +; The following algorithm is used to distinguish between these cases. +; A. If at least one entry of the partition table is invalid, this is +; a bootsector. See the description of 'is_partition_table_entry' for +; definition of validity. +; B. If all entries are empty (filesystem type field is zero) and the first +; byte is jmp opcode (0EBh or 0E9h), this is a bootsector which happens to +; have zeros in the place of partition table. +; C. Otherwise, this is an MBR. +; 9. Test for MBR vs bootsector. +; 9a. Check entries. If any is invalid, go to 10 (rule A). + call is_partition_table_entry + jc .notmbr + add ecx, 10h + call is_partition_table_entry + jc .notmbr + add ecx, 10h + call is_partition_table_entry + jc .notmbr + add ecx, 10h + call is_partition_table_entry + jc .notmbr +; 9b. Check types of the entries. If at least one is nonzero, go to 11 (rule C). + mov al, [ecx-30h+PARTITION_TABLE_ENTRY.Type] + or al, [ecx-20h+PARTITION_TABLE_ENTRY.Type] + or al, [ecx-10h+PARTITION_TABLE_ENTRY.Type] + or al, [ecx+PARTITION_TABLE_ENTRY.Type] + jnz .mbr +; 9c. Empty partition table or bootsector with many zeroes? (rule B) + cmp byte [ebx], 0EBh + jz .notmbr + cmp byte [ebx], 0E9h + jnz .mbr +.notmbr: +; 10. This is not an MBR. The media is not partitioned. Create one partition +; which covers all the media and abort the loop. + stdcall disk_add_partition, 0, 0, \ + dword [esi+DISK.MediaInfo.Capacity], dword [esi+DISK.MediaInfo.Capacity+4] + jmp .done +.mbr: +; 11. Process all entries of the new MBR/EBR + lea ecx, [ebx+0x1be] ; ecx -> partition table + push 0 ; assume no extended partition + call process_partition_table_entry + add ecx, 10h + call process_partition_table_entry + add ecx, 10h + call process_partition_table_entry + add ecx, 10h + call process_partition_table_entry + pop ebp +; 12. Test whether we found a new EBR and should continue the loop. +; 12a. If there was no next EBR, return. + test ebp, ebp + jz .done +; Ok, we have EBR. +; 12b. EBRs addresses are relative to the start of extended partition. +; For simplicity, just abort if an 32-bit overflow occurs; large disks +; are most likely partitioned with GPT, not MBR scheme, since the precise +; calculation here would increase limit just twice at the price of big +; compatibility problems. + pop eax ; load extended partition + add ebp, eax + jc .mbr_failed +; 12c. If extended partition has not yet started, start it. + test eax, eax + jnz @f + mov eax, ebp +@@: +; 12c. If the limit is not exceeded, continue the loop. + dec dword [esp] + push eax ; store extended partition + jnz .new_mbr +.mbr_failed: +.done: +; 13. Cleanup after the loop. + pop eax ; not important anymore + pop eax ; not important anymore + pop ebp ; restore ebp +; 14. Release the buffer. +; 14a. Test whether it is the global buffer or we have allocated it. + cmp ebx, mbr_buffer + jz .release_partition_buffer +; 14b. If we have allocated it, free it. + xchg eax, ebx + call free + jmp .nothing +; 14c. Otherwise, release reference. +.release_partition_buffer: + lock dec [partition_buffer_users] +.nothing: +; 15. Return. + ret + +; This is an internal function called from disk_scan_partitions. It checks +; whether the entry pointed to by ecx is a valid entry of partition table. +; The entry is valid if the first byte is 0 or 80h, the first sector plus the +; length is less than twice the size of media. Multiplication by two is +; required since the size mentioned in the partition table can be slightly +; greater than the real size. +is_partition_table_entry: +; 1. Check .Bootable field. + mov al, [ecx+PARTITION_TABLE_ENTRY.Bootable] + and al, 7Fh + jnz .invalid +; 3. Calculate first sector + length. Note that .FirstAbsSector is relative +; to the MBR/EBR, so the real sum is ebp + .FirstAbsSector + .Length. + mov eax, ebp + xor edx, edx + add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] + adc edx, 0 + add eax, [ecx+PARTITION_TABLE_ENTRY.Length] + adc edx, 0 +; 4. Divide by two. + shr edx, 1 + rcr eax, 1 +; 5. Compare with capacity. If the subtraction (edx:eax) - .Capacity does not +; overflow, this is bad. + sub eax, dword [esi+DISK.MediaInfo.Capacity] + sbb edx, dword [esi+DISK.MediaInfo.Capacity+4] + jnc .invalid +.valid: +; 5. Return success: CF is cleared. + clc + ret +.invalid: +; 6. Return fail: CF is set. + stc + ret + +; This is an internal function called from disk_scan_partitions. It processes +; the entry pointed to by ecx. +; * If the entry is invalid, just ignore this entry. +; * If the type is zero, just ignore this entry. +; * If the type is one of types for extended partition, store the address +; of this partition as the new MBR in [esp+4]. +; * Otherwise, add the partition to the list of partitions for this disk. +; We don't use the type from the entry to identify the file system; +; fs-specific checks do this more reliably. +process_partition_table_entry: +; 1. Check for valid entry. If invalid, return (go to 5). + call is_partition_table_entry + jc .nothing +; 2. Check for empty entry. If invalid, return (go to 5). + mov al, [ecx+PARTITION_TABLE_ENTRY.Type] + test al, al + jz .nothing +; 3. Check for extended partition. If extended, go to 6. +irp type,\ + 0x05,\ ; DOS: extended partition + 0x0f,\ ; WIN95: extended partition, LBA-mapped + 0xc5,\ ; DRDOS/secured: extended partition + 0xd5 ; Old Multiuser DOS secured: extended partition +{ + cmp al, type + jz .extended +} +; 4. If we are here, that is a normal partition. Add it to the list. +; Note that the first sector is relative to MBR/EBR. + mov eax, ebp + xor edx, edx + add eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] + adc edx, 0 + push ecx + stdcall disk_add_partition, eax, edx, \ + [ecx+PARTITION_TABLE_ENTRY.Length], 0 + pop ecx +.nothing: +; 5. Return. + ret +.extended: +; 6. If we are here, that is an extended partition. Store the address. + mov eax, [ecx+PARTITION_TABLE_ENTRY.FirstAbsSector] + mov [esp+4], eax + ret + +; This is an internal function called from disk_scan_partitions and +; process_partition_table_entry. It adds one partition to the list of +; partitions for the media. +proc disk_add_partition stdcall uses ebx edi, start:qword, length:qword +; 1. Check that this partition will not exceed the limit on total number. + cmp [esi+DISK.NumPartitions], MAX_NUM_PARTITIONS + jae .nothing +; 2. Check that this partition does not overlap with any already registered +; partition. Since any file system assumes that the disk data will not change +; outside of its control, such overlap could be destructive. +; Since the number of partitions is usually very small and is guaranteed not +; to be large, the simple linear search is sufficient. +; 2a. Prepare the loop: edi will point to the current item of .Partitions +; array, ecx will be the current item, ebx will hold number of items left. + mov edi, [esi+DISK.Partitions] + mov ebx, [esi+DISK.NumPartitions] + test ebx, ebx + jz .partitionok +.scan_existing: +; 2b. Get the next partition. + mov ecx, [edi] + add edi, 4 +; The range [.FirstSector, .FirstSector+.Length) must be either entirely to +; the left of [start, start+length) or entirely to the right. +; 2c. Subtract .FirstSector - start. The possible overflow distinguish between +; cases "to the left" (2e) and "to the right" (2d). + mov eax, dword [ecx+PARTITION.FirstSector] + mov edx, dword [ecx+PARTITION.FirstSector+4] + sub eax, dword [start] + sbb edx, dword [start+4] + jb .less +; 2d. .FirstSector is greater than or equal to start. Check that .FirstSector +; is greater than or equal to start+length; the subtraction +; (.FirstSector-start) - length must not cause overflow. Go to 2g if life is +; good or to 2f in the other case. + sub eax, dword [length] + sbb edx, dword [length+4] + jb .overlap + jmp .next_existing +.less: +; 2e. .FirstSector is less than start. Check that .FirstSector+.Length is less +; than or equal to start. If the addition (.FirstSector-start) + .Length does +; not cause overflow, then .FirstSector + .Length is strictly less than start; +; since the equality is also valid, use decrement preliminarily. Go to 2g or +; 2f depending on the overflow. + sub eax, 1 + sbb edx, 0 + add eax, dword [ecx+PARTITION.Length] + adc edx, dword [ecx+PARTITION.Length+4] + jnc .next_existing +.overlap: +; 2f. The partition overlaps with previously registered partition. Say warning +; and return with nothing done. + dbgstr 'two partitions overlap, ignoring the last one' + jmp .nothing +.next_existing: +; 2g. The partition does not overlap with the current partition. Continue the +; loop. + dec ebx + jnz .scan_existing +.partitionok: +; 3. The partition has passed tests. Reallocate the partitions array for a new +; entry. +; 3a. Call the allocator. + mov eax, [esi+DISK.NumPartitions] + inc eax ; one more entry + shl eax, 2 ; each entry is dword + call malloc +; 3b. Test the result. If failed, return with nothing done. + test eax, eax + jz .nothing +; 3c. Copy the old array to the new array. + mov edi, eax + push esi + mov ecx, [esi+DISK.NumPartitions] + mov esi, [esi+DISK.Partitions] + rep movsd + pop esi +; 3d. Set the field in the DISK structure to the new array. + xchg [esi+DISK.Partitions], eax +; 3e. Free the old array. + call free +; 4. Recognize the file system. +; 4a. Call the filesystem recognizer. It will allocate the PARTITION structure +; with possible filesystem-specific fields. + call disk_detect_partition +; 4b. Check return value. If zero, return with list not changed; so far only +; the array was reallocated, this is ok for other code. + test eax, eax + jz .nothing +; 5. Insert the new partition to the list. + stosd + inc [esi+DISK.NumPartitions] +; 6. Return. +.nothing: + ret +endp + +; This is an internal function called from disk_add_partition. +; It tries to recognize the file system on the partition and allocates the +; corresponding PARTITION structure with filesystem-specific fields. +disk_detect_partition: +; This function inherits the stack frame from disk_add_partition. In stdcall +; with ebp-based frame arguments start from ebp+8, since [ebp]=saved ebp +; and [ebp+4]=return address. +virtual at ebp+8 +.start dq ? +.length dq ? +end virtual +; Currently no file systems are supported, so just allocate the PARTITION +; structure without extra fields. +; 1. Allocate and check result. + push sizeof.PARTITION + pop eax + call malloc + test eax, eax + jz .nothing +; 2. Fill the common fields: copy .start and .length. + mov edx, dword [.start] + mov dword [eax+PARTITION.FirstSector], edx + mov edx, dword [.start+4] + mov dword [eax+PARTITION.FirstSector+4], edx + mov edx, dword [.length] + mov dword [eax+PARTITION.Length], edx + mov edx, dword [.length+4] + mov dword [eax+PARTITION.Length+4], edx +.nothing: +; 3. Return with eax = pointer to PARTITION or NULL. + ret + +; This function is called from file_system_lfn. +; This handler gets the control each time when fn 70 is called +; with unknown item of root subdirectory. +; in: esi -> name +; ebp = 0 or rest of name relative to esi +; out: if the handler processes path, it must not return in file_system_lfn, +; but instead pop return address and return directly to the caller +; otherwise simply return +dyndisk_handler: + push ebx edi ; save registers used in file_system_lfn +; 1. Acquire the mutex. + mov ecx, disk_list_mutex + call mutex_lock +; 2. Loop over the list of DISK structures. +; 2a. Initialize. + mov ebx, disk_list +.scan: +; 2b. Get the next item. + mov ebx, [ebx+DISK.Next] +; 2c. Check whether the list is done. If so, go to 3. + cmp ebx, disk_list + jz .notfound +; 2d. Compare names. If names match, go to 5. + mov edi, [ebx+DISK.Name] + push esi +@@: +; esi points to the name from fs operation; it is terminated by zero or slash. + lodsb + test al, al + jz .eoin_dec + cmp al, '/' + jz .eoin +; edi points to the disk name. + inc edi +; edi points to lowercase name, this is a requirement for the driver. +; Characters at esi can have any register. Lowercase the current character. +; This lowercasing works for latin letters and digits; since the disk name +; should not contain other symbols, this is ok. + or al, 20h + cmp al, [edi-1] + jz @b +.wrongname: +; 2f. Names don't match. Continue the loop. + pop esi + jmp .scan +.notfound: +; The loop is done and no name matches. +; 3. Release the mutex. + call mutex_unlock +; 4. Return normally. + pop edi ebx ; restore registers used in file_system_lfn + ret +; part of 2d: the name matches partially, but we must check that this is full +; equality. +.eoin_dec: + dec esi +.eoin: + cmp byte [edi], 0 + jnz .wrongname +; We found the addressed DISK structure. +; 5. Reference the disk. + lock inc [ebx+DISK.RefCount] +; 6. Now we are sure that the DISK structure is not going to die at least +; while we are working with it, so release the global mutex. + call mutex_unlock +; 7. Acquire the mutex for media object. + pop edi ; restore edi + lea ecx, [ebx+DISK.MediaLock] + call mutex_lock +; 8. Get the media object. If it is not NULL, reference it. + xor edx, edx + cmp [ebx+DISK.MediaInserted], dl + jz @f + mov edx, ebx + inc [ebx+DISK.MediaRefCount] +@@: +; 9. Now we are sure that the media object, if it exists, is not going to die +; at least while we are working with it, so release the mutex for media object. + call mutex_unlock + mov ecx, ebx + pop ebx eax ; restore ebx, pop return address +; 10. Check whether the fs operation wants to enumerate partitions (go to 11) +; or work with some concrete partition (go to 12). + cmp byte [esi], 0 + jnz .haspartition +; 11. The fs operation wants to enumerate partitions. +; 11a. Only "list directory" operation is applicable to / path. Check +; the operation code. If wrong, go to 13. + cmp dword [ebx], 1 + jnz .access_denied +; 11b. If the media is inserted, use 'fs_dyndisk_next' as an enumeration +; procedure. Otherwise, use 'fs_dyndisk_next_nomedia'. + mov esi, fs_dyndisk_next_nomedia + test edx, edx + jz @f + mov esi, fs_dyndisk_next +@@: +; 11c. Let the procedure from fs_lfn.inc do the job. + jmp file_system_lfn.maindir_noesi +.haspartition: +; 12. The fs operation has specified some partition. +; 12a. Store parameters for callback functions. + push edx + push ecx +; 12b. Store callback functions. + push dyndisk_cleanup + push fs_dyndisk + mov edi, esp +; 12c. Let the procedure from fs_lfn.inc do the job. + jmp file_system_lfn.found2 +.access_denied: +; 13. Fail the operation with the appropriate code. + mov dword [esp+32], ERROR_ACCESS_DENIED +.cleanup: +; 14. Cleanup. + mov esi, ecx ; disk*dereference assume that esi points to DISK +.cleanup_esi: + test edx, edx ; if there are no media, we didn't reference it + jz @f + call disk_media_dereference +@@: + call disk_dereference +; 15. Return. + ret + +; This is a callback for cleaning up things called from file_system_lfn.found2. +dyndisk_cleanup: + mov esi, [edi+8] + mov edx, [edi+12] + jmp dyndisk_handler.cleanup_esi + +; This is a callback for enumerating partitions called from +; file_system_lfn.maindir in the case of inserted media. +; It just increments eax until DISK.NumPartitions reached and then +; cleans up. +fs_dyndisk_next: + cmp eax, [ecx+DISK.NumPartitions] + jae .nomore + inc eax + clc + ret +.nomore: + pusha + mov esi, ecx + call disk_media_dereference + call disk_dereference + popa + stc + ret + +; This is a callback for enumerating partitions called from +; file_system_lfn.maindir in the case of missing media. +; In this case we create one pseudo-partition. +fs_dyndisk_next_nomedia: + cmp eax, 1 + jae .nomore + inc eax + clc + ret +.nomore: + pusha + mov esi, ecx + call disk_dereference + popa + stc + ret + +; This is a callback for doing real work with selected partition. +; Currently this is just placeholder, since no file systems are supported. +; edi = esp -> {dd fs_dyndisk, dd dyndisk_cleanup, dd pointer to DISK, dd media object} +; ecx = partition number, esi+ebp = ASCIIZ name +fs_dyndisk: + dec ecx ; convert to zero-based partition index + pop edx edx edx eax ; edx = pointer to DISK, eax = NULL or edx + test eax, eax + jz .nomedia +.main: + cmp ecx, [edx+DISK.NumPartitions] + jae .notfound + mov dword [esp+32], ERROR_UNKNOWN_FS +.cleanup: + mov esi, edx + call disk_media_dereference + call disk_dereference + ret +.notfound: + mov dword [esp+32], ERROR_FILE_NOT_FOUND + jmp .cleanup +.nomedia: + test ecx, ecx + jnz .notfound + test byte [edx+DISK.DriverFlags], DISK_NO_INSERT_NOTIFICATION + jz .deverror +; if the driver does not support insert notifications and we are the only fs +; operation with this disk, issue the fake insert notification; if media is +; still not inserted, 'disk_media_changed' will detect this and do nothing +;;; push ebx + lea ecx, [edx+DISK.MediaLock] + call mutex_lock + cmp [edx+DISK.MediaRefCount], 1 + jnz .noluck + call mutex_unlock + push edx + stdcall disk_media_changed, edx, 1 + pop edx + lea ecx, [edx+DISK.MediaLock] + call mutex_lock + cmp [edx+DISK.MediaInserted], 0 + jz .noluck + lock inc [edx+DISK.MediaRefCount] + call mutex_unlock + xor ecx, ecx + jmp .main +.noluck: + call mutex_unlock +.deverror: + mov dword [esp+32], ERROR_DEVICE + mov esi, edx + call disk_dereference + ret + +; This function is called from file_system_lfn. +; This handler is called when virtual root is enumerated +; and must return all items which can be handled by this. +; It is called several times, first time with eax=0 +; in: eax = 0 for first call, previously returned value for subsequent calls +; out: eax = 0 => no more items +; eax != 0 => buffer pointed to by edi contains name of item +dyndisk_enum_root: + push edx ; save register used in file_system_lfn + mov ecx, disk_list_mutex ; it will be useful +; 1. If this is the first call, acquire the mutex and initialize. + test eax, eax + jnz .notfirst + call mutex_lock + mov eax, disk_list +.notfirst: +; 2. Get next item. + mov eax, [eax+DISK.Next] +; 3. If there are no more items, go to 6. + cmp eax, disk_list + jz .last +; 4. Copy name from the DISK structure to edi. + push eax esi + mov esi, [eax+DISK.Name] +@@: + lodsb + stosb + test al, al + jnz @b + pop esi eax +; 5. Return with eax = item. + pop edx ; restore register used in file_system_lfn + ret +.last: +; 6. Release the mutex and return with eax = 0. + call mutex_unlock + xor eax, eax + pop edx ; restore register used in file_system_lfn + ret diff --git a/kernel/trunk/blkdev/disk_cache.inc b/kernel/trunk/blkdev/disk_cache.inc index b62384d2a..e5bd223a6 100644 --- a/kernel/trunk/blkdev/disk_cache.inc +++ b/kernel/trunk/blkdev/disk_cache.inc @@ -1,592 +1,592 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; This function is intended to replace the old 'hd_read' function when -; [hdd_appl_data] = 0, so its input/output parameters are the same, except -; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. -; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure -; eax is relative to partition start -; out: eax = error code; 0 = ok -fs_read32_sys: -; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, -; this request should be processed by hd_read. - cmp [ebp+PARTITION.Disk], 'old' - jnz @f - mov [hdd_appl_data], 0 - call hd_read - mov [hdd_appl_data], 1 ; restore to default state - ret -@@: -; In the normal case, save ecx, set ecx to SysCache and let the common part -; do its work. - push ecx - mov ecx, [ebp+PARTITION.Disk] - add ecx, DISK.SysCache - jmp fs_read32_common - -; This function is intended to replace the old 'hd_read' function when -; [hdd_appl_data] = 1, so its input/output parameters are the same, except -; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. -; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure -; eax is relative to partition start -; out: eax = error code; 0 = ok -fs_read32_app: -; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, -; this request should be processed by hd_read. - cmp [ebp+PARTITION.Disk], 'old' - jnz @f - mov [hdd_appl_data], 1 - jmp hd_read -@@: -; In the normal case, save ecx, set ecx to AppCache and let the common part -; do its work. - push ecx - mov ecx, [ebp+PARTITION.Disk] - add ecx, DISK.AppCache - -; This label is the common part of fs_read32_sys and fs_read32_app. -fs_read32_common: -; 1. Check that the required sector is inside the partition. If no, return -; DISK_STATUS_END_OF_MEDIA. - cmp dword [ebp+PARTITION.Length+4], 0 - jnz @f - cmp dword [ebp+PARTITION.Length], eax - ja @f - mov eax, DISK_STATUS_END_OF_MEDIA - pop ecx - ret -@@: -; 2. Get the absolute sector on the disk. - push edx - xor edx, edx - add eax, dword [ebp+PARTITION.FirstSector] - adc edx, dword [ebp+PARTITION.FirstSector+4] -; 3. If there is no cache for this disk, just pass the request to the driver. - cmp [ecx+DISKCACHE.pointer], 0 - jnz .scancache - push 1 - push esp ; numsectors - push edx ; startsector - push eax ; startsector - push ebx ; buffer - mov al, DISKFUNC.read - call disk_call_driver - pop ecx - pop edx - pop ecx - ret -.scancache: -; 4. Scan the cache. - push esi edi ecx ; scan cache - push edx eax -virtual at esp -.sector_lo dd ? -.sector_hi dd ? -.cache dd ? -end virtual -; The following code is inherited from hd_read. The differences are: -; all code is protected by the cache lock; instead of static calls -; to hd_read_dma/hd_read_pio/bd_read the dynamic call to DISKFUNC.read is used; -; sector is 64-bit, not 32-bit. - call mutex_lock - mov eax, [.sector_lo] - mov edx, [.sector_hi] - mov esi, [ecx+DISKCACHE.pointer] - mov ecx, [ecx+DISKCACHE.sad_size] - add esi, 12 - - mov edi, 1 - -.hdreadcache: - - cmp dword [esi+8], 0 ; empty - je .nohdcache - - cmp [esi], eax ; correct sector - jne .nohdcache - cmp [esi+4], edx ; correct sector - je .yeshdcache - -.nohdcache: - - add esi, 12 - inc edi - dec ecx - jnz .hdreadcache - - mov esi, [.cache] - call find_empty_slot64 ; ret in edi - test eax, eax - jnz .read_done - - push 1 - push esp - push edx - push [.sector_lo+12] - mov ecx, [.cache] - mov eax, edi - shl eax, 9 - add eax, [ecx+DISKCACHE.data] - push eax - mov esi, [ebp+PARTITION.Disk] - mov al, DISKFUNC.read - call disk_call_driver - pop ecx - dec ecx - jnz .read_done - - mov ecx, [.cache] - lea eax, [edi*3] - mov esi, [ecx+DISKCACHE.pointer] - lea esi, [eax*4+esi] - - mov eax, [.sector_lo] - mov edx, [.sector_hi] - mov [esi], eax ; sector number - mov [esi+4], edx ; sector number - mov dword [esi+8], 1; hd read - mark as same as in hd - -.yeshdcache: - - mov esi, edi - mov ecx, [.cache] - shl esi, 9 - add esi, [ecx+DISKCACHE.data] - - mov edi, ebx - mov ecx, 512/4 - rep movsd ; move data - xor eax, eax ; successful read -.read_done: - mov ecx, [.cache] - push eax - call mutex_unlock - pop eax - add esp, 12 - pop edi esi edx ecx - ret - -; This function is intended to replace the old 'hd_write' function when -; [hdd_appl_data] = 0, so its input/output parameters are the same, except -; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. -; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure -; eax is relative to partition start -; out: eax = error code; 0 = ok -fs_write32_sys: -; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, -; this request should be processed by hd_write. - cmp [ebp+PARTITION.Disk], 'old' - jnz @f - mov [hdd_appl_data], 0 - call hd_write - mov [hdd_appl_data], 1 ; restore to default state - ret -@@: -; In the normal case, save ecx, set ecx to SysCache and let the common part -; do its work. - push ecx - mov ecx, [ebp+PARTITION.Disk] - add ecx, DISK.SysCache - jmp fs_write32_common - -; This function is intended to replace the old 'hd_write' function when -; [hdd_appl_data] = 1, so its input/output parameters are the same, except -; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. -; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure -; eax is relative to partition start -; out: eax = error code; 0 = ok -fs_write32_app: -; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, -; this request should be processed by hd_write. - cmp [ebp+PARTITION.Disk], 'old' - jnz @f - mov [hdd_appl_data], 1 - jmp hd_write -@@: -; In the normal case, save ecx, set ecx to AppCache and let the common part -; do its work. - push ecx - mov ecx, [ebp+PARTITION.Disk] - add ecx, DISK.AppCache - -; This label is the common part of fs_read32_sys and fs_read32_app. -fs_write32_common: -; 1. Check that the required sector is inside the partition. If no, return -; DISK_STATUS_END_OF_MEDIA. - cmp dword [ebp+PARTITION.Length+4], 0 - jnz @f - cmp dword [ebp+PARTITION.Length], eax - ja @f - mov eax, DISK_STATUS_END_OF_MEDIA - pop ecx - ret -@@: - push edx -; 2. Get the absolute sector on the disk. - xor edx, edx - add eax, dword [ebp+PARTITION.FirstSector] - adc edx, dword [ebp+PARTITION.FirstSector+4] -; 3. If there is no cache for this disk, just pass request to the driver. - cmp [ecx+DISKCACHE.pointer], 0 - jnz .scancache - push 1 - push esp ; numsectors - push edx ; startsector - push eax ; startsector - push ebx ; buffer - mov al, DISKFUNC.write - call disk_call_driver - pop ecx - pop edx - pop ecx - ret -.scancache: -; 4. Scan the cache. - push esi edi ecx ; scan cache - push edx eax -virtual at esp -.sector_lo dd ? -.sector_hi dd ? -.cache dd ? -end virtual -; The following code is inherited from hd_write. The differences are: -; all code is protected by the cache lock; -; sector is 64-bit, not 32-bit. - call mutex_lock - - ; check if the cache already has the sector and overwrite it - mov eax, [.sector_lo] - mov edx, [.sector_hi] - mov esi, [ecx+DISKCACHE.pointer] - mov ecx, [ecx+DISKCACHE.sad_size] - add esi, 12 - - mov edi, 1 - -.hdwritecache: - cmp dword [esi+8], 0 ; if cache slot is empty - je .not_in_cache_write - - cmp [esi], eax ; if the slot has the sector - jne .not_in_cache_write - cmp [esi+4], edx ; if the slot has the sector - je .yes_in_cache_write - -.not_in_cache_write: - - add esi, 12 - inc edi - dec ecx - jnz .hdwritecache - - ; sector not found in cache - ; write the block to a new location - - mov esi, [.cache] - call find_empty_slot64 ; ret in edi - test eax, eax - jne .hd_write_access_denied - - mov ecx, [.cache] - lea eax, [edi*3] - mov esi, [ecx+DISKCACHE.pointer] - lea esi, [eax*4+esi] - - mov eax, [.sector_lo] - mov edx, [.sector_hi] - mov [esi], eax ; sector number - mov [esi+4], edx ; sector number - -.yes_in_cache_write: - - mov dword [esi+4], 2 ; write - differs from hd - - shl edi, 9 - mov ecx, [.cache] - add edi, [ecx+DISKCACHE.data] - - mov esi, ebx - mov ecx, 512/4 - rep movsd ; move data - xor eax, eax ; success -.hd_write_access_denied: - mov ecx, [.cache] - push eax - call mutex_unlock - pop eax - add esp, 12 - pop edi esi edx ecx - ret - -; This internal function is called from fs_read32_* and fs_write32_*. It is the -; analogue of find_empty_slot for 64-bit sectors. -find_empty_slot64: -;----------------------------------------------------------- -; find empty or read slot, flush cache if next 12.5% is used by write -; output : edi = cache slot -;----------------------------------------------------------- -.search_again: - mov ecx, [esi+DISKCACHE.sad_size] - mov edi, [esi+DISKCACHE.search_start] - shr ecx, 3 -.search_for_empty: - inc edi - cmp edi, [esi+DISKCACHE.sad_size] - jbe .inside_cache - mov edi, 1 -.inside_cache: - lea eax, [edi*3] - shl eax, 2 - add eax, [esi+DISKCACHE.pointer] - cmp dword [eax+8], 2 - jb .found_slot ; it's empty or read - dec ecx - jnz .search_for_empty - call write_cache64 ; no empty slots found, write all - test eax, eax - jne .found_slot_access_denied - jmp .search_again ; and start again -.found_slot: - mov [esi+DISKCACHE.search_start], edi - xor eax, eax ; success -.found_slot_access_denied: - ret - -; This function is intended to replace the old 'write_cache' function. -proc write_cache64 uses ecx edx esi edi -locals -cache_chain_started dd ? -cache_chain_size dd ? -cache_chain_pos dd ? -cache_chain_ptr dd ? -endl -; If there is no cache for this disk, nothing to do. - cmp [esi+DISKCACHE.pointer], 0 - jz .flush -;----------------------------------------------------------- -; write all changed sectors to disk -;----------------------------------------------------------- - - ; write difference ( 2 ) from cache to DISK - mov ecx, [esi+DISKCACHE.sad_size] - mov esi, [esi+DISKCACHE.pointer] - add esi, 12 - mov edi, 1 -.write_cache_more: - cmp dword [esi+8], 2 ; if cache slot is not different - jne .write_chain - mov dword [esi+8], 1 ; same as in hd - mov eax, [esi] - mov edx, [esi+4] ; edx:eax = sector to write -; Объединяем запись цепочки последовательных секторов в одно обращение к диску - cmp ecx, 1 - jz .nonext - cmp dword [esi+12+8], 2 - jnz .nonext - push eax edx - add eax, 1 - adc edx, 0 - cmp eax, [esi+12] - jnz @f - cmp edx, [esi+12+4] -@@: - pop edx eax - jnz .nonext - cmp [cache_chain_started], 1 - jz @f - mov [cache_chain_started], 1 - mov [cache_chain_size], 0 - mov [cache_chain_pos], edi - mov [cache_chain_ptr], esi -@@: - inc [cache_chain_size] - cmp [cache_chain_size], 16 - jnz .continue - jmp .write_chain -.nonext: - call .flush_cache_chain - test eax, eax - jnz .nothing - mov [cache_chain_size], 1 - mov [cache_chain_ptr], esi - call .write_cache_sector - test eax, eax - jnz .nothing - jmp .continue -.write_chain: - call .flush_cache_chain - test eax, eax - jnz .nothing -.continue: - add esi, 12 - inc edi - dec ecx - jnz .write_cache_more - call .flush_cache_chain - test eax, eax - jnz .nothing -.flush: - mov esi, [ebp] - mov esi, [esi+PARTITION.Disk] - mov al, DISKFUNC.flush - call disk_call_driver -.nothing: - ret - -.flush_cache_chain: - xor eax, eax - cmp [cache_chain_started], eax - jz @f - call .write_cache_chain - mov [cache_chain_started], 0 -@@: - retn - -.write_cache_sector: - mov [cache_chain_size], 1 - mov [cache_chain_pos], edi -.write_cache_chain: - pusha - mov edi, [cache_chain_pos] - mov ecx, [ebp-12] - shl edi, 9 - add edi, [ecx+DISKCACHE.data] - mov ecx, [cache_chain_size] - push ecx - push esp ; numsectors - mov eax, [cache_chain_ptr] - pushd [eax+4] - pushd [eax] ; startsector - push edi ; buffer - mov esi, [ebp] - mov esi, [esi+PARTITION.Disk] - mov al, DISKFUNC.write - call disk_call_driver - pop ecx - mov [esp+28], eax - popa - retn -endp - -; This internal function is called from disk_add to initialize the caching for -; a new DISK. -; The algorithm is inherited from getcache.inc: take 1/32 part of the available -; physical memory, round down to 8 pages, limit by 128K from below and by 1M -; from above. Reserve 1/8 part of the cache for system data and 7/8 for app -; data. -; After the size is calculated, but before the cache is allocated, the device -; driver can adjust the size. In particular, setting size to zero disables -; caching: there is no sense in a cache for a ramdisk. In fact, such action -; is most useful example of a non-trivial adjustment. -; esi = pointer to DISK structure -disk_init_cache: -; 1. Calculate the suggested cache size. -; 1a. Get the size of free physical memory in pages. - mov eax, [pg_data.pages_free] -; 1b. Use the value to calculate the size. - shl eax, 12 - 5 ; 1/32 of it in bytes - and eax, -8*4096 ; round down to the multiple of 8 pages -; 1c. Force lower and upper limits. - cmp eax, 1024*1024 - jb @f - mov eax, 1024*1024 -@@: - cmp eax, 128*1024 - ja @f - mov eax, 128*1024 -@@: -; 1d. Give a chance to the driver to adjust the size. - push eax - mov al, DISKFUNC.adjust_cache_size - call disk_call_driver -; Cache size calculated. - mov [esi+DISK.cache_size], eax - test eax, eax - jz .nocache -; 2. Allocate memory for the cache. -; 2a. Call the allocator. - stdcall kernel_alloc, eax - test eax, eax - jnz @f -; 2b. If it failed, say a message and return with eax = 0. - dbgstr 'no memory for disk cache' - jmp .nothing -@@: -; 3. Fill two DISKCACHE structures. - mov [esi+DISK.SysCache.pointer], eax - lea ecx, [esi+DISK.SysCache.Lock] - call mutex_init - lea ecx, [esi+DISK.AppCache.Lock] - call mutex_init -; The following code is inherited from getcache.inc. - mov edx, [esi+DISK.SysCache.pointer] - and [esi+DISK.SysCache.search_start], 0 - and [esi+DISK.AppCache.search_start], 0 - mov eax, [esi+DISK.cache_size] - shr eax, 3 - mov [esi+DISK.SysCache.data_size], eax - add edx, eax - imul eax, 7 - mov [esi+DISK.AppCache.data_size], eax - mov [esi+DISK.AppCache.pointer], edx - - mov eax, [esi+DISK.SysCache.data_size] - push ebx - call calculate_for_hd - pop ebx - add eax, [esi+DISK.SysCache.pointer] - mov [esi+DISK.SysCache.data], eax - mov [esi+DISK.SysCache.sad_size], ecx - - push edi - mov edi, [esi+DISK.SysCache.pointer] - lea ecx, [ecx*3] - xor eax, eax - rep stosd - pop edi - - mov eax, [esi+DISK.AppCache.data_size] - push ebx - call calculate_for_hd - pop ebx - add eax, [esi+DISK.AppCache.pointer] - mov [esi+DISK.AppCache.data], eax - mov [esi+DISK.AppCache.sad_size], ecx - - push edi - mov edi, [esi+DISK.AppCache.pointer] - lea ecx, [ecx*3] - xor eax, eax - rep stosd - pop edi - -; 4. Return with nonzero al. - mov al, 1 -; 5. Return. -.nothing: - ret -; No caching is required for this driver. Zero cache pointers and return with -; nonzero al. -.nocache: - mov [esi+DISK.SysCache.pointer], eax - mov [esi+DISK.AppCache.pointer], eax - mov al, 1 - ret - -; This internal function is called from disk_media_dereference to free the -; allocated cache, if there is one. -; esi = pointer to DISK structure -disk_free_cache: -; The algorithm is straightforward. - mov eax, [esi+DISK.SysCache.pointer] - test eax, eax - jz .nothing - stdcall kernel_free, eax -.nothing: - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; This function is intended to replace the old 'hd_read' function when +; [hdd_appl_data] = 0, so its input/output parameters are the same, except +; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. +; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure +; eax is relative to partition start +; out: eax = error code; 0 = ok +fs_read32_sys: +; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, +; this request should be processed by hd_read. + cmp [ebp+PARTITION.Disk], 'old' + jnz @f + mov [hdd_appl_data], 0 + call hd_read + mov [hdd_appl_data], 1 ; restore to default state + ret +@@: +; In the normal case, save ecx, set ecx to SysCache and let the common part +; do its work. + push ecx + mov ecx, [ebp+PARTITION.Disk] + add ecx, DISK.SysCache + jmp fs_read32_common + +; This function is intended to replace the old 'hd_read' function when +; [hdd_appl_data] = 1, so its input/output parameters are the same, except +; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. +; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure +; eax is relative to partition start +; out: eax = error code; 0 = ok +fs_read32_app: +; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, +; this request should be processed by hd_read. + cmp [ebp+PARTITION.Disk], 'old' + jnz @f + mov [hdd_appl_data], 1 + jmp hd_read +@@: +; In the normal case, save ecx, set ecx to AppCache and let the common part +; do its work. + push ecx + mov ecx, [ebp+PARTITION.Disk] + add ecx, DISK.AppCache + +; This label is the common part of fs_read32_sys and fs_read32_app. +fs_read32_common: +; 1. Check that the required sector is inside the partition. If no, return +; DISK_STATUS_END_OF_MEDIA. + cmp dword [ebp+PARTITION.Length+4], 0 + jnz @f + cmp dword [ebp+PARTITION.Length], eax + ja @f + mov eax, DISK_STATUS_END_OF_MEDIA + pop ecx + ret +@@: +; 2. Get the absolute sector on the disk. + push edx + xor edx, edx + add eax, dword [ebp+PARTITION.FirstSector] + adc edx, dword [ebp+PARTITION.FirstSector+4] +; 3. If there is no cache for this disk, just pass the request to the driver. + cmp [ecx+DISKCACHE.pointer], 0 + jnz .scancache + push 1 + push esp ; numsectors + push edx ; startsector + push eax ; startsector + push ebx ; buffer + mov al, DISKFUNC.read + call disk_call_driver + pop ecx + pop edx + pop ecx + ret +.scancache: +; 4. Scan the cache. + push esi edi ecx ; scan cache + push edx eax +virtual at esp +.sector_lo dd ? +.sector_hi dd ? +.cache dd ? +end virtual +; The following code is inherited from hd_read. The differences are: +; all code is protected by the cache lock; instead of static calls +; to hd_read_dma/hd_read_pio/bd_read the dynamic call to DISKFUNC.read is used; +; sector is 64-bit, not 32-bit. + call mutex_lock + mov eax, [.sector_lo] + mov edx, [.sector_hi] + mov esi, [ecx+DISKCACHE.pointer] + mov ecx, [ecx+DISKCACHE.sad_size] + add esi, 12 + + mov edi, 1 + +.hdreadcache: + + cmp dword [esi+8], 0 ; empty + je .nohdcache + + cmp [esi], eax ; correct sector + jne .nohdcache + cmp [esi+4], edx ; correct sector + je .yeshdcache + +.nohdcache: + + add esi, 12 + inc edi + dec ecx + jnz .hdreadcache + + mov esi, [.cache] + call find_empty_slot64 ; ret in edi + test eax, eax + jnz .read_done + + push 1 + push esp + push edx + push [.sector_lo+12] + mov ecx, [.cache] + mov eax, edi + shl eax, 9 + add eax, [ecx+DISKCACHE.data] + push eax + mov esi, [ebp+PARTITION.Disk] + mov al, DISKFUNC.read + call disk_call_driver + pop ecx + dec ecx + jnz .read_done + + mov ecx, [.cache] + lea eax, [edi*3] + mov esi, [ecx+DISKCACHE.pointer] + lea esi, [eax*4+esi] + + mov eax, [.sector_lo] + mov edx, [.sector_hi] + mov [esi], eax ; sector number + mov [esi+4], edx ; sector number + mov dword [esi+8], 1; hd read - mark as same as in hd + +.yeshdcache: + + mov esi, edi + mov ecx, [.cache] + shl esi, 9 + add esi, [ecx+DISKCACHE.data] + + mov edi, ebx + mov ecx, 512/4 + rep movsd ; move data + xor eax, eax ; successful read +.read_done: + mov ecx, [.cache] + push eax + call mutex_unlock + pop eax + add esp, 12 + pop edi esi edx ecx + ret + +; This function is intended to replace the old 'hd_write' function when +; [hdd_appl_data] = 0, so its input/output parameters are the same, except +; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. +; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure +; eax is relative to partition start +; out: eax = error code; 0 = ok +fs_write32_sys: +; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, +; this request should be processed by hd_write. + cmp [ebp+PARTITION.Disk], 'old' + jnz @f + mov [hdd_appl_data], 0 + call hd_write + mov [hdd_appl_data], 1 ; restore to default state + ret +@@: +; In the normal case, save ecx, set ecx to SysCache and let the common part +; do its work. + push ecx + mov ecx, [ebp+PARTITION.Disk] + add ecx, DISK.SysCache + jmp fs_write32_common + +; This function is intended to replace the old 'hd_write' function when +; [hdd_appl_data] = 1, so its input/output parameters are the same, except +; that it can't use the global variables 'hd_error' and 'hdd_appl_data'. +; in: eax = sector, ebx = buffer, ebp = pointer to PARTITION structure +; eax is relative to partition start +; out: eax = error code; 0 = ok +fs_write32_app: +; Compatibility hack: if PARTITION.Disk is 'old', there is no DISK structure, +; this request should be processed by hd_write. + cmp [ebp+PARTITION.Disk], 'old' + jnz @f + mov [hdd_appl_data], 1 + jmp hd_write +@@: +; In the normal case, save ecx, set ecx to AppCache and let the common part +; do its work. + push ecx + mov ecx, [ebp+PARTITION.Disk] + add ecx, DISK.AppCache + +; This label is the common part of fs_read32_sys and fs_read32_app. +fs_write32_common: +; 1. Check that the required sector is inside the partition. If no, return +; DISK_STATUS_END_OF_MEDIA. + cmp dword [ebp+PARTITION.Length+4], 0 + jnz @f + cmp dword [ebp+PARTITION.Length], eax + ja @f + mov eax, DISK_STATUS_END_OF_MEDIA + pop ecx + ret +@@: + push edx +; 2. Get the absolute sector on the disk. + xor edx, edx + add eax, dword [ebp+PARTITION.FirstSector] + adc edx, dword [ebp+PARTITION.FirstSector+4] +; 3. If there is no cache for this disk, just pass request to the driver. + cmp [ecx+DISKCACHE.pointer], 0 + jnz .scancache + push 1 + push esp ; numsectors + push edx ; startsector + push eax ; startsector + push ebx ; buffer + mov al, DISKFUNC.write + call disk_call_driver + pop ecx + pop edx + pop ecx + ret +.scancache: +; 4. Scan the cache. + push esi edi ecx ; scan cache + push edx eax +virtual at esp +.sector_lo dd ? +.sector_hi dd ? +.cache dd ? +end virtual +; The following code is inherited from hd_write. The differences are: +; all code is protected by the cache lock; +; sector is 64-bit, not 32-bit. + call mutex_lock + + ; check if the cache already has the sector and overwrite it + mov eax, [.sector_lo] + mov edx, [.sector_hi] + mov esi, [ecx+DISKCACHE.pointer] + mov ecx, [ecx+DISKCACHE.sad_size] + add esi, 12 + + mov edi, 1 + +.hdwritecache: + cmp dword [esi+8], 0 ; if cache slot is empty + je .not_in_cache_write + + cmp [esi], eax ; if the slot has the sector + jne .not_in_cache_write + cmp [esi+4], edx ; if the slot has the sector + je .yes_in_cache_write + +.not_in_cache_write: + + add esi, 12 + inc edi + dec ecx + jnz .hdwritecache + + ; sector not found in cache + ; write the block to a new location + + mov esi, [.cache] + call find_empty_slot64 ; ret in edi + test eax, eax + jne .hd_write_access_denied + + mov ecx, [.cache] + lea eax, [edi*3] + mov esi, [ecx+DISKCACHE.pointer] + lea esi, [eax*4+esi] + + mov eax, [.sector_lo] + mov edx, [.sector_hi] + mov [esi], eax ; sector number + mov [esi+4], edx ; sector number + +.yes_in_cache_write: + + mov dword [esi+4], 2 ; write - differs from hd + + shl edi, 9 + mov ecx, [.cache] + add edi, [ecx+DISKCACHE.data] + + mov esi, ebx + mov ecx, 512/4 + rep movsd ; move data + xor eax, eax ; success +.hd_write_access_denied: + mov ecx, [.cache] + push eax + call mutex_unlock + pop eax + add esp, 12 + pop edi esi edx ecx + ret + +; This internal function is called from fs_read32_* and fs_write32_*. It is the +; analogue of find_empty_slot for 64-bit sectors. +find_empty_slot64: +;----------------------------------------------------------- +; find empty or read slot, flush cache if next 12.5% is used by write +; output : edi = cache slot +;----------------------------------------------------------- +.search_again: + mov ecx, [esi+DISKCACHE.sad_size] + mov edi, [esi+DISKCACHE.search_start] + shr ecx, 3 +.search_for_empty: + inc edi + cmp edi, [esi+DISKCACHE.sad_size] + jbe .inside_cache + mov edi, 1 +.inside_cache: + lea eax, [edi*3] + shl eax, 2 + add eax, [esi+DISKCACHE.pointer] + cmp dword [eax+8], 2 + jb .found_slot ; it's empty or read + dec ecx + jnz .search_for_empty + call write_cache64 ; no empty slots found, write all + test eax, eax + jne .found_slot_access_denied + jmp .search_again ; and start again +.found_slot: + mov [esi+DISKCACHE.search_start], edi + xor eax, eax ; success +.found_slot_access_denied: + ret + +; This function is intended to replace the old 'write_cache' function. +proc write_cache64 uses ecx edx esi edi +locals +cache_chain_started dd ? +cache_chain_size dd ? +cache_chain_pos dd ? +cache_chain_ptr dd ? +endl +; If there is no cache for this disk, nothing to do. + cmp [esi+DISKCACHE.pointer], 0 + jz .flush +;----------------------------------------------------------- +; write all changed sectors to disk +;----------------------------------------------------------- + + ; write difference ( 2 ) from cache to DISK + mov ecx, [esi+DISKCACHE.sad_size] + mov esi, [esi+DISKCACHE.pointer] + add esi, 12 + mov edi, 1 +.write_cache_more: + cmp dword [esi+8], 2 ; if cache slot is not different + jne .write_chain + mov dword [esi+8], 1 ; same as in hd + mov eax, [esi] + mov edx, [esi+4] ; edx:eax = sector to write +; Объединяем запись цепочки последовательных секторов в одно обращение к диску + cmp ecx, 1 + jz .nonext + cmp dword [esi+12+8], 2 + jnz .nonext + push eax edx + add eax, 1 + adc edx, 0 + cmp eax, [esi+12] + jnz @f + cmp edx, [esi+12+4] +@@: + pop edx eax + jnz .nonext + cmp [cache_chain_started], 1 + jz @f + mov [cache_chain_started], 1 + mov [cache_chain_size], 0 + mov [cache_chain_pos], edi + mov [cache_chain_ptr], esi +@@: + inc [cache_chain_size] + cmp [cache_chain_size], 16 + jnz .continue + jmp .write_chain +.nonext: + call .flush_cache_chain + test eax, eax + jnz .nothing + mov [cache_chain_size], 1 + mov [cache_chain_ptr], esi + call .write_cache_sector + test eax, eax + jnz .nothing + jmp .continue +.write_chain: + call .flush_cache_chain + test eax, eax + jnz .nothing +.continue: + add esi, 12 + inc edi + dec ecx + jnz .write_cache_more + call .flush_cache_chain + test eax, eax + jnz .nothing +.flush: + mov esi, [ebp] + mov esi, [esi+PARTITION.Disk] + mov al, DISKFUNC.flush + call disk_call_driver +.nothing: + ret + +.flush_cache_chain: + xor eax, eax + cmp [cache_chain_started], eax + jz @f + call .write_cache_chain + mov [cache_chain_started], 0 +@@: + retn + +.write_cache_sector: + mov [cache_chain_size], 1 + mov [cache_chain_pos], edi +.write_cache_chain: + pusha + mov edi, [cache_chain_pos] + mov ecx, [ebp-12] + shl edi, 9 + add edi, [ecx+DISKCACHE.data] + mov ecx, [cache_chain_size] + push ecx + push esp ; numsectors + mov eax, [cache_chain_ptr] + pushd [eax+4] + pushd [eax] ; startsector + push edi ; buffer + mov esi, [ebp] + mov esi, [esi+PARTITION.Disk] + mov al, DISKFUNC.write + call disk_call_driver + pop ecx + mov [esp+28], eax + popa + retn +endp + +; This internal function is called from disk_add to initialize the caching for +; a new DISK. +; The algorithm is inherited from getcache.inc: take 1/32 part of the available +; physical memory, round down to 8 pages, limit by 128K from below and by 1M +; from above. Reserve 1/8 part of the cache for system data and 7/8 for app +; data. +; After the size is calculated, but before the cache is allocated, the device +; driver can adjust the size. In particular, setting size to zero disables +; caching: there is no sense in a cache for a ramdisk. In fact, such action +; is most useful example of a non-trivial adjustment. +; esi = pointer to DISK structure +disk_init_cache: +; 1. Calculate the suggested cache size. +; 1a. Get the size of free physical memory in pages. + mov eax, [pg_data.pages_free] +; 1b. Use the value to calculate the size. + shl eax, 12 - 5 ; 1/32 of it in bytes + and eax, -8*4096 ; round down to the multiple of 8 pages +; 1c. Force lower and upper limits. + cmp eax, 1024*1024 + jb @f + mov eax, 1024*1024 +@@: + cmp eax, 128*1024 + ja @f + mov eax, 128*1024 +@@: +; 1d. Give a chance to the driver to adjust the size. + push eax + mov al, DISKFUNC.adjust_cache_size + call disk_call_driver +; Cache size calculated. + mov [esi+DISK.cache_size], eax + test eax, eax + jz .nocache +; 2. Allocate memory for the cache. +; 2a. Call the allocator. + stdcall kernel_alloc, eax + test eax, eax + jnz @f +; 2b. If it failed, say a message and return with eax = 0. + dbgstr 'no memory for disk cache' + jmp .nothing +@@: +; 3. Fill two DISKCACHE structures. + mov [esi+DISK.SysCache.pointer], eax + lea ecx, [esi+DISK.SysCache.Lock] + call mutex_init + lea ecx, [esi+DISK.AppCache.Lock] + call mutex_init +; The following code is inherited from getcache.inc. + mov edx, [esi+DISK.SysCache.pointer] + and [esi+DISK.SysCache.search_start], 0 + and [esi+DISK.AppCache.search_start], 0 + mov eax, [esi+DISK.cache_size] + shr eax, 3 + mov [esi+DISK.SysCache.data_size], eax + add edx, eax + imul eax, 7 + mov [esi+DISK.AppCache.data_size], eax + mov [esi+DISK.AppCache.pointer], edx + + mov eax, [esi+DISK.SysCache.data_size] + push ebx + call calculate_for_hd + pop ebx + add eax, [esi+DISK.SysCache.pointer] + mov [esi+DISK.SysCache.data], eax + mov [esi+DISK.SysCache.sad_size], ecx + + push edi + mov edi, [esi+DISK.SysCache.pointer] + lea ecx, [ecx*3] + xor eax, eax + rep stosd + pop edi + + mov eax, [esi+DISK.AppCache.data_size] + push ebx + call calculate_for_hd + pop ebx + add eax, [esi+DISK.AppCache.pointer] + mov [esi+DISK.AppCache.data], eax + mov [esi+DISK.AppCache.sad_size], ecx + + push edi + mov edi, [esi+DISK.AppCache.pointer] + lea ecx, [ecx*3] + xor eax, eax + rep stosd + pop edi + +; 4. Return with nonzero al. + mov al, 1 +; 5. Return. +.nothing: + ret +; No caching is required for this driver. Zero cache pointers and return with +; nonzero al. +.nocache: + mov [esi+DISK.SysCache.pointer], eax + mov [esi+DISK.AppCache.pointer], eax + mov al, 1 + ret + +; This internal function is called from disk_media_dereference to free the +; allocated cache, if there is one. +; esi = pointer to DISK structure +disk_free_cache: +; The algorithm is straightforward. + mov eax, [esi+DISK.SysCache.pointer] + test eax, eax + jz .nothing + stdcall kernel_free, eax +.nothing: + ret diff --git a/kernel/trunk/blkdev/fdc.inc b/kernel/trunk/blkdev/fdc.inc index 65f4af940..1c27d72e7 100644 --- a/kernel/trunk/blkdev/fdc.inc +++ b/kernel/trunk/blkdev/fdc.inc @@ -1,71 +1,71 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -iglobal - ;function pointers. - fdc_irq_func dd fdc_null -endg - -uglobal - dmasize db 0x0 - dmamode db 0x0 -endg - -fdc_init: ;start with clean tracks. - mov edi,OS_BASE+0xD201 - mov al,0 - mov ecx,160 - rep stosb -ret - -fdc_irq: - call [fdc_irq_func] -fdc_null: -ret - -save_image: - call reserve_flp - call restorefatchain - pusha - call check_label - cmp [FDC_Status],0 - jne unnecessary_save_image - mov [FDD_Track],0 ; Цилиндр - mov [FDD_Head],0 ; Сторона - mov [FDD_Sector],1 ; Сектор - mov esi,RAMDISK - call SeekTrack -save_image_1: - push esi - call take_data_from_application_1 - pop esi - add esi,512 - call WriteSectWithRetr -; call WriteSector - cmp [FDC_Status],0 - jne unnecessary_save_image - inc [FDD_Sector] - cmp [FDD_Sector],19 - jne save_image_1 - mov [FDD_Sector],1 - inc [FDD_Head] - cmp [FDD_Head],2 - jne save_image_1 - mov [FDD_Head],0 - inc [FDD_Track] - call SeekTrack - cmp [FDD_Track],80 - jne save_image_1 -unnecessary_save_image: - mov [fdc_irq_func],fdc_null - popa - mov [flp_status],0 - ret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +iglobal + ;function pointers. + fdc_irq_func dd fdc_null +endg + +uglobal + dmasize db 0x0 + dmamode db 0x0 +endg + +fdc_init: ;start with clean tracks. + mov edi, OS_BASE+0xD201 + mov al, 0 + mov ecx, 160 + rep stosb + ret + +fdc_irq: + call [fdc_irq_func] +fdc_null: + ret + +save_image: + call reserve_flp + call restorefatchain + pusha + call check_label + cmp [FDC_Status], 0 + jne unnecessary_save_image + mov [FDD_Track], 0; Цилиндр + mov [FDD_Head], 0; Сторона + mov [FDD_Sector], 1; Сектор + mov esi, RAMDISK + call SeekTrack +save_image_1: + push esi + call take_data_from_application_1 + pop esi + add esi, 512 + call WriteSectWithRetr +; call WriteSector + cmp [FDC_Status], 0 + jne unnecessary_save_image + inc [FDD_Sector] + cmp [FDD_Sector], 19 + jne save_image_1 + mov [FDD_Sector], 1 + inc [FDD_Head] + cmp [FDD_Head], 2 + jne save_image_1 + mov [FDD_Head], 0 + inc [FDD_Track] + call SeekTrack + cmp [FDD_Track], 80 + jne save_image_1 +unnecessary_save_image: + mov [fdc_irq_func], fdc_null + popa + mov [flp_status], 0 + ret + diff --git a/kernel/trunk/blkdev/flp_drv.inc b/kernel/trunk/blkdev/flp_drv.inc index 127bfe48e..df1cfb23c 100644 --- a/kernel/trunk/blkdev/flp_drv.inc +++ b/kernel/trunk/blkdev/flp_drv.inc @@ -1,626 +1,630 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;********************************************************** -; Непосредственная работа с контроллером гибкого диска -;********************************************************** -; Автор исходного текста Кулаков Владимир Геннадьевич. -; Адаптация и доработка Mario79 - -;give_back_application_data: ; переслать приложению -; mov edi,[TASK_BASE] -; mov edi,[edi+TASKDATA.mem_start] -; add edi,ecx -give_back_application_data_1: - mov esi,FDD_BUFF ;FDD_DataBuffer ;0x40000 - xor ecx,ecx - mov cx,128 - cld - rep movsd - ret - -;take_data_from_application: ; взять из приложени -; mov esi,[TASK_BASE] -; mov esi,[esi+TASKDATA.mem_start] -; add esi,ecx -take_data_from_application_1: - mov edi,FDD_BUFF ;FDD_DataBuffer ;0x40000 - xor ecx,ecx - mov cx,128 - cld - rep movsd - ret - -; Коды завершения операции с контроллером (FDC_Status) -FDC_Normal equ 0 ;нормальное завершение -FDC_TimeOut equ 1 ;ошибка тайм-аута -FDC_DiskNotFound equ 2 ;в дисководе нет диска -FDC_TrackNotFound equ 3 ;дорожка не найдена -FDC_SectorNotFound equ 4 ;сектор не найден - -; Максимальные значения координат сектора (заданные -; значения соответствуют параметрам стандартного -; трехдюймового гибкого диска объемом 1,44 Мб) -MAX_Track equ 79 -MAX_Head equ 1 -MAX_Sector equ 18 - -uglobal -; Счетчик тиков таймера -TickCounter dd ? -; Код завершения операции с контроллером НГМД -FDC_Status DB ? -; Флаг прерывания от НГМД -FDD_IntFlag DB ? -; Момент начала последней операции с НГМД -FDD_Time DD ? -; Номер дисковода -FDD_Type db 0 -; Координаты сектора -FDD_Track DB ? -FDD_Head DB ? -FDD_Sector DB ? - -; Блок результата операции -FDC_ST0 DB ? -FDC_ST1 DB ? -FDC_ST2 DB ? -FDC_C DB ? -FDC_H DB ? -FDC_R DB ? -FDC_N DB ? -; Счетчик повторения операции чтени -ReadRepCounter DB ? -; Счетчик повторения операции рекалибровки -RecalRepCounter DB ? -endg -; Область памяти для хранения прочитанного сектора -;FDD_DataBuffer: times 512 db 0 ;DB 512 DUP (?) -fdd_motor_status db 0 -timer_fdd_motor dd 0 - -;************************************* -;* ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПДП ДЛЯ НГМД * -;************************************* -Init_FDC_DMA: - pushad - mov al,0 - out 0x0c,al ; reset the flip-flop to a known state. - mov al,6 ; mask channel 2 so we can reprogram it. - out 0x0a,al - mov al,[dmamode] ; 0x46 -> Read from floppy - 0x4A Write to floppy - out 0x0b,al - mov al,0 - out 0x0c,al ; reset the flip-flop to a known state. - mov eax,0xD000 - out 0x04,al ; set the channel 2 starting address to 0 - shr eax,8 - out 0x04,al - shr eax,8 - out 0x81,al - mov al,0 - out 0x0c, al ; reset flip-flop - mov al, 0xff ;set count (actual size -1) - out 0x5, al - mov al,0x1 ;[dmasize] ;(0x1ff = 511 / 0x23ff =9215) - out 0x5,al - mov al,2 - out 0xa,al - popad - ret - -;*********************************** -;* ЗАПИСАТЬ БАЙТ В ПОРТ ДАННЫХ FDC * -;* Параметры: * -;* AL - выводимый байт. * -;*********************************** -FDCDataOutput: -; pusha - push eax ecx edx - mov AH,AL ;запомнить байт в AH -; Сбросить переменную состояния контроллера - mov [FDC_Status],FDC_Normal -; Проверить готовность контроллера к приему данных - mov DX,3F4h ;(порт состояния FDC) - mov ecx, 0x10000 ;установить счетчик тайм-аута -@@TestRS: - in AL,DX ;прочитать регистр RS - and AL,0C0h ;выделить разряды 6 и 7 - cmp AL,80h ;проверить разряды 6 и 7 - je @@OutByteToFDC - loop @@TestRS -; Ошибка тайм-аута - mov [FDC_Status],FDC_TimeOut - jmp @@End_5 -; Вывести байт в порт данных -@@OutByteToFDC: - inc DX - mov AL,AH - out DX,AL -@@End_5: -; popa - pop edx ecx eax - ret - -;****************************************** -;* ПРОЧИТАТЬ БАЙТ ИЗ ПОРТА ДАННЫХ FDC * -;* Процедура не имеет входных параметров. * -;* Выходные данные: * -;* AL - считанный байт. * -;****************************************** -FDCDataInput: - push ECX - push DX -; Сбросить переменную состояния контроллера - mov [FDC_Status],FDC_Normal -; Проверить готовность контроллера к передаче данных - mov DX,3F4h ;(порт состояния FDC) - xor CX,CX ;установить счетчик тайм-аута -@@TestRS_1: - in AL,DX ;прочитать регистр RS - and AL,0C0h ;выдлить разряды 6 и 7 - cmp AL,0C0h ;проверить разряды 6 и 7 - je @@GetByteFromFDC - loop @@TestRS_1 -; Ошибка тайм-аута - mov [FDC_Status],FDC_TimeOut - jmp @@End_6 -; Ввести байт из порта данных -@@GetByteFromFDC: - inc DX - in AL,DX -@@End_6: pop DX - pop ECX - ret - -;********************************************* -;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД * -;********************************************* -FDCInterrupt: -; Установить флаг прерывани - mov [FDD_IntFlag],1 - ret - - -;****************************************** -;* УСТАНОВИТЬ НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЙ * -;* НГМД * -;****************************************** -SetUserInterrupts: - mov [fdc_irq_func],FDCInterrupt - ret - -;******************************************* -;* ОЖИДАНИЕ ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД * -;******************************************* -WaitFDCInterrupt: - pusha -; Сбросить байт состояния операции - mov [FDC_Status],FDC_Normal -; Сбросить флаг прерывани - mov [FDD_IntFlag],0 -; Обнулить счетчик тиков - mov eax,[timer_ticks] - mov [TickCounter],eax -; Ожидать установки флага прерывания НГМД -@@TestRS_2: - cmp [FDD_IntFlag],0 - jnz @@End_7 ;прерывание произошло - call change_task - mov eax,[timer_ticks] - sub eax,[TickCounter] - cmp eax,50 ;25 ;5 ;ожидать 5 тиков - jb @@TestRS_2 -; jl @@TestRS_2 -; Ошибка тайм-аута - mov [FDC_Status],FDC_TimeOut -; mov [flp_status],0 -@@End_7: popa - ret - -;********************************* -;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" * -;********************************* -FDDMotorON: - pusha -; cmp [fdd_motor_status],1 -; je fdd_motor_on - mov al,[flp_number] - cmp [fdd_motor_status],al - je fdd_motor_on -; Произвести сброс контроллера НГМД - mov DX,3F2h ;порт управления двигателями - mov AL,0 - out DX,AL -; Выбрать и включить мотор дисковода - cmp [flp_number],1 - jne FDDMotorON_B -; call FDDMotorOFF_B - mov AL,1Ch ; Floppy A - jmp FDDMotorON_1 -FDDMotorON_B: -; call FDDMotorOFF_A - mov AL,2Dh ; Floppy B -FDDMotorON_1: - out DX,AL -; Обнулить счетчик тиков - mov eax,[timer_ticks] - mov [TickCounter],eax -; Ожидать 0,5 с -@@dT: - call change_task - mov eax,[timer_ticks] - sub eax,[TickCounter] - cmp eax,50 ;10 - jb @@dT - cmp [flp_number],1 - jne fdd_motor_on_B - mov [fdd_motor_status],1 - jmp fdd_motor_on -fdd_motor_on_B: - mov [fdd_motor_status],2 -fdd_motor_on: - call save_timer_fdd_motor - popa - ret - -;***************************************** -;* СОХРАНЕНИЕ УКАЗАТЕЛЯ ВРЕМЕНИ * -;***************************************** -save_timer_fdd_motor: - mov eax,[timer_ticks] - mov [timer_fdd_motor],eax - ret - -;***************************************** -;* ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА * -;***************************************** -align 4 -check_fdd_motor_status: - cmp [fdd_motor_status],0 - je end_check_fdd_motor_status_1 - mov eax,[timer_ticks] - sub eax,[timer_fdd_motor] - cmp eax,500 - jb end_check_fdd_motor_status - call FDDMotorOFF - mov [fdd_motor_status],0 -end_check_fdd_motor_status_1: - mov [flp_status],0 -end_check_fdd_motor_status: - ret - -;********************************** -;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА * -;********************************** -FDDMotorOFF: - push AX - push DX - cmp [flp_number],1 - jne FDDMotorOFF_1 - call FDDMotorOFF_A - jmp FDDMotorOFF_2 -FDDMotorOFF_1: - call FDDMotorOFF_B -FDDMotorOFF_2: - pop DX - pop AX - ; сброс флагов кеширования в связи с устареванием информации - mov [root_read],0 - mov [flp_fat],0 - ret - -FDDMotorOFF_A: - mov DX,3F2h ;порт управления двигателями - mov AL,0Ch ; Floppy A - out DX,AL - ret - -FDDMotorOFF_B: - mov DX,3F2h ;порт управления двигателями - mov AL,5h ; Floppy B - out DX,AL - ret - -;******************************* -;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" * -;******************************* -RecalibrateFDD: - pusha - call save_timer_fdd_motor -; Подать команду "Рекалибровка" - mov AL,07h - call FDCDataOutput - mov AL,00h - call FDCDataOutput -; Ожидать завершения операции - call WaitFDCInterrupt -; cmp [FDC_Status],0 -; je no_fdc_status_error -; mov [flp_status],0 -;no_fdc_status_error: - call save_timer_fdd_motor - popa - ret - -;***************************************************** -;* ПОИСК ДОРОЖКИ * -;* Параметры передаются через глобальные переменные: * -;* FDD_Track - номер дорожки (0-79); * -;* FDD_Head - номер головки (0-1). * -;* Результат операции заносится в FDC_Status. * -;***************************************************** -SeekTrack: - pusha - call save_timer_fdd_motor -; Подать команду "Поиск" - mov AL,0Fh - call FDCDataOutput - ; Передать байт номера головки/накопител - mov AL,[FDD_Head] - shl AL,2 - call FDCDataOutput - ; Передать байт номера дорожки - mov AL,[FDD_Track] - call FDCDataOutput -; Ожидать завершения операции - call WaitFDCInterrupt - cmp [FDC_Status],FDC_Normal - jne @@Exit -; Сохранить результат поиска - mov AL,08h - call FDCDataOutput - call FDCDataInput - mov [FDC_ST0],AL - call FDCDataInput - mov [FDC_C],AL -; Проверить результат поиска - ; Поиск завершен? - test [FDC_ST0],100000b - je @@Err - ; Заданный трек найден? - mov AL,[FDC_C] - cmp AL,[FDD_Track] - jne @@Err - ; Номер головки совпадает с заданным? - mov AL,[FDC_ST0] - and AL,100b - shr AL,2 - cmp AL,[FDD_Head] - jne @@Err - ; Операция завершена успешно - mov [FDC_Status],FDC_Normal - jmp @@Exit -@@Err: ; Трек не найден - mov [FDC_Status],FDC_TrackNotFound -; mov [flp_status],0 -@@Exit: - call save_timer_fdd_motor - popa - ret - -;******************************************************* -;* ЧТЕНИЕ СЕКТОРА ДАННЫХ * -;* Параметры передаются через глобальные переменные: * -;* FDD_Track - номер дорожки (0-79); * -;* FDD_Head - номер головки (0-1); * -;* FDD_Sector - номер сектора (1-18). * -;* Результат операции заносится в FDC_Status. * -;* В случае успешного выполнения операции чтения * -;* содержимое сектора будет занесено в FDD_DataBuffer. * -;******************************************************* -ReadSector: - pushad - call save_timer_fdd_motor -; Установить скорость передачи 500 Кбайт/с - mov AX,0 - mov DX,03F7h - out DX,AL -; Инициализировать канал прямого доступа к памяти - mov [dmamode],0x46 - call Init_FDC_DMA -; Подать команду "Чтение данных" - mov AL,0E6h ;чтение в мультитрековом режиме - call FDCDataOutput - mov AL,[FDD_Head] - shl AL,2 - call FDCDataOutput - mov AL,[FDD_Track] - call FDCDataOutput - mov AL,[FDD_Head] - call FDCDataOutput - mov AL,[FDD_Sector] - call FDCDataOutput - mov AL,2 ;код размера сектора (512 байт) - call FDCDataOutput - mov AL,18 ;+1; 3Fh ;число секторов на дорожке - call FDCDataOutput - mov AL,1Bh ;значение GPL - call FDCDataOutput - mov AL,0FFh ;значение DTL - call FDCDataOutput -; Ожидаем прерывание по завершении операции - call WaitFDCInterrupt - cmp [FDC_Status],FDC_Normal - jne @@Exit_1 -; Считываем статус завершения операции - call GetStatusInfo - test [FDC_ST0],11011000b - jnz @@Err_1 - mov [FDC_Status],FDC_Normal - jmp @@Exit_1 -@@Err_1: mov [FDC_Status],FDC_SectorNotFound -; mov [flp_status],0 -@@Exit_1: - call save_timer_fdd_motor - popad - ret - -;******************************************************* -;* ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) * -;* Параметры передаются через глобальные переменные: * -;* FDD_Track - номер дорожки (0-79); * -;* FDD_Head - номер головки (0-1); * -;* FDD_Sector - номер сектора (1-18). * -;* Результат операции заносится в FDC_Status. * -;* В случае успешного выполнения операции чтения * -;* содержимое сектора будет занесено в FDD_DataBuffer. * -;******************************************************* -ReadSectWithRetr: - pusha -; Обнулить счетчик повторения операции рекалибровки - mov [RecalRepCounter],0 -@@TryAgain: -; Обнулить счетчик повторения операции чтени - mov [ReadRepCounter],0 -@@ReadSector_1: - call ReadSector - cmp [FDC_Status],0 - je @@Exit_2 - cmp [FDC_Status],1 - je @@Err_3 - ; Троекратное повторение чтени - inc [ReadRepCounter] - cmp [ReadRepCounter],3 - jb @@ReadSector_1 - ; Троекратное повторение рекалибровки - call RecalibrateFDD - call SeekTrack - inc [RecalRepCounter] - cmp [RecalRepCounter],3 - jb @@TryAgain -; mov [flp_status],0 -@@Exit_2: - popa - ret -@@Err_3: - mov [flp_status],0 - popa - ret - -;******************************************************* -;* ЗАПИСЬ СЕКТОРА ДАННЫХ * -;* Параметры передаются через глобальные переменные: * -;* FDD_Track - номер дорожки (0-79); * -;* FDD_Head - номер головки (0-1); * -;* FDD_Sector - номер сектора (1-18). * -;* Результат операции заносится в FDC_Status. * -;* В случае успешного выполнения операции записи * -;* содержимое FDD_DataBuffer будет занесено в сектор. * -;******************************************************* -WriteSector: - pushad - call save_timer_fdd_motor -; Установить скорость передачи 500 Кбайт/с - mov AX,0 - mov DX,03F7h - out DX,AL -; Инициализировать канал прямого доступа к памяти - mov [dmamode],0x4A - call Init_FDC_DMA -; Подать команду "Запись данных" - mov AL,0xC5 ;0x45 ;запись в мультитрековом режиме - call FDCDataOutput - mov AL,[FDD_Head] - shl AL,2 - call FDCDataOutput - mov AL,[FDD_Track] - call FDCDataOutput - mov AL,[FDD_Head] - call FDCDataOutput - mov AL,[FDD_Sector] - call FDCDataOutput - mov AL,2 ;код размера сектора (512 байт) - call FDCDataOutput - mov AL,18; 3Fh ;число секторов на дорожке - call FDCDataOutput - mov AL,1Bh ;значение GPL - call FDCDataOutput - mov AL,0FFh ;значение DTL - call FDCDataOutput -; Ожидаем прерывание по завершении операции - call WaitFDCInterrupt - cmp [FDC_Status],FDC_Normal - jne @@Exit_3 -; Считываем статус завершения операции - call GetStatusInfo - test [FDC_ST0],11000000b ;11011000b - jnz @@Err_2 - mov [FDC_Status],FDC_Normal - jmp @@Exit_3 -@@Err_2: mov [FDC_Status],FDC_SectorNotFound -@@Exit_3: - call save_timer_fdd_motor - popad - ret - -;******************************************************* -;* ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) * -;* Параметры передаются через глобальные переменные: * -;* FDD_Track - номер дорожки (0-79); * -;* FDD_Head - номер головки (0-1); * -;* FDD_Sector - номер сектора (1-18). * -;* Результат операции заносится в FDC_Status. * -;* В случае успешного выполнения операции записи * -;* содержимое FDD_DataBuffer будет занесено в сектор. * -;******************************************************* -WriteSectWithRetr: - pusha -; Обнулить счетчик повторения операции рекалибровки - mov [RecalRepCounter],0 -@@TryAgain_1: -; Обнулить счетчик повторения операции чтени - mov [ReadRepCounter],0 -@@WriteSector_1: - call WriteSector - cmp [FDC_Status],0 - je @@Exit_4 - cmp [FDC_Status],1 - je @@Err_4 - ; Троекратное повторение чтени - inc [ReadRepCounter] - cmp [ReadRepCounter],3 - jb @@WriteSector_1 - ; Троекратное повторение рекалибровки - call RecalibrateFDD - call SeekTrack - inc [RecalRepCounter] - cmp [RecalRepCounter],3 - jb @@TryAgain_1 -@@Exit_4: - popa - ret -@@Err_4: - mov [flp_status],0 - popa - ret - -;********************************************* -;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ * -;********************************************* -GetStatusInfo: - push AX - call FDCDataInput - mov [FDC_ST0],AL - call FDCDataInput - mov [FDC_ST1],AL - call FDCDataInput - mov [FDC_ST2],AL - call FDCDataInput - mov [FDC_C],AL - call FDCDataInput - mov [FDC_H],AL - call FDCDataInput - mov [FDC_R],AL - call FDCDataInput - mov [FDC_N],AL - pop AX - ret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;********************************************************** +; Непосредственная работа с контроллером гибкого диска +;********************************************************** +; Автор исходного текста Кулаков Владимир Геннадьевич. +; Адаптация и доработка Mario79 + +;give_back_application_data: ; переслать приложению +; mov edi,[TASK_BASE] +; mov edi,[edi+TASKDATA.mem_start] +; add edi,ecx +give_back_application_data_1: + mov esi, FDD_BUFF;FDD_DataBuffer ;0x40000 + xor ecx, ecx + mov cx, 128 + cld + rep movsd + ret + +;take_data_from_application: ; взять из приложени +; mov esi,[TASK_BASE] +; mov esi,[esi+TASKDATA.mem_start] +; add esi,ecx +take_data_from_application_1: + mov edi, FDD_BUFF;FDD_DataBuffer ;0x40000 + xor ecx, ecx + mov cx, 128 + cld + rep movsd + ret + +; Коды завершения операции с контроллером (FDC_Status) +FDC_Normal equ 0 ;нормальное завершение +FDC_TimeOut equ 1 ;ошибка тайм-аута +FDC_DiskNotFound equ 2 ;в дисководе нет диска +FDC_TrackNotFound equ 3 ;дорожка не найдена +FDC_SectorNotFound equ 4 ;сектор не найден + +; Максимальные значения координат сектора (заданные +; значения соответствуют параметрам стандартного +; трехдюймового гибкого диска объемом 1,44 Мб) +MAX_Track equ 79 +MAX_Head equ 1 +MAX_Sector equ 18 + +uglobal +; Счетчик тиков таймера +TickCounter dd ? +; Код завершения операции с контроллером НГМД +FDC_Status DB ? +; Флаг прерывания от НГМД +FDD_IntFlag DB ? +; Момент начала последней операции с НГМД +FDD_Time DD ? +; Номер дисковода +FDD_Type db 0 +; Координаты сектора +FDD_Track DB ? +FDD_Head DB ? +FDD_Sector DB ? + +; Блок результата операции +FDC_ST0 DB ? +FDC_ST1 DB ? +FDC_ST2 DB ? +FDC_C DB ? +FDC_H DB ? +FDC_R DB ? +FDC_N DB ? +; Счетчик повторения операции чтени +ReadRepCounter DB ? +; Счетчик повторения операции рекалибровки +RecalRepCounter DB ? +endg +; Область памяти для хранения прочитанного сектора +;FDD_DataBuffer: times 512 db 0 ;DB 512 DUP (?) +fdd_motor_status db 0 +timer_fdd_motor dd 0 + +;************************************* +;* ИНИЦИАЛИЗАЦИЯ РЕЖИМА ПДП ДЛЯ НГМД * +;************************************* +Init_FDC_DMA: + pushad + mov al, 0 + out 0x0c, al; reset the flip-flop to a known state. + mov al, 6 ; mask channel 2 so we can reprogram it. + out 0x0a, al + mov al, [dmamode]; 0x46 -> Read from floppy - 0x4A Write to floppy + out 0x0b, al + mov al, 0 + out 0x0c, al; reset the flip-flop to a known state. + mov eax, 0xD000 + out 0x04, al; set the channel 2 starting address to 0 + shr eax, 8 + out 0x04, al + shr eax, 8 + out 0x81, al + mov al, 0 + out 0x0c, al; reset flip-flop + mov al, 0xff;set count (actual size -1) + out 0x5, al + mov al, 0x1;[dmasize] ;(0x1ff = 511 / 0x23ff =9215) + out 0x5, al + mov al, 2 + out 0xa, al + popad + ret + +;*********************************** +;* ЗАПИСАТЬ БАЙТ В ПОРТ ДАННЫХ FDC * +;* Параметры: * +;* AL - выводимый байт. * +;*********************************** +FDCDataOutput: +; pusha + push eax ecx edx + mov AH, AL ;запомнить байт в AH +; Сбросить переменную состояния контроллера + mov [FDC_Status], FDC_Normal +; Проверить готовность контроллера к приему данных + mov DX, 3F4h ;(порт состояния FDC) + mov ecx, 0x10000 ;установить счетчик тайм-аута +@@TestRS: + in AL, DX ;прочитать регистр RS + and AL, 0C0h ;выделить разряды 6 и 7 + cmp AL, 80h ;проверить разряды 6 и 7 + je @@OutByteToFDC + loop @@TestRS +; Ошибка тайм-аута + mov [FDC_Status], FDC_TimeOut + jmp @@End_5 +; Вывести байт в порт данных +@@OutByteToFDC: + inc DX + mov AL, AH + out DX, AL +@@End_5: +; popa + pop edx ecx eax + ret + +;****************************************** +;* ПРОЧИТАТЬ БАЙТ ИЗ ПОРТА ДАННЫХ FDC * +;* Процедура не имеет входных параметров. * +;* Выходные данные: * +;* AL - считанный байт. * +;****************************************** +FDCDataInput: + push ECX + push DX +; Сбросить переменную состояния контроллера + mov [FDC_Status], FDC_Normal +; Проверить готовность контроллера к передаче данных + mov DX, 3F4h ;(порт состояния FDC) + xor CX, CX ;установить счетчик тайм-аута +@@TestRS_1: + in AL, DX ;прочитать регистр RS + and AL, 0C0h ;выдлить разряды 6 и 7 + cmp AL, 0C0h ;проверить разряды 6 и 7 + je @@GetByteFromFDC + loop @@TestRS_1 +; Ошибка тайм-аута + mov [FDC_Status], FDC_TimeOut + jmp @@End_6 +; Ввести байт из порта данных +@@GetByteFromFDC: + inc DX + in AL, DX +@@End_6: + pop DX + pop ECX + ret + +;********************************************* +;* ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД * +;********************************************* +FDCInterrupt: +; Установить флаг прерывани + mov [FDD_IntFlag], 1 + ret + + +;****************************************** +;* УСТАНОВИТЬ НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЙ * +;* НГМД * +;****************************************** +SetUserInterrupts: + mov [fdc_irq_func], FDCInterrupt + ret + +;******************************************* +;* ОЖИДАНИЕ ПРЕРЫВАНИЯ ОТ КОНТРОЛЛЕРА НГМД * +;******************************************* +WaitFDCInterrupt: + pusha +; Сбросить байт состояния операции + mov [FDC_Status], FDC_Normal +; Сбросить флаг прерывани + mov [FDD_IntFlag], 0 +; Обнулить счетчик тиков + mov eax, [timer_ticks] + mov [TickCounter], eax +; Ожидать установки флага прерывания НГМД +@@TestRS_2: + cmp [FDD_IntFlag], 0 + jnz @@End_7 ;прерывание произошло + call change_task + mov eax, [timer_ticks] + sub eax, [TickCounter] + cmp eax, 50 ;25 ;5 ;ожидать 5 тиков + jb @@TestRS_2 +; jl @@TestRS_2 +; Ошибка тайм-аута + mov [FDC_Status], FDC_TimeOut +; mov [flp_status],0 +@@End_7: + popa + ret + +;********************************* +;* ВКЛЮЧИТЬ МОТОР ДИСКОВОДА "A:" * +;********************************* +FDDMotorON: + pusha +; cmp [fdd_motor_status],1 +; je fdd_motor_on + mov al, [flp_number] + cmp [fdd_motor_status], al + je fdd_motor_on +; Произвести сброс контроллера НГМД + mov DX, 3F2h;порт управления двигателями + mov AL, 0 + out DX, AL +; Выбрать и включить мотор дисковода + cmp [flp_number], 1 + jne FDDMotorON_B +; call FDDMotorOFF_B + mov AL, 1Ch ; Floppy A + jmp FDDMotorON_1 +FDDMotorON_B: +; call FDDMotorOFF_A + mov AL, 2Dh ; Floppy B +FDDMotorON_1: + out DX, AL +; Обнулить счетчик тиков + mov eax, [timer_ticks] + mov [TickCounter], eax +; Ожидать 0,5 с +@@dT: + call change_task + mov eax, [timer_ticks] + sub eax, [TickCounter] + cmp eax, 50 ;10 + jb @@dT + cmp [flp_number], 1 + jne fdd_motor_on_B + mov [fdd_motor_status], 1 + jmp fdd_motor_on +fdd_motor_on_B: + mov [fdd_motor_status], 2 +fdd_motor_on: + call save_timer_fdd_motor + popa + ret + +;***************************************** +;* СОХРАНЕНИЕ УКАЗАТЕЛЯ ВРЕМЕНИ * +;***************************************** +save_timer_fdd_motor: + mov eax, [timer_ticks] + mov [timer_fdd_motor], eax + ret + +;***************************************** +;* ПРОВЕРКА ЗАДЕРЖКИ ВЫКЛЮЧЕНИЯ МОТОРА * +;***************************************** +align 4 +check_fdd_motor_status: + cmp [fdd_motor_status], 0 + je end_check_fdd_motor_status_1 + mov eax, [timer_ticks] + sub eax, [timer_fdd_motor] + cmp eax, 500 + jb end_check_fdd_motor_status + call FDDMotorOFF + mov [fdd_motor_status], 0 +end_check_fdd_motor_status_1: + mov [flp_status], 0 +end_check_fdd_motor_status: + ret + +;********************************** +;* ВЫКЛЮЧИТЬ МОТОР ДИСКОВОДА * +;********************************** +FDDMotorOFF: + push AX + push DX + cmp [flp_number], 1 + jne FDDMotorOFF_1 + call FDDMotorOFF_A + jmp FDDMotorOFF_2 +FDDMotorOFF_1: + call FDDMotorOFF_B +FDDMotorOFF_2: + pop DX + pop AX + ; сброс флагов кеширования в связи с устареванием информации + mov [root_read], 0 + mov [flp_fat], 0 + ret + +FDDMotorOFF_A: + mov DX, 3F2h;порт управления двигателями + mov AL, 0Ch ; Floppy A + out DX, AL + ret + +FDDMotorOFF_B: + mov DX, 3F2h;порт управления двигателями + mov AL, 5h ; Floppy B + out DX, AL + ret + +;******************************* +;* РЕКАЛИБРОВКА ДИСКОВОДА "A:" * +;******************************* +RecalibrateFDD: + pusha + call save_timer_fdd_motor +; Подать команду "Рекалибровка" + mov AL, 07h + call FDCDataOutput + mov AL, 00h + call FDCDataOutput +; Ожидать завершения операции + call WaitFDCInterrupt +; cmp [FDC_Status],0 +; je no_fdc_status_error +; mov [flp_status],0 +;no_fdc_status_error: + call save_timer_fdd_motor + popa + ret + +;***************************************************** +;* ПОИСК ДОРОЖКИ * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1). * +;* Результат операции заносится в FDC_Status. * +;***************************************************** +SeekTrack: + pusha + call save_timer_fdd_motor +; Подать команду "Поиск" + mov AL, 0Fh + call FDCDataOutput + ; Передать байт номера головки/накопител + mov AL, [FDD_Head] + shl AL, 2 + call FDCDataOutput + ; Передать байт номера дорожки + mov AL, [FDD_Track] + call FDCDataOutput +; Ожидать завершения операции + call WaitFDCInterrupt + cmp [FDC_Status], FDC_Normal + jne @@Exit +; Сохранить результат поиска + mov AL, 08h + call FDCDataOutput + call FDCDataInput + mov [FDC_ST0], AL + call FDCDataInput + mov [FDC_C], AL +; Проверить результат поиска + ; Поиск завершен? + test [FDC_ST0], 100000b + je @@Err + ; Заданный трек найден? + mov AL, [FDC_C] + cmp AL, [FDD_Track] + jne @@Err + ; Номер головки совпадает с заданным? + mov AL, [FDC_ST0] + and AL, 100b + shr AL, 2 + cmp AL, [FDD_Head] + jne @@Err + ; Операция завершена успешно + mov [FDC_Status], FDC_Normal + jmp @@Exit +@@Err: ; Трек не найден + mov [FDC_Status], FDC_TrackNotFound +; mov [flp_status],0 +@@Exit: + call save_timer_fdd_motor + popa + ret + +;******************************************************* +;* ЧТЕНИЕ СЕКТОРА ДАННЫХ * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции чтения * +;* содержимое сектора будет занесено в FDD_DataBuffer. * +;******************************************************* +ReadSector: + pushad + call save_timer_fdd_motor +; Установить скорость передачи 500 Кбайт/с + mov AX, 0 + mov DX, 03F7h + out DX, AL +; Инициализировать канал прямого доступа к памяти + mov [dmamode], 0x46 + call Init_FDC_DMA +; Подать команду "Чтение данных" + mov AL, 0E6h ;чтение в мультитрековом режиме + call FDCDataOutput + mov AL, [FDD_Head] + shl AL, 2 + call FDCDataOutput + mov AL, [FDD_Track] + call FDCDataOutput + mov AL, [FDD_Head] + call FDCDataOutput + mov AL, [FDD_Sector] + call FDCDataOutput + mov AL, 2 ;код размера сектора (512 байт) + call FDCDataOutput + mov AL, 18 ;+1; 3Fh ;число секторов на дорожке + call FDCDataOutput + mov AL, 1Bh ;значение GPL + call FDCDataOutput + mov AL, 0FFh;значение DTL + call FDCDataOutput +; Ожидаем прерывание по завершении операции + call WaitFDCInterrupt + cmp [FDC_Status], FDC_Normal + jne @@Exit_1 +; Считываем статус завершения операции + call GetStatusInfo + test [FDC_ST0], 11011000b + jnz @@Err_1 + mov [FDC_Status], FDC_Normal + jmp @@Exit_1 +@@Err_1: + mov [FDC_Status], FDC_SectorNotFound +; mov [flp_status],0 +@@Exit_1: + call save_timer_fdd_motor + popad + ret + +;******************************************************* +;* ЧТЕНИЕ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции чтения * +;* содержимое сектора будет занесено в FDD_DataBuffer. * +;******************************************************* +ReadSectWithRetr: + pusha +; Обнулить счетчик повторения операции рекалибровки + mov [RecalRepCounter], 0 +@@TryAgain: +; Обнулить счетчик повторения операции чтени + mov [ReadRepCounter], 0 +@@ReadSector_1: + call ReadSector + cmp [FDC_Status], 0 + je @@Exit_2 + cmp [FDC_Status], 1 + je @@Err_3 + ; Троекратное повторение чтени + inc [ReadRepCounter] + cmp [ReadRepCounter], 3 + jb @@ReadSector_1 + ; Троекратное повторение рекалибровки + call RecalibrateFDD + call SeekTrack + inc [RecalRepCounter] + cmp [RecalRepCounter], 3 + jb @@TryAgain +; mov [flp_status],0 +@@Exit_2: + popa + ret +@@Err_3: + mov [flp_status], 0 + popa + ret + +;******************************************************* +;* ЗАПИСЬ СЕКТОРА ДАННЫХ * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции записи * +;* содержимое FDD_DataBuffer будет занесено в сектор. * +;******************************************************* +WriteSector: + pushad + call save_timer_fdd_motor +; Установить скорость передачи 500 Кбайт/с + mov AX, 0 + mov DX, 03F7h + out DX, AL +; Инициализировать канал прямого доступа к памяти + mov [dmamode], 0x4A + call Init_FDC_DMA +; Подать команду "Запись данных" + mov AL, 0xC5 ;0x45 ;запись в мультитрековом режиме + call FDCDataOutput + mov AL, [FDD_Head] + shl AL, 2 + call FDCDataOutput + mov AL, [FDD_Track] + call FDCDataOutput + mov AL, [FDD_Head] + call FDCDataOutput + mov AL, [FDD_Sector] + call FDCDataOutput + mov AL, 2 ;код размера сектора (512 байт) + call FDCDataOutput + mov AL, 18; 3Fh ;число секторов на дорожке + call FDCDataOutput + mov AL, 1Bh ;значение GPL + call FDCDataOutput + mov AL, 0FFh;значение DTL + call FDCDataOutput +; Ожидаем прерывание по завершении операции + call WaitFDCInterrupt + cmp [FDC_Status], FDC_Normal + jne @@Exit_3 +; Считываем статус завершения операции + call GetStatusInfo + test [FDC_ST0], 11000000b ;11011000b + jnz @@Err_2 + mov [FDC_Status], FDC_Normal + jmp @@Exit_3 +@@Err_2: + mov [FDC_Status], FDC_SectorNotFound +@@Exit_3: + call save_timer_fdd_motor + popad + ret + +;******************************************************* +;* ЗАПИСЬ СЕКТОРА (С ПОВТОРЕНИЕМ ОПЕРАЦИИ ПРИ СБОЕ) * +;* Параметры передаются через глобальные переменные: * +;* FDD_Track - номер дорожки (0-79); * +;* FDD_Head - номер головки (0-1); * +;* FDD_Sector - номер сектора (1-18). * +;* Результат операции заносится в FDC_Status. * +;* В случае успешного выполнения операции записи * +;* содержимое FDD_DataBuffer будет занесено в сектор. * +;******************************************************* +WriteSectWithRetr: + pusha +; Обнулить счетчик повторения операции рекалибровки + mov [RecalRepCounter], 0 +@@TryAgain_1: +; Обнулить счетчик повторения операции чтени + mov [ReadRepCounter], 0 +@@WriteSector_1: + call WriteSector + cmp [FDC_Status], 0 + je @@Exit_4 + cmp [FDC_Status], 1 + je @@Err_4 + ; Троекратное повторение чтени + inc [ReadRepCounter] + cmp [ReadRepCounter], 3 + jb @@WriteSector_1 + ; Троекратное повторение рекалибровки + call RecalibrateFDD + call SeekTrack + inc [RecalRepCounter] + cmp [RecalRepCounter], 3 + jb @@TryAgain_1 +@@Exit_4: + popa + ret +@@Err_4: + mov [flp_status], 0 + popa + ret + +;********************************************* +;* ПОЛУЧИТЬ ИНФОРМАЦИЮ О РЕЗУЛЬТАТЕ ОПЕРАЦИИ * +;********************************************* +GetStatusInfo: + push AX + call FDCDataInput + mov [FDC_ST0], AL + call FDCDataInput + mov [FDC_ST1], AL + call FDCDataInput + mov [FDC_ST2], AL + call FDCDataInput + mov [FDC_C], AL + call FDCDataInput + mov [FDC_H], AL + call FDCDataInput + mov [FDC_R], AL + call FDCDataInput + mov [FDC_N], AL + pop AX + ret + diff --git a/kernel/trunk/blkdev/hd_drv.inc b/kernel/trunk/blkdev/hd_drv.inc index ab5af9362..bd99cac72 100644 --- a/kernel/trunk/blkdev/hd_drv.inc +++ b/kernel/trunk/blkdev/hd_drv.inc @@ -1,947 +1,947 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; Low-level driver for HDD access -; DMA support by Mario79 -; Access through BIOS by diamond - -align 4 -hd_read: -;----------------------------------------------------------- -; input : eax = block to read -; ebx = destination -;----------------------------------------------------------- - and [hd_error], 0 - push ecx esi edi ; scan cache - -; mov ecx,cache_max ; entries in cache -; mov esi,HD_CACHE+8 - call calculate_cache - add esi,8 - - mov edi,1 - - hdreadcache: - - cmp dword [esi+4],0 ; empty - je nohdcache - - cmp [esi],eax ; correct sector - je yeshdcache - - nohdcache: - - add esi,8 - inc edi - dec ecx - jnz hdreadcache - - call find_empty_slot ; ret in edi - cmp [hd_error],0 - jne return_01 -; Read through BIOS? - cmp [hdpos], 0x80 - jae .bios -; hd_read_{dma,pio} use old ATA with 28 bit for sector number - cmp eax, 0x10000000 - jb @f - inc [hd_error] - jmp return_01 -@@: -; DMA read is permitted if [allow_dma_access]=1 or 2 - cmp [allow_dma_access], 2 - ja .nodma - cmp [dma_hdd], 1 - jnz .nodma - call hd_read_dma - jmp @f -.nodma: - call hd_read_pio - jmp @f -.bios: - call bd_read -@@: - cmp [hd_error], 0 - jne return_01 -; lea esi,[edi*8+HD_CACHE] -; push eax - call calculate_cache_1 - lea esi,[edi*8+esi] -; pop eax - - mov [esi],eax ; sector number - mov dword [esi+4],1 ; hd read - mark as same as in hd - - yeshdcache: - - mov esi,edi - shl esi,9 -; add esi,HD_CACHE+65536 - push eax - call calculate_cache_2 - add esi,eax - pop eax - - mov edi,ebx - mov ecx,512/4 - cld - rep movsd ; move data - return_01: - pop edi esi ecx - ret - -align 4 -hd_read_pio: - push eax edx - - call wait_for_hd_idle - cmp [hd_error],0 - jne hd_read_error - - cli - xor eax,eax - mov edx,[hdbase] - inc edx - out dx,al ; ATAFeatures ॣЁбва "®б®ЎҐ­­®б⥩" - inc edx - inc eax - out dx,al ; ATASectorCount бзсвзЁЄ ᥪв®а®ў - inc edx - mov eax,[esp+4] - out dx,al ; ATASectorNumber ॣЁбва ­®¬Ґа  ᥪв®а  - shr eax,8 - inc edx - out dx,al ; ATACylinder ­®¬Ґа жЁ«Ё­¤а  (¬« ¤иЁ© Ў ©в) - shr eax,8 - inc edx - out dx,al ; ­®¬Ґа жЁ«Ё­¤а  (бв аиЁ© Ў ©в) - shr eax,8 - inc edx - and al,1+2+4+8 - add al,byte [hdid] - add al,128+64+32 - out dx,al ; ­®¬Ґа Ј®«®ўЄЁ/­®¬Ґа ¤ЁбЄ  - inc edx - mov al,20h - out dx,al ; ATACommand ॣЁбва Є®¬ ­¤ - sti - - call wait_for_sector_buffer - - cmp [hd_error],0 - jne hd_read_error - - cli - push edi - shl edi,9 -; add edi,HD_CACHE+65536 - push eax - call calculate_cache_2 - add edi,eax - pop eax - - mov ecx,256 - mov edx,[hdbase] - cld - rep insw - pop edi - sti - - pop edx eax - ret - -disable_ide_int: -; mov edx,[hdbase] -; add edx,0x206 -; mov al,2 -; out dx,al - cli - ret - -enable_ide_int: -; mov edx,[hdbase] -; add edx,0x206 -; mov al,0 -; out dx,al - sti - ret - -align 4 -hd_write: -;----------------------------------------------------------- -; input : eax = block -; ebx = pointer to memory -;----------------------------------------------------------- - push ecx esi edi - - ; check if the cache already has the sector and overwrite it - -; mov ecx,cache_max -; mov esi,HD_CACHE+8 - call calculate_cache - add esi,8 - - mov edi,1 - - hdwritecache: - - cmp dword [esi+4],0 ; if cache slot is empty - je not_in_cache_write - - cmp [esi],eax ; if the slot has the sector - je yes_in_cache_write - - not_in_cache_write: - - add esi,8 - inc edi - dec ecx - jnz hdwritecache - - ; sector not found in cache - ; write the block to a new location - - call find_empty_slot ; ret in edi - cmp [hd_error],0 - jne hd_write_access_denied - -; lea esi,[edi*8+HD_CACHE] -; push eax - call calculate_cache_1 - lea esi,[edi*8+esi] -; pop eax - - mov [esi],eax ; sector number - - yes_in_cache_write: - - mov dword [esi+4],2 ; write - differs from hd - - shl edi,9 -; add edi,HD_CACHE+65536 - push eax - call calculate_cache_2 - add edi,eax - pop eax - - mov esi,ebx - mov ecx,512/4 - cld - rep movsd ; move data - hd_write_access_denied: - pop edi esi ecx - ret - -align 4 -cache_write_pio: - cmp dword[esi],0x10000000 - jae .bad -; call disable_ide_int - - call wait_for_hd_idle - cmp [hd_error],0 - jne hd_write_error - - cli - xor eax,eax - mov edx,[hdbase] - inc edx - out dx,al - inc edx - inc eax - out dx,al - inc edx - mov eax,[esi] ; eax = sector to write - out dx,al - shr eax,8 - inc edx - out dx,al - shr eax,8 - inc edx - out dx,al - shr eax,8 - inc edx - and al,1+2+4+8 - add al,byte [hdid] - add al,128+64+32 - out dx,al - inc edx - mov al,30h - out dx,al - sti - - call wait_for_sector_buffer - - cmp [hd_error],0 - jne hd_write_error - - push ecx esi - - cli - mov esi,edi - shl esi,9 -; add esi,HD_CACHE+65536 ; esi = from memory position - push eax - call calculate_cache_2 - add esi,eax - pop eax - - mov ecx,256 - mov edx,[hdbase] - cld - rep outsw - sti - -; call enable_ide_int - pop esi ecx - - ret -.bad: - inc [hd_error] - ret - -save_hd_wait_timeout: - - push eax - mov eax,[timer_ticks] - add eax,300 ; 3 sec timeout - mov [hd_wait_timeout],eax - pop eax - ret - -align 4 -check_hd_wait_timeout: - - push eax - mov eax,[hd_wait_timeout] - cmp [timer_ticks], eax - jg hd_timeout_error - pop eax - mov [hd_error],0 - ret - -;iglobal -; hd_timeout_str db 'K : FS - HD timeout',0 -; hd_read_str db 'K : FS - HD read error',0 -; hd_write_str db 'K : FS - HD write error',0 -; hd_lba_str db 'K : FS - HD LBA error',0 -;endg - -hd_timeout_error: - -; call clear_hd_cache -; call clear_application_table_status -; mov esi,hd_timeout_str -; call sys_msg_board_str - DEBUGF 1,"K : FS - HD timeout\n" - - mov [hd_error],1 - pop eax - ret - -hd_read_error: - -; call clear_hd_cache -; call clear_application_table_status -; mov esi,hd_read_str -; call sys_msg_board_str - DEBUGF 1,"K : FS - HD read error\n" - pop edx eax - ret - -hd_write_error: - -; call clear_hd_cache -; call clear_application_table_status -; mov esi,hd_write_str -; call sys_msg_board_str - DEBUGF 1,"K : FS - HD write error\n" - ret - -hd_write_error_dma: -; call clear_hd_cache -; call clear_application_table_status -; mov esi, hd_write_str -; call sys_msg_board_str - DEBUGF 1,"K : FS - HD read error\n" - pop esi - ret - -hd_lba_error: -; call clear_hd_cache -; call clear_application_table_status -; mov esi,hd_lba_str -; call sys_msg_board_str - DEBUGF 1,"K : FS - HD LBA error\n" - jmp LBA_read_ret - - -align 4 -wait_for_hd_idle: - - push eax edx - - call save_hd_wait_timeout - - mov edx,[hdbase] - add edx,0x7 - - wfhil1: - - call check_hd_wait_timeout - cmp [hd_error],0 - jne @f - - in al,dx - test al,128 - jnz wfhil1 - - @@: - - pop edx eax - ret - - -align 4 -wait_for_sector_buffer: - - push eax edx - - mov edx,[hdbase] - add edx,0x7 - - call save_hd_wait_timeout - - hdwait_sbuf: ; wait for sector buffer to be ready - - call check_hd_wait_timeout - cmp [hd_error],0 - jne @f - - in al,dx - test al,8 - jz hdwait_sbuf - - mov [hd_error],0 - - cmp [hd_setup],1 ; do not mark error for setup request - je buf_wait_ok - - test al,1 ; previous command ended up with an error - jz buf_wait_ok - @@: - mov [hd_error],1 - - buf_wait_ok: - - pop edx eax - ret - -; \begin{Mario79} -align 4 -wait_for_sector_dma_ide0: - push eax - push edx - call save_hd_wait_timeout -.wait: - call change_task - cmp [irq14_func], hdd_irq14 - jnz .done - call check_hd_wait_timeout - cmp [hd_error], 0 - jz .wait - mov [irq14_func], hdd_irq_null - mov dx, [IDEContrRegsBaseAddr] - mov al, 0 - out dx, al -.done: - pop edx - pop eax - ret - -align 4 -wait_for_sector_dma_ide1: - push eax - push edx - call save_hd_wait_timeout -.wait: - call change_task - cmp [irq15_func], hdd_irq15 - jnz .done - call check_hd_wait_timeout - cmp [hd_error], 0 - jz .wait - mov [irq15_func], hdd_irq_null - mov dx, [IDEContrRegsBaseAddr] - add dx, 8 - mov al, 0 - out dx, al -.done: - pop edx - pop eax - ret - -iglobal -align 4 -; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary -IDE_descriptor_table: - dd IDE_DMA - dw 0x2000 - dw 0x8000 - -dma_cur_sector dd not 40h -dma_hdpos dd 0 -irq14_func dd hdd_irq_null -irq15_func dd hdd_irq_null -endg - -uglobal -; all uglobals are zeroed at boot -dma_process dd 0 -dma_slot_ptr dd 0 -cache_chain_pos dd 0 -cache_chain_ptr dd 0 -cache_chain_size db 0 -cache_chain_started db 0 -dma_task_switched db 0 -dma_hdd db 0 -allow_dma_access db 0 -endg - -align 4 -hdd_irq14: - pushfd - cli - pushad - mov [irq14_func], hdd_irq_null - mov dx, [IDEContrRegsBaseAddr] - mov al, 0 - out dx, al -; call update_counters -; mov ebx, [dma_process] -; cmp [CURRENT_TASK], ebx -; jz .noswitch -; mov [dma_task_switched], 1 -; mov edi, [dma_slot_ptr] -; mov eax, [CURRENT_TASK] -; mov [dma_process], eax -; mov eax, [TASK_BASE] -; mov [dma_slot_ptr], eax -; mov [CURRENT_TASK], ebx -; mov [TASK_BASE], edi -; mov byte [DONT_SWITCH], 1 -; call do_change_task -.noswitch: - popad - popfd -align 4 -hdd_irq_null: - ret - -align 4 -hdd_irq15: - pushfd - cli - pushad - mov [irq15_func], hdd_irq_null - mov dx, [IDEContrRegsBaseAddr] - add dx, 8 - mov al, 0 - out dx, al -; call update_counters -; mov ebx, [dma_process] -; cmp [CURRENT_TASK], ebx -; jz .noswitch -; mov [dma_task_switched], 1 -; mov edi, [dma_slot_ptr] -; mov eax, [CURRENT_TASK] -; mov [dma_process], eax -; mov eax, [TASK_BASE] -; mov [dma_slot_ptr], eax -; mov [CURRENT_TASK], ebx -; mov [TASK_BASE], edi -; mov byte [DONT_SWITCH], 1 -; call do_change_task -.noswitch: - popad - popfd - ret - -align 4 -hd_read_dma: - push eax - push edx - mov edx,[dma_hdpos] - cmp edx,[hdpos] - jne .notread - mov edx, [dma_cur_sector] - cmp eax, edx - jb .notread - add edx, 15 - cmp [esp+4], edx - ja .notread - mov eax, [esp+4] - sub eax, [dma_cur_sector] - shl eax, 9 - add eax, (OS_BASE+IDE_DMA) - push ecx esi edi - mov esi, eax - shl edi, 9 -; add edi, HD_CACHE+0x10000 - push eax - call calculate_cache_2 - add edi,eax - pop eax - - mov ecx, 512/4 - cld - rep movsd - pop edi esi ecx - pop edx - pop eax - ret -.notread: - mov eax, IDE_descriptor_table - mov dword [eax], IDE_DMA - mov word [eax+4], 0x2000 - sub eax, OS_BASE - mov dx, [IDEContrRegsBaseAddr] - cmp [hdbase], 0x1F0 - jz @f - add edx, 8 -@@: - push edx - add edx, 4 - out dx, eax - pop edx - mov al, 0 - out dx, al - add edx, 2 - mov al, 6 - out dx, al - call wait_for_hd_idle - cmp [hd_error], 0 - jnz hd_read_error - call disable_ide_int - xor eax, eax - mov edx, [hdbase] - inc edx - out dx, al - inc edx - mov eax, 10h - out dx, al - inc edx - mov eax, [esp+4] - out dx, al - shr eax, 8 - inc edx - out dx, al - shr eax, 8 - inc edx - out dx, al - shr eax, 8 - inc edx - and al, 0xF - add al, byte [hdid] - add al, 11100000b - out dx, al - inc edx - mov al, 0xC8 - out dx, al - mov dx, [IDEContrRegsBaseAddr] - cmp [hdbase], 0x1F0 - jz @f - add dx, 8 -@@: - mov al, 9 - out dx, al - mov eax, [CURRENT_TASK] - mov [dma_process], eax - mov eax, [TASK_BASE] - mov [dma_slot_ptr], eax - cmp [hdbase], 0x1F0 - jnz .ide1 - mov [irq14_func], hdd_irq14 - jmp @f -.ide1: - mov [irq15_func], hdd_irq15 -@@: - call enable_ide_int - cmp [hdbase], 0x1F0 - jnz .wait_ide1 - call wait_for_sector_dma_ide0 - jmp @f -.wait_ide1: - call wait_for_sector_dma_ide1 -@@: - cmp [hd_error], 0 - jnz hd_read_error - mov eax,[hdpos] - mov [dma_hdpos],eax - pop edx - pop eax - mov [dma_cur_sector], eax - jmp hd_read_dma - -align 4 -write_cache_sector: - mov [cache_chain_size],1 - mov [cache_chain_pos],edi -write_cache_chain: - cmp [hdpos], 0x80 - jae bd_write_cache_chain - mov eax,[cache_chain_ptr] - cmp dword[eax],0x10000000 - jae .bad - push esi - mov eax, IDE_descriptor_table - mov edx,eax - pusha - mov esi,[cache_chain_pos] - shl esi, 9 - call calculate_cache_2 - add esi,eax - mov edi, (OS_BASE+IDE_DMA) - mov dword [edx], IDE_DMA - movzx ecx, [cache_chain_size] - shl ecx, 9 - mov word [edx+4], cx - shr ecx,2 - cld - rep movsd - popa - sub eax, OS_BASE - mov dx, [IDEContrRegsBaseAddr] - cmp [hdbase], 0x1F0 - jz @f - add edx, 8 -@@: - push edx - add edx, 4 - out dx, eax - pop edx - mov al, 0 - out dx, al - add edx, 2 - mov al, 6 - out dx, al - call wait_for_hd_idle - cmp [hd_error], 0 - jnz hd_write_error_dma - call disable_ide_int - xor eax, eax - mov edx, [hdbase] - inc edx - out dx, al - inc edx - mov al, [cache_chain_size] - out dx, al - inc edx - mov esi, [cache_chain_ptr] - mov eax, [esi] - out dx, al - shr eax, 8 - inc edx - out dx, al - shr eax, 8 - inc edx - out dx, al - shr eax, 8 - inc edx - and al, 0xF - add al, byte [hdid] - add al, 11100000b - out dx, al - inc edx - mov al, 0xCA - out dx, al - mov dx, [IDEContrRegsBaseAddr] - cmp [hdbase], 0x1F0 - jz @f - add dx, 8 -@@: - mov al, 1 - out dx, al - mov eax, [CURRENT_TASK] - mov [dma_process], eax - mov eax, [TASK_BASE] - mov [dma_slot_ptr], eax - cmp [hdbase], 0x1F0 - jnz .ide1 - mov [irq14_func], hdd_irq14 - jmp @f -.ide1: - mov [irq15_func], hdd_irq15 -@@: - call enable_ide_int - mov [dma_cur_sector], not 0x40 - cmp [hdbase], 0x1F0 - jnz .wait_ide1 - call wait_for_sector_dma_ide0 - jmp @f -.wait_ide1: - call wait_for_sector_dma_ide1 -@@: - cmp [hd_error], 0 - jnz hd_write_error_dma - pop esi - ret -.bad: - inc [hd_error] - ret - -uglobal -IDEContrRegsBaseAddr dw ? -endg -; \end{Mario79} - -; \begin{diamond} -uglobal -bios_hdpos dd 0 ; 0 is invalid value for [hdpos] -bios_cur_sector dd ? -bios_read_len dd ? -endg -bd_read: - push eax - push edx - mov edx, [bios_hdpos] - cmp edx, [hdpos] - jne .notread - mov edx, [bios_cur_sector] - cmp eax, edx - jb .notread - add edx, [bios_read_len] - dec edx - cmp eax, edx - ja .notread - sub eax, [bios_cur_sector] - shl eax, 9 - add eax, (OS_BASE+0x9A000) - push ecx esi edi - mov esi, eax - shl edi, 9 -; add edi, HD_CACHE+0x10000 - push eax - call calculate_cache_2 - add edi,eax - pop eax - - mov ecx, 512/4 - cld - rep movsd - pop edi esi ecx - pop edx - pop eax - ret -.notread: - push ecx - mov dl, 42h - mov ecx, 16 - call int13_call - pop ecx - test eax, eax - jnz .v86err - test edx, edx - jz .readerr - mov [bios_read_len], edx - mov edx, [hdpos] - mov [bios_hdpos], edx - pop edx - pop eax - mov [bios_cur_sector], eax - jmp bd_read -.readerr: -.v86err: - mov [hd_error], 1 - jmp hd_read_error - -bd_write_cache_chain: - pusha - mov esi, [cache_chain_pos] - shl esi, 9 - call calculate_cache_2 - add esi, eax - mov edi, OS_BASE + 0x9A000 - movzx ecx, [cache_chain_size] - push ecx - shl ecx, 9-2 - rep movsd - pop ecx - mov dl, 43h - mov eax, [cache_chain_ptr] - mov eax, [eax] - call int13_call - test eax, eax - jnz .v86err - cmp edx, ecx - jnz .writeerr - popa - ret -.v86err: -.writeerr: - popa - mov [hd_error], 1 - jmp hd_write_error - -uglobal -int13_regs_in rb v86_regs.size -int13_regs_out rb v86_regs.size -endg - -int13_call: -; Because this code uses fixed addresses, -; it can not be run simultaniously by many threads. -; In current implementation it is protected by common mutex 'hd1_status' - mov word [OS_BASE + 510h], 10h ; packet length - mov word [OS_BASE + 512h], cx ; number of sectors - mov dword [OS_BASE + 514h], 9A000000h ; buffer 9A00:0000 - mov dword [OS_BASE + 518h], eax - and dword [OS_BASE + 51Ch], 0 - push ebx ecx esi edi - mov ebx, int13_regs_in - mov edi, ebx - mov ecx, v86_regs.size/4 - xor eax, eax - rep stosd - mov byte [ebx+v86_regs.eax+1], dl - mov eax, [hdpos] - lea eax, [BiosDisksData+(eax-80h)*4] - mov dl, [eax] - mov byte [ebx+v86_regs.edx], dl - movzx edx, byte [eax+1] -; mov dl, 5 - test edx, edx - jnz .hasirq - dec edx - jmp @f -.hasirq: - pushad - stdcall enable_irq, edx - popad -@@: - mov word [ebx+v86_regs.esi], 510h - mov word [ebx+v86_regs.ss], 9000h - mov word [ebx+v86_regs.esp], 0A000h - mov word [ebx+v86_regs.eip], 500h - mov [ebx+v86_regs.eflags], 20200h - mov esi, [sys_v86_machine] - mov ecx, 0x502 - push fs - call v86_start - pop fs - and [bios_hdpos], 0 - pop edi esi ecx ebx - movzx edx, byte [OS_BASE + 512h] - test byte [int13_regs_out+v86_regs.eflags], 1 - jnz @f - mov edx, ecx -@@: - ret -; \end{diamond} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; Low-level driver for HDD access +; DMA support by Mario79 +; Access through BIOS by diamond + +align 4 +hd_read: +;----------------------------------------------------------- +; input : eax = block to read +; ebx = destination +;----------------------------------------------------------- + and [hd_error], 0 + push ecx esi edi ; scan cache + +; mov ecx,cache_max ; entries in cache +; mov esi,HD_CACHE+8 + call calculate_cache + add esi, 8 + + mov edi, 1 + + hdreadcache: + + cmp dword [esi+4], 0; empty + je nohdcache + + cmp [esi], eax ; correct sector + je yeshdcache + + nohdcache: + + add esi, 8 + inc edi + dec ecx + jnz hdreadcache + + call find_empty_slot ; ret in edi + cmp [hd_error], 0 + jne return_01 +; Read through BIOS? + cmp [hdpos], 0x80 + jae .bios +; hd_read_{dma,pio} use old ATA with 28 bit for sector number + cmp eax, 0x10000000 + jb @f + inc [hd_error] + jmp return_01 +@@: +; DMA read is permitted if [allow_dma_access]=1 or 2 + cmp [allow_dma_access], 2 + ja .nodma + cmp [dma_hdd], 1 + jnz .nodma + call hd_read_dma + jmp @f +.nodma: + call hd_read_pio + jmp @f +.bios: + call bd_read +@@: + cmp [hd_error], 0 + jne return_01 +; lea esi,[edi*8+HD_CACHE] +; push eax + call calculate_cache_1 + lea esi, [edi*8+esi] +; pop eax + + mov [esi], eax ; sector number + mov dword [esi+4], 1; hd read - mark as same as in hd + + yeshdcache: + + mov esi, edi + shl esi, 9 +; add esi,HD_CACHE+65536 + push eax + call calculate_cache_2 + add esi, eax + pop eax + + mov edi, ebx + mov ecx, 512/4 + cld + rep movsd ; move data + return_01: + pop edi esi ecx + ret + +align 4 +hd_read_pio: + push eax edx + + call wait_for_hd_idle + cmp [hd_error], 0 + jne hd_read_error + + cli + xor eax, eax + mov edx, [hdbase] + inc edx + out dx, al; ATAFeatures ॣЁбва "®б®ЎҐ­­®б⥩" + inc edx + inc eax + out dx, al; ATASectorCount бзсвзЁЄ ᥪв®а®ў + inc edx + mov eax, [esp+4] + out dx, al; ATASectorNumber ॣЁбва ­®¬Ґа  ᥪв®а  + shr eax, 8 + inc edx + out dx, al; ATACylinder ­®¬Ґа жЁ«Ё­¤а  (¬« ¤иЁ© Ў ©в) + shr eax, 8 + inc edx + out dx, al; ­®¬Ґа жЁ«Ё­¤а  (бв аиЁ© Ў ©в) + shr eax, 8 + inc edx + and al, 1+2+4+8 + add al, byte [hdid] + add al, 128+64+32 + out dx, al; ­®¬Ґа Ј®«®ўЄЁ/­®¬Ґа ¤ЁбЄ  + inc edx + mov al, 20h + out dx, al; ATACommand ॣЁбва Є®¬ ­¤ + sti + + call wait_for_sector_buffer + + cmp [hd_error], 0 + jne hd_read_error + + cli + push edi + shl edi, 9 +; add edi,HD_CACHE+65536 + push eax + call calculate_cache_2 + add edi, eax + pop eax + + mov ecx, 256 + mov edx, [hdbase] + cld + rep insw + pop edi + sti + + pop edx eax + ret + +disable_ide_int: +; mov edx,[hdbase] +; add edx,0x206 +; mov al,2 +; out dx,al + cli + ret + +enable_ide_int: +; mov edx,[hdbase] +; add edx,0x206 +; mov al,0 +; out dx,al + sti + ret + +align 4 +hd_write: +;----------------------------------------------------------- +; input : eax = block +; ebx = pointer to memory +;----------------------------------------------------------- + push ecx esi edi + + ; check if the cache already has the sector and overwrite it + +; mov ecx,cache_max +; mov esi,HD_CACHE+8 + call calculate_cache + add esi, 8 + + mov edi, 1 + + hdwritecache: + + cmp dword [esi+4], 0; if cache slot is empty + je not_in_cache_write + + cmp [esi], eax ; if the slot has the sector + je yes_in_cache_write + + not_in_cache_write: + + add esi, 8 + inc edi + dec ecx + jnz hdwritecache + + ; sector not found in cache + ; write the block to a new location + + call find_empty_slot ; ret in edi + cmp [hd_error], 0 + jne hd_write_access_denied + +; lea esi,[edi*8+HD_CACHE] +; push eax + call calculate_cache_1 + lea esi, [edi*8+esi] +; pop eax + + mov [esi], eax ; sector number + + yes_in_cache_write: + + mov dword [esi+4], 2; write - differs from hd + + shl edi, 9 +; add edi,HD_CACHE+65536 + push eax + call calculate_cache_2 + add edi, eax + pop eax + + mov esi, ebx + mov ecx, 512/4 + cld + rep movsd ; move data + hd_write_access_denied: + pop edi esi ecx + ret + +align 4 +cache_write_pio: + cmp dword[esi], 0x10000000 + jae .bad +; call disable_ide_int + + call wait_for_hd_idle + cmp [hd_error], 0 + jne hd_write_error + + cli + xor eax, eax + mov edx, [hdbase] + inc edx + out dx, al + inc edx + inc eax + out dx, al + inc edx + mov eax, [esi] ; eax = sector to write + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + and al, 1+2+4+8 + add al, byte [hdid] + add al, 128+64+32 + out dx, al + inc edx + mov al, 30h + out dx, al + sti + + call wait_for_sector_buffer + + cmp [hd_error], 0 + jne hd_write_error + + push ecx esi + + cli + mov esi, edi + shl esi, 9 +; add esi,HD_CACHE+65536 ; esi = from memory position + push eax + call calculate_cache_2 + add esi, eax + pop eax + + mov ecx, 256 + mov edx, [hdbase] + cld + rep outsw + sti + +; call enable_ide_int + pop esi ecx + + ret +.bad: + inc [hd_error] + ret + +save_hd_wait_timeout: + + push eax + mov eax, [timer_ticks] + add eax, 300 ; 3 sec timeout + mov [hd_wait_timeout], eax + pop eax + ret + +align 4 +check_hd_wait_timeout: + + push eax + mov eax, [hd_wait_timeout] + cmp [timer_ticks], eax + jg hd_timeout_error + pop eax + mov [hd_error], 0 + ret + +;iglobal +; hd_timeout_str db 'K : FS - HD timeout',0 +; hd_read_str db 'K : FS - HD read error',0 +; hd_write_str db 'K : FS - HD write error',0 +; hd_lba_str db 'K : FS - HD LBA error',0 +;endg + +hd_timeout_error: + +; call clear_hd_cache +; call clear_application_table_status +; mov esi,hd_timeout_str +; call sys_msg_board_str + DEBUGF 1,"K : FS - HD timeout\n" + + mov [hd_error], 1 + pop eax + ret + +hd_read_error: + +; call clear_hd_cache +; call clear_application_table_status +; mov esi,hd_read_str +; call sys_msg_board_str + DEBUGF 1,"K : FS - HD read error\n" + pop edx eax + ret + +hd_write_error: + +; call clear_hd_cache +; call clear_application_table_status +; mov esi,hd_write_str +; call sys_msg_board_str + DEBUGF 1,"K : FS - HD write error\n" + ret + +hd_write_error_dma: +; call clear_hd_cache +; call clear_application_table_status +; mov esi, hd_write_str +; call sys_msg_board_str + DEBUGF 1,"K : FS - HD read error\n" + pop esi + ret + +hd_lba_error: +; call clear_hd_cache +; call clear_application_table_status +; mov esi,hd_lba_str +; call sys_msg_board_str + DEBUGF 1,"K : FS - HD LBA error\n" + jmp LBA_read_ret + + +align 4 +wait_for_hd_idle: + + push eax edx + + call save_hd_wait_timeout + + mov edx, [hdbase] + add edx, 0x7 + + wfhil1: + + call check_hd_wait_timeout + cmp [hd_error], 0 + jne @f + + in al, dx + test al, 128 + jnz wfhil1 + + @@: + + pop edx eax + ret + + +align 4 +wait_for_sector_buffer: + + push eax edx + + mov edx, [hdbase] + add edx, 0x7 + + call save_hd_wait_timeout + + hdwait_sbuf: ; wait for sector buffer to be ready + + call check_hd_wait_timeout + cmp [hd_error], 0 + jne @f + + in al, dx + test al, 8 + jz hdwait_sbuf + + mov [hd_error], 0 + + cmp [hd_setup], 1 ; do not mark error for setup request + je buf_wait_ok + + test al, 1 ; previous command ended up with an error + jz buf_wait_ok + @@: + mov [hd_error], 1 + + buf_wait_ok: + + pop edx eax + ret + +; \begin{Mario79} +align 4 +wait_for_sector_dma_ide0: + push eax + push edx + call save_hd_wait_timeout +.wait: + call change_task + cmp [irq14_func], hdd_irq14 + jnz .done + call check_hd_wait_timeout + cmp [hd_error], 0 + jz .wait + mov [irq14_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + mov al, 0 + out dx, al +.done: + pop edx + pop eax + ret + +align 4 +wait_for_sector_dma_ide1: + push eax + push edx + call save_hd_wait_timeout +.wait: + call change_task + cmp [irq15_func], hdd_irq15 + jnz .done + call check_hd_wait_timeout + cmp [hd_error], 0 + jz .wait + mov [irq15_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + add dx, 8 + mov al, 0 + out dx, al +.done: + pop edx + pop eax + ret + +iglobal +align 4 +; note that IDE descriptor table must be 4-byte aligned and do not cross 4K boundary +IDE_descriptor_table: + dd IDE_DMA + dw 0x2000 + dw 0x8000 + +dma_cur_sector dd not 40h +dma_hdpos dd 0 +irq14_func dd hdd_irq_null +irq15_func dd hdd_irq_null +endg + +uglobal +; all uglobals are zeroed at boot +dma_process dd 0 +dma_slot_ptr dd 0 +cache_chain_pos dd 0 +cache_chain_ptr dd 0 +cache_chain_size db 0 +cache_chain_started db 0 +dma_task_switched db 0 +dma_hdd db 0 +allow_dma_access db 0 +endg + +align 4 +hdd_irq14: + pushfd + cli + pushad + mov [irq14_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + mov al, 0 + out dx, al +; call update_counters +; mov ebx, [dma_process] +; cmp [CURRENT_TASK], ebx +; jz .noswitch +; mov [dma_task_switched], 1 +; mov edi, [dma_slot_ptr] +; mov eax, [CURRENT_TASK] +; mov [dma_process], eax +; mov eax, [TASK_BASE] +; mov [dma_slot_ptr], eax +; mov [CURRENT_TASK], ebx +; mov [TASK_BASE], edi +; mov byte [DONT_SWITCH], 1 +; call do_change_task +.noswitch: + popad + popfd +align 4 +hdd_irq_null: + ret + +align 4 +hdd_irq15: + pushfd + cli + pushad + mov [irq15_func], hdd_irq_null + mov dx, [IDEContrRegsBaseAddr] + add dx, 8 + mov al, 0 + out dx, al +; call update_counters +; mov ebx, [dma_process] +; cmp [CURRENT_TASK], ebx +; jz .noswitch +; mov [dma_task_switched], 1 +; mov edi, [dma_slot_ptr] +; mov eax, [CURRENT_TASK] +; mov [dma_process], eax +; mov eax, [TASK_BASE] +; mov [dma_slot_ptr], eax +; mov [CURRENT_TASK], ebx +; mov [TASK_BASE], edi +; mov byte [DONT_SWITCH], 1 +; call do_change_task +.noswitch: + popad + popfd + ret + +align 4 +hd_read_dma: + push eax + push edx + mov edx, [dma_hdpos] + cmp edx, [hdpos] + jne .notread + mov edx, [dma_cur_sector] + cmp eax, edx + jb .notread + add edx, 15 + cmp [esp+4], edx + ja .notread + mov eax, [esp+4] + sub eax, [dma_cur_sector] + shl eax, 9 + add eax, (OS_BASE+IDE_DMA) + push ecx esi edi + mov esi, eax + shl edi, 9 +; add edi, HD_CACHE+0x10000 + push eax + call calculate_cache_2 + add edi, eax + pop eax + + mov ecx, 512/4 + cld + rep movsd + pop edi esi ecx + pop edx + pop eax + ret +.notread: + mov eax, IDE_descriptor_table + mov dword [eax], IDE_DMA + mov word [eax+4], 0x2000 + sub eax, OS_BASE + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add edx, 8 +@@: + push edx + add edx, 4 + out dx, eax + pop edx + mov al, 0 + out dx, al + add edx, 2 + mov al, 6 + out dx, al + call wait_for_hd_idle + cmp [hd_error], 0 + jnz hd_read_error + call disable_ide_int + xor eax, eax + mov edx, [hdbase] + inc edx + out dx, al + inc edx + mov eax, 10h + out dx, al + inc edx + mov eax, [esp+4] + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + and al, 0xF + add al, byte [hdid] + add al, 11100000b + out dx, al + inc edx + mov al, 0xC8 + out dx, al + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add dx, 8 +@@: + mov al, 9 + out dx, al + mov eax, [CURRENT_TASK] + mov [dma_process], eax + mov eax, [TASK_BASE] + mov [dma_slot_ptr], eax + cmp [hdbase], 0x1F0 + jnz .ide1 + mov [irq14_func], hdd_irq14 + jmp @f +.ide1: + mov [irq15_func], hdd_irq15 +@@: + call enable_ide_int + cmp [hdbase], 0x1F0 + jnz .wait_ide1 + call wait_for_sector_dma_ide0 + jmp @f +.wait_ide1: + call wait_for_sector_dma_ide1 +@@: + cmp [hd_error], 0 + jnz hd_read_error + mov eax, [hdpos] + mov [dma_hdpos], eax + pop edx + pop eax + mov [dma_cur_sector], eax + jmp hd_read_dma + +align 4 +write_cache_sector: + mov [cache_chain_size], 1 + mov [cache_chain_pos], edi +write_cache_chain: + cmp [hdpos], 0x80 + jae bd_write_cache_chain + mov eax, [cache_chain_ptr] + cmp dword[eax], 0x10000000 + jae .bad + push esi + mov eax, IDE_descriptor_table + mov edx, eax + pusha + mov esi, [cache_chain_pos] + shl esi, 9 + call calculate_cache_2 + add esi, eax + mov edi, (OS_BASE+IDE_DMA) + mov dword [edx], IDE_DMA + movzx ecx, [cache_chain_size] + shl ecx, 9 + mov word [edx+4], cx + shr ecx, 2 + cld + rep movsd + popa + sub eax, OS_BASE + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add edx, 8 +@@: + push edx + add edx, 4 + out dx, eax + pop edx + mov al, 0 + out dx, al + add edx, 2 + mov al, 6 + out dx, al + call wait_for_hd_idle + cmp [hd_error], 0 + jnz hd_write_error_dma + call disable_ide_int + xor eax, eax + mov edx, [hdbase] + inc edx + out dx, al + inc edx + mov al, [cache_chain_size] + out dx, al + inc edx + mov esi, [cache_chain_ptr] + mov eax, [esi] + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + and al, 0xF + add al, byte [hdid] + add al, 11100000b + out dx, al + inc edx + mov al, 0xCA + out dx, al + mov dx, [IDEContrRegsBaseAddr] + cmp [hdbase], 0x1F0 + jz @f + add dx, 8 +@@: + mov al, 1 + out dx, al + mov eax, [CURRENT_TASK] + mov [dma_process], eax + mov eax, [TASK_BASE] + mov [dma_slot_ptr], eax + cmp [hdbase], 0x1F0 + jnz .ide1 + mov [irq14_func], hdd_irq14 + jmp @f +.ide1: + mov [irq15_func], hdd_irq15 +@@: + call enable_ide_int + mov [dma_cur_sector], not 0x40 + cmp [hdbase], 0x1F0 + jnz .wait_ide1 + call wait_for_sector_dma_ide0 + jmp @f +.wait_ide1: + call wait_for_sector_dma_ide1 +@@: + cmp [hd_error], 0 + jnz hd_write_error_dma + pop esi + ret +.bad: + inc [hd_error] + ret + +uglobal +IDEContrRegsBaseAddr dw ? +endg +; \end{Mario79} + +; \begin{diamond} +uglobal +bios_hdpos dd 0 ; 0 is invalid value for [hdpos] +bios_cur_sector dd ? +bios_read_len dd ? +endg +bd_read: + push eax + push edx + mov edx, [bios_hdpos] + cmp edx, [hdpos] + jne .notread + mov edx, [bios_cur_sector] + cmp eax, edx + jb .notread + add edx, [bios_read_len] + dec edx + cmp eax, edx + ja .notread + sub eax, [bios_cur_sector] + shl eax, 9 + add eax, (OS_BASE+0x9A000) + push ecx esi edi + mov esi, eax + shl edi, 9 +; add edi, HD_CACHE+0x10000 + push eax + call calculate_cache_2 + add edi, eax + pop eax + + mov ecx, 512/4 + cld + rep movsd + pop edi esi ecx + pop edx + pop eax + ret +.notread: + push ecx + mov dl, 42h + mov ecx, 16 + call int13_call + pop ecx + test eax, eax + jnz .v86err + test edx, edx + jz .readerr + mov [bios_read_len], edx + mov edx, [hdpos] + mov [bios_hdpos], edx + pop edx + pop eax + mov [bios_cur_sector], eax + jmp bd_read +.readerr: +.v86err: + mov [hd_error], 1 + jmp hd_read_error + +bd_write_cache_chain: + pusha + mov esi, [cache_chain_pos] + shl esi, 9 + call calculate_cache_2 + add esi, eax + mov edi, OS_BASE + 0x9A000 + movzx ecx, [cache_chain_size] + push ecx + shl ecx, 9-2 + rep movsd + pop ecx + mov dl, 43h + mov eax, [cache_chain_ptr] + mov eax, [eax] + call int13_call + test eax, eax + jnz .v86err + cmp edx, ecx + jnz .writeerr + popa + ret +.v86err: +.writeerr: + popa + mov [hd_error], 1 + jmp hd_write_error + +uglobal +int13_regs_in rb v86_regs.size +int13_regs_out rb v86_regs.size +endg + +int13_call: +; Because this code uses fixed addresses, +; it can not be run simultaniously by many threads. +; In current implementation it is protected by common mutex 'hd1_status' + mov word [OS_BASE + 510h], 10h ; packet length + mov word [OS_BASE + 512h], cx ; number of sectors + mov dword [OS_BASE + 514h], 9A000000h ; buffer 9A00:0000 + mov dword [OS_BASE + 518h], eax + and dword [OS_BASE + 51Ch], 0 + push ebx ecx esi edi + mov ebx, int13_regs_in + mov edi, ebx + mov ecx, v86_regs.size/4 + xor eax, eax + rep stosd + mov byte [ebx+v86_regs.eax+1], dl + mov eax, [hdpos] + lea eax, [BiosDisksData+(eax-80h)*4] + mov dl, [eax] + mov byte [ebx+v86_regs.edx], dl + movzx edx, byte [eax+1] +; mov dl, 5 + test edx, edx + jnz .hasirq + dec edx + jmp @f +.hasirq: + pushad + stdcall enable_irq, edx + popad +@@: + mov word [ebx+v86_regs.esi], 510h + mov word [ebx+v86_regs.ss], 9000h + mov word [ebx+v86_regs.esp], 0A000h + mov word [ebx+v86_regs.eip], 500h + mov [ebx+v86_regs.eflags], 20200h + mov esi, [sys_v86_machine] + mov ecx, 0x502 + push fs + call v86_start + pop fs + and [bios_hdpos], 0 + pop edi esi ecx ebx + movzx edx, byte [OS_BASE + 512h] + test byte [int13_regs_out+v86_regs.eflags], 1 + jnz @f + mov edx, ecx +@@: + ret +; \end{diamond} diff --git a/kernel/trunk/blkdev/ide_cache.inc b/kernel/trunk/blkdev/ide_cache.inc index 453cbf6a2..473be7a31 100644 --- a/kernel/trunk/blkdev/ide_cache.inc +++ b/kernel/trunk/blkdev/ide_cache.inc @@ -1,922 +1,922 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;************************************************************************** -; -; [cache_ide[X]_pointer] -; or [cache_ide[X]_data_pointer] first entry in cache list -; -; +0 - lba sector -; +4 - state of cache sector -; 0 = empty -; 1 = used for read ( same as in hd ) -; 2 = used for write ( differs from hd ) -; -; [cache_ide[X]_system_data] -; or [cache_ide[x]_appl_data] - cache entries -; -;************************************************************************** - -$Revision$ - - -align 4 -write_cache: -;----------------------------------------------------------- -; write all changed sectors to disk -;----------------------------------------------------------- - push eax ecx edx esi edi - - ; write difference ( 2 ) from cache to hd - call calculate_cache - add esi,8 - mov edi,1 -write_cache_more: - cmp dword [esi+4],2 ; if cache slot is not different - jne .write_chain - mov dword [esi+4],1 ; same as in hd - mov eax,[esi] ; eax = sector to write - cmp eax,[PARTITION_START] - jb danger - cmp eax,[PARTITION_END] - ja danger - cmp [hdpos], 0x80 - jae @f -; DMA write is permitted only if [allow_dma_access]=1 - cmp [allow_dma_access], 2 - jae .nodma - cmp [dma_hdd], 1 - jnz .nodma -@@: -; ЋЎкҐ¤Ё­пҐ¬ § ЇЁбм 楯®зЄЁ Ї®б«Ґ¤®ў вҐ«м­ле ᥪв®а®ў ў ®¤­® ®Ўа йҐ­ЁҐ Є ¤ЁбЄг - cmp ecx, 1 - jz .nonext - cmp dword [esi+8+4], 2 - jnz .nonext - push eax - inc eax - cmp eax, [esi+8] - pop eax - jnz .nonext - cmp [cache_chain_started], 1 - jz @f - mov [cache_chain_started], 1 - mov [cache_chain_size], 0 - mov [cache_chain_pos], edi - mov [cache_chain_ptr], esi -@@: - inc [cache_chain_size] - cmp [cache_chain_size], 16 - jnz .continue - jmp .write_chain -.nonext: - call flush_cache_chain - mov [cache_chain_size], 1 - mov [cache_chain_ptr], esi - call write_cache_sector - jmp .continue -.nodma: - call cache_write_pio -.write_chain: - call flush_cache_chain -.continue: -danger: - add esi,8 - inc edi - dec ecx - jnz write_cache_more - call flush_cache_chain - return_02: - pop edi esi edx ecx eax - ret - -flush_cache_chain: - cmp [cache_chain_started], 0 - jz @f - call write_cache_chain - mov [cache_chain_started], 0 -@@: - ret -;-------------------------------------------------------------------- -align 4 -find_empty_slot: -;----------------------------------------------------------- -; find empty or read slot, flush cache if next 10% is used by write -; output : edi = cache slot -;----------------------------------------------------------- -; push ecx esi - -search_again: - call calculate_cache_3 - shr ecx,3 -search_for_empty: - inc edi - call calculate_cache_4 - jbe inside_cache - mov edi,1 -inside_cache: - push esi - call calculate_cache_1 - cmp dword [edi*8+esi+4],2 - pop esi - jb found_slot ; it's empty or read - dec ecx - jnz search_for_empty - call write_cache ; no empty slots found, write all - cmp [hd_error],0 - jne found_slot_access_denied - jmp search_again ; and start again -found_slot: - call calculate_cache_5 -found_slot_access_denied: - ret -;-------------------------------------------------------------------- -align 4 -clear_hd_cache: - mov [fat_in_cache],-1 - mov [fat_change],0 - ret -;-------------------------------------------------------------------- -align 4 -calculate_cache: -; mov ecx,cache_max ; entries in cache -; mov esi,HD_CACHE+8 - -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [hdpos],1 - jne .ide1 - cmp [hdd_appl_data],0 - jne .ide0_appl_data - mov ecx,[cache_ide0_system_sad_size] - mov esi,[cache_ide0_pointer] - ret -.ide0_appl_data: - mov ecx,[cache_ide0_appl_sad_size] - mov esi,[cache_ide0_data_pointer] - ret -.ide1: - cmp [hdpos],2 - jne .ide2 - cmp [hdd_appl_data],0 - jne .ide1_appl_data - mov ecx,[cache_ide1_system_sad_size] - mov esi,[cache_ide1_pointer] - ret -.ide1_appl_data: - mov ecx,[cache_ide1_appl_sad_size] - mov esi,[cache_ide1_data_pointer] - ret -.ide2: - cmp [hdpos],3 - jne .ide3 - cmp [hdd_appl_data],0 - jne .ide2_appl_data - mov ecx,[cache_ide2_system_sad_size] - mov esi,[cache_ide2_pointer] - ret -.ide2_appl_data: - mov ecx,[cache_ide2_appl_sad_size] - mov esi,[cache_ide2_data_pointer] - ret -.ide3: - cmp [hdpos],4 - jne .noide - cmp [hdd_appl_data],0 - jne .ide3_appl_data - mov ecx,[cache_ide3_system_sad_size] - mov esi,[cache_ide3_pointer] - ret -.ide3_appl_data: - mov ecx,[cache_ide3_appl_sad_size] - mov esi,[cache_ide3_data_pointer] - ret -.noide: - push eax - mov eax,[hdpos] - sub eax,80h - cmp byte [BiosDisksData+eax*4+2], -1 - jz @f - movzx eax,byte [BiosDisksData+eax*4+2] - imul eax,cache_ide1-cache_ide0 - add eax,cache_ide0 - jmp .get -@@: - imul eax,cache_ide1-cache_ide0 - add eax,BiosDiskCaches -.get: - cmp [hdd_appl_data],0 - jne .bd_appl_data - mov ecx,[cache_ide0_system_sad_size-cache_ide0+eax] - mov esi,[cache_ide0_pointer-cache_ide0+eax] - pop eax - ret -.bd_appl_data: - mov ecx,[cache_ide0_appl_sad_size-cache_ide0+eax] - mov esi,[cache_ide0_data_pointer-cache_ide0+eax] - pop eax - ret -;-------------------------------------------------------------------- -align 4 -calculate_cache_1: -; lea esi,[edi*8+HD_CACHE] -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [hdpos],1 - jne .ide1 - cmp [hdd_appl_data],0 - jne .ide0_appl_data - mov esi,[cache_ide0_pointer] - ret -.ide0_appl_data: - mov esi,[cache_ide0_data_pointer] - ret -.ide1: - cmp [hdpos],2 - jne .ide2 - cmp [hdd_appl_data],0 - jne .ide1_appl_data - mov esi,[cache_ide1_pointer] - ret -.ide1_appl_data: - mov esi,[cache_ide1_data_pointer] - ret -.ide2: - cmp [hdpos],3 - jne .ide3 - cmp [hdd_appl_data],0 - jne .ide2_appl_data - mov esi,[cache_ide2_pointer] - ret -.ide2_appl_data: - mov esi,[cache_ide2_data_pointer] - ret -.ide3: - cmp [hdpos],4 - jne .noide - cmp [hdd_appl_data],0 - jne .ide3_appl_data - mov esi,[cache_ide3_pointer] - ret -.ide3_appl_data: - mov esi,[cache_ide3_data_pointer] - ret -.noide: - push eax - mov eax,[hdpos] - sub eax,80h - cmp byte [BiosDisksData+eax*4+2], -1 - jz @f - movzx eax,byte [BiosDisksData+eax*4+2] - imul eax,cache_ide1-cache_ide0 - add eax,cache_ide0 - jmp .get -@@: - imul eax,cache_ide1-cache_ide0 - add eax,BiosDiskCaches -.get: - cmp [hdd_appl_data],0 - jne .bd_appl_data - mov esi,[cache_ide0_pointer-cache_ide0+eax] - pop eax - ret -.bd_appl_data: - mov esi,[cache_ide0_data_pointer-cache_ide0+eax] - pop eax - ret - -;-------------------------------------------------------------------- -align 4 -calculate_cache_2: -; add esi,HD_CACHE+65536 -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [hdpos],1 - jne .ide1 - cmp [hdd_appl_data],0 - jne .ide0_appl_data - mov eax,[cache_ide0_system_data] - ret -.ide0_appl_data: - mov eax,[cache_ide0_appl_data] - ret -.ide1: - cmp [hdpos],2 - jne .ide2 - cmp [hdd_appl_data],0 - jne .ide1_appl_data - mov eax,[cache_ide1_system_data] - ret -.ide1_appl_data: - mov eax,[cache_ide1_appl_data] - ret -.ide2: - cmp [hdpos],3 - jne .ide3 - cmp [hdd_appl_data],0 - jne .ide2_appl_data - mov eax,[cache_ide2_system_data] - ret -.ide2_appl_data: - mov eax,[cache_ide2_appl_data] - ret -.ide3: - cmp [hdpos],4 - jne .noide - cmp [hdd_appl_data],0 - jne .ide3_appl_data - mov eax,[cache_ide3_system_data] - ret -.ide3_appl_data: - mov eax,[cache_ide3_appl_data] - ret -.noide: - mov eax,[hdpos] - sub eax,80h - cmp byte [BiosDisksData+eax*4+2], -1 - jz @f - movzx eax,byte [BiosDisksData+eax*4+2] - imul eax,cache_ide1-cache_ide0 - add eax,cache_ide0 - jmp .get -@@: - imul eax,cache_ide1-cache_ide0 - add eax,BiosDiskCaches -.get: - cmp [hdd_appl_data],0 - jne .bd_appl_data - mov eax,[cache_ide0_system_data-cache_ide0+eax] - ret -.bd_appl_data: - mov eax,[cache_ide0_appl_data-cache_ide0+eax] - ret -;-------------------------------------------------------------------- -align 4 -calculate_cache_3: -; mov ecx,cache_max*10/100 -; mov edi,[cache_search_start] - -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [hdpos],1 - jne .ide1 - cmp [hdd_appl_data],0 - jne .ide0_appl_data - mov ecx,[cache_ide0_system_sad_size] - mov edi,[cache_ide0_search_start] - ret -.ide0_appl_data: - mov ecx,[cache_ide0_appl_sad_size] - mov edi,[cache_ide0_appl_search_start] - ret -.ide1: - cmp [hdpos],2 - jne .ide2 - cmp [hdd_appl_data],0 - jne .ide1_appl_data - mov ecx,[cache_ide1_system_sad_size] - mov edi,[cache_ide1_search_start] - ret -.ide1_appl_data: - mov ecx,[cache_ide1_appl_sad_size] - mov edi,[cache_ide1_appl_search_start] - ret -.ide2: - cmp [hdpos],3 - jne .ide3 - cmp [hdd_appl_data],0 - jne .ide2_appl_data - mov ecx,[cache_ide2_system_sad_size] - mov edi,[cache_ide2_search_start] - ret -.ide2_appl_data: - mov ecx,[cache_ide2_appl_sad_size] - mov edi,[cache_ide2_appl_search_start] - ret -.ide3: - cmp [hdpos],4 - jne .noide - cmp [hdd_appl_data],0 - jne .ide3_appl_data - mov ecx,[cache_ide3_system_sad_size] - mov edi,[cache_ide3_search_start] - ret -.ide3_appl_data: - mov ecx,[cache_ide3_appl_sad_size] - mov edi,[cache_ide3_appl_search_start] - ret -.noide: - push eax - mov eax,[hdpos] - sub eax,80h - cmp byte [BiosDisksData+eax*4+2], -1 - jz @f - movzx eax,byte [BiosDisksData+eax*4+2] - imul eax,cache_ide1-cache_ide0 - add eax,cache_ide0 - jmp .get -@@: - imul eax,cache_ide1-cache_ide0 - add eax,BiosDiskCaches -.get: - cmp [hdd_appl_data],0 - jne .bd_appl_data - mov ecx,[cache_ide0_system_sad_size-cache_ide0+eax] - mov edi,[cache_ide0_search_start-cache_ide0+eax] - pop eax - ret -.bd_appl_data: - mov ecx,[cache_ide0_appl_sad_size-cache_ide0+eax] - mov edi,[cache_ide0_appl_search_start-cache_ide0+eax] - pop eax - ret -;-------------------------------------------------------------------- -align 4 -calculate_cache_4: -; cmp edi,cache_max -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [hdpos],1 - jne .ide1 - cmp [hdd_appl_data],0 - jne .ide0_appl_data - cmp edi,[cache_ide0_system_sad_size] - ret -.ide0_appl_data: - cmp edi,[cache_ide0_appl_sad_size] - ret -.ide1: - cmp [hdpos],2 - jne .ide2 - cmp [hdd_appl_data],0 - jne .ide1_appl_data - cmp edi,[cache_ide1_system_sad_size] - ret -.ide1_appl_data: - cmp edi,[cache_ide1_appl_sad_size] - ret -.ide2: - cmp [hdpos],3 - jne .ide3 - cmp [hdd_appl_data],0 - jne .ide2_appl_data - cmp edi,[cache_ide2_system_sad_size] - ret -.ide2_appl_data: - cmp edi,[cache_ide2_appl_sad_size] - ret -.ide3: - cmp [hdpos],4 - jne .noide - cmp [hdd_appl_data],0 - jne .ide3_appl_data - cmp edi,[cache_ide3_system_sad_size] - ret -.ide3_appl_data: - cmp edi,[cache_ide3_appl_sad_size] - ret -.noide: - push eax - mov eax,[hdpos] - sub eax,80h - cmp byte [BiosDisksData+eax*4+2], -1 - jz @f - movzx eax,byte [BiosDisksData+eax*4+2] - imul eax,cache_ide1-cache_ide0 - add eax,cache_ide0 - jmp .get -@@: - imul eax,cache_ide1-cache_ide0 - add eax,BiosDiskCaches -.get: - cmp [hdd_appl_data],0 - jne .bd_appl_data - cmp edi,[cache_ide0_system_sad_size-cache_ide0+eax] - pop eax - ret -.bd_appl_data: - cmp edi,[cache_ide0_appl_sad_size-cache_ide0+eax] - pop eax - ret - -;-------------------------------------------------------------------- -align 4 -calculate_cache_5: -; mov [cache_search_start],edi -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [hdpos],1 - jne .ide1 - cmp [hdd_appl_data],0 - jne .ide0_appl_data - mov [cache_ide0_search_start],edi - ret -.ide0_appl_data: - mov [cache_ide0_appl_search_start],edi - ret -.ide1: - cmp [hdpos],2 - jne .ide2 - cmp [hdd_appl_data],0 - jne .ide1_appl_data - mov [cache_ide1_search_start],edi - ret -.ide1_appl_data: - mov [cache_ide1_appl_search_start],edi - ret -.ide2: - cmp [hdpos],3 - jne .ide3 - cmp [hdd_appl_data],0 - jne .ide2_appl_data - mov [cache_ide2_search_start],edi - ret -.ide2_appl_data: - mov [cache_ide2_appl_search_start],edi - ret -.ide3: - cmp [hdpos],4 - jne .noide - cmp [hdd_appl_data],0 - jne .ide3_appl_data - mov [cache_ide3_search_start],edi - ret -.ide3_appl_data: - mov [cache_ide3_appl_search_start],edi - ret -.noide: - push eax - mov eax,[hdpos] - sub eax,80h - cmp byte [BiosDisksData+eax*4+2], -1 - jz @f - movzx eax,byte [BiosDisksData+eax*4+2] - imul eax,cache_ide1-cache_ide0 - add eax,cache_ide0 - jmp .get -@@: - imul eax,cache_ide1-cache_ide0 - add eax,BiosDiskCaches -.get: - cmp [hdd_appl_data],0 - jne .bd_appl_data - mov [cache_ide0_search_start-cache_ide0+eax],edi - pop eax - ret -.bd_appl_data: - mov [cache_ide0_appl_search_start-cache_ide0+eax],edi - pop eax - ret - -;-------------------------------------------------------------------- -align 4 -find_empty_slot_CD_cache: -;----------------------------------------------------------- -; find empty or read slot, flush cache if next 10% is used by write -; output : edi = cache slot -;----------------------------------------------------------- -.search_again: - call cd_calculate_cache_3 -.search_for_empty: - inc edi - call cd_calculate_cache_4 - jbe .inside_cache - mov edi,1 -.inside_cache: - call cd_calculate_cache_5 - ret -;-------------------------------------------------------------------- -clear_CD_cache: - pusha -.ide0: - xor eax,eax - cmp [cdpos],1 - jne .ide1 - mov [cache_ide0_search_start],eax - mov ecx,[cache_ide0_system_sad_size] - mov edi,[cache_ide0_pointer] - call .clear - mov [cache_ide0_appl_search_start],eax - mov ecx,[cache_ide0_appl_sad_size] - mov edi,[cache_ide0_data_pointer] - jmp .continue -.ide1: - cmp [cdpos],2 - jne .ide2 - mov [cache_ide1_search_start],eax - mov ecx,[cache_ide1_system_sad_size] - mov edi,[cache_ide1_pointer] - call .clear - mov [cache_ide1_appl_search_start],eax - mov ecx,[cache_ide1_appl_sad_size] - mov edi,[cache_ide1_data_pointer] - jmp .continue -.ide2: - cmp [cdpos],3 - jne .ide3 - mov [cache_ide2_search_start],eax - mov ecx,[cache_ide2_system_sad_size] - mov edi,[cache_ide2_pointer] - call .clear - mov [cache_ide2_appl_search_start],eax - mov ecx,[cache_ide2_appl_sad_size] - mov edi,[cache_ide2_data_pointer] - jmp .continue -.ide3: - mov [cache_ide3_search_start],eax - mov ecx,[cache_ide3_system_sad_size] - mov edi,[cache_ide3_pointer] - call .clear - mov [cache_ide3_appl_search_start],eax - mov ecx,[cache_ide3_appl_sad_size] - mov edi,[cache_ide3_data_pointer] -.continue: - call .clear - popa - ret -.clear: - shl ecx,1 - cld - rep stosd - ret -;-------------------------------------------------------------------- -align 4 -cd_calculate_cache: -; mov ecx,cache_max ; entries in cache -; mov esi,HD_CACHE+8 - -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [cdpos],1 - jne .ide1 - cmp [cd_appl_data],0 - jne .ide0_appl_data - mov ecx,[cache_ide0_system_sad_size] - mov esi,[cache_ide0_pointer] - ret -.ide0_appl_data: - mov ecx,[cache_ide0_appl_sad_size] - mov esi,[cache_ide0_data_pointer] - ret -.ide1: - cmp [cdpos],2 - jne .ide2 - cmp [cd_appl_data],0 - jne .ide1_appl_data - mov ecx,[cache_ide1_system_sad_size] - mov esi,[cache_ide1_pointer] - ret -.ide1_appl_data: - mov ecx,[cache_ide1_appl_sad_size] - mov esi,[cache_ide1_data_pointer] - ret -.ide2: - cmp [cdpos],3 - jne .ide3 - cmp [cd_appl_data],0 - jne .ide2_appl_data - mov ecx,[cache_ide2_system_sad_size] - mov esi,[cache_ide2_pointer] - ret -.ide2_appl_data: - mov ecx,[cache_ide2_appl_sad_size] - mov esi,[cache_ide2_data_pointer] - ret -.ide3: - cmp [cd_appl_data],0 - jne .ide3_appl_data - mov ecx,[cache_ide3_system_sad_size] - mov esi,[cache_ide3_pointer] - ret -.ide3_appl_data: - mov ecx,[cache_ide3_appl_sad_size] - mov esi,[cache_ide3_data_pointer] - ret -;-------------------------------------------------------------------- -align 4 -cd_calculate_cache_1: -; lea esi,[edi*8+HD_CACHE] -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [cdpos],1 - jne .ide1 - cmp [cd_appl_data],0 - jne .ide0_appl_data - mov esi,[cache_ide0_pointer] - ret -.ide0_appl_data: - mov esi,[cache_ide0_data_pointer] - ret -.ide1: - cmp [cdpos],2 - jne .ide2 - cmp [cd_appl_data],0 - jne .ide1_appl_data - mov esi,[cache_ide1_pointer] - ret -.ide1_appl_data: - mov esi,[cache_ide1_data_pointer] - ret -.ide2: - cmp [cdpos],3 - jne .ide3 - cmp [cd_appl_data],0 - jne .ide2_appl_data - mov esi,[cache_ide2_pointer] - ret -.ide2_appl_data: - mov esi,[cache_ide2_data_pointer] - ret -.ide3: - cmp [cd_appl_data],0 - jne .ide3_appl_data - mov esi,[cache_ide3_pointer] - ret -.ide3_appl_data: - mov esi,[cache_ide3_data_pointer] - ret -;-------------------------------------------------------------------- -align 4 -cd_calculate_cache_2: -; add esi,HD_CACHE+65536 -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [cdpos],1 - jne .ide1 - cmp [cd_appl_data],0 - jne .ide0_appl_data - mov eax,[cache_ide0_system_data] - ret -.ide0_appl_data: - mov eax,[cache_ide0_appl_data] - ret -.ide1: - cmp [cdpos],2 - jne .ide2 - cmp [cd_appl_data],0 - jne .ide1_appl_data - mov eax,[cache_ide1_system_data] - ret -.ide1_appl_data: - mov eax,[cache_ide1_appl_data] - ret -.ide2: - cmp [cdpos],3 - jne .ide3 - cmp [cd_appl_data],0 - jne .ide2_appl_data - mov eax,[cache_ide2_system_data] - ret -.ide2_appl_data: - mov eax,[cache_ide2_appl_data] - ret -.ide3: - cmp [cd_appl_data],0 - jne .ide3_appl_data - mov eax,[cache_ide3_system_data] - ret -.ide3_appl_data: - mov eax,[cache_ide3_appl_data] - ret -;-------------------------------------------------------------------- -align 4 -cd_calculate_cache_3: -; mov ecx,cache_max*10/100 -; mov edi,[cache_search_start] - -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [cdpos],1 - jne .ide1 - cmp [cd_appl_data],0 - jne .ide0_appl_data - mov edi,[cache_ide0_search_start] - ret -.ide0_appl_data: - mov edi,[cache_ide0_appl_search_start] - ret -.ide1: - cmp [cdpos],2 - jne .ide2 - cmp [cd_appl_data],0 - jne .ide1_appl_data - mov edi,[cache_ide1_search_start] - ret -.ide1_appl_data: - mov edi,[cache_ide1_appl_search_start] - ret -.ide2: - cmp [cdpos],3 - jne .ide3 - cmp [cd_appl_data],0 - jne .ide2_appl_data - mov edi,[cache_ide2_search_start] - ret -.ide2_appl_data: - mov edi,[cache_ide2_appl_search_start] - ret -.ide3: - cmp [cd_appl_data],0 - jne .ide3_appl_data - mov edi,[cache_ide3_search_start] - ret -.ide3_appl_data: - mov edi,[cache_ide3_appl_search_start] - ret -;-------------------------------------------------------------------- -align 4 -cd_calculate_cache_4: -; cmp edi,cache_max -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [cdpos],1 - jne .ide1 - cmp [cd_appl_data],0 - jne .ide0_appl_data - cmp edi,[cache_ide0_system_sad_size] - ret -.ide0_appl_data: - cmp edi,[cache_ide0_appl_sad_size] - ret -.ide1: - cmp [cdpos],2 - jne .ide2 - cmp [cd_appl_data],0 - jne .ide1_appl_data - cmp edi,[cache_ide1_system_sad_size] - ret -.ide1_appl_data: - cmp edi,[cache_ide1_appl_sad_size] - ret -.ide2: - cmp [cdpos],3 - jne .ide3 - cmp [cd_appl_data],0 - jne .ide2_appl_data - cmp edi,[cache_ide2_system_sad_size] - ret -.ide2_appl_data: - cmp edi,[cache_ide2_appl_sad_size] - ret -.ide3: - cmp [cd_appl_data],0 - jne .ide3_appl_data - cmp edi,[cache_ide3_system_sad_size] - ret -.ide3_appl_data: - cmp edi,[cache_ide3_appl_sad_size] - ret -;-------------------------------------------------------------------- -align 4 -cd_calculate_cache_5: -; mov [cache_search_start],edi -; 1 - IDE0 ... 4 - IDE3 -.ide0: - cmp [cdpos],1 - jne .ide1 - cmp [cd_appl_data],0 - jne .ide0_appl_data - mov [cache_ide0_search_start],edi - ret -.ide0_appl_data: - mov [cache_ide0_appl_search_start],edi - ret -.ide1: - cmp [cdpos],2 - jne .ide2 - cmp [cd_appl_data],0 - jne .ide1_appl_data - mov [cache_ide1_search_start],edi - ret -.ide1_appl_data: - mov [cache_ide1_appl_search_start],edi - ret -.ide2: - cmp [cdpos],3 - jne .ide3 - cmp [cd_appl_data],0 - jne .ide2_appl_data - mov [cache_ide2_search_start],edi - ret -.ide2_appl_data: - mov [cache_ide2_appl_search_start],edi - ret -.ide3: - cmp [cd_appl_data],0 - jne .ide3_appl_data - mov [cache_ide3_search_start],edi - ret -.ide3_appl_data: - mov [cache_ide3_appl_search_start],edi - ret -;-------------------------------------------------------------------- -;align 4 -;calculate_linear_to_real: -; shr eax, 12 -; mov eax, [page_tabs+eax*4] -; and eax, 0xFFFFF000 -; ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;************************************************************************** +; +; [cache_ide[X]_pointer] +; or [cache_ide[X]_data_pointer] first entry in cache list +; +; +0 - lba sector +; +4 - state of cache sector +; 0 = empty +; 1 = used for read ( same as in hd ) +; 2 = used for write ( differs from hd ) +; +; [cache_ide[X]_system_data] +; or [cache_ide[x]_appl_data] - cache entries +; +;************************************************************************** + +$Revision$ + + +align 4 +write_cache: +;----------------------------------------------------------- +; write all changed sectors to disk +;----------------------------------------------------------- + push eax ecx edx esi edi + + ; write difference ( 2 ) from cache to hd + call calculate_cache + add esi, 8 + mov edi, 1 +write_cache_more: + cmp dword [esi+4], 2; if cache slot is not different + jne .write_chain + mov dword [esi+4], 1; same as in hd + mov eax, [esi] ; eax = sector to write + cmp eax, [PARTITION_START] + jb danger + cmp eax, [PARTITION_END] + ja danger + cmp [hdpos], 0x80 + jae @f +; DMA write is permitted only if [allow_dma_access]=1 + cmp [allow_dma_access], 2 + jae .nodma + cmp [dma_hdd], 1 + jnz .nodma +@@: +; ЋЎкҐ¤Ё­пҐ¬ § ЇЁбм 楯®зЄЁ Ї®б«Ґ¤®ў вҐ«м­ле ᥪв®а®ў ў ®¤­® ®Ўа йҐ­ЁҐ Є ¤ЁбЄг + cmp ecx, 1 + jz .nonext + cmp dword [esi+8+4], 2 + jnz .nonext + push eax + inc eax + cmp eax, [esi+8] + pop eax + jnz .nonext + cmp [cache_chain_started], 1 + jz @f + mov [cache_chain_started], 1 + mov [cache_chain_size], 0 + mov [cache_chain_pos], edi + mov [cache_chain_ptr], esi +@@: + inc [cache_chain_size] + cmp [cache_chain_size], 16 + jnz .continue + jmp .write_chain +.nonext: + call flush_cache_chain + mov [cache_chain_size], 1 + mov [cache_chain_ptr], esi + call write_cache_sector + jmp .continue +.nodma: + call cache_write_pio +.write_chain: + call flush_cache_chain +.continue: +danger: + add esi, 8 + inc edi + dec ecx + jnz write_cache_more + call flush_cache_chain + return_02: + pop edi esi edx ecx eax + ret + +flush_cache_chain: + cmp [cache_chain_started], 0 + jz @f + call write_cache_chain + mov [cache_chain_started], 0 +@@: + ret +;-------------------------------------------------------------------- +align 4 +find_empty_slot: +;----------------------------------------------------------- +; find empty or read slot, flush cache if next 10% is used by write +; output : edi = cache slot +;----------------------------------------------------------- +; push ecx esi + +search_again: + call calculate_cache_3 + shr ecx, 3 +search_for_empty: + inc edi + call calculate_cache_4 + jbe inside_cache + mov edi, 1 +inside_cache: + push esi + call calculate_cache_1 + cmp dword [edi*8+esi+4], 2 + pop esi + jb found_slot ; it's empty or read + dec ecx + jnz search_for_empty + call write_cache ; no empty slots found, write all + cmp [hd_error], 0 + jne found_slot_access_denied + jmp search_again ; and start again +found_slot: + call calculate_cache_5 +found_slot_access_denied: + ret +;-------------------------------------------------------------------- +align 4 +clear_hd_cache: + mov [fat_in_cache], -1 + mov [fat_change], 0 + ret +;-------------------------------------------------------------------- +align 4 +calculate_cache: +; mov ecx,cache_max ; entries in cache +; mov esi,HD_CACHE+8 + +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [hdpos], 1 + jne .ide1 + cmp [hdd_appl_data], 0 + jne .ide0_appl_data + mov ecx, [cache_ide0_system_sad_size] + mov esi, [cache_ide0_pointer] + ret +.ide0_appl_data: + mov ecx, [cache_ide0_appl_sad_size] + mov esi, [cache_ide0_data_pointer] + ret +.ide1: + cmp [hdpos], 2 + jne .ide2 + cmp [hdd_appl_data], 0 + jne .ide1_appl_data + mov ecx, [cache_ide1_system_sad_size] + mov esi, [cache_ide1_pointer] + ret +.ide1_appl_data: + mov ecx, [cache_ide1_appl_sad_size] + mov esi, [cache_ide1_data_pointer] + ret +.ide2: + cmp [hdpos], 3 + jne .ide3 + cmp [hdd_appl_data], 0 + jne .ide2_appl_data + mov ecx, [cache_ide2_system_sad_size] + mov esi, [cache_ide2_pointer] + ret +.ide2_appl_data: + mov ecx, [cache_ide2_appl_sad_size] + mov esi, [cache_ide2_data_pointer] + ret +.ide3: + cmp [hdpos], 4 + jne .noide + cmp [hdd_appl_data], 0 + jne .ide3_appl_data + mov ecx, [cache_ide3_system_sad_size] + mov esi, [cache_ide3_pointer] + ret +.ide3_appl_data: + mov ecx, [cache_ide3_appl_sad_size] + mov esi, [cache_ide3_data_pointer] + ret +.noide: + push eax + mov eax, [hdpos] + sub eax, 80h + cmp byte [BiosDisksData+eax*4+2], -1 + jz @f + movzx eax, byte [BiosDisksData+eax*4+2] + imul eax, cache_ide1-cache_ide0 + add eax, cache_ide0 + jmp .get +@@: + imul eax, cache_ide1-cache_ide0 + add eax, BiosDiskCaches +.get: + cmp [hdd_appl_data], 0 + jne .bd_appl_data + mov ecx, [cache_ide0_system_sad_size-cache_ide0+eax] + mov esi, [cache_ide0_pointer-cache_ide0+eax] + pop eax + ret +.bd_appl_data: + mov ecx, [cache_ide0_appl_sad_size-cache_ide0+eax] + mov esi, [cache_ide0_data_pointer-cache_ide0+eax] + pop eax + ret +;-------------------------------------------------------------------- +align 4 +calculate_cache_1: +; lea esi,[edi*8+HD_CACHE] +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [hdpos], 1 + jne .ide1 + cmp [hdd_appl_data], 0 + jne .ide0_appl_data + mov esi, [cache_ide0_pointer] + ret +.ide0_appl_data: + mov esi, [cache_ide0_data_pointer] + ret +.ide1: + cmp [hdpos], 2 + jne .ide2 + cmp [hdd_appl_data], 0 + jne .ide1_appl_data + mov esi, [cache_ide1_pointer] + ret +.ide1_appl_data: + mov esi, [cache_ide1_data_pointer] + ret +.ide2: + cmp [hdpos], 3 + jne .ide3 + cmp [hdd_appl_data], 0 + jne .ide2_appl_data + mov esi, [cache_ide2_pointer] + ret +.ide2_appl_data: + mov esi, [cache_ide2_data_pointer] + ret +.ide3: + cmp [hdpos], 4 + jne .noide + cmp [hdd_appl_data], 0 + jne .ide3_appl_data + mov esi, [cache_ide3_pointer] + ret +.ide3_appl_data: + mov esi, [cache_ide3_data_pointer] + ret +.noide: + push eax + mov eax, [hdpos] + sub eax, 80h + cmp byte [BiosDisksData+eax*4+2], -1 + jz @f + movzx eax, byte [BiosDisksData+eax*4+2] + imul eax, cache_ide1-cache_ide0 + add eax, cache_ide0 + jmp .get +@@: + imul eax, cache_ide1-cache_ide0 + add eax, BiosDiskCaches +.get: + cmp [hdd_appl_data], 0 + jne .bd_appl_data + mov esi, [cache_ide0_pointer-cache_ide0+eax] + pop eax + ret +.bd_appl_data: + mov esi, [cache_ide0_data_pointer-cache_ide0+eax] + pop eax + ret + +;-------------------------------------------------------------------- +align 4 +calculate_cache_2: +; add esi,HD_CACHE+65536 +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [hdpos], 1 + jne .ide1 + cmp [hdd_appl_data], 0 + jne .ide0_appl_data + mov eax, [cache_ide0_system_data] + ret +.ide0_appl_data: + mov eax, [cache_ide0_appl_data] + ret +.ide1: + cmp [hdpos], 2 + jne .ide2 + cmp [hdd_appl_data], 0 + jne .ide1_appl_data + mov eax, [cache_ide1_system_data] + ret +.ide1_appl_data: + mov eax, [cache_ide1_appl_data] + ret +.ide2: + cmp [hdpos], 3 + jne .ide3 + cmp [hdd_appl_data], 0 + jne .ide2_appl_data + mov eax, [cache_ide2_system_data] + ret +.ide2_appl_data: + mov eax, [cache_ide2_appl_data] + ret +.ide3: + cmp [hdpos], 4 + jne .noide + cmp [hdd_appl_data], 0 + jne .ide3_appl_data + mov eax, [cache_ide3_system_data] + ret +.ide3_appl_data: + mov eax, [cache_ide3_appl_data] + ret +.noide: + mov eax, [hdpos] + sub eax, 80h + cmp byte [BiosDisksData+eax*4+2], -1 + jz @f + movzx eax, byte [BiosDisksData+eax*4+2] + imul eax, cache_ide1-cache_ide0 + add eax, cache_ide0 + jmp .get +@@: + imul eax, cache_ide1-cache_ide0 + add eax, BiosDiskCaches +.get: + cmp [hdd_appl_data], 0 + jne .bd_appl_data + mov eax, [cache_ide0_system_data-cache_ide0+eax] + ret +.bd_appl_data: + mov eax, [cache_ide0_appl_data-cache_ide0+eax] + ret +;-------------------------------------------------------------------- +align 4 +calculate_cache_3: +; mov ecx,cache_max*10/100 +; mov edi,[cache_search_start] + +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [hdpos], 1 + jne .ide1 + cmp [hdd_appl_data], 0 + jne .ide0_appl_data + mov ecx, [cache_ide0_system_sad_size] + mov edi, [cache_ide0_search_start] + ret +.ide0_appl_data: + mov ecx, [cache_ide0_appl_sad_size] + mov edi, [cache_ide0_appl_search_start] + ret +.ide1: + cmp [hdpos], 2 + jne .ide2 + cmp [hdd_appl_data], 0 + jne .ide1_appl_data + mov ecx, [cache_ide1_system_sad_size] + mov edi, [cache_ide1_search_start] + ret +.ide1_appl_data: + mov ecx, [cache_ide1_appl_sad_size] + mov edi, [cache_ide1_appl_search_start] + ret +.ide2: + cmp [hdpos], 3 + jne .ide3 + cmp [hdd_appl_data], 0 + jne .ide2_appl_data + mov ecx, [cache_ide2_system_sad_size] + mov edi, [cache_ide2_search_start] + ret +.ide2_appl_data: + mov ecx, [cache_ide2_appl_sad_size] + mov edi, [cache_ide2_appl_search_start] + ret +.ide3: + cmp [hdpos], 4 + jne .noide + cmp [hdd_appl_data], 0 + jne .ide3_appl_data + mov ecx, [cache_ide3_system_sad_size] + mov edi, [cache_ide3_search_start] + ret +.ide3_appl_data: + mov ecx, [cache_ide3_appl_sad_size] + mov edi, [cache_ide3_appl_search_start] + ret +.noide: + push eax + mov eax, [hdpos] + sub eax, 80h + cmp byte [BiosDisksData+eax*4+2], -1 + jz @f + movzx eax, byte [BiosDisksData+eax*4+2] + imul eax, cache_ide1-cache_ide0 + add eax, cache_ide0 + jmp .get +@@: + imul eax, cache_ide1-cache_ide0 + add eax, BiosDiskCaches +.get: + cmp [hdd_appl_data], 0 + jne .bd_appl_data + mov ecx, [cache_ide0_system_sad_size-cache_ide0+eax] + mov edi, [cache_ide0_search_start-cache_ide0+eax] + pop eax + ret +.bd_appl_data: + mov ecx, [cache_ide0_appl_sad_size-cache_ide0+eax] + mov edi, [cache_ide0_appl_search_start-cache_ide0+eax] + pop eax + ret +;-------------------------------------------------------------------- +align 4 +calculate_cache_4: +; cmp edi,cache_max +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [hdpos], 1 + jne .ide1 + cmp [hdd_appl_data], 0 + jne .ide0_appl_data + cmp edi, [cache_ide0_system_sad_size] + ret +.ide0_appl_data: + cmp edi, [cache_ide0_appl_sad_size] + ret +.ide1: + cmp [hdpos], 2 + jne .ide2 + cmp [hdd_appl_data], 0 + jne .ide1_appl_data + cmp edi, [cache_ide1_system_sad_size] + ret +.ide1_appl_data: + cmp edi, [cache_ide1_appl_sad_size] + ret +.ide2: + cmp [hdpos], 3 + jne .ide3 + cmp [hdd_appl_data], 0 + jne .ide2_appl_data + cmp edi, [cache_ide2_system_sad_size] + ret +.ide2_appl_data: + cmp edi, [cache_ide2_appl_sad_size] + ret +.ide3: + cmp [hdpos], 4 + jne .noide + cmp [hdd_appl_data], 0 + jne .ide3_appl_data + cmp edi, [cache_ide3_system_sad_size] + ret +.ide3_appl_data: + cmp edi, [cache_ide3_appl_sad_size] + ret +.noide: + push eax + mov eax, [hdpos] + sub eax, 80h + cmp byte [BiosDisksData+eax*4+2], -1 + jz @f + movzx eax, byte [BiosDisksData+eax*4+2] + imul eax, cache_ide1-cache_ide0 + add eax, cache_ide0 + jmp .get +@@: + imul eax, cache_ide1-cache_ide0 + add eax, BiosDiskCaches +.get: + cmp [hdd_appl_data], 0 + jne .bd_appl_data + cmp edi, [cache_ide0_system_sad_size-cache_ide0+eax] + pop eax + ret +.bd_appl_data: + cmp edi, [cache_ide0_appl_sad_size-cache_ide0+eax] + pop eax + ret + +;-------------------------------------------------------------------- +align 4 +calculate_cache_5: +; mov [cache_search_start],edi +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [hdpos], 1 + jne .ide1 + cmp [hdd_appl_data], 0 + jne .ide0_appl_data + mov [cache_ide0_search_start], edi + ret +.ide0_appl_data: + mov [cache_ide0_appl_search_start], edi + ret +.ide1: + cmp [hdpos], 2 + jne .ide2 + cmp [hdd_appl_data], 0 + jne .ide1_appl_data + mov [cache_ide1_search_start], edi + ret +.ide1_appl_data: + mov [cache_ide1_appl_search_start], edi + ret +.ide2: + cmp [hdpos], 3 + jne .ide3 + cmp [hdd_appl_data], 0 + jne .ide2_appl_data + mov [cache_ide2_search_start], edi + ret +.ide2_appl_data: + mov [cache_ide2_appl_search_start], edi + ret +.ide3: + cmp [hdpos], 4 + jne .noide + cmp [hdd_appl_data], 0 + jne .ide3_appl_data + mov [cache_ide3_search_start], edi + ret +.ide3_appl_data: + mov [cache_ide3_appl_search_start], edi + ret +.noide: + push eax + mov eax, [hdpos] + sub eax, 80h + cmp byte [BiosDisksData+eax*4+2], -1 + jz @f + movzx eax, byte [BiosDisksData+eax*4+2] + imul eax, cache_ide1-cache_ide0 + add eax, cache_ide0 + jmp .get +@@: + imul eax, cache_ide1-cache_ide0 + add eax, BiosDiskCaches +.get: + cmp [hdd_appl_data], 0 + jne .bd_appl_data + mov [cache_ide0_search_start-cache_ide0+eax], edi + pop eax + ret +.bd_appl_data: + mov [cache_ide0_appl_search_start-cache_ide0+eax], edi + pop eax + ret + +;-------------------------------------------------------------------- +align 4 +find_empty_slot_CD_cache: +;----------------------------------------------------------- +; find empty or read slot, flush cache if next 10% is used by write +; output : edi = cache slot +;----------------------------------------------------------- +.search_again: + call cd_calculate_cache_3 +.search_for_empty: + inc edi + call cd_calculate_cache_4 + jbe .inside_cache + mov edi, 1 +.inside_cache: + call cd_calculate_cache_5 + ret +;-------------------------------------------------------------------- +clear_CD_cache: + pusha +.ide0: + xor eax, eax + cmp [cdpos], 1 + jne .ide1 + mov [cache_ide0_search_start], eax + mov ecx, [cache_ide0_system_sad_size] + mov edi, [cache_ide0_pointer] + call .clear + mov [cache_ide0_appl_search_start], eax + mov ecx, [cache_ide0_appl_sad_size] + mov edi, [cache_ide0_data_pointer] + jmp .continue +.ide1: + cmp [cdpos], 2 + jne .ide2 + mov [cache_ide1_search_start], eax + mov ecx, [cache_ide1_system_sad_size] + mov edi, [cache_ide1_pointer] + call .clear + mov [cache_ide1_appl_search_start], eax + mov ecx, [cache_ide1_appl_sad_size] + mov edi, [cache_ide1_data_pointer] + jmp .continue +.ide2: + cmp [cdpos], 3 + jne .ide3 + mov [cache_ide2_search_start], eax + mov ecx, [cache_ide2_system_sad_size] + mov edi, [cache_ide2_pointer] + call .clear + mov [cache_ide2_appl_search_start], eax + mov ecx, [cache_ide2_appl_sad_size] + mov edi, [cache_ide2_data_pointer] + jmp .continue +.ide3: + mov [cache_ide3_search_start], eax + mov ecx, [cache_ide3_system_sad_size] + mov edi, [cache_ide3_pointer] + call .clear + mov [cache_ide3_appl_search_start], eax + mov ecx, [cache_ide3_appl_sad_size] + mov edi, [cache_ide3_data_pointer] +.continue: + call .clear + popa + ret +.clear: + shl ecx, 1 + cld + rep stosd + ret +;-------------------------------------------------------------------- +align 4 +cd_calculate_cache: +; mov ecx,cache_max ; entries in cache +; mov esi,HD_CACHE+8 + +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [cdpos], 1 + jne .ide1 + cmp [cd_appl_data], 0 + jne .ide0_appl_data + mov ecx, [cache_ide0_system_sad_size] + mov esi, [cache_ide0_pointer] + ret +.ide0_appl_data: + mov ecx, [cache_ide0_appl_sad_size] + mov esi, [cache_ide0_data_pointer] + ret +.ide1: + cmp [cdpos], 2 + jne .ide2 + cmp [cd_appl_data], 0 + jne .ide1_appl_data + mov ecx, [cache_ide1_system_sad_size] + mov esi, [cache_ide1_pointer] + ret +.ide1_appl_data: + mov ecx, [cache_ide1_appl_sad_size] + mov esi, [cache_ide1_data_pointer] + ret +.ide2: + cmp [cdpos], 3 + jne .ide3 + cmp [cd_appl_data], 0 + jne .ide2_appl_data + mov ecx, [cache_ide2_system_sad_size] + mov esi, [cache_ide2_pointer] + ret +.ide2_appl_data: + mov ecx, [cache_ide2_appl_sad_size] + mov esi, [cache_ide2_data_pointer] + ret +.ide3: + cmp [cd_appl_data], 0 + jne .ide3_appl_data + mov ecx, [cache_ide3_system_sad_size] + mov esi, [cache_ide3_pointer] + ret +.ide3_appl_data: + mov ecx, [cache_ide3_appl_sad_size] + mov esi, [cache_ide3_data_pointer] + ret +;-------------------------------------------------------------------- +align 4 +cd_calculate_cache_1: +; lea esi,[edi*8+HD_CACHE] +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [cdpos], 1 + jne .ide1 + cmp [cd_appl_data], 0 + jne .ide0_appl_data + mov esi, [cache_ide0_pointer] + ret +.ide0_appl_data: + mov esi, [cache_ide0_data_pointer] + ret +.ide1: + cmp [cdpos], 2 + jne .ide2 + cmp [cd_appl_data], 0 + jne .ide1_appl_data + mov esi, [cache_ide1_pointer] + ret +.ide1_appl_data: + mov esi, [cache_ide1_data_pointer] + ret +.ide2: + cmp [cdpos], 3 + jne .ide3 + cmp [cd_appl_data], 0 + jne .ide2_appl_data + mov esi, [cache_ide2_pointer] + ret +.ide2_appl_data: + mov esi, [cache_ide2_data_pointer] + ret +.ide3: + cmp [cd_appl_data], 0 + jne .ide3_appl_data + mov esi, [cache_ide3_pointer] + ret +.ide3_appl_data: + mov esi, [cache_ide3_data_pointer] + ret +;-------------------------------------------------------------------- +align 4 +cd_calculate_cache_2: +; add esi,HD_CACHE+65536 +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [cdpos], 1 + jne .ide1 + cmp [cd_appl_data], 0 + jne .ide0_appl_data + mov eax, [cache_ide0_system_data] + ret +.ide0_appl_data: + mov eax, [cache_ide0_appl_data] + ret +.ide1: + cmp [cdpos], 2 + jne .ide2 + cmp [cd_appl_data], 0 + jne .ide1_appl_data + mov eax, [cache_ide1_system_data] + ret +.ide1_appl_data: + mov eax, [cache_ide1_appl_data] + ret +.ide2: + cmp [cdpos], 3 + jne .ide3 + cmp [cd_appl_data], 0 + jne .ide2_appl_data + mov eax, [cache_ide2_system_data] + ret +.ide2_appl_data: + mov eax, [cache_ide2_appl_data] + ret +.ide3: + cmp [cd_appl_data], 0 + jne .ide3_appl_data + mov eax, [cache_ide3_system_data] + ret +.ide3_appl_data: + mov eax, [cache_ide3_appl_data] + ret +;-------------------------------------------------------------------- +align 4 +cd_calculate_cache_3: +; mov ecx,cache_max*10/100 +; mov edi,[cache_search_start] + +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [cdpos], 1 + jne .ide1 + cmp [cd_appl_data], 0 + jne .ide0_appl_data + mov edi, [cache_ide0_search_start] + ret +.ide0_appl_data: + mov edi, [cache_ide0_appl_search_start] + ret +.ide1: + cmp [cdpos], 2 + jne .ide2 + cmp [cd_appl_data], 0 + jne .ide1_appl_data + mov edi, [cache_ide1_search_start] + ret +.ide1_appl_data: + mov edi, [cache_ide1_appl_search_start] + ret +.ide2: + cmp [cdpos], 3 + jne .ide3 + cmp [cd_appl_data], 0 + jne .ide2_appl_data + mov edi, [cache_ide2_search_start] + ret +.ide2_appl_data: + mov edi, [cache_ide2_appl_search_start] + ret +.ide3: + cmp [cd_appl_data], 0 + jne .ide3_appl_data + mov edi, [cache_ide3_search_start] + ret +.ide3_appl_data: + mov edi, [cache_ide3_appl_search_start] + ret +;-------------------------------------------------------------------- +align 4 +cd_calculate_cache_4: +; cmp edi,cache_max +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [cdpos], 1 + jne .ide1 + cmp [cd_appl_data], 0 + jne .ide0_appl_data + cmp edi, [cache_ide0_system_sad_size] + ret +.ide0_appl_data: + cmp edi, [cache_ide0_appl_sad_size] + ret +.ide1: + cmp [cdpos], 2 + jne .ide2 + cmp [cd_appl_data], 0 + jne .ide1_appl_data + cmp edi, [cache_ide1_system_sad_size] + ret +.ide1_appl_data: + cmp edi, [cache_ide1_appl_sad_size] + ret +.ide2: + cmp [cdpos], 3 + jne .ide3 + cmp [cd_appl_data], 0 + jne .ide2_appl_data + cmp edi, [cache_ide2_system_sad_size] + ret +.ide2_appl_data: + cmp edi, [cache_ide2_appl_sad_size] + ret +.ide3: + cmp [cd_appl_data], 0 + jne .ide3_appl_data + cmp edi, [cache_ide3_system_sad_size] + ret +.ide3_appl_data: + cmp edi, [cache_ide3_appl_sad_size] + ret +;-------------------------------------------------------------------- +align 4 +cd_calculate_cache_5: +; mov [cache_search_start],edi +; 1 - IDE0 ... 4 - IDE3 +.ide0: + cmp [cdpos], 1 + jne .ide1 + cmp [cd_appl_data], 0 + jne .ide0_appl_data + mov [cache_ide0_search_start], edi + ret +.ide0_appl_data: + mov [cache_ide0_appl_search_start], edi + ret +.ide1: + cmp [cdpos], 2 + jne .ide2 + cmp [cd_appl_data], 0 + jne .ide1_appl_data + mov [cache_ide1_search_start], edi + ret +.ide1_appl_data: + mov [cache_ide1_appl_search_start], edi + ret +.ide2: + cmp [cdpos], 3 + jne .ide3 + cmp [cd_appl_data], 0 + jne .ide2_appl_data + mov [cache_ide2_search_start], edi + ret +.ide2_appl_data: + mov [cache_ide2_appl_search_start], edi + ret +.ide3: + cmp [cd_appl_data], 0 + jne .ide3_appl_data + mov [cache_ide3_search_start], edi + ret +.ide3_appl_data: + mov [cache_ide3_appl_search_start], edi + ret +;-------------------------------------------------------------------- +;align 4 +;calculate_linear_to_real: +; shr eax, 12 +; mov eax, [page_tabs+eax*4] +; and eax, 0xFFFFF000 +; ret diff --git a/kernel/trunk/blkdev/rd.inc b/kernel/trunk/blkdev/rd.inc index 8227c20b1..414dafe91 100644 --- a/kernel/trunk/blkdev/rd.inc +++ b/kernel/trunk/blkdev/rd.inc @@ -1,2272 +1,2273 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; RAMDISK functions ;; -;; (C) 2004 Ville Turjanmaa, License: GPL ;; -;; Addings by M.Lisovin ;; -;; LFN support by diamond ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; calculate fat chain - -calculatefatchain: - - pushad - - mov esi,RAMDISK+512 - mov edi,RAMDISK_FAT - - fcnew: - mov eax,dword [esi] - mov ebx,dword [esi+4] - mov ecx,dword [esi+8] - mov edx,ecx - shr edx,4 ;8 ok - shr dx,4 ;7 ok - xor ch,ch - shld ecx,ebx,20 ;6 ok - shr cx,4 ;5 ok - shld ebx,eax,12 - and ebx,0x0fffffff ;4 ok - shr bx,4 ;3 ok - shl eax,4 - and eax,0x0fffffff ;2 ok - shr ax,4 ;1 ok - mov dword [edi],eax - mov dword [edi+4],ebx - mov dword [edi+8],ecx - mov dword [edi+12],edx - add edi,16 - add esi,12 - - cmp edi,RAMDISK_FAT+2856*2 ;2849 clusters - jnz fcnew - - popad - ret - - -restorefatchain: ; restore fat chain - - pushad - - mov esi,RAMDISK_FAT - mov edi,RAMDISK+512 - - fcnew2: - mov eax,dword [esi] - mov ebx,dword [esi+4] - shl ax,4 - shl eax,4 - shl bx,4 - shr ebx,4 - shrd eax,ebx,8 - shr ebx,8 - mov dword [edi],eax - mov word [edi+4],bx - add edi,6 - add esi,8 - - cmp edi,RAMDISK+512+4278 ;4274 bytes - all used FAT - jb fcnew2 - - mov esi,RAMDISK+512 ; duplicate fat chain - mov edi,RAMDISK+512+0x1200 - mov ecx,1069 ;4274/4 - cld - rep movsd - - popad - ret - - -ramdisk_free_space: -;--------------------------------------------- -; -; returns free space in edi -; rewr.by Mihasik -;--------------------------------------------- - - push eax ebx ecx - - mov edi,RAMDISK_FAT ;start of FAT - xor ax,ax ;Free cluster=0x0000 in FAT - xor ebx,ebx ;counter - mov ecx,2849 ;2849 clusters - cld - rdfs1: - repne scasw - jnz rdfs2 ;if last cluster not 0 - inc ebx - test ecx, ecx - jnz rdfs1 - rdfs2: - shl ebx,9 ;free clusters*512 - mov edi,ebx - - pop ecx ebx eax - ret - - -expand_filename: -;--------------------------------------------- -; -; exapand filename with '.' to 11 character -; eax - pointer to filename -;--------------------------------------------- - - push esi edi ebx - - mov edi,esp ; check for '.' in the name - add edi,12+8 - - mov esi,eax - - mov eax,edi - mov [eax+0],dword ' ' - mov [eax+4],dword ' ' - mov [eax+8],dword ' ' - - flr1: - - cmp [esi],byte '.' - jne flr2 - mov edi,eax - add edi,7 - jmp flr3 - - flr2: - - mov bl,[esi] - mov [edi],bl - - flr3: - - inc esi - inc edi - - mov ebx,eax - add ebx,11 - - cmp edi,ebx - jbe flr1 - - pop ebx edi esi - ret - -fileread: -;---------------------------------------------------------------- -; -; fileread - sys floppy -; -; eax points to filename 11 chars -; ebx first wanted block ; 1+ ; if 0 then set to 1 -; ecx number of blocks to read ; 1+ ; if 0 then set to 1 -; edx mem location to return data -; esi length of filename 12*X 0=root -; -; ret ebx = size or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- - test ebx,ebx ;if ebx=0 - set to 1 - jnz frfl5 - inc ebx - frfl5: - test ecx,ecx ;if ecx=0 - set to 1 - jnz frfl6 - inc ecx - frfl6: - test esi,esi ; return ramdisk root - jnz fr_noroot ;if not root - cmp ebx,14 ;14 clusters=root dir - ja oorr - cmp ecx,14 - ja oorr - jmp fr_do - oorr: - mov eax,5 ;out of root range (fnf) - xor ebx,ebx - dec ebx ;0xffffffff - ret - - fr_do: ;reading rootdir - mov edi,edx - dec ebx - push edx - mov edx,ecx - add edx,ebx - cmp edx,15 ;ebx+ecx=14+1 - pushf - jbe fr_do1 - sub edx,14 - sub ecx,edx - fr_do1: - shl ebx,9 - mov esi,RAMDISK+512*19 - add esi,ebx - shl ecx,7 - cld - rep movsd - popf - pop edx - jae fr_do2 - xor eax,eax ; ok read - xor ebx,ebx - ret - fr_do2: ;if last cluster - mov eax,6 ;end of file - xor ebx,ebx - ret - - fr_noroot: - - sub esp,32 - call expand_filename - - dec ebx - - push eax - - push eax ebx ecx edx esi edi - call rd_findfile - je fifound - add esp,32+28 ;if file not found - ret - - fifound: - - mov ebx,[edi-11+28] ;file size - mov [esp+20],ebx - mov [esp+24],ebx - add edi,0xf - movzx eax,word [edi] - mov edi,eax ;edi=cluster - - frnew: - - add eax,31 ;bootsector+2*fat+filenames - shl eax,9 ;*512 - add eax,RAMDISK ;image base - mov ebx,[esp+8] - mov ecx,512 ;[esp+4] - - cmp [esp+16],dword 0 ; wanted cluster ? - jne frfl7 - call memmove - add [esp+8],dword 512 - dec dword [esp+12] ; last wanted cluster ? - je frnoread - jmp frfl8 - frfl7: - dec dword [esp+16] - frfl8: - movzx eax,word [edi*2+RAMDISK_FAT] ; find next cluster from FAT - mov edi,eax - cmp edi,4095 ;eof - cluster - jz frnoread2 - - cmp [esp+24],dword 512 ;eof - size - jb frnoread - sub [esp+24],dword 512 - - jmp frnew - - frnoread2: - - cmp [esp+16],dword 0 ; eof without read ? - je frnoread - - pop edi esi edx ecx - add esp,4 - pop ebx ; ebx <- eax : size of file - add esp,36 - mov eax,6 ; end of file - ret - - frnoread: - - pop edi esi edx ecx - add esp,4 - pop ebx ; ebx <- eax : size of file - add esp,36 - xor eax,eax ;read ok - ret - - - - rd_findfile: - ;by Mihasik - ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx - - mov edi,RAMDISK+512*18+512 ;Point at directory - cld - rd_newsearch: - mov esi,eax - mov ecx,11 - rep cmpsb - je rd_ff - add cl,21 - add edi,ecx - cmp edi,RAMDISK+512*33 - jb rd_newsearch - mov eax,5 ;if file not found - eax=5 - xor ebx,ebx - dec ebx ;ebx=0xffffffff and zf=0 - rd_ff: - ret - -; \begin{diamond} - -uni2ansi_str: -; convert UNICODE zero-terminated string to ASCII-string (codepage 866) -; in: esi->source, edi->buffer (may be esi=edi) -; destroys: eax,esi,edi - lodsw - test ax, ax - jz .done - cmp ax, 0x80 - jb .ascii - cmp ax, 0x401 - jz .yo1 - cmp ax, 0x451 - jz .yo2 - cmp ax, 0x410 - jb .unk - cmp ax, 0x440 - jb .rus1 - cmp ax, 0x450 - jb .rus2 -.unk: - mov al, '_' - jmp .doit -.yo1: - mov al, 'р' - jmp .doit -.yo2: - mov al, 'с' - jmp .doit -.rus1: -; 0x410-0x43F -> 0x80-0xAF - add al, 0x70 - jmp .doit -.rus2: -; 0x440-0x44F -> 0xE0-0xEF - add al, 0xA0 -.ascii: -.doit: - stosb - jmp uni2ansi_str -.done: - mov byte [edi], 0 - ret - -ansi2uni_char: -; convert ANSI character in al to UNICODE character in ax, using cp866 encoding - mov ah, 0 -; 0x00-0x7F - trivial map - cmp al, 0x80 - jb .ret -; 0x80-0xAF -> 0x410-0x43F - cmp al, 0xB0 - jae @f - add ax, 0x410-0x80 -.ret: - ret -@@: -; 0xE0-0xEF -> 0x440-0x44F - cmp al, 0xE0 - jb .unk - cmp al, 0xF0 - jae @f - add ax, 0x440-0xE0 - ret -; 0xF0 -> 0x401 -; 0xF1 -> 0x451 -@@: - cmp al, 'р' - jz .yo1 - cmp al, 'с' - jz .yo2 -.unk: - mov al, '_' ; ah=0 - ret -.yo1: - mov ax, 0x401 - ret -.yo2: - mov ax, 0x451 - ret - -char_toupper: -; convert character to uppercase, using cp866 encoding -; in: al=symbol -; out: al=converted symbol - cmp al, 'a' - jb .ret - cmp al, 'z' - jbe .az - cmp al, 'с' - jz .yo1 - cmp al, ' ' - jb .ret - cmp al, 'а' - jb .rus1 - cmp al, 'п' - ja .ret -; 0xE0-0xEF -> 0x90-0x9F - sub al, 'а'-'ђ' -.ret: - ret -.rus1: -; 0xA0-0xAF -> 0x80-0x8F -.az: - and al, not 0x20 - ret -.yo1: -; 0xF1 -> 0xF0 - dec ax - ret - -fat_get_name: -; in: edi->FAT entry -; out: CF=1 - no valid entry -; else CF=0 and ebp->ASCIIZ-name -; (maximum length of filename is 255 (wide) symbols without trailing 0, -; but implementation requires buffer 261 words) -; destroys eax - cmp byte [edi], 0 - jz .no - cmp byte [edi], 0xE5 - jnz @f -.no: - stc - ret -@@: - cmp byte [edi+11], 0xF - jz .longname - test byte [edi+11], 8 - jnz .no - push ecx - push edi ebp - test byte [ebp-4], 1 - jnz .unicode_short - - mov eax, [edi] - mov ecx, [edi+4] - mov [ebp], eax - mov [ebp+4], ecx - - mov ecx, 8 -@@: - cmp byte [ebp+ecx-1], ' ' - loope @b - - mov eax, [edi+8] - cmp al, ' ' - je .done - shl eax, 8 - mov al, '.' - - lea ebp, [ebp+ecx+1] - mov [ebp], eax - mov ecx, 3 -@@: - rol eax, 8 - cmp al, ' ' - jne .done - loop @b - dec ebp -.done: - and byte [ebp+ecx+1], 0 ; CF=0 - pop ebp edi ecx - ret -.unicode_short: - mov ecx, 8 - push ecx -@@: - mov al, [edi] - inc edi - call ansi2uni_char - mov [ebp], ax - inc ebp - inc ebp - loop @b - pop ecx -@@: - cmp word [ebp-2], ' ' - jnz @f - dec ebp - dec ebp - loop @b -@@: - mov word [ebp], '.' - inc ebp - inc ebp - mov ecx, 3 - push ecx -@@: - mov al, [edi] - inc edi - call ansi2uni_char - mov [ebp], ax - inc ebp - inc ebp - loop @b - pop ecx -@@: - cmp word [ebp-2], ' ' - jnz @f - dec ebp - dec ebp - loop @b - dec ebp - dec ebp -@@: - and word [ebp], 0 ; CF=0 - pop ebp edi ecx - ret -.longname: -; LFN - mov al, byte [edi] - and eax, 0x3F - dec eax - cmp al, 20 - jae .no ; ignore invalid entries - mov word [ebp+260*2], 0 ; force null-terminating for orphans - imul eax, 13*2 - add ebp, eax - test byte [edi], 0x40 - jz @f - mov word [ebp+13*2], 0 -@@: - push eax -; now copy name from edi to ebp ... - mov eax, [edi+1] - mov [ebp], eax ; symbols 1,2 - mov eax, [edi+5] - mov [ebp+4], eax ; 3,4 - mov eax, [edi+9] - mov [ebp+8], ax ; 5 - mov eax, [edi+14] - mov [ebp+10], eax ; 6,7 - mov eax, [edi+18] - mov [ebp+14], eax ; 8,9 - mov eax, [edi+22] - mov [ebp+18], eax ; 10,11 - mov eax, [edi+28] - mov [ebp+22], eax ; 12,13 -; ... done - pop eax - sub ebp, eax - test eax, eax - jz @f -; if this is not first entry, more processing required - stc - ret -@@: -; if this is first entry: - test byte [ebp-4], 1 - jnz .ret -; buffer at ebp contains UNICODE name, convert it to ANSI - push esi edi - mov esi, ebp - mov edi, ebp - call uni2ansi_str - pop edi esi -.ret: - clc - ret - -fat_compare_name: -; compares ASCIIZ-names, case-insensitive (cp866 encoding) -; in: esi->name, ebp->name -; out: if names match: ZF=1 and esi->next component of name -; else: ZF=0, esi is not changed -; destroys eax - push ebp esi -.loop: - mov al, [ebp] - inc ebp - call char_toupper - push eax - lodsb - call char_toupper - cmp al, [esp] - jnz .done - pop eax - test al, al - jnz .loop - dec esi - pop eax - pop ebp - xor eax, eax ; set ZF flag - ret -.done: - cmp al, '/' - jnz @f - cmp byte [esp], 0 - jnz @f - mov [esp+4], esi -@@: - pop eax - pop esi ebp - ret - -fat_time_to_bdfe: -; in: eax=FAT time -; out: eax=BDFE time - push ecx edx - mov ecx, eax - mov edx, eax - shr eax, 11 - shl eax, 16 ; hours - and edx, 0x1F - add edx, edx - mov al, dl ; seconds - shr ecx, 5 - and ecx, 0x3F - mov ah, cl ; minutes - pop edx ecx - ret - -fat_date_to_bdfe: - push ecx edx - mov ecx, eax - mov edx, eax - shr eax, 9 - add ax, 1980 - shl eax, 16 ; year - and edx, 0x1F - mov al, dl ; day - shr ecx, 5 - and ecx, 0xF - mov ah, cl ; month - pop edx ecx - ret - -bdfe_to_fat_time: - push edx - mov edx, eax - shr eax, 16 - and dh, 0x3F - shl eax, 6 - or al, dh - shr dl, 1 - and dl, 0x1F - shl eax, 5 - or al, dl - pop edx - ret - -bdfe_to_fat_date: - push edx - mov edx, eax - shr eax, 16 - sub ax, 1980 - and dh, 0xF - shl eax, 4 - or al, dh - and dl, 0x1F - shl eax, 5 - or al, dl - pop edx - ret - -fat_entry_to_bdfe: -; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi -; destroys eax - mov eax, [ebp-4] - mov [esi+4], eax ; ASCII/UNICODE name -fat_entry_to_bdfe2: - movzx eax, byte [edi+11] - mov [esi], eax ; attributes - movzx eax, word [edi+14] - call fat_time_to_bdfe - mov [esi+8], eax ; creation time - movzx eax, word [edi+16] - call fat_date_to_bdfe - mov [esi+12], eax ; creation date - and dword [esi+16], 0 ; last access time is not supported on FAT - movzx eax, word [edi+18] - call fat_date_to_bdfe - mov [esi+20], eax ; last access date - movzx eax, word [edi+22] - call fat_time_to_bdfe - mov [esi+24], eax ; last write time - movzx eax, word [edi+24] - call fat_date_to_bdfe - mov [esi+28], eax ; last write date - mov eax, [edi+28] - mov [esi+32], eax ; file size (low dword) - xor eax, eax - mov [esi+36], eax ; file size (high dword) - test ebp, ebp - jz .ret - push ecx edi - lea edi, [esi+40] - mov esi, ebp - test byte [esi-4], 1 - jz .ansi - mov ecx, 260/2 - rep movsd - mov [edi-2], ax -@@: - mov esi, edi - pop edi ecx -.ret: - ret -.ansi: - mov ecx, 264/4 - rep movsd - mov [edi-1], al - jmp @b - -bdfe_to_fat_entry: -; convert BDFE at edx to FAT entry at edi -; destroys eax -; attributes byte - test byte [edi+11], 8 ; volume label? - jnz @f - mov al, [edx] - and al, 0x27 - and byte [edi+11], 0x10 - or byte [edi+11], al -@@: - mov eax, [edx+8] - call bdfe_to_fat_time - mov [edi+14], ax ; creation time - mov eax, [edx+12] - call bdfe_to_fat_date - mov [edi+16], ax ; creation date - mov eax, [edx+20] - call bdfe_to_fat_date - mov [edi+18], ax ; last access date - mov eax, [edx+24] - call bdfe_to_fat_time - mov [edi+22], ax ; last write time - mov eax, [edx+28] - call bdfe_to_fat_date - mov [edi+24], ax ; last write date - ret - -ramdisk_root_first: - mov edi, RAMDISK+512*19 - clc - ret -ramdisk_root_next: - add edi, 0x20 - cmp edi, RAMDISK+512*33 - cmc - ret - -ramdisk_root_extend_dir: - stc - ret - -uglobal -; this is for delete support -rd_prev_sector dd ? -rd_prev_prev_sector dd ? -endg - -ramdisk_notroot_next: - add edi, 0x20 - test edi, 0x1FF - jz ramdisk_notroot_next_sector - ret ; CF=0 -ramdisk_notroot_next_sector: - push ecx - mov ecx, [eax] - push [rd_prev_sector] - pop [rd_prev_prev_sector] - mov [rd_prev_sector], ecx - mov ecx, [ecx*2+RAMDISK_FAT] - and ecx, 0xFFF - cmp ecx, 2849 - jae ramdisk_notroot_first.err2 - mov [eax], ecx - pop ecx -ramdisk_notroot_first: - mov eax, [eax] - cmp eax, 2 - jb .err - cmp eax, 2849 - jae .err - shl eax, 9 - lea edi, [eax+(31 shl 9)+RAMDISK] - clc - ret -.err2: - pop ecx -.err: - stc - ret -ramdisk_notroot_next_write: - test edi, 0x1FF - jz ramdisk_notroot_next_sector -ramdisk_root_next_write: - ret - -ramdisk_notroot_extend_dir: - pusha - xor eax, eax - mov edi, RAMDISK_FAT - mov ecx, 2849 - repnz scasw - jnz .notfound - mov word [edi-2], 0xFFF - sub edi, RAMDISK_FAT - shr edi, 1 - dec edi - mov eax, [esp+28] - mov ecx, [eax] - mov [RAMDISK_FAT+ecx*2], di - mov [eax], edi - shl edi, 9 - add edi, (31 shl 9)+RAMDISK - mov [esp], edi - xor eax, eax - mov ecx, 128 - rep stosd - popa - clc - ret -.notfound: - popa - stc - ret - -rd_find_lfn: -; in: esi+ebp -> name -; out: CF=1 - file not found -; else CF=0 and edi->direntry - push esi edi - push 0 - push ramdisk_root_first - push ramdisk_root_next -.loop: - call fat_find_lfn - jc .notfound - cmp byte [esi], 0 - jz .found -.continue: - test byte [edi+11], 10h - jz .notfound - movzx eax, word [edi+26] - mov [esp+8], eax - mov dword [esp+4], ramdisk_notroot_first - mov dword [esp], ramdisk_notroot_next - test eax, eax - jnz .loop - mov dword [esp+4], ramdisk_root_first - mov dword [esp], ramdisk_notroot_next - jmp .loop -.notfound: - add esp, 12 - pop edi esi - stc - ret -.found: - test ebp, ebp - jz @f - mov esi, ebp - xor ebp, ebp - jmp .continue -@@: - mov eax, [esp+8] - add esp, 16 ; CF=0 - pop esi - ret - -;---------------------------------------------------------------- -; -; fs_RamdiskRead - LFN variant for reading sys floppy -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to read, 0+ -; edx mem location to return data -; -; ret ebx = bytes read or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_RamdiskRead: - cmp byte [esi], 0 - jnz @f - or ebx, -1 - mov eax, 10 ; access denied - ret -@@: - push edi - call rd_find_lfn - jnc .found - pop edi - or ebx, -1 - mov eax, 5 ; file not found - ret -.found: - test ebx, ebx - jz .l1 - cmp dword [ebx+4], 0 - jz @f - xor ebx, ebx -.reteof: - mov eax, 6 ; EOF - pop edi - ret -@@: - mov ebx, [ebx] -.l1: - push ecx edx - push 0 - mov eax, [edi+28] - sub eax, ebx - jb .eof - cmp eax, ecx - jae @f - mov ecx, eax - mov byte [esp], 6 ; EOF -@@: - movzx edi, word [edi+26] ; cluster -.new: - jecxz .done - test edi, edi - jz .eof - cmp edi, 0xFF8 - jae .eof - lea eax, [edi+31] ; bootsector+2*fat+filenames - shl eax, 9 ; *512 - add eax, RAMDISK ; image base -; now eax points to data of cluster - sub ebx, 512 - jae .skip - lea eax, [eax+ebx+512] - neg ebx - push ecx - cmp ecx, ebx - jbe @f - mov ecx, ebx -@@: - mov ebx, edx - call memmove - add edx, ecx - sub [esp], ecx - pop ecx - xor ebx, ebx -.skip: - movzx edi, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT - jmp .new -.eof: - mov ebx, edx - pop eax edx ecx - sub ebx, edx - jmp .reteof -.done: - mov ebx, edx - pop eax edx ecx edi - sub ebx, edx - ret - -;---------------------------------------------------------------- -; -; fs_RamdiskReadFolder - LFN variant for reading sys floppy folder -; -; esi points to filename; only root is folder on ramdisk -; ebx pointer to structure 32-bit number = first wanted block -; & flags (bitfields) -; flags: bit 0: 0=ANSI names, 1=UNICODE names -; ecx number of blocks to read, 0+ -; edx mem location to return data -; -; ret ebx = size or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_RamdiskReadFolder: - push edi - cmp byte [esi], 0 - jz .root - call rd_find_lfn - jnc .found - pop edi - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret -.found: - test byte [edi+11], 0x10 - jnz .found_dir - pop edi - or ebx, -1 - mov eax, ERROR_ACCESS_DENIED - ret -.found_dir: - movzx eax, word [edi+26] - add eax, 31 - push 0 - jmp .doit -.root: - mov eax, 19 - push 14 -.doit: - push esi ecx ebp - sub esp, 262*2 ; reserve space for LFN - mov ebp, esp - push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names - mov ebx, [ebx] -; init header - push eax ecx - mov edi, edx - mov ecx, 32/4 - xor eax, eax - rep stosd - mov byte [edx], 1 ; version - pop ecx eax - mov esi, edi ; esi points to block of data of folder entry (BDFE) -.main_loop: - mov edi, eax - shl edi, 9 - add edi, RAMDISK - push eax -.l1: - call fat_get_name - jc .l2 - cmp byte [edi+11], 0xF - jnz .do_bdfe - add edi, 0x20 - test edi, 0x1FF - jnz .do_bdfe - pop eax - inc eax - dec byte [esp+262*2+16] - jz .done - jns @f -; read next sector from FAT - mov eax, [(eax-31-1)*2+RAMDISK_FAT] - and eax, 0xFFF - cmp eax, 0xFF8 - jae .done - add eax, 31 - mov byte [esp+262*2+16], 0 -@@: - mov edi, eax - shl edi, 9 - add edi, RAMDISK - push eax -.do_bdfe: - inc dword [edx+8] ; new file found - dec ebx - jns .l2 - dec ecx - js .l2 - inc dword [edx+4] ; new file block copied - call fat_entry_to_bdfe -.l2: - add edi, 0x20 - test edi, 0x1FF - jnz .l1 - pop eax - inc eax - dec byte [esp+262*2+16] - jz .done - jns @f -; read next sector from FAT - mov eax, [(eax-31-1)*2+RAMDISK_FAT] - and eax, 0xFFF - cmp eax, 0xFF8 - jae .done - add eax, 31 - mov byte [esp+262*2+16], 0 -@@: - jmp .main_loop -.done: - add esp, 262*2+4 - pop ebp - mov ebx, [edx+4] - xor eax, eax - dec ecx - js @f - mov al, ERROR_END_OF_FILE -@@: - pop ecx esi edi edi - ret - -iglobal -label fat_legal_chars byte -; 0 = not allowed -; 1 = allowed only in long names -; 3 = allowed - times 32 db 0 -; ! " # $ % & ' ( ) * + , - . / - db 1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0 -; 0 1 2 3 4 5 6 7 8 9 : ; < = > ? - db 3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0 -; @ A B C D E F G H I J K L M N O - db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 -; P Q R S T U V W X Y Z [ \ ] ^ _ - db 3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3 -; ` a b c d e f g h i j k l m n o - db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 -; p q r s t u v w x y z { | } ~ - db 3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0 -endg - -fat_name_is_legal: -; in: esi->(long) name -; out: CF set <=> legal -; destroys eax - push esi - xor eax, eax -@@: - lodsb - test al, al - jz .done - cmp al, 80h - jae .big - test [fat_legal_chars+eax], 1 - jnz @b -.err: - pop esi - clc - ret -.big: -; 0x80-0xAF, 0xE0-0xEF - cmp al, 0xB0 - jb @b - cmp al, 0xE0 - jb .err - cmp al, 0xF0 - jb @b - jmp .err -.done: - sub esi, [esp] - cmp esi, 257 - pop esi - ret - -fat_next_short_name: -; in: edi->8+3 name -; out: name corrected -; CF=1 <=> error - pushad - mov ecx, 8 - mov al, '~' - std - push edi - add edi, 7 - repnz scasb - pop edi - cld - jz .tilde -; tilde is not found, insert "~1" at end - add edi, 6 - cmp word [edi], ' ' - jnz .insert_tilde -@@: dec edi - cmp byte [edi], ' ' - jz @b - inc edi -.insert_tilde: - mov word [edi], '~1' - popad - clc - ret -.tilde: - push edi - add edi, 7 - xor ecx, ecx -@@: -; after tilde may be only digits and trailing spaces - cmp byte [edi], '~' - jz .break - cmp byte [edi], ' ' - jz .space - cmp byte [edi], '9' - jnz .found - dec edi - jmp @b -.space: - dec edi - inc ecx - jmp @b -.found: - inc byte [edi] - add dword [esp], 8 - jmp .zerorest -.break: - jecxz .noplace - inc edi - mov al, '1' -@@: - xchg al, [edi] - inc edi - cmp al, ' ' - mov al, '0' - jnz @b -.succ: - pop edi - popad - clc - ret -.noplace: - dec edi - cmp edi, [esp] - jz .err - add dword [esp], 8 - mov word [edi], '~1' - inc edi - inc edi -@@: - mov byte [edi], '0' -.zerorest: - inc edi - cmp edi, [esp] - jb @b - pop edi - popad - ;clc ; automatically - ret -.err: - pop edi - popad - stc - ret - -fat_gen_short_name: -; in: esi->long name -; edi->buffer (8+3=11 chars) -; out: buffer filled - pushad - mov eax, ' ' - push edi - stosd - stosd - stosd - pop edi - xor eax, eax - push 8 - pop ebx - lea ecx, [edi+8] -.loop: - lodsb - test al, al - jz .done - call char_toupper - cmp al, ' ' - jz .space - cmp al, 80h - ja .big - test [fat_legal_chars+eax], 2 - jnz .symbol -.inv_symbol: - mov al, '_' - or bh, 1 -.symbol: - cmp al, '.' - jz .dot -.normal_symbol: - dec bl - jns .store - mov bl, 0 -.space: - or bh, 1 - jmp .loop -.store: - stosb - jmp .loop -.big: - cmp al, 0xB0 - jb .normal_symbol - cmp al, 0xE0 - jb .inv_symbol - cmp al, 0xF0 - jb .normal_symbol - jmp .inv_symbol -.dot: - test bh, 2 - jz .firstdot - pop ebx - add ebx, edi - sub ebx, ecx - push ebx - cmp ebx, ecx - jb @f - pop ebx - push ecx -@@: - cmp edi, ecx - jbe .skip -@@: - dec edi - mov al, [edi] - dec ebx - mov [ebx], al - mov byte [edi], ' ' - cmp edi, ecx - ja @b -.skip: - mov bh, 3 - jmp @f -.firstdot: - cmp bl, 8 - jz .space - push edi - or bh, 2 -@@: - mov edi, ecx - mov bl, 3 - jmp .loop -.done: - test bh, 2 - jz @f - pop edi -@@: - lea edi, [ecx-8] - test bh, 1 - jz @f - call fat_next_short_name -@@: - popad - ret - -;---------------------------------------------------------------- -; -; fs_RamdiskRewrite - LFN variant for writing ramdisk -; fs_RamdiskCreateFolder - create folder on ramdisk -; -; esi points to file/folder name -; ebx ignored (reserved) -; ecx number of bytes to write, 0+ (ignored for folders) -; edx mem location to data (ignored for folders) -; -; ret ebx = number of written bytes -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -@@: - mov eax, ERROR_ACCESS_DENIED - xor ebx, ebx - ret - -fs_RamdiskCreateFolder: - mov al, 1 ; create folder - jmp fs_RamdiskRewrite.common - -fs_RamdiskRewrite: - xor eax, eax ; create file -.common: - cmp byte [esi], 0 - jz @b - pushad - xor edi, edi - push esi - test ebp, ebp - jz @f - mov esi, ebp -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jnz @b - lea edi, [esi-1] - jmp @b -@@: - pop esi - test edi, edi - jnz .noroot - test ebp, ebp - jnz .hasebp - push ramdisk_root_extend_dir - push ramdisk_root_next_write - push edi - push ramdisk_root_first - push ramdisk_root_next - jmp .common1 -.hasebp: - mov eax, ERROR_ACCESS_DENIED - cmp byte [ebp], 0 - jz .ret1 - push ebp - xor ebp, ebp - call rd_find_lfn - pop esi - jc .notfound0 - jmp .common0 -.noroot: - mov eax, ERROR_ACCESS_DENIED - cmp byte [edi+1], 0 - jz .ret1 -; check existence - mov byte [edi], 0 - push edi - call rd_find_lfn - pop esi - mov byte [esi], '/' - jnc @f -.notfound0: - mov eax, ERROR_FILE_NOT_FOUND -.ret1: - mov [esp+28], eax - popad - xor ebx, ebx - ret -@@: - inc esi -.common0: - test byte [edi+11], 0x10 ; must be directory - mov eax, ERROR_ACCESS_DENIED - jz .ret1 - movzx ebp, word [edi+26] ; ebp=cluster - mov eax, ERROR_FAT_TABLE - cmp ebp, 2 - jb .ret1 - cmp ebp, 2849 - jae .ret1 - push ramdisk_notroot_extend_dir - push ramdisk_notroot_next_write - push ebp - push ramdisk_notroot_first - push ramdisk_notroot_next -.common1: - call fat_find_lfn - jc .notfound -; found - test byte [edi+11], 10h - jz .exists_file -; found directory; if we are creating directory, return OK, -; if we are creating file, say "access denied" - add esp, 20 - popad - test al, al - mov eax, ERROR_ACCESS_DENIED - jz @f - mov al, 0 -@@: - xor ebx, ebx - ret -.exists_file: -; found file; if we are creating directory, return "access denied", -; if we are creating file, delete existing file and continue - cmp byte [esp+20+28], 0 - jz @f - add esp, 20 - popad - mov eax, ERROR_ACCESS_DENIED - xor ebx, ebx - ret -@@: -; delete FAT chain - push edi - xor eax, eax - mov dword [edi+28], eax ; zero size - xchg ax, word [edi+26] ; start cluster - test eax, eax - jz .done1 -@@: - cmp eax, 0xFF8 - jae .done1 - lea edi, [RAMDISK_FAT + eax*2] ; position in FAT - xor eax, eax - xchg ax, [edi] - jmp @b -.done1: - pop edi - call get_time_for_file - mov [edi+22], ax - call get_date_for_file - mov [edi+24], ax - mov [edi+18], ax - or byte [edi+11], 20h ; set 'archive' attribute - jmp .doit -.notfound: -; file is not found; generate short name - call fat_name_is_legal - jc @f - add esp, 20 - popad - mov eax, ERROR_FILE_NOT_FOUND - xor ebx, ebx - ret -@@: - sub esp, 12 - mov edi, esp - call fat_gen_short_name -.test_short_name_loop: - push esi edi ecx - mov esi, edi - lea eax, [esp+12+12+8] - mov [eax], ebp - call dword [eax-4] - jc .found -.test_short_name_entry: - cmp byte [edi+11], 0xF - jz .test_short_name_cont - mov ecx, 11 - push esi edi - repz cmpsb - pop edi esi - jz .short_name_found -.test_short_name_cont: - lea eax, [esp+12+12+8] - call dword [eax-8] - jnc .test_short_name_entry - jmp .found -.short_name_found: - pop ecx edi esi - call fat_next_short_name - jnc .test_short_name_loop -.disk_full: - add esp, 12+20 - popad - mov eax, ERROR_DISK_FULL - xor ebx, ebx - ret -.found: - pop ecx edi esi -; now find space in directory -; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' - mov al, '~' - push ecx edi - mov ecx, 8 - repnz scasb - push 1 - pop eax ; 1 entry - jnz .notilde -; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total - xor eax, eax -@@: - cmp byte [esi], 0 - jz @f - inc esi - inc eax - jmp @b -@@: - sub esi, eax - add eax, 12+13 - mov ecx, 13 - push edx - cdq - div ecx - pop edx -.notilde: - push -1 - push -1 -; find successive entries in directory - xor ecx, ecx - push eax - lea eax, [esp+12+8+12+8] - mov [eax], ebp - call dword [eax-4] - pop eax -.scan_dir: - cmp byte [edi], 0 - jz .free - cmp byte [edi], 0xE5 - jz .free - xor ecx, ecx -.scan_cont: - push eax - lea eax, [esp+12+8+12+8] - call dword [eax-8] - pop eax - jnc .scan_dir - push eax - lea eax, [esp+12+8+12+8] - call dword [eax+8] ; extend directory - pop eax - jnc .scan_dir - add esp, 8+8+12+20 - popad - mov eax, ERROR_DISK_FULL - xor ebx, ebx - ret -.free: - test ecx, ecx - jnz @f - mov [esp], edi - mov ecx, [esp+8+8+12+8] - mov [esp+4], ecx - xor ecx, ecx -@@: - inc ecx - cmp ecx, eax - jb .scan_cont -; found! -; calculate name checksum - push esi ecx - mov esi, [esp+8+8] - mov ecx, 11 - xor eax, eax -@@: - ror al, 1 - add al, [esi] - inc esi - loop @b - pop ecx esi - pop edi - pop dword [esp+8+12+8] -; edi points to last entry in free chunk - dec ecx - jz .nolfn - push esi - push eax - mov al, 40h -.writelfn: - or al, cl - mov esi, [esp+4] - push ecx - dec ecx - imul ecx, 13 - add esi, ecx - stosb - mov cl, 5 - call .read_symbols - mov ax, 0xF - stosw - mov al, [esp+4] - stosb - mov cl, 6 - call .read_symbols - xor eax, eax - stosw - mov cl, 2 - call .read_symbols - pop ecx - lea eax, [esp+8+8+12+8] - call dword [eax+4] ; next write - xor eax, eax - loop .writelfn - pop eax - pop esi -.nolfn: - xchg esi, [esp] - mov ecx, 11 - rep movsb - mov word [edi], 20h ; attributes - sub edi, 11 - pop esi ecx - add esp, 12 - mov byte [edi+13], 0 ; tenths of a second at file creation time - call get_time_for_file - mov [edi+14], ax ; creation time - mov [edi+22], ax ; last write time - call get_date_for_file - mov [edi+16], ax ; creation date - mov [edi+24], ax ; last write date - mov [edi+18], ax ; last access date - and word [edi+20], 0 ; high word of cluster - and word [edi+26], 0 ; low word of cluster - to be filled - and dword [edi+28], 0 ; file size - to be filled - cmp byte [esp+20+28], 0 - jz .doit -; create directory - mov byte [edi+11], 10h ; attributes: folder - mov ecx, 32*2 - mov edx, edi -.doit: - push edx - push ecx - push edi - add edi, 26 ; edi points to low word of cluster - push edi - jecxz .done - mov ecx, 2849 - mov edi, RAMDISK_FAT -.write_loop: -; allocate new cluster - xor eax, eax - repnz scasw - jnz .disk_full2 - dec edi - dec edi - - ; lea eax, [edi-(RAMDISK_FAT)] - - mov eax, edi - sub eax, RAMDISK_FAT - - shr eax, 1 ; eax = cluster - mov word [edi], 0xFFF ; mark as last cluster - xchg edi, [esp] - stosw - pop edi - push edi - inc ecx -; write data - cmp byte [esp+16+20+28], 0 - jnz .writedir - shl eax, 9 - add eax, RAMDISK+31*512 -.writefile: - mov ebx, edx - xchg eax, ebx - push ecx - mov ecx, 512 - cmp dword [esp+12], ecx - jae @f - mov ecx, [esp+12] -@@: - call memmove - add edx, ecx - sub [esp+12], ecx - pop ecx - jnz .write_loop -.done: - mov ebx, edx - pop edi edi ecx edx - sub ebx, edx - mov [edi+28], ebx - add esp, 20 - mov [esp+16], ebx - popad - xor eax, eax - ret -.disk_full2: - mov ebx, edx - pop edi edi ecx edx - sub ebx, edx - mov [edi+28], ebx - add esp, 20 - mov [esp+16], ebx - popad - push ERROR_DISK_FULL - pop eax - ret -.writedir: - mov edi, eax - shl edi, 9 - add edi, RAMDISK+31*512 - mov esi, edx - mov ecx, 32/4 - push ecx - rep movsd - mov dword [edi-32], '. ' - mov dword [edi-32+4], ' ' - mov dword [edi-32+8], ' ' - mov byte [edi-32+11], 10h - mov word [edi-32+26], ax - mov esi, edx - pop ecx - rep movsd - mov dword [edi-32], '.. ' - mov dword [edi-32+4], ' ' - mov dword [edi-32+8], ' ' - mov byte [edi-32+11], 10h - mov eax, [esp+16+8] - mov word [edi-32+26], ax - xor eax, eax - mov ecx, (512-32*2)/4 - rep stosd - pop edi edi ecx edx - add esp, 20 - popad - xor eax, eax - xor ebx, ebx - ret - -.read_symbol: - or ax, -1 - test esi, esi - jz .retFFFF - lodsb - test al, al - jnz ansi2uni_char - xor eax, eax - xor esi, esi -.retFFFF: - ret - -.read_symbols: - call .read_symbol - stosw - loop .read_symbols - ret - -;---------------------------------------------------------------- -; -; fs_RamdiskWrite - LFN variant for writing to sys floppy -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to write, 0+ -; edx mem location to data -; -; ret ebx = bytes written (maybe 0) -; eax = 0 ok write or other = errormsg -; -;-------------------------------------------------------------- -@@: - push ERROR_ACCESS_DENIED -fs_RamdiskWrite.ret0: - pop eax - xor ebx, ebx - ret - -fs_RamdiskWrite: - cmp byte [esi], 0 - jz @b - pushad - call rd_find_lfn - jnc .found - popad - push ERROR_FILE_NOT_FOUND - jmp .ret0 -.found: -; must not be directory - test byte [edi+11], 10h - jz @f - popad - push ERROR_ACCESS_DENIED - jmp .ret0 -@@: -; FAT does not support files larger than 4GB - test ebx, ebx - jz .l1 - cmp dword [ebx+4], 0 - jz @f -.eof: - popad - push ERROR_END_OF_FILE - jmp .ret0 -@@: - mov ebx, [ebx] -.l1: -; now edi points to direntry, ebx=start byte to write, -; ecx=number of bytes to write, edx=data pointer - call fat_update_datetime - -; extend file if needed - add ecx, ebx - jc .eof ; FAT does not support files larger than 4GB - push 0 ; return value=0 - cmp ecx, [edi+28] - jbe .length_ok - cmp ecx, ebx - jz .length_ok - call ramdisk_extend_file - jnc .length_ok -; ramdisk_extend_file can return two error codes: FAT table error or disk full. -; First case is fatal error, in second case we may write some data - mov [esp], eax - cmp al, ERROR_DISK_FULL - jz .disk_full - pop eax - mov [esp+28], eax - popad - xor ebx, ebx - ret -.disk_full: -; correct number of bytes to write - mov ecx, [edi+28] - cmp ecx, ebx - ja .length_ok -.ret: - pop eax - mov [esp+28], eax ; eax=return value - sub edx, [esp+20] - mov [esp+16], edx ; ebx=number of written bytes - popad - ret -.length_ok: -; now ebx=start pos, ecx=end pos, both lie inside file - sub ecx, ebx - jz .ret - movzx edi, word [edi+26] ; starting cluster -.write_loop: - sub ebx, 0x200 - jae .next_cluster - push ecx - neg ebx - cmp ecx, ebx - jbe @f - mov ecx, ebx -@@: - mov eax, edi - shl eax, 9 - add eax, RAMDISK+31*512+0x200 - sub eax, ebx - mov ebx, eax - mov eax, edx - call memmove - xor ebx, ebx - add edx, ecx - sub [esp], ecx - pop ecx - jz .ret -.next_cluster: - movzx edi, word [edi*2+RAMDISK_FAT] - jmp .write_loop - -ramdisk_extend_file.zero_size: - xor eax, eax - jmp ramdisk_extend_file.start_extend - -; extends file on ramdisk to given size, new data area is filled by 0 -; in: edi->direntry, ecx=new size -; out: CF=0 => OK, eax=0 -; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) -ramdisk_extend_file: - push ecx -; find the last cluster of file - movzx eax, word [edi+26] ; first cluster - mov ecx, [edi+28] - jecxz .zero_size -@@: - sub ecx, 0x200 - jbe @f - mov eax, [eax*2+RAMDISK_FAT] - and eax, 0xFFF - jz .fat_err - cmp eax, 0xFF8 - jb @b -.fat_err: - pop ecx - push ERROR_FAT_TABLE - pop eax - stc - ret -@@: - push eax - mov eax, [eax*2+RAMDISK_FAT] - and eax, 0xFFF - cmp eax, 0xFF8 - pop eax - jb .fat_err -; set length to full number of sectors and make sure that last sector is zero-padded - sub [edi+28], ecx - push eax edi - mov edi, eax - shl edi, 9 - lea edi, [edi+RAMDISK+31*512+0x200+ecx] - neg ecx - xor eax, eax - rep stosb - pop edi eax -.start_extend: - pop ecx -; now do extend - push edx esi - mov esi, RAMDISK_FAT+2*2 ; start scan from cluster 2 - mov edx, 2847 ; number of clusters to scan -.extend_loop: - cmp [edi+28], ecx - jae .extend_done -; add new sector - push ecx - mov ecx, edx - push edi - mov edi, esi - jecxz .disk_full - push eax - xor eax, eax - repnz scasw - pop eax - jnz .disk_full - mov word [edi-2], 0xFFF - mov esi, edi - mov edx, ecx - sub edi, RAMDISK_FAT - shr edi, 1 - dec edi ; now edi=new cluster - test eax, eax - jz .first_cluster - mov [RAMDISK_FAT+eax*2], di - jmp @f -.first_cluster: - pop eax ; eax->direntry - push eax - mov [eax+26], di -@@: - push edi - shl edi, 9 - add edi, RAMDISK+31*512 - xor eax, eax - mov ecx, 512/4 - rep stosd - pop eax ; eax=new cluster - pop edi ; edi->direntry - pop ecx ; ecx=required size - add dword [edi+28], 0x200 - jmp .extend_loop -.extend_done: - mov [edi+28], ecx - pop esi edx - xor eax, eax ; CF=0 - ret -.disk_full: - pop edi ecx - pop esi edx - stc - push ERROR_DISK_FULL - pop eax - ret - -fat_update_datetime: - call get_time_for_file - mov [edi+22], ax ; last write time - call get_date_for_file - mov [edi+24], ax ; last write date - mov [edi+18], ax ; last access date - ret - -;---------------------------------------------------------------- -; -; fs_RamdiskSetFileEnd - set end of file on ramdisk -; -; esi points to filename -; ebx points to 64-bit number = new file size -; ecx ignored (reserved) -; edx ignored (reserved) -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -fs_RamdiskSetFileEnd: - cmp byte [esi], 0 - jnz @f -.access_denied: - push ERROR_ACCESS_DENIED - jmp .ret -@@: - push edi - call rd_find_lfn - jnc @f - pop edi - push ERROR_FILE_NOT_FOUND -.ret: - pop eax - ret -@@: -; must not be directory - test byte [edi+11], 10h - jz @f - pop edi - jmp .access_denied -@@: -; file size must not exceed 4Gb - cmp dword [ebx+4], 0 - jz @f - pop edi - push ERROR_END_OF_FILE - jmp .ret -@@: -; set file modification date/time to current - call fat_update_datetime - mov eax, [ebx] - cmp eax, [edi+28] - jb .truncate - ja .expand - pop edi - xor eax, eax - ret -.expand: - push ecx - mov ecx, eax - call ramdisk_extend_file - pop ecx - pop edi - ret -.truncate: - mov [edi+28], eax - push ecx - movzx ecx, word [edi+26] - test eax, eax - jz .zero_size -; find new last sector -@@: - sub eax, 0x200 - jbe @f - movzx ecx, word [RAMDISK_FAT+ecx*2] - jmp @b -@@: -; zero data at the end of last sector - push ecx - mov edi, ecx - shl edi, 9 - lea edi, [edi+RAMDISK+31*512+eax+0x200] - mov ecx, eax - neg ecx - xor eax, eax - rep stosb - pop ecx -; terminate FAT chain - lea ecx, [RAMDISK_FAT+ecx+ecx] - push dword [ecx] - mov word [ecx], 0xFFF - pop ecx - and ecx, 0xFFF - jmp .delete -.zero_size: - and word [edi+26], 0 -.delete: -; delete FAT chain starting with ecx -; mark all clusters as free - cmp ecx, 0xFF8 - jae .deleted - lea ecx, [RAMDISK_FAT+ecx+ecx] - push dword [ecx] - and word [ecx], 0 - pop ecx - and ecx, 0xFFF - jmp .delete -.deleted: - pop ecx - pop edi - xor eax, eax - ret - -fs_RamdiskGetFileInfo: - cmp byte [esi], 0 - jnz @f - mov eax, 2 ; unsupported - ret -@@: - push edi - call rd_find_lfn -fs_GetFileInfo_finish: - jnc @f - pop edi - mov eax, ERROR_FILE_NOT_FOUND - ret -@@: - push esi ebp - xor ebp, ebp - mov esi, edx - and dword [esi+4], 0 - call fat_entry_to_bdfe2 - pop ebp esi - pop edi - xor eax, eax - ret - -fs_RamdiskSetFileInfo: - cmp byte [esi], 0 - jnz @f - mov eax, 2 ; unsupported - ret -@@: - push edi - call rd_find_lfn - jnc @f - pop edi - mov eax, ERROR_FILE_NOT_FOUND - ret -@@: - call bdfe_to_fat_entry - pop edi - xor eax, eax - ret - -;---------------------------------------------------------------- -; -; fs_RamdiskDelete - delete file or empty folder from ramdisk -; -; esi points to filename -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -fs_RamdiskDelete: - cmp byte [esi], 0 - jnz @f -; cannot delete root! -.access_denied: - push ERROR_ACCESS_DENIED -.pop_ret: - pop eax - ret -@@: - and [rd_prev_sector], 0 - and [rd_prev_prev_sector], 0 - push edi - call rd_find_lfn - jnc .found - pop edi - push ERROR_FILE_NOT_FOUND - jmp .pop_ret -.found: - cmp dword [edi], '. ' - jz .access_denied2 - cmp dword [edi], '.. ' - jz .access_denied2 - test byte [edi+11], 10h - jz .dodel -; we can delete only empty folders! - movzx eax, word [edi+26] - push ebx - mov ebx, eax - shl ebx, 9 - add ebx, RAMDISK + 31*0x200 + 2*0x20 -.checkempty: - cmp byte [ebx], 0 - jz .empty - cmp byte [ebx], 0xE5 - jnz .notempty - add ebx, 0x20 - test ebx, 0x1FF - jnz .checkempty - movzx eax, word [RAMDISK_FAT + eax*2] - test eax, eax - jz .empty - mov ebx, eax - shl ebx, 9 - add ebx, RAMDISK + 31*0x200 - jmp .checkempty -.notempty: - pop ebx -.access_denied2: - pop edi - jmp .access_denied -.empty: - pop ebx -.dodel: - movzx eax, word [edi+26] -; delete folder entry - mov byte [edi], 0xE5 -; delete LFN (if present) -.lfndel: - test edi, 0x1FF - jnz @f - cmp [rd_prev_sector], 0 - jz @f - cmp [rd_prev_sector], -1 - jz .lfndone - mov edi, [rd_prev_sector] - push [rd_prev_prev_sector] - pop [rd_prev_sector] - or [rd_prev_prev_sector], -1 - shl edi, 9 - add edi, RAMDISK + 31*0x200 + 0x200 -@@: - sub edi, 0x20 - cmp byte [edi], 0xE5 - jz .lfndone - cmp byte [edi+11], 0xF - jnz .lfndone - mov byte [edi], 0xE5 - jmp .lfndel -.lfndone: -; delete FAT chain - test eax, eax - jz .done - lea eax, [RAMDISK_FAT + eax*2] - push dword [eax] - and word [eax], 0 - pop eax - and eax, 0xFFF - jmp .lfndone -.done: - pop edi - xor eax, eax - ret - -; \end{diamond} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; RAMDISK functions ;; +;; (C) 2004 Ville Turjanmaa, License: GPL ;; +;; Addings by M.Lisovin ;; +;; LFN support by diamond ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; calculate fat chain + +calculatefatchain: + + pushad + + mov esi, RAMDISK+512 + mov edi, RAMDISK_FAT + + fcnew: + mov eax, dword [esi] + mov ebx, dword [esi+4] + mov ecx, dword [esi+8] + mov edx, ecx + shr edx, 4;8 ok + shr dx, 4;7 ok + xor ch, ch + shld ecx, ebx, 20;6 ok + shr cx, 4;5 ok + shld ebx, eax, 12 + and ebx, 0x0fffffff;4 ok + shr bx, 4;3 ok + shl eax, 4 + and eax, 0x0fffffff;2 ok + shr ax, 4;1 ok + mov dword [edi], eax + mov dword [edi+4], ebx + mov dword [edi+8], ecx + mov dword [edi+12], edx + add edi, 16 + add esi, 12 + + cmp edi, RAMDISK_FAT+2856*2;2849 clusters + jnz fcnew + + popad + ret + + +restorefatchain: ; restore fat chain + + pushad + + mov esi, RAMDISK_FAT + mov edi, RAMDISK+512 + + fcnew2: + mov eax, dword [esi] + mov ebx, dword [esi+4] + shl ax, 4 + shl eax, 4 + shl bx, 4 + shr ebx, 4 + shrd eax, ebx, 8 + shr ebx, 8 + mov dword [edi], eax + mov word [edi+4], bx + add edi, 6 + add esi, 8 + + cmp edi, RAMDISK+512+4278;4274 bytes - all used FAT + jb fcnew2 + + mov esi, RAMDISK+512 ; duplicate fat chain + mov edi, RAMDISK+512+0x1200 + mov ecx, 1069;4274/4 + cld + rep movsd + + popad + ret + + +ramdisk_free_space: +;--------------------------------------------- +; +; returns free space in edi +; rewr.by Mihasik +;--------------------------------------------- + + push eax ebx ecx + + mov edi, RAMDISK_FAT;start of FAT + xor ax, ax;Free cluster=0x0000 in FAT + xor ebx, ebx;counter + mov ecx, 2849;2849 clusters + cld + rdfs1: + repne scasw + jnz rdfs2 ;if last cluster not 0 + inc ebx + test ecx, ecx + jnz rdfs1 + rdfs2: + shl ebx, 9;free clusters*512 + mov edi, ebx + + pop ecx ebx eax + ret + + +expand_filename: +;--------------------------------------------- +; +; exapand filename with '.' to 11 character +; eax - pointer to filename +;--------------------------------------------- + + push esi edi ebx + + mov edi, esp ; check for '.' in the name + add edi, 12+8 + + mov esi, eax + + mov eax, edi + mov [eax+0], dword ' ' + mov [eax+4], dword ' ' + mov [eax+8], dword ' ' + + flr1: + + cmp [esi], byte '.' + jne flr2 + mov edi, eax + add edi, 7 + jmp flr3 + + flr2: + + mov bl, [esi] + mov [edi], bl + + flr3: + + inc esi + inc edi + + mov ebx, eax + add ebx, 11 + + cmp edi, ebx + jbe flr1 + + pop ebx edi esi + ret + +fileread: +;---------------------------------------------------------------- +; +; fileread - sys floppy +; +; eax points to filename 11 chars +; ebx first wanted block ; 1+ ; if 0 then set to 1 +; ecx number of blocks to read ; 1+ ; if 0 then set to 1 +; edx mem location to return data +; esi length of filename 12*X 0=root +; +; ret ebx = size or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- + test ebx, ebx;if ebx=0 - set to 1 + jnz frfl5 + inc ebx + frfl5: + test ecx, ecx;if ecx=0 - set to 1 + jnz frfl6 + inc ecx + frfl6: + test esi, esi ; return ramdisk root + jnz fr_noroot ;if not root + cmp ebx, 14 ;14 clusters=root dir + ja oorr + cmp ecx, 14 + ja oorr + jmp fr_do + oorr: + mov eax, 5 ;out of root range (fnf) + xor ebx, ebx + dec ebx ;0xffffffff + ret + + fr_do: ;reading rootdir + mov edi, edx + dec ebx + push edx + mov edx, ecx + add edx, ebx + cmp edx, 15 ;ebx+ecx=14+1 + pushf + jbe fr_do1 + sub edx, 14 + sub ecx, edx + fr_do1: + shl ebx, 9 + mov esi, RAMDISK+512*19 + add esi, ebx + shl ecx, 7 + cld + rep movsd + popf + pop edx + jae fr_do2 + xor eax, eax; ok read + xor ebx, ebx + ret + fr_do2: ;if last cluster + mov eax, 6;end of file + xor ebx, ebx + ret + + fr_noroot: + + sub esp, 32 + call expand_filename + + dec ebx + + push eax + + push eax ebx ecx edx esi edi + call rd_findfile + je fifound + add esp, 32+28 ;if file not found + ret + + fifound: + + mov ebx, [edi-11+28] ;file size + mov [esp+20], ebx + mov [esp+24], ebx + add edi, 0xf + movzx eax, word [edi] + mov edi, eax ;edi=cluster + + frnew: + + add eax, 31 ;bootsector+2*fat+filenames + shl eax, 9 ;*512 + add eax, RAMDISK ;image base + mov ebx, [esp+8] + mov ecx, 512 ;[esp+4] + + cmp [esp+16], dword 0 ; wanted cluster ? + jne frfl7 + call memmove + add [esp+8], dword 512 + dec dword [esp+12] ; last wanted cluster ? + je frnoread + jmp frfl8 + frfl7: + dec dword [esp+16] + frfl8: + movzx eax, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT + mov edi, eax + cmp edi, 4095 ;eof - cluster + jz frnoread2 + + cmp [esp+24], dword 512 ;eof - size + jb frnoread + sub [esp+24], dword 512 + + jmp frnew + + frnoread2: + + cmp [esp+16], dword 0 ; eof without read ? + je frnoread + + pop edi esi edx ecx + add esp, 4 + pop ebx ; ebx <- eax : size of file + add esp, 36 + mov eax, 6 ; end of file + ret + + frnoread: + + pop edi esi edx ecx + add esp, 4 + pop ebx ; ebx <- eax : size of file + add esp, 36 + xor eax, eax;read ok + ret + + + + rd_findfile: + ;by Mihasik + ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx + + mov edi, RAMDISK+512*18+512;Point at directory + cld + rd_newsearch: + mov esi, eax + mov ecx, 11 + rep cmpsb + je rd_ff + add cl, 21 + add edi, ecx + cmp edi, RAMDISK+512*33 + jb rd_newsearch + mov eax, 5 ;if file not found - eax=5 + xor ebx, ebx + dec ebx ;ebx=0xffffffff and zf=0 + rd_ff: + ret + +; \begin{diamond} + +uni2ansi_str: +; convert UNICODE zero-terminated string to ASCII-string (codepage 866) +; in: esi->source, edi->buffer (may be esi=edi) +; destroys: eax,esi,edi + lodsw + test ax, ax + jz .done + cmp ax, 0x80 + jb .ascii + cmp ax, 0x401 + jz .yo1 + cmp ax, 0x451 + jz .yo2 + cmp ax, 0x410 + jb .unk + cmp ax, 0x440 + jb .rus1 + cmp ax, 0x450 + jb .rus2 +.unk: + mov al, '_' + jmp .doit +.yo1: + mov al, 'р' + jmp .doit +.yo2: + mov al, 'с' + jmp .doit +.rus1: +; 0x410-0x43F -> 0x80-0xAF + add al, 0x70 + jmp .doit +.rus2: +; 0x440-0x44F -> 0xE0-0xEF + add al, 0xA0 +.ascii: +.doit: + stosb + jmp uni2ansi_str +.done: + mov byte [edi], 0 + ret + +ansi2uni_char: +; convert ANSI character in al to UNICODE character in ax, using cp866 encoding + mov ah, 0 +; 0x00-0x7F - trivial map + cmp al, 0x80 + jb .ret +; 0x80-0xAF -> 0x410-0x43F + cmp al, 0xB0 + jae @f + add ax, 0x410-0x80 +.ret: + ret +@@: +; 0xE0-0xEF -> 0x440-0x44F + cmp al, 0xE0 + jb .unk + cmp al, 0xF0 + jae @f + add ax, 0x440-0xE0 + ret +; 0xF0 -> 0x401 +; 0xF1 -> 0x451 +@@: + cmp al, 'р' + jz .yo1 + cmp al, 'с' + jz .yo2 +.unk: + mov al, '_' ; ah=0 + ret +.yo1: + mov ax, 0x401 + ret +.yo2: + mov ax, 0x451 + ret + +char_toupper: +; convert character to uppercase, using cp866 encoding +; in: al=symbol +; out: al=converted symbol + cmp al, 'a' + jb .ret + cmp al, 'z' + jbe .az + cmp al, 'с' + jz .yo1 + cmp al, ' ' + jb .ret + cmp al, 'а' + jb .rus1 + cmp al, 'п' + ja .ret +; 0xE0-0xEF -> 0x90-0x9F + sub al, 'а'-'ђ' +.ret: + ret +.rus1: +; 0xA0-0xAF -> 0x80-0x8F +.az: + and al, not 0x20 + ret +.yo1: +; 0xF1 -> 0xF0 + dec ax + ret + +fat_get_name: +; in: edi->FAT entry +; out: CF=1 - no valid entry +; else CF=0 and ebp->ASCIIZ-name +; (maximum length of filename is 255 (wide) symbols without trailing 0, +; but implementation requires buffer 261 words) +; destroys eax + cmp byte [edi], 0 + jz .no + cmp byte [edi], 0xE5 + jnz @f +.no: + stc + ret +@@: + cmp byte [edi+11], 0xF + jz .longname + test byte [edi+11], 8 + jnz .no + push ecx + push edi ebp + test byte [ebp-4], 1 + jnz .unicode_short + + mov eax, [edi] + mov ecx, [edi+4] + mov [ebp], eax + mov [ebp+4], ecx + + mov ecx, 8 +@@: + cmp byte [ebp+ecx-1], ' ' + loope @b + + mov eax, [edi+8] + cmp al, ' ' + je .done + shl eax, 8 + mov al, '.' + + lea ebp, [ebp+ecx+1] + mov [ebp], eax + mov ecx, 3 +@@: + rol eax, 8 + cmp al, ' ' + jne .done + loop @b + dec ebp +.done: + and byte [ebp+ecx+1], 0 ; CF=0 + pop ebp edi ecx + ret +.unicode_short: + mov ecx, 8 + push ecx +@@: + mov al, [edi] + inc edi + call ansi2uni_char + mov [ebp], ax + inc ebp + inc ebp + loop @b + pop ecx +@@: + cmp word [ebp-2], ' ' + jnz @f + dec ebp + dec ebp + loop @b +@@: + mov word [ebp], '.' + inc ebp + inc ebp + mov ecx, 3 + push ecx +@@: + mov al, [edi] + inc edi + call ansi2uni_char + mov [ebp], ax + inc ebp + inc ebp + loop @b + pop ecx +@@: + cmp word [ebp-2], ' ' + jnz @f + dec ebp + dec ebp + loop @b + dec ebp + dec ebp +@@: + and word [ebp], 0 ; CF=0 + pop ebp edi ecx + ret +.longname: +; LFN + mov al, byte [edi] + and eax, 0x3F + dec eax + cmp al, 20 + jae .no ; ignore invalid entries + mov word [ebp+260*2], 0 ; force null-terminating for orphans + imul eax, 13*2 + add ebp, eax + test byte [edi], 0x40 + jz @f + mov word [ebp+13*2], 0 +@@: + push eax +; now copy name from edi to ebp ... + mov eax, [edi+1] + mov [ebp], eax ; symbols 1,2 + mov eax, [edi+5] + mov [ebp+4], eax ; 3,4 + mov eax, [edi+9] + mov [ebp+8], ax ; 5 + mov eax, [edi+14] + mov [ebp+10], eax ; 6,7 + mov eax, [edi+18] + mov [ebp+14], eax ; 8,9 + mov eax, [edi+22] + mov [ebp+18], eax ; 10,11 + mov eax, [edi+28] + mov [ebp+22], eax ; 12,13 +; ... done + pop eax + sub ebp, eax + test eax, eax + jz @f +; if this is not first entry, more processing required + stc + ret +@@: +; if this is first entry: + test byte [ebp-4], 1 + jnz .ret +; buffer at ebp contains UNICODE name, convert it to ANSI + push esi edi + mov esi, ebp + mov edi, ebp + call uni2ansi_str + pop edi esi +.ret: + clc + ret + +fat_compare_name: +; compares ASCIIZ-names, case-insensitive (cp866 encoding) +; in: esi->name, ebp->name +; out: if names match: ZF=1 and esi->next component of name +; else: ZF=0, esi is not changed +; destroys eax + push ebp esi +.loop: + mov al, [ebp] + inc ebp + call char_toupper + push eax + lodsb + call char_toupper + cmp al, [esp] + jnz .done + pop eax + test al, al + jnz .loop + dec esi + pop eax + pop ebp + xor eax, eax ; set ZF flag + ret +.done: + cmp al, '/' + jnz @f + cmp byte [esp], 0 + jnz @f + mov [esp+4], esi +@@: + pop eax + pop esi ebp + ret + +fat_time_to_bdfe: +; in: eax=FAT time +; out: eax=BDFE time + push ecx edx + mov ecx, eax + mov edx, eax + shr eax, 11 + shl eax, 16 ; hours + and edx, 0x1F + add edx, edx + mov al, dl ; seconds + shr ecx, 5 + and ecx, 0x3F + mov ah, cl ; minutes + pop edx ecx + ret + +fat_date_to_bdfe: + push ecx edx + mov ecx, eax + mov edx, eax + shr eax, 9 + add ax, 1980 + shl eax, 16 ; year + and edx, 0x1F + mov al, dl ; day + shr ecx, 5 + and ecx, 0xF + mov ah, cl ; month + pop edx ecx + ret + +bdfe_to_fat_time: + push edx + mov edx, eax + shr eax, 16 + and dh, 0x3F + shl eax, 6 + or al, dh + shr dl, 1 + and dl, 0x1F + shl eax, 5 + or al, dl + pop edx + ret + +bdfe_to_fat_date: + push edx + mov edx, eax + shr eax, 16 + sub ax, 1980 + and dh, 0xF + shl eax, 4 + or al, dh + and dl, 0x1F + shl eax, 5 + or al, dl + pop edx + ret + +fat_entry_to_bdfe: +; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi +; destroys eax + mov eax, [ebp-4] + mov [esi+4], eax ; ASCII/UNICODE name +fat_entry_to_bdfe2: + movzx eax, byte [edi+11] + mov [esi], eax ; attributes + movzx eax, word [edi+14] + call fat_time_to_bdfe + mov [esi+8], eax ; creation time + movzx eax, word [edi+16] + call fat_date_to_bdfe + mov [esi+12], eax ; creation date + and dword [esi+16], 0 ; last access time is not supported on FAT + movzx eax, word [edi+18] + call fat_date_to_bdfe + mov [esi+20], eax ; last access date + movzx eax, word [edi+22] + call fat_time_to_bdfe + mov [esi+24], eax ; last write time + movzx eax, word [edi+24] + call fat_date_to_bdfe + mov [esi+28], eax ; last write date + mov eax, [edi+28] + mov [esi+32], eax ; file size (low dword) + xor eax, eax + mov [esi+36], eax ; file size (high dword) + test ebp, ebp + jz .ret + push ecx edi + lea edi, [esi+40] + mov esi, ebp + test byte [esi-4], 1 + jz .ansi + mov ecx, 260/2 + rep movsd + mov [edi-2], ax +@@: + mov esi, edi + pop edi ecx +.ret: + ret +.ansi: + mov ecx, 264/4 + rep movsd + mov [edi-1], al + jmp @b + +bdfe_to_fat_entry: +; convert BDFE at edx to FAT entry at edi +; destroys eax +; attributes byte + test byte [edi+11], 8 ; volume label? + jnz @f + mov al, [edx] + and al, 0x27 + and byte [edi+11], 0x10 + or byte [edi+11], al +@@: + mov eax, [edx+8] + call bdfe_to_fat_time + mov [edi+14], ax ; creation time + mov eax, [edx+12] + call bdfe_to_fat_date + mov [edi+16], ax ; creation date + mov eax, [edx+20] + call bdfe_to_fat_date + mov [edi+18], ax ; last access date + mov eax, [edx+24] + call bdfe_to_fat_time + mov [edi+22], ax ; last write time + mov eax, [edx+28] + call bdfe_to_fat_date + mov [edi+24], ax ; last write date + ret + +ramdisk_root_first: + mov edi, RAMDISK+512*19 + clc + ret +ramdisk_root_next: + add edi, 0x20 + cmp edi, RAMDISK+512*33 + cmc + ret + +ramdisk_root_extend_dir: + stc + ret + +uglobal +; this is for delete support +rd_prev_sector dd ? +rd_prev_prev_sector dd ? +endg + +ramdisk_notroot_next: + add edi, 0x20 + test edi, 0x1FF + jz ramdisk_notroot_next_sector + ret ; CF=0 +ramdisk_notroot_next_sector: + push ecx + mov ecx, [eax] + push [rd_prev_sector] + pop [rd_prev_prev_sector] + mov [rd_prev_sector], ecx + mov ecx, [ecx*2+RAMDISK_FAT] + and ecx, 0xFFF + cmp ecx, 2849 + jae ramdisk_notroot_first.err2 + mov [eax], ecx + pop ecx +ramdisk_notroot_first: + mov eax, [eax] + cmp eax, 2 + jb .err + cmp eax, 2849 + jae .err + shl eax, 9 + lea edi, [eax+(31 shl 9)+RAMDISK] + clc + ret +.err2: + pop ecx +.err: + stc + ret +ramdisk_notroot_next_write: + test edi, 0x1FF + jz ramdisk_notroot_next_sector +ramdisk_root_next_write: + ret + +ramdisk_notroot_extend_dir: + pusha + xor eax, eax + mov edi, RAMDISK_FAT + mov ecx, 2849 + repnz scasw + jnz .notfound + mov word [edi-2], 0xFFF + sub edi, RAMDISK_FAT + shr edi, 1 + dec edi + mov eax, [esp+28] + mov ecx, [eax] + mov [RAMDISK_FAT+ecx*2], di + mov [eax], edi + shl edi, 9 + add edi, (31 shl 9)+RAMDISK + mov [esp], edi + xor eax, eax + mov ecx, 128 + rep stosd + popa + clc + ret +.notfound: + popa + stc + ret + +rd_find_lfn: +; in: esi+ebp -> name +; out: CF=1 - file not found +; else CF=0 and edi->direntry + push esi edi + push 0 + push ramdisk_root_first + push ramdisk_root_next +.loop: + call fat_find_lfn + jc .notfound + cmp byte [esi], 0 + jz .found +.continue: + test byte [edi+11], 10h + jz .notfound + movzx eax, word [edi+26] + mov [esp+8], eax + mov dword [esp+4], ramdisk_notroot_first + mov dword [esp], ramdisk_notroot_next + test eax, eax + jnz .loop + mov dword [esp+4], ramdisk_root_first + mov dword [esp], ramdisk_notroot_next + jmp .loop +.notfound: + add esp, 12 + pop edi esi + stc + ret +.found: + test ebp, ebp + jz @f + mov esi, ebp + xor ebp, ebp + jmp .continue +@@: + mov eax, [esp+8] + add esp, 16 ; CF=0 + pop esi + ret + +;---------------------------------------------------------------- +; +; fs_RamdiskRead - LFN variant for reading sys floppy +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to read, 0+ +; edx mem location to return data +; +; ret ebx = bytes read or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_RamdiskRead: + cmp byte [esi], 0 + jnz @f + or ebx, -1 + mov eax, 10 ; access denied + ret +@@: + push edi + call rd_find_lfn + jnc .found + pop edi + or ebx, -1 + mov eax, 5 ; file not found + ret +.found: + test ebx, ebx + jz .l1 + cmp dword [ebx+4], 0 + jz @f + xor ebx, ebx +.reteof: + mov eax, 6 ; EOF + pop edi + ret +@@: + mov ebx, [ebx] +.l1: + push ecx edx + push 0 + mov eax, [edi+28] + sub eax, ebx + jb .eof + cmp eax, ecx + jae @f + mov ecx, eax + mov byte [esp], 6 ; EOF +@@: + movzx edi, word [edi+26] ; cluster +.new: + jecxz .done + test edi, edi + jz .eof + cmp edi, 0xFF8 + jae .eof + lea eax, [edi+31] ; bootsector+2*fat+filenames + shl eax, 9 ; *512 + add eax, RAMDISK ; image base +; now eax points to data of cluster + sub ebx, 512 + jae .skip + lea eax, [eax+ebx+512] + neg ebx + push ecx + cmp ecx, ebx + jbe @f + mov ecx, ebx +@@: + mov ebx, edx + call memmove + add edx, ecx + sub [esp], ecx + pop ecx + xor ebx, ebx +.skip: + movzx edi, word [edi*2+RAMDISK_FAT] ; find next cluster from FAT + jmp .new +.eof: + mov ebx, edx + pop eax edx ecx + sub ebx, edx + jmp .reteof +.done: + mov ebx, edx + pop eax edx ecx edi + sub ebx, edx + ret + +;---------------------------------------------------------------- +; +; fs_RamdiskReadFolder - LFN variant for reading sys floppy folder +; +; esi points to filename; only root is folder on ramdisk +; ebx pointer to structure 32-bit number = first wanted block +; & flags (bitfields) +; flags: bit 0: 0=ANSI names, 1=UNICODE names +; ecx number of blocks to read, 0+ +; edx mem location to return data +; +; ret ebx = size or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_RamdiskReadFolder: + push edi + cmp byte [esi], 0 + jz .root + call rd_find_lfn + jnc .found + pop edi + or ebx, -1 + mov eax, ERROR_FILE_NOT_FOUND + ret +.found: + test byte [edi+11], 0x10 + jnz .found_dir + pop edi + or ebx, -1 + mov eax, ERROR_ACCESS_DENIED + ret +.found_dir: + movzx eax, word [edi+26] + add eax, 31 + push 0 + jmp .doit +.root: + mov eax, 19 + push 14 +.doit: + push esi ecx ebp + sub esp, 262*2 ; reserve space for LFN + mov ebp, esp + push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names + mov ebx, [ebx] +; init header + push eax ecx + mov edi, edx + mov ecx, 32/4 + xor eax, eax + rep stosd + mov byte [edx], 1 ; version + pop ecx eax + mov esi, edi ; esi points to block of data of folder entry (BDFE) +.main_loop: + mov edi, eax + shl edi, 9 + add edi, RAMDISK + push eax +.l1: + call fat_get_name + jc .l2 + cmp byte [edi+11], 0xF + jnz .do_bdfe + add edi, 0x20 + test edi, 0x1FF + jnz .do_bdfe + pop eax + inc eax + dec byte [esp+262*2+16] + jz .done + jns @f +; read next sector from FAT + mov eax, [(eax-31-1)*2+RAMDISK_FAT] + and eax, 0xFFF + cmp eax, 0xFF8 + jae .done + add eax, 31 + mov byte [esp+262*2+16], 0 +@@: + mov edi, eax + shl edi, 9 + add edi, RAMDISK + push eax +.do_bdfe: + inc dword [edx+8] ; new file found + dec ebx + jns .l2 + dec ecx + js .l2 + inc dword [edx+4] ; new file block copied + call fat_entry_to_bdfe +.l2: + add edi, 0x20 + test edi, 0x1FF + jnz .l1 + pop eax + inc eax + dec byte [esp+262*2+16] + jz .done + jns @f +; read next sector from FAT + mov eax, [(eax-31-1)*2+RAMDISK_FAT] + and eax, 0xFFF + cmp eax, 0xFF8 + jae .done + add eax, 31 + mov byte [esp+262*2+16], 0 +@@: + jmp .main_loop +.done: + add esp, 262*2+4 + pop ebp + mov ebx, [edx+4] + xor eax, eax + dec ecx + js @f + mov al, ERROR_END_OF_FILE +@@: + pop ecx esi edi edi + ret + +iglobal +label fat_legal_chars byte +; 0 = not allowed +; 1 = allowed only in long names +; 3 = allowed + times 32 db 0 +; ! " # $ % & ' ( ) * + , - . / + db 1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0 +; 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + db 3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0 +; @ A B C D E F G H I J K L M N O + db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 +; P Q R S T U V W X Y Z [ \ ] ^ _ + db 3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3 +; ` a b c d e f g h i j k l m n o + db 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 +; p q r s t u v w x y z { | } ~ + db 3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0 +endg + +fat_name_is_legal: +; in: esi->(long) name +; out: CF set <=> legal +; destroys eax + push esi + xor eax, eax +@@: + lodsb + test al, al + jz .done + cmp al, 80h + jae .big + test [fat_legal_chars+eax], 1 + jnz @b +.err: + pop esi + clc + ret +.big: +; 0x80-0xAF, 0xE0-0xEF + cmp al, 0xB0 + jb @b + cmp al, 0xE0 + jb .err + cmp al, 0xF0 + jb @b + jmp .err +.done: + sub esi, [esp] + cmp esi, 257 + pop esi + ret + +fat_next_short_name: +; in: edi->8+3 name +; out: name corrected +; CF=1 <=> error + pushad + mov ecx, 8 + mov al, '~' + std + push edi + add edi, 7 + repnz scasb + pop edi + cld + jz .tilde +; tilde is not found, insert "~1" at end + add edi, 6 + cmp word [edi], ' ' + jnz .insert_tilde +@@: + dec edi + cmp byte [edi], ' ' + jz @b + inc edi +.insert_tilde: + mov word [edi], '~1' + popad + clc + ret +.tilde: + push edi + add edi, 7 + xor ecx, ecx +@@: +; after tilde may be only digits and trailing spaces + cmp byte [edi], '~' + jz .break + cmp byte [edi], ' ' + jz .space + cmp byte [edi], '9' + jnz .found + dec edi + jmp @b +.space: + dec edi + inc ecx + jmp @b +.found: + inc byte [edi] + add dword [esp], 8 + jmp .zerorest +.break: + jecxz .noplace + inc edi + mov al, '1' +@@: + xchg al, [edi] + inc edi + cmp al, ' ' + mov al, '0' + jnz @b +.succ: + pop edi + popad + clc + ret +.noplace: + dec edi + cmp edi, [esp] + jz .err + add dword [esp], 8 + mov word [edi], '~1' + inc edi + inc edi +@@: + mov byte [edi], '0' +.zerorest: + inc edi + cmp edi, [esp] + jb @b + pop edi + popad + ;clc ; automatically + ret +.err: + pop edi + popad + stc + ret + +fat_gen_short_name: +; in: esi->long name +; edi->buffer (8+3=11 chars) +; out: buffer filled + pushad + mov eax, ' ' + push edi + stosd + stosd + stosd + pop edi + xor eax, eax + push 8 + pop ebx + lea ecx, [edi+8] +.loop: + lodsb + test al, al + jz .done + call char_toupper + cmp al, ' ' + jz .space + cmp al, 80h + ja .big + test [fat_legal_chars+eax], 2 + jnz .symbol +.inv_symbol: + mov al, '_' + or bh, 1 +.symbol: + cmp al, '.' + jz .dot +.normal_symbol: + dec bl + jns .store + mov bl, 0 +.space: + or bh, 1 + jmp .loop +.store: + stosb + jmp .loop +.big: + cmp al, 0xB0 + jb .normal_symbol + cmp al, 0xE0 + jb .inv_symbol + cmp al, 0xF0 + jb .normal_symbol + jmp .inv_symbol +.dot: + test bh, 2 + jz .firstdot + pop ebx + add ebx, edi + sub ebx, ecx + push ebx + cmp ebx, ecx + jb @f + pop ebx + push ecx +@@: + cmp edi, ecx + jbe .skip +@@: + dec edi + mov al, [edi] + dec ebx + mov [ebx], al + mov byte [edi], ' ' + cmp edi, ecx + ja @b +.skip: + mov bh, 3 + jmp @f +.firstdot: + cmp bl, 8 + jz .space + push edi + or bh, 2 +@@: + mov edi, ecx + mov bl, 3 + jmp .loop +.done: + test bh, 2 + jz @f + pop edi +@@: + lea edi, [ecx-8] + test bh, 1 + jz @f + call fat_next_short_name +@@: + popad + ret + +;---------------------------------------------------------------- +; +; fs_RamdiskRewrite - LFN variant for writing ramdisk +; fs_RamdiskCreateFolder - create folder on ramdisk +; +; esi points to file/folder name +; ebx ignored (reserved) +; ecx number of bytes to write, 0+ (ignored for folders) +; edx mem location to data (ignored for folders) +; +; ret ebx = number of written bytes +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +@@: + mov eax, ERROR_ACCESS_DENIED + xor ebx, ebx + ret + +fs_RamdiskCreateFolder: + mov al, 1 ; create folder + jmp fs_RamdiskRewrite.common + +fs_RamdiskRewrite: + xor eax, eax ; create file +.common: + cmp byte [esi], 0 + jz @b + pushad + xor edi, edi + push esi + test ebp, ebp + jz @f + mov esi, ebp +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jnz @b + lea edi, [esi-1] + jmp @b +@@: + pop esi + test edi, edi + jnz .noroot + test ebp, ebp + jnz .hasebp + push ramdisk_root_extend_dir + push ramdisk_root_next_write + push edi + push ramdisk_root_first + push ramdisk_root_next + jmp .common1 +.hasebp: + mov eax, ERROR_ACCESS_DENIED + cmp byte [ebp], 0 + jz .ret1 + push ebp + xor ebp, ebp + call rd_find_lfn + pop esi + jc .notfound0 + jmp .common0 +.noroot: + mov eax, ERROR_ACCESS_DENIED + cmp byte [edi+1], 0 + jz .ret1 +; check existence + mov byte [edi], 0 + push edi + call rd_find_lfn + pop esi + mov byte [esi], '/' + jnc @f +.notfound0: + mov eax, ERROR_FILE_NOT_FOUND +.ret1: + mov [esp+28], eax + popad + xor ebx, ebx + ret +@@: + inc esi +.common0: + test byte [edi+11], 0x10 ; must be directory + mov eax, ERROR_ACCESS_DENIED + jz .ret1 + movzx ebp, word [edi+26] ; ebp=cluster + mov eax, ERROR_FAT_TABLE + cmp ebp, 2 + jb .ret1 + cmp ebp, 2849 + jae .ret1 + push ramdisk_notroot_extend_dir + push ramdisk_notroot_next_write + push ebp + push ramdisk_notroot_first + push ramdisk_notroot_next +.common1: + call fat_find_lfn + jc .notfound +; found + test byte [edi+11], 10h + jz .exists_file +; found directory; if we are creating directory, return OK, +; if we are creating file, say "access denied" + add esp, 20 + popad + test al, al + mov eax, ERROR_ACCESS_DENIED + jz @f + mov al, 0 +@@: + xor ebx, ebx + ret +.exists_file: +; found file; if we are creating directory, return "access denied", +; if we are creating file, delete existing file and continue + cmp byte [esp+20+28], 0 + jz @f + add esp, 20 + popad + mov eax, ERROR_ACCESS_DENIED + xor ebx, ebx + ret +@@: +; delete FAT chain + push edi + xor eax, eax + mov dword [edi+28], eax ; zero size + xchg ax, word [edi+26] ; start cluster + test eax, eax + jz .done1 +@@: + cmp eax, 0xFF8 + jae .done1 + lea edi, [RAMDISK_FAT + eax*2] ; position in FAT + xor eax, eax + xchg ax, [edi] + jmp @b +.done1: + pop edi + call get_time_for_file + mov [edi+22], ax + call get_date_for_file + mov [edi+24], ax + mov [edi+18], ax + or byte [edi+11], 20h ; set 'archive' attribute + jmp .doit +.notfound: +; file is not found; generate short name + call fat_name_is_legal + jc @f + add esp, 20 + popad + mov eax, ERROR_FILE_NOT_FOUND + xor ebx, ebx + ret +@@: + sub esp, 12 + mov edi, esp + call fat_gen_short_name +.test_short_name_loop: + push esi edi ecx + mov esi, edi + lea eax, [esp+12+12+8] + mov [eax], ebp + call dword [eax-4] + jc .found +.test_short_name_entry: + cmp byte [edi+11], 0xF + jz .test_short_name_cont + mov ecx, 11 + push esi edi + repz cmpsb + pop edi esi + jz .short_name_found +.test_short_name_cont: + lea eax, [esp+12+12+8] + call dword [eax-8] + jnc .test_short_name_entry + jmp .found +.short_name_found: + pop ecx edi esi + call fat_next_short_name + jnc .test_short_name_loop +.disk_full: + add esp, 12+20 + popad + mov eax, ERROR_DISK_FULL + xor ebx, ebx + ret +.found: + pop ecx edi esi +; now find space in directory +; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' + mov al, '~' + push ecx edi + mov ecx, 8 + repnz scasb + push 1 + pop eax ; 1 entry + jnz .notilde +; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total + xor eax, eax +@@: + cmp byte [esi], 0 + jz @f + inc esi + inc eax + jmp @b +@@: + sub esi, eax + add eax, 12+13 + mov ecx, 13 + push edx + cdq + div ecx + pop edx +.notilde: + push -1 + push -1 +; find successive entries in directory + xor ecx, ecx + push eax + lea eax, [esp+12+8+12+8] + mov [eax], ebp + call dword [eax-4] + pop eax +.scan_dir: + cmp byte [edi], 0 + jz .free + cmp byte [edi], 0xE5 + jz .free + xor ecx, ecx +.scan_cont: + push eax + lea eax, [esp+12+8+12+8] + call dword [eax-8] + pop eax + jnc .scan_dir + push eax + lea eax, [esp+12+8+12+8] + call dword [eax+8] ; extend directory + pop eax + jnc .scan_dir + add esp, 8+8+12+20 + popad + mov eax, ERROR_DISK_FULL + xor ebx, ebx + ret +.free: + test ecx, ecx + jnz @f + mov [esp], edi + mov ecx, [esp+8+8+12+8] + mov [esp+4], ecx + xor ecx, ecx +@@: + inc ecx + cmp ecx, eax + jb .scan_cont +; found! +; calculate name checksum + push esi ecx + mov esi, [esp+8+8] + mov ecx, 11 + xor eax, eax +@@: + ror al, 1 + add al, [esi] + inc esi + loop @b + pop ecx esi + pop edi + pop dword [esp+8+12+8] +; edi points to last entry in free chunk + dec ecx + jz .nolfn + push esi + push eax + mov al, 40h +.writelfn: + or al, cl + mov esi, [esp+4] + push ecx + dec ecx + imul ecx, 13 + add esi, ecx + stosb + mov cl, 5 + call .read_symbols + mov ax, 0xF + stosw + mov al, [esp+4] + stosb + mov cl, 6 + call .read_symbols + xor eax, eax + stosw + mov cl, 2 + call .read_symbols + pop ecx + lea eax, [esp+8+8+12+8] + call dword [eax+4] ; next write + xor eax, eax + loop .writelfn + pop eax + pop esi +.nolfn: + xchg esi, [esp] + mov ecx, 11 + rep movsb + mov word [edi], 20h ; attributes + sub edi, 11 + pop esi ecx + add esp, 12 + mov byte [edi+13], 0 ; tenths of a second at file creation time + call get_time_for_file + mov [edi+14], ax ; creation time + mov [edi+22], ax ; last write time + call get_date_for_file + mov [edi+16], ax ; creation date + mov [edi+24], ax ; last write date + mov [edi+18], ax ; last access date + and word [edi+20], 0 ; high word of cluster + and word [edi+26], 0 ; low word of cluster - to be filled + and dword [edi+28], 0 ; file size - to be filled + cmp byte [esp+20+28], 0 + jz .doit +; create directory + mov byte [edi+11], 10h ; attributes: folder + mov ecx, 32*2 + mov edx, edi +.doit: + push edx + push ecx + push edi + add edi, 26 ; edi points to low word of cluster + push edi + jecxz .done + mov ecx, 2849 + mov edi, RAMDISK_FAT +.write_loop: +; allocate new cluster + xor eax, eax + repnz scasw + jnz .disk_full2 + dec edi + dec edi + + ; lea eax, [edi-(RAMDISK_FAT)] + + mov eax, edi + sub eax, RAMDISK_FAT + + shr eax, 1 ; eax = cluster + mov word [edi], 0xFFF ; mark as last cluster + xchg edi, [esp] + stosw + pop edi + push edi + inc ecx +; write data + cmp byte [esp+16+20+28], 0 + jnz .writedir + shl eax, 9 + add eax, RAMDISK+31*512 +.writefile: + mov ebx, edx + xchg eax, ebx + push ecx + mov ecx, 512 + cmp dword [esp+12], ecx + jae @f + mov ecx, [esp+12] +@@: + call memmove + add edx, ecx + sub [esp+12], ecx + pop ecx + jnz .write_loop +.done: + mov ebx, edx + pop edi edi ecx edx + sub ebx, edx + mov [edi+28], ebx + add esp, 20 + mov [esp+16], ebx + popad + xor eax, eax + ret +.disk_full2: + mov ebx, edx + pop edi edi ecx edx + sub ebx, edx + mov [edi+28], ebx + add esp, 20 + mov [esp+16], ebx + popad + push ERROR_DISK_FULL + pop eax + ret +.writedir: + mov edi, eax + shl edi, 9 + add edi, RAMDISK+31*512 + mov esi, edx + mov ecx, 32/4 + push ecx + rep movsd + mov dword [edi-32], '. ' + mov dword [edi-32+4], ' ' + mov dword [edi-32+8], ' ' + mov byte [edi-32+11], 10h + mov word [edi-32+26], ax + mov esi, edx + pop ecx + rep movsd + mov dword [edi-32], '.. ' + mov dword [edi-32+4], ' ' + mov dword [edi-32+8], ' ' + mov byte [edi-32+11], 10h + mov eax, [esp+16+8] + mov word [edi-32+26], ax + xor eax, eax + mov ecx, (512-32*2)/4 + rep stosd + pop edi edi ecx edx + add esp, 20 + popad + xor eax, eax + xor ebx, ebx + ret + +.read_symbol: + or ax, -1 + test esi, esi + jz .retFFFF + lodsb + test al, al + jnz ansi2uni_char + xor eax, eax + xor esi, esi +.retFFFF: + ret + +.read_symbols: + call .read_symbol + stosw + loop .read_symbols + ret + +;---------------------------------------------------------------- +; +; fs_RamdiskWrite - LFN variant for writing to sys floppy +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to write, 0+ +; edx mem location to data +; +; ret ebx = bytes written (maybe 0) +; eax = 0 ok write or other = errormsg +; +;-------------------------------------------------------------- +@@: + push ERROR_ACCESS_DENIED +fs_RamdiskWrite.ret0: + pop eax + xor ebx, ebx + ret + +fs_RamdiskWrite: + cmp byte [esi], 0 + jz @b + pushad + call rd_find_lfn + jnc .found + popad + push ERROR_FILE_NOT_FOUND + jmp .ret0 +.found: +; must not be directory + test byte [edi+11], 10h + jz @f + popad + push ERROR_ACCESS_DENIED + jmp .ret0 +@@: +; FAT does not support files larger than 4GB + test ebx, ebx + jz .l1 + cmp dword [ebx+4], 0 + jz @f +.eof: + popad + push ERROR_END_OF_FILE + jmp .ret0 +@@: + mov ebx, [ebx] +.l1: +; now edi points to direntry, ebx=start byte to write, +; ecx=number of bytes to write, edx=data pointer + call fat_update_datetime + +; extend file if needed + add ecx, ebx + jc .eof ; FAT does not support files larger than 4GB + push 0 ; return value=0 + cmp ecx, [edi+28] + jbe .length_ok + cmp ecx, ebx + jz .length_ok + call ramdisk_extend_file + jnc .length_ok +; ramdisk_extend_file can return two error codes: FAT table error or disk full. +; First case is fatal error, in second case we may write some data + mov [esp], eax + cmp al, ERROR_DISK_FULL + jz .disk_full + pop eax + mov [esp+28], eax + popad + xor ebx, ebx + ret +.disk_full: +; correct number of bytes to write + mov ecx, [edi+28] + cmp ecx, ebx + ja .length_ok +.ret: + pop eax + mov [esp+28], eax ; eax=return value + sub edx, [esp+20] + mov [esp+16], edx ; ebx=number of written bytes + popad + ret +.length_ok: +; now ebx=start pos, ecx=end pos, both lie inside file + sub ecx, ebx + jz .ret + movzx edi, word [edi+26] ; starting cluster +.write_loop: + sub ebx, 0x200 + jae .next_cluster + push ecx + neg ebx + cmp ecx, ebx + jbe @f + mov ecx, ebx +@@: + mov eax, edi + shl eax, 9 + add eax, RAMDISK+31*512+0x200 + sub eax, ebx + mov ebx, eax + mov eax, edx + call memmove + xor ebx, ebx + add edx, ecx + sub [esp], ecx + pop ecx + jz .ret +.next_cluster: + movzx edi, word [edi*2+RAMDISK_FAT] + jmp .write_loop + +ramdisk_extend_file.zero_size: + xor eax, eax + jmp ramdisk_extend_file.start_extend + +; extends file on ramdisk to given size, new data area is filled by 0 +; in: edi->direntry, ecx=new size +; out: CF=0 => OK, eax=0 +; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) +ramdisk_extend_file: + push ecx +; find the last cluster of file + movzx eax, word [edi+26] ; first cluster + mov ecx, [edi+28] + jecxz .zero_size +@@: + sub ecx, 0x200 + jbe @f + mov eax, [eax*2+RAMDISK_FAT] + and eax, 0xFFF + jz .fat_err + cmp eax, 0xFF8 + jb @b +.fat_err: + pop ecx + push ERROR_FAT_TABLE + pop eax + stc + ret +@@: + push eax + mov eax, [eax*2+RAMDISK_FAT] + and eax, 0xFFF + cmp eax, 0xFF8 + pop eax + jb .fat_err +; set length to full number of sectors and make sure that last sector is zero-padded + sub [edi+28], ecx + push eax edi + mov edi, eax + shl edi, 9 + lea edi, [edi+RAMDISK+31*512+0x200+ecx] + neg ecx + xor eax, eax + rep stosb + pop edi eax +.start_extend: + pop ecx +; now do extend + push edx esi + mov esi, RAMDISK_FAT+2*2 ; start scan from cluster 2 + mov edx, 2847 ; number of clusters to scan +.extend_loop: + cmp [edi+28], ecx + jae .extend_done +; add new sector + push ecx + mov ecx, edx + push edi + mov edi, esi + jecxz .disk_full + push eax + xor eax, eax + repnz scasw + pop eax + jnz .disk_full + mov word [edi-2], 0xFFF + mov esi, edi + mov edx, ecx + sub edi, RAMDISK_FAT + shr edi, 1 + dec edi ; now edi=new cluster + test eax, eax + jz .first_cluster + mov [RAMDISK_FAT+eax*2], di + jmp @f +.first_cluster: + pop eax ; eax->direntry + push eax + mov [eax+26], di +@@: + push edi + shl edi, 9 + add edi, RAMDISK+31*512 + xor eax, eax + mov ecx, 512/4 + rep stosd + pop eax ; eax=new cluster + pop edi ; edi->direntry + pop ecx ; ecx=required size + add dword [edi+28], 0x200 + jmp .extend_loop +.extend_done: + mov [edi+28], ecx + pop esi edx + xor eax, eax ; CF=0 + ret +.disk_full: + pop edi ecx + pop esi edx + stc + push ERROR_DISK_FULL + pop eax + ret + +fat_update_datetime: + call get_time_for_file + mov [edi+22], ax ; last write time + call get_date_for_file + mov [edi+24], ax ; last write date + mov [edi+18], ax ; last access date + ret + +;---------------------------------------------------------------- +; +; fs_RamdiskSetFileEnd - set end of file on ramdisk +; +; esi points to filename +; ebx points to 64-bit number = new file size +; ecx ignored (reserved) +; edx ignored (reserved) +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +fs_RamdiskSetFileEnd: + cmp byte [esi], 0 + jnz @f +.access_denied: + push ERROR_ACCESS_DENIED + jmp .ret +@@: + push edi + call rd_find_lfn + jnc @f + pop edi + push ERROR_FILE_NOT_FOUND +.ret: + pop eax + ret +@@: +; must not be directory + test byte [edi+11], 10h + jz @f + pop edi + jmp .access_denied +@@: +; file size must not exceed 4Gb + cmp dword [ebx+4], 0 + jz @f + pop edi + push ERROR_END_OF_FILE + jmp .ret +@@: +; set file modification date/time to current + call fat_update_datetime + mov eax, [ebx] + cmp eax, [edi+28] + jb .truncate + ja .expand + pop edi + xor eax, eax + ret +.expand: + push ecx + mov ecx, eax + call ramdisk_extend_file + pop ecx + pop edi + ret +.truncate: + mov [edi+28], eax + push ecx + movzx ecx, word [edi+26] + test eax, eax + jz .zero_size +; find new last sector +@@: + sub eax, 0x200 + jbe @f + movzx ecx, word [RAMDISK_FAT+ecx*2] + jmp @b +@@: +; zero data at the end of last sector + push ecx + mov edi, ecx + shl edi, 9 + lea edi, [edi+RAMDISK+31*512+eax+0x200] + mov ecx, eax + neg ecx + xor eax, eax + rep stosb + pop ecx +; terminate FAT chain + lea ecx, [RAMDISK_FAT+ecx+ecx] + push dword [ecx] + mov word [ecx], 0xFFF + pop ecx + and ecx, 0xFFF + jmp .delete +.zero_size: + and word [edi+26], 0 +.delete: +; delete FAT chain starting with ecx +; mark all clusters as free + cmp ecx, 0xFF8 + jae .deleted + lea ecx, [RAMDISK_FAT+ecx+ecx] + push dword [ecx] + and word [ecx], 0 + pop ecx + and ecx, 0xFFF + jmp .delete +.deleted: + pop ecx + pop edi + xor eax, eax + ret + +fs_RamdiskGetFileInfo: + cmp byte [esi], 0 + jnz @f + mov eax, 2 ; unsupported + ret +@@: + push edi + call rd_find_lfn +fs_GetFileInfo_finish: + jnc @f + pop edi + mov eax, ERROR_FILE_NOT_FOUND + ret +@@: + push esi ebp + xor ebp, ebp + mov esi, edx + and dword [esi+4], 0 + call fat_entry_to_bdfe2 + pop ebp esi + pop edi + xor eax, eax + ret + +fs_RamdiskSetFileInfo: + cmp byte [esi], 0 + jnz @f + mov eax, 2 ; unsupported + ret +@@: + push edi + call rd_find_lfn + jnc @f + pop edi + mov eax, ERROR_FILE_NOT_FOUND + ret +@@: + call bdfe_to_fat_entry + pop edi + xor eax, eax + ret + +;---------------------------------------------------------------- +; +; fs_RamdiskDelete - delete file or empty folder from ramdisk +; +; esi points to filename +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +fs_RamdiskDelete: + cmp byte [esi], 0 + jnz @f +; cannot delete root! +.access_denied: + push ERROR_ACCESS_DENIED +.pop_ret: + pop eax + ret +@@: + and [rd_prev_sector], 0 + and [rd_prev_prev_sector], 0 + push edi + call rd_find_lfn + jnc .found + pop edi + push ERROR_FILE_NOT_FOUND + jmp .pop_ret +.found: + cmp dword [edi], '. ' + jz .access_denied2 + cmp dword [edi], '.. ' + jz .access_denied2 + test byte [edi+11], 10h + jz .dodel +; we can delete only empty folders! + movzx eax, word [edi+26] + push ebx + mov ebx, eax + shl ebx, 9 + add ebx, RAMDISK + 31*0x200 + 2*0x20 +.checkempty: + cmp byte [ebx], 0 + jz .empty + cmp byte [ebx], 0xE5 + jnz .notempty + add ebx, 0x20 + test ebx, 0x1FF + jnz .checkempty + movzx eax, word [RAMDISK_FAT + eax*2] + test eax, eax + jz .empty + mov ebx, eax + shl ebx, 9 + add ebx, RAMDISK + 31*0x200 + jmp .checkempty +.notempty: + pop ebx +.access_denied2: + pop edi + jmp .access_denied +.empty: + pop ebx +.dodel: + movzx eax, word [edi+26] +; delete folder entry + mov byte [edi], 0xE5 +; delete LFN (if present) +.lfndel: + test edi, 0x1FF + jnz @f + cmp [rd_prev_sector], 0 + jz @f + cmp [rd_prev_sector], -1 + jz .lfndone + mov edi, [rd_prev_sector] + push [rd_prev_prev_sector] + pop [rd_prev_sector] + or [rd_prev_prev_sector], -1 + shl edi, 9 + add edi, RAMDISK + 31*0x200 + 0x200 +@@: + sub edi, 0x20 + cmp byte [edi], 0xE5 + jz .lfndone + cmp byte [edi+11], 0xF + jnz .lfndone + mov byte [edi], 0xE5 + jmp .lfndel +.lfndone: +; delete FAT chain + test eax, eax + jz .done + lea eax, [RAMDISK_FAT + eax*2] + push dword [eax] + and word [eax], 0 + pop eax + and eax, 0xFFF + jmp .lfndone +.done: + pop edi + xor eax, eax + ret + +; \end{diamond} diff --git a/kernel/trunk/blkdev/rdsave.inc b/kernel/trunk/blkdev/rdsave.inc index 158704e2d..dc1c1edb8 100644 --- a/kernel/trunk/blkdev/rdsave.inc +++ b/kernel/trunk/blkdev/rdsave.inc @@ -1,30 +1,30 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -iglobal -saverd_fileinfo: - dd 2 ; subfunction: write - dd 0 ; (reserved) - dd 0 ; (reserved) - dd 1440*1024 ; size 1440 Kb - dd RAMDISK - db 0 -.name: - dd ? -endg -sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only) - call restorefatchain - mov ebx, saverd_fileinfo - mov [saverd_fileinfo.name], ecx - pushad - call file_system_lfn ;in ebx - popad - mov [esp+32], eax - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +iglobal +saverd_fileinfo: + dd 2 ; subfunction: write + dd 0 ; (reserved) + dd 0 ; (reserved) + dd 1440*1024 ; size 1440 Kb + dd RAMDISK + db 0 +.name: + dd ? +endg +sysfn_saveramdisk: ; 18.6 = SAVE FLOPPY IMAGE (HD version only) + call restorefatchain + mov ebx, saverd_fileinfo + mov [saverd_fileinfo.name], ecx + pushad + call file_system_lfn ;in ebx + popad + mov [esp+32], eax + ret diff --git a/kernel/trunk/boot/bootcode.inc b/kernel/trunk/boot/bootcode.inc index fb310eb3a..2a7586036 100644 --- a/kernel/trunk/boot/bootcode.inc +++ b/kernel/trunk/boot/bootcode.inc @@ -1,1370 +1,1377 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; BOOTCODE.INC ;; -;; ;; -;; KolibriOS 16-bit loader, ;; -;; based on bootcode for MenuetOS ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;========================================================================== -; -; 16 BIT FUNCTIONS -; -;========================================================================== - - -putchar: -; in: al=character - mov ah, 0Eh - mov bh, 0 - int 10h - ret - -print: -; in: si->string - mov al, 186 - call putchar - mov al, ' ' - call putchar - -printplain: -; in: si->string - pusha - lodsb -@@: - call putchar - lodsb - test al,al - jnz @b - popa - ret - -getkey: -; get number in range [bl,bh] (bl,bh in ['0'..'9']) -; in: bx=range -; out: ax=digit (1..9, 10 for 0) - mov ah, 0 - int 16h - cmp al, bl - jb getkey - cmp al, bh - ja getkey - push ax - call putchar - pop ax - and ax, 0Fh - jnz @f - mov al, 10 -@@: - ret - -setcursor: -; in: dl=column, dh=row - mov ah, 2 - mov bh, 0 - int 10h - ret - -macro _setcursor row,column -{ - mov dx, row*256 + column - call setcursor -} - -boot_read_floppy: - push si - xor si, si - mov ah, 2 ; read -@@: - push ax - int 0x13 - pop ax - jnc @f - inc si - cmp si, 10 - jb @b -sayerr_badsect: - mov si, badsect -sayerr_plain: - call printplain - jmp $ -@@: - pop si - ret - -; convert abs. sector number (AX) to BIOS T:H:S -; sector number = (abs.sector%BPB_SecPerTrk)+1 -; pre.track number = (abs.sector/BPB_SecPerTrk) -; head number = pre.track number%BPB_NumHeads -; track number = pre.track number/BPB_NumHeads -; Return: cl - sector number -; ch - track number -; dl - drive number (0 = a:) -; dh - head number -conv_abs_to_THS: - push bx - mov bx,word [BPB_SecPerTrk] - xor dx,dx - div bx - inc dx - mov cl, dl ; cl = sector number - mov bx,word [BPB_NumHeads] - xor dx,dx - div bx - ; !!!!!!! ax = track number, dx = head number - mov ch,al ; ch=track number - xchg dh,dl ; dh=head number - mov dl,0 ; dl=0 (drive 0 (a:)) - pop bx - retn -; needed variables -BPB_SecPerTrk dw 0 ; sectors per track -BPB_NumHeads dw 0 ; number of heads -BPB_FATSz16 dw 0 ; size of FAT -BPB_RootEntCnt dw 0 ; count of root dir. entries -BPB_BytsPerSec dw 0 ; bytes per sector -BPB_RsvdSecCnt dw 0 ; number of reserved sectors -BPB_TotSec16 dw 0 ; count of the sectors on the volume -BPB_SecPerClus db 0 ; number of sectors per cluster -BPB_NumFATs db 0 ; number of FAT tables -abs_sector_adj dw 0 ; adjustment to make abs. sector number -end_of_FAT dw 0 ; end of FAT table -FirstDataSector dw 0 ; begin of data - -;========================================================================= -; -; 16 BIT CODE -; -;========================================================================= - -include 'bootvesa.inc' ;Include source for boot vesa -if defined extended_primary_loader -include 'parsers.inc' -end if - -start_of_code: - -if defined extended_primary_loader -; save data from primary loader - mov word [cs:bootcallback], si - mov word [cs:bootcallback+2], ds - push cs - pop ds - mov [bootdevice], ax - mov [bootfs], bx - -; set up stack - mov ax, 3000h - mov ss, ax - mov sp, 0EC00h - -; try to load configuration file - mov ax, 1 - mov di, config_file_struct - call [bootcallback] - cld - push cs - pop es -; bx=0 - ok, bx=1 - part of file loaded, assume this is ok - cmp bx, 1 - ja .config_bad -; configuration file was loaded, parse -; if length is too big, use first 0FFFFh bytes - test dx, dx - jz @f - mov ax, 0FFFFh -@@: -; ds:si will be pointer to current data, dx = limit - xchg ax, dx - push 4000h - pop ds - xor si, si -.parse_loop: -; skip spaces - cmp si, dx - jae .parse_done - lodsb - cmp al, ' ' - jbe .parse_loop - dec si -; loop over all possible configuration values - mov bx, config_file_variables -.find_variant: -; get length - mov cx, [es:bx] -; zero length = end of list - jecxz .find_newline -; skip over length - inc bx - inc bx - mov di, bx -; skip over string - add bx, cx -; test whether we have at least cx symbols left - mov ax, cx - add ax, si - jc .next_variant1 - cmp ax, dx - jae .next_variant1 -; save current position - push si -; compare strings - repz cmpsb - jnz .next_variant2 -; strings are equal; look for "=" with possible spaces before and after -@@: - cmp si, dx - jae .next_variant2 - lodsb - cmp al, ' ' - jbe @b - cmp al, '=' - jnz .next_variant2 -; ok, we found the true variant -; ignore saved position on the stack - pop ax -; call the parser - call word [es:bx] -; line parsed, find next -.find_newline: - cmp si, dx - jae .parse_done - lodsb - cmp al, 13 - jz .parse_loop - cmp al, 10 - jz .parse_loop - jmp .find_newline -.next_variant2: -; continue to the next variant, restoring current position - pop si -.next_variant1: -; continue to the next variant -; skip over the parser - inc bx - inc bx - jmp .find_variant -.parse_done: -.config_bad: - -; set up segment registers - push cs - pop ds -else - cld -; \begin{diamond}[02.12.2005] -; if bootloader sets ax = 'KL', then ds:si points to loader block - cmp ax, 'KL' - jnz @f - mov word [cs:cfgmanager.loader_block], si - mov word [cs:cfgmanager.loader_block+2], ds -@@: -; \end{diamond}[02.12.2005] - -; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk -; (see comment to bx_from_load) - cmp cx, 'HA' - jnz no_hd_load - cmp dx,'RD' - jnz no_hd_load - mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] -no_hd_load: - -; set up stack - mov ax, 3000h - mov ss, ax - mov sp, 0EC00h -; set up segment registers - push cs - pop ds - push cs - pop es -end if - -; set videomode - mov ax, 3 - int 0x10 - -if lang eq ru - ; Load & set russian VGA font (RU.INC) - mov bp, RU_FNT1 ; RU_FNT1 - First part - mov bx, 1000h ; 768 bytes - mov cx, 30h ; 48 symbols - mov dx, 80h ; 128 - position of first symbol - mov ax, 1100h - int 10h - - mov bp, RU_FNT2 ; RU_FNT2 -Second part - mov bx, 1000h ; 512 bytes - mov cx, 20h ; 32 symbols - mov dx, 0E0h ; 224 - position of first symbol - mov ax, 1100h - int 10h - ; End set VGA russian font -else if lang eq et - mov bp, ET_FNT ; ET_FNT1 - mov bx, 1000h ; - mov cx, 255 ; 256 symbols - xor dx, dx ; 0 - position of first symbol - mov ax, 1100h - int 10h -end if - -; draw frames - push 0xb800 - pop es - xor di, di - mov ah, 1*16+15 - -; draw top - mov si, d80x25_top - mov cx, d80x25_top_num * 80 -@@: - lodsb - stosw - loop @b -; draw spaces - mov si, space_msg - mov dx, 25 - d80x25_top_num - d80x25_bottom_num -dfl1: - push si - mov cx, 80 -@@: - lodsb - stosw - loop @b - pop si - dec dx - jnz dfl1 -; draw bottom - mov si, d80x25_bottom - mov cx, d80x25_bottom_num * 80 -@@: - lodsb - stosw - loop @b - - mov byte [space_msg+80], 0 ; now space_msg is null terminated - - _setcursor d80x25_top_num,0 - - -; TEST FOR 386+ - - mov bx, 0x4000 - pushf - pop ax - mov dx, ax - xor ax, bx - push ax - popf - pushf - pop ax - and ax, bx - and dx, bx - cmp ax, dx - jnz cpugood - mov si, not386 -sayerr: - call print - jmp $ - cpugood: - - push 0 - popf - sti - -; set up esp - movzx esp, sp - - push 0 - pop es - and word [es:0x9031], 0 -; \begin{Mario79} -; find HDD IDE DMA PCI device -; check for PCI BIOS - mov ax, 0xB101 - int 0x1A - jc .nopci - cmp edx, 'PCI ' - jnz .nopci -; find PCI class code -; class 1 = mass storage -; subclass 1 = IDE controller -; a) class 1, subclass 1, programming interface 0x80 - mov ax, 0xB103 - mov ecx, 1*10000h + 1*100h + 0x80 - xor si, si ; device index = 0 - int 0x1A - jnc .found -; b) class 1, subclass 1, programming interface 0x8A - mov ax, 0xB103 - mov ecx, 1*10000h + 1*100h + 0x8A - xor si, si ; device index = 0 - int 0x1A - jnc .found -; c) class 1, subclass 1, programming interface 0x85 - mov ax, 0xB103 - mov ecx, 1*10000h + 1*100h + 0x85 - xor si, si - int 0x1A - jc .nopci -.found: -; get memory base - mov ax, 0xB10A - mov di, 0x20 ; memory base is config register at 0x20 - int 0x1A - jc .nopci - and cx, 0xFFF0 ; clear address decode type - mov [es:0x9031], cx -.nopci: -; \end{Mario79} - - mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование - out 0x60, al - xor cx, cx -wait_loop: ; variant 2 -; reading state of port of 8042 controller - in al, 64h - and al, 00000010b ; ready flag -; wait until 8042 controller is ready - loopnz wait_loop - -;;;/diamond today 5.02.2008 -; set keyboard typematic rate & delay - mov al, 0xf3 - out 0x60, al - xor cx, cx -@@: - in al, 64h - test al, 2 - loopnz @b - mov al, 0 - out 0x60, al - xor cx, cx -@@: - in al, 64h - test al, 2 - loopnz @b -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; --------------- APM --------------------- - and word [es:0x9044], 0 ; ver = 0.0 (APM not found) - mov ax, 0x5300 - xor bx, bx - int 0x15 - jc apm_end ; APM not found - test cx, 2 - jz apm_end ; APM 32-bit protected-mode interface not supported - mov [es:0x9044], ax ; Save APM Version - mov [es:0x9046], cx ; Save APM flags - - ; Write APM ver ---- - and ax, 0xf0f - add ax, '00' - mov si, msg_apm - mov [si + 5], ah - mov [si + 7], al - _setcursor 0, 3 - call printplain - ; ------------------ - - mov ax, 0x5304 ; Disconnect interface - xor bx, bx - int 0x15 - mov ax, 0x5303 ; Connect 32 bit mode interface - xor bx, bx - int 0x15 - - mov [es:0x9040], ebx - mov [es:0x9050], ax - mov [es:0x9052], cx - mov [es:0x9054], dx - -apm_end: - _setcursor d80x25_top_num, 0 - -if ~ defined extended_primary_loader -;CHECK current of code - cmp [cfgmanager.loader_block], -1 - jz noloaderblock - les bx, [cfgmanager.loader_block] - cmp byte [es:bx], 1 - mov si, loader_block_error - jnz sayerr - push 0 - pop es -end if - -noloaderblock: -; DISPLAY VESA INFORMATION - call print_vesa_info - call calc_vmodes_table - call check_first_parm ;check and enable cursor_pos - -; \begin{diamond}[30.11.2005] -cfgmanager: -; settings: -; a) preboot_graph = graphical mode -; preboot_gprobe = probe this mode? -; b) preboot_dma = use DMA access? -; c) preboot_vrrm = use VRR? -; d) preboot_device = from what boot? - -; determine default settings -if ~ defined extended_primary_loader - mov [.bSettingsChanged], 0 -end if - -;.preboot_gr_end: - mov di, preboot_device -; if image in memory is present and [preboot_device] is uninitialized, -; set it to use this preloaded image - cmp byte [di], 0 - jnz .preboot_device_inited -if defined extended_primary_loader - inc byte [di] - cmp byte [bootdevice], 'f' ; floppy? - jz .preboot_device_inited - inc byte [di] -else - cmp [.loader_block], -1 - jz @f - les bx, [.loader_block] - test byte [es:bx+1], 1 - jz @f - mov byte [di], 3 - jmp .preboot_device_inited -@@: -; otherwise, set [preboot_device] to 1 (default value - boot from floppy) - mov byte [di], 1 -end if -.preboot_device_inited: -; following 4 lines set variables to 1 if its current value is 0 - cmp byte [di+preboot_dma-preboot_device], 1 - adc byte [di+preboot_dma-preboot_device], 0 - cmp byte [di+preboot_biosdisk-preboot_device], 1 - adc byte [di+preboot_biosdisk-preboot_device], 0 -;; default value for VRR is OFF -; cmp byte [di+preboot_vrrm-preboot_device], 0 -; jnz @f -; mov byte [di+preboot_vrrm-preboot_device], 2 -;@@: -; notify user - _setcursor 5,2 - - mov si, linef - call printplain - mov si, start_msg - call print - mov si, time_msg - call print -; get start time - call .gettime - mov [.starttime], eax - mov word [.timer], .newtimer - mov word [.timer+2], cs -.printcfg: - - _setcursor 9,0 - mov si, current_cfg_msg - call print - mov si, curvideo_msg - call print - - call draw_current_vmode - - mov si, usebd_msg - cmp [preboot_biosdisk], 1 - call .say_on_off -; mov si, vrrm_msg -; cmp [preboot_vrrm], 1 -; call .say_on_off - mov si, preboot_device_msg - call print - mov al, [preboot_device] -if defined extended_primary_loader - and eax, 3 -else - and eax, 7 -end if - mov si, [preboot_device_msgs+eax*2] - call printplain -.show_remarks: -; show remarks in gray color - mov di, ((21-num_remarks)*80 + 2)*2 - push 0xB800 - pop es - mov cx, num_remarks - mov si, remarks -.write_remarks: - lodsw - push si - xchg ax, si - mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) - push di -.write_remark: - lodsb - test al, al - jz @f - stosw - jmp .write_remark -@@: - pop di - pop si - add di, 80*2 - loop .write_remarks -.wait: - _setcursor 25,0 ; out of screen -; set timer interrupt handler - cli - push 0 - pop es - push dword [es:8*4] - pop dword [.oldtimer] - push dword [.timer] - pop dword [es:8*4] -; mov eax, [es:8*4] -; mov [.oldtimer], eax -; mov eax, [.timer] -; mov [es:8*4], eax - sti -; wait for keypressed - xor ax,ax - int 16h - push ax -; restore timer interrupt -; push 0 -; pop es - mov eax, [.oldtimer] - mov [es:8*4], eax - mov [.timer], eax - - _setcursor 7,0 - mov si, space_msg - call printplain -; clear remarks and restore normal attributes - push es - mov di, ((21-num_remarks)*80 + 2)*2 - push 0xB800 - pop es - mov cx, num_remarks - mov ax, ' ' + (1*16 + 15)*100h -@@: - push cx - mov cx, 76 - rep stosw - pop cx - add di, 4*2 - loop @b - pop es - pop ax -; switch on key - cmp al, 13 - jz .continue - or al, 20h - cmp al, 'a' - jz .change_a - cmp al, 'b' - jz .change_b -; cmp al, 'c' -; jz .change_c - cmp al, 'c' ; 'd' - jnz .show_remarks - _setcursor 15,0 - mov si, bdev - call print -if defined extended_primary_loader - mov bx, '12' -else - mov bx, '14' -end if - call getkey - mov [preboot_device], al - _setcursor 13,0 -.d: -if ~ defined extended_primary_loader - mov [.bSettingsChanged], 1 -end if - call clear_vmodes_table ;clear vmodes_table - jmp .printcfg -.change_a: -.loops: - call draw_vmodes_table - _setcursor 25,0 ; out of screen - xor ax,ax - int 0x16 -; call clear_table_cursor ;clear current position of cursor - - mov si,word [cursor_pos] - - cmp ah,0x48;x,0x48E0 ; up - jne .down - cmp si,modes_table - jbe .loops - sub word [cursor_pos],size_of_step - jmp .loops - -.down: cmp ah,0x50;x,0x50E0 ; down - jne .pgup - cmp word[es:si+10],-1 - je .loops - add word [cursor_pos],size_of_step - jmp .loops - -.pgup: cmp ah,0x49 ; page up - jne .pgdn - sub si, size_of_step*long_v_table - cmp si, modes_table - jae @f - mov si, modes_table -@@: - mov word [cursor_pos], si - mov si, word [home_cursor] - sub si, size_of_step*long_v_table - cmp si, modes_table - jae @f - mov si, modes_table -@@: - mov word [home_cursor], si - jmp .loops - -.pgdn: cmp ah,0x51 ; page down - jne .enter - mov ax, [end_cursor] - add si, size_of_step*long_v_table - cmp si, ax - jb @f - mov si, ax - sub si, size_of_step -@@: - mov word [cursor_pos], si - mov si, word [home_cursor] - sub ax, size_of_step*long_v_table - add si, size_of_step*long_v_table - cmp si, ax - jb @f - mov si, ax -@@: - mov word [home_cursor], si - jmp .loops - -.enter: cmp al,0x0D;x,0x1C0D ; enter - jne .loops - push word [cursor_pos] - pop bp - push word [es:bp] - pop word [x_save] - push word [es:bp+2] - pop word [y_save] - push word [es:bp+6] - pop word [number_vm] - mov word [preboot_graph],bp ;save choose - - jmp .d - -.change_b: - _setcursor 15,0 -; mov si, ask_dma -; call print -; mov bx, '13' -; call getkey -; mov [preboot_dma], al - mov si, ask_bd - call print - mov bx, '12' - call getkey - mov [preboot_biosdisk], al - _setcursor 11,0 - jmp .d -;.change_c: -; _setcursor 15,0 -; mov si, vrrmprint -; call print -; mov bx, '12' -; call getkey -; mov [preboot_vrrm], al -; _setcursor 12,0 -; jmp .d -;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.say_on_off: - pushf - call print - mov si, on_msg - popf - jz @f - mov si, off_msg -@@: jmp printplain -; novesa and vervesa strings are not used at the moment of executing this code -virtual at novesa -.oldtimer dd ? -.starttime dd ? -if ~ defined extended_primary_loader -.bSettingsChanged db ? -end if -.timer dd ? -end virtual -if ~ defined extended_primary_loader -.loader_block dd -1 -end if -.gettime: - mov ah, 0 - int 1Ah - xchg ax, cx - shl eax, 10h - xchg ax, dx - ret -.newtimer: - push ds - push cs - pop ds - pushf - call [.oldtimer] - pushad - call .gettime - sub eax, [.starttime] -if defined extended_primary_loader - sub ax, [preboot_timeout] -else - sub ax, 18*5 -end if - jae .timergo - neg ax - add ax, 18-1 - mov bx, 18 - xor dx, dx - div bx -if lang eq ru -; Ї®¤®¦¤ЁвҐ 5 ᥪ㭤, 4/3/2 ᥪ㭤л, 1 ᥪ㭤г - cmp al, 5 - mov cl, ' ' - jae @f - cmp al, 1 - mov cl, 'г' - jz @f - mov cl, 'л' -@@: mov [time_str+9], cl -else if lang eq et - cmp al, 1 - ja @f - mov [time_str+9], ' ' - mov [time_str+10],' ' -@@: -else -; wait 5/4/3/2 seconds, 1 second - cmp al, 1 - mov cl, 's' - ja @f - mov cl, ' ' -@@: mov [time_str+9], cl -end if - add al, '0' - mov [time_str+1], al - mov si, time_msg - _setcursor 7,0 - call print - _setcursor 25,0 - popad - pop ds - iret -.timergo: - push 0 - pop es - mov eax, [.oldtimer] - mov [es:8*4], eax - mov sp, 0EC00h -.continue: - sti - _setcursor 6,0 - mov si, space_msg - call printplain - call printplain - _setcursor 6,0 - mov si, loading_msg - call print - _setcursor 15,0 -if ~ defined extended_primary_loader - cmp [.bSettingsChanged], 0 - jz .load - cmp [.loader_block], -1 - jz .load - les bx, [.loader_block] - mov eax, [es:bx+3] - push ds - pop es - test eax, eax - jz .load - push eax - mov si, save_quest - call print -.waityn: - mov ah, 0 - int 16h - or al, 20h - cmp al, 'n' - jz .loadc - cmp al, 'y' - jnz .waityn - call putchar - mov byte [space_msg+80], 186 - - pop eax - push cs - push .cont - push eax - retf ;call back -.loadc: - pop eax -.cont: - push cs - pop ds - mov si, space_msg - mov byte [si+80], 0 - _setcursor 15,0 - call printplain - _setcursor 15,0 -.load: -end if -; \end{diamond}[02.12.2005] - -; ASK GRAPHICS MODE - - call set_vmode - -; GRAPHICS ACCELERATION -; force yes - mov [es:0x901C], byte 1 - -; DMA ACCESS TO HD - - mov al, [preboot_dma] - mov [es:0x901F], al - -;; VRR_M USE -; -; mov al,[preboot_vrrm] -; mov [es:0x9030], al - mov [es:0x901E], byte 1 - -; BOOT DEVICE - - mov al, [preboot_device] - dec al - mov [boot_dev], al - -; GET MEMORY MAP -include '../detect/biosmem.inc' - -; READ DISKETTE TO MEMORY - - cmp [boot_dev],0 - jne no_sys_on_floppy - mov si,diskload - call print - xor ax, ax ; reset drive - xor dx, dx - int 0x13 -; do we boot from CD-ROM? - mov ah, 41h - mov bx, 55AAh - xor dx, dx - int 0x13 - jc .nocd - cmp bx, 0AA55h - jnz .nocd - mov ah, 48h - push ds - push es - pop ds - mov si, 0xa000 - mov word [si], 30 - int 0x13 - pop ds - jc .nocd - push ds - lds si, [es:si+26] - test byte [ds:si+10], 40h - pop ds - jz .nocd -; yes - read all floppy by 18 sectors - -; TODO: !!!! read only first sector and set variables !!!!! -; ... -; TODO: !!! then read flippy image track by track - - mov cx, 0x0001 ; startcyl,startsector -.a1: - push cx dx - mov al, 18 - mov bx, 0xa000 - call boot_read_floppy - mov si, movedesc - push es - push ds - pop es - mov cx, 256*18 - mov ah, 0x87 - int 0x15 - pop es - pop dx cx - test ah, ah - jnz sayerr_floppy - add dword [si+8*3+2], 512*18 - inc dh - cmp dh, 2 - jnz .a1 - mov dh, 0 - inc ch - cmp ch, 80 - jae ok_sys_on_floppy - pusha - mov al, ch - shr ch, 2 - add al, ch - aam - xchg al, ah - add ax, '00' - mov si, pros - mov [si], ax - call printplain - popa - jmp .a1 -.nocd: -; no - read only used sectors from floppy -; now load floppy image to memory -; at first load boot sector and first FAT table - -; read only first sector and fill variables - mov cx, 0x0001 ; first logical sector - xor dx, dx ; head = 0, drive = 0 (a:) - mov al, 1 ; read one sector - mov bx, 0xB000 ; es:bx -> data area - call boot_read_floppy -; fill the necessary parameters to work with a floppy - mov ax, word [es:bx+24] - mov word [BPB_SecPerTrk], ax - mov ax, word [es:bx+26] - mov word [BPB_NumHeads], ax - mov ax, word [es:bx+17] - mov word [BPB_RootEntCnt], ax - mov ax, word [es:bx+14] - mov word [BPB_RsvdSecCnt], ax - mov ax, word [es:bx+19] - mov word [BPB_TotSec16], ax - mov al, byte [es:bx+13] - mov byte [BPB_SecPerClus], al - mov al, byte [es:bx+16] - mov byte [BPB_NumFATs], al -; 18.11.2008 - mov ax, word [es:bx+22] - mov word [BPB_FATSz16], ax - mov cx, word [es:bx+11] - mov word [BPB_BytsPerSec], cx - -; count of clusters in FAT12 ((size_of_FAT*2)/3) -; mov ax, word [BPB_FATSz16] -; mov cx, word [BPB_BytsPerSec] -;end 18.11.2008 - xor dx, dx - mul cx - shl ax, 1 - mov cx, 3 - div cx ; now ax - number of clusters in FAT12 - mov word [end_of_FAT], ax - -; load first FAT table - mov cx, 0x0002 ; startcyl,startsector ; TODO!!!!! - xor dx, dx ; starthead,drive - mov al, byte [BPB_FATSz16] ; no of sectors to read - add bx, word [BPB_BytsPerSec] ; es:bx -> data area - call boot_read_floppy - mov bx, 0xB000 - -; and copy them to extended memory - mov si, movedesc - mov [si+8*2+3], bh ; from - - mov ax, word [BPB_BytsPerSec] - shr ax, 1 ; words per sector - mov cx, word [BPB_RsvdSecCnt] - add cx, word [BPB_FATSz16] - mul cx - push ax ; save to stack count of words in boot+FAT - xchg ax, cx - - push es - push ds - pop es - mov ah, 0x87 - int 0x15 - pop es - test ah, ah - jz @f -sayerr_floppy: - mov dx, 0x3f2 - mov al, 0 - out dx, al -sayerr_memmove: - mov si, memmovefailed - jmp sayerr_plain -@@: - pop ax ; restore from stack count of words in boot+FAT - shl ax, 1 ; make bytes count from count of words - and eax, 0ffffh - add dword [si+8*3+2], eax - -; copy first FAT to second copy -; TODO: BPB_NumFATs !!!!! - add bx, word [BPB_BytsPerSec] ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!! - mov byte [si+8*2+3], bh ; bx - begin of FAT - - mov ax, word [BPB_BytsPerSec] - shr ax, 1 ; words per sector - mov cx, word [BPB_FATSz16] - mul cx - mov cx, ax ; cx - count of words in FAT - - push es - push ds - pop es - mov ah, 0x87 - int 0x15 - pop es - test ah, ah - jnz sayerr_floppy - - mov ax, cx - shl ax, 1 - and eax, 0ffffh ; ax - count of bytes in FAT - add dword [si+8*3+2], eax - -; reading RootDir -; TODO: BPB_NumFATs - add bx, ax - add bx, 100h - and bx, 0ff00h ; bx - place in buffer to write RootDir - push bx - - mov bx, word [BPB_BytsPerSec] - shr bx, 5 ; divide bx by 32 - mov ax, word [BPB_RootEntCnt] - xor dx, dx - div bx - push ax ; ax - count of RootDir sectors - - mov ax, word [BPB_FATSz16] - xor cx, cx - mov cl, byte [BPB_NumFATs] - mul cx - add ax, word [BPB_RsvdSecCnt] ; ax - first sector of RootDir - - mov word [FirstDataSector], ax - pop bx - push bx - add word [FirstDataSector], bx ; Begin of data region of floppy - -; read RootDir - call conv_abs_to_THS - pop ax - pop bx ; place in buffer to write - push ax - call boot_read_floppy ; read RootDir into buffer -; copy RootDir - mov byte [si+8*2+3], bh ; from buffer - pop ax ; ax = count of RootDir sectors - mov cx, word [BPB_BytsPerSec] - mul cx - shr ax, 1 - mov cx, ax ; count of words to copy - push es - push ds - pop es - mov ah, 0x87 - int 0x15 - pop es - - mov ax, cx - shl ax, 1 - and eax, 0ffffh ; ax - count of bytes in RootDir - add dword [si+8*3+2], eax ; add count of bytes copied - -; Reading data clusters from floppy - mov byte [si+8*2+3], bh - push bx - - mov di, 2 ; First data cluster -.read_loop: - mov bx, di - shr bx, 1 ; bx+di = di*1.5 - jnc .even - test word [es:bx+di+0xB200], 0xFFF0 ; TODO: may not be 0xB200 !!! - jmp @f -.even: - test word [es:bx+di+0xB200], 0xFFF ; TODO: may not be 0xB200 !!! - -@@: - jz .skip -; read cluster di -;.read: - ;conv cluster di to abs. sector ax - ; ax = (N-2) * BPB_SecPerClus + FirstDataSector - mov ax, di - sub ax, 2 - xor bx, bx - mov bl, byte [BPB_SecPerClus] - mul bx - add ax, word [FirstDataSector] - call conv_abs_to_THS - pop bx - push bx - mov al, byte [BPB_SecPerClus] ; number of sectors in cluster - call boot_read_floppy - push es - push ds - pop es - pusha -; - mov ax, word [BPB_BytsPerSec] - xor cx, cx - mov cl, byte [BPB_SecPerClus] - mul cx - shr ax, 1 ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2 - mov cx, ax ; number of words to copy (count words in cluster) -; - mov ah, 0x87 - int 0x15 ; copy data - test ah, ah - popa - pop es - jnz sayerr_floppy -; skip cluster di -.skip: - mov ax, word [BPB_BytsPerSec] - xor cx, cx - mov cl, byte [BPB_SecPerClus] - mul cx - and eax, 0ffffh ; ax - count of bytes in cluster - add dword [si+8*3+2], eax - - mov ax, word [end_of_FAT] ; max cluster number - pusha -; draw percentage -; total clusters: ax -; read clusters: di - xchg ax, di - mov cx, 100 - mul cx - div di - aam - xchg al, ah - add ax, '00' - mov si, pros - cmp [si], ax - jz @f - mov [si], ax - call printplain -@@: - popa - inc di - cmp di, word [end_of_FAT] ; max number of cluster - jnz .read_loop - pop bx ; clear stack - -ok_sys_on_floppy: - mov si, backspace2 - call printplain - mov si, okt - call printplain -no_sys_on_floppy: - xor ax, ax ; reset drive - xor dx, dx - int 0x13 - mov dx, 0x3f2 ; floppy motor off - mov al, 0 - out dx, al - -if defined extended_primary_loader - cmp [boot_dev], 1 - jne no_sys_from_primary -; load kolibri.img using callback from primary loader - and word [movedesc + 24 + 2], 0 - mov byte [movedesc + 24 + 4], 10h -; read in blocks of 64K until file is fully loaded - mov ax, 1 -.repeat: - mov di, image_file_struct - call [bootcallback] - push cs - pop ds - push cs - pop es - cmp bx, 1 - ja sayerr_badsect - push bx - mov si, movedesc - and word [si + 16 + 2], 0 - mov byte [si + 16 + 4], 4 - mov ah, 87h - mov cx, 8000h - int 15h - pop bx - test ah, ah - jnz sayerr_memmove - inc byte [si + 24 + 4] - test bx, bx - jz no_sys_from_primary - mov ax, 2 - jmp .repeat -no_sys_from_primary: -end if - -; SET GRAPHICS - - xor ax, ax - mov es, ax - - mov ax, [es:0x9008] ; vga & 320x200 - mov bx, ax - cmp ax, 0x13 - je setgr - cmp ax, 0x12 - je setgr - mov ax, 0x4f02 ; Vesa -setgr: - int 0x10 - test ah, ah - mov si, fatalsel - jnz v_mode_error -; set mode 0x12 graphics registers: - cmp bx, 0x12 - jne gmok2 - - mov al, 0x05 - mov dx, 0x03ce - push dx - out dx, al ; select GDC mode register - mov al, 0x02 - inc dx - out dx, al ; set write mode 2 - - mov al, 0x02 - mov dx, 0x03c4 - out dx, al ; select VGA sequencer map mask register - mov al, 0x0f - inc dx - out dx, al ; set mask for all planes 0-3 - - mov al, 0x08 - pop dx - out dx, al ; select GDC bit mask register - ; for writes to 0x03cf -gmok2: - push ds - pop es +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; BOOTCODE.INC ;; +;; ;; +;; KolibriOS 16-bit loader, ;; +;; based on bootcode for MenuetOS ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;========================================================================== +; +; 16 BIT FUNCTIONS +; +;========================================================================== + + +putchar: +; in: al=character + mov ah, 0Eh + mov bh, 0 + int 10h + ret + +print: +; in: si->string + mov al, 186 + call putchar + mov al, ' ' + call putchar + +printplain: +; in: si->string + pusha + lodsb +@@: + call putchar + lodsb + test al, al + jnz @b + popa + ret + +getkey: +; get number in range [bl,bh] (bl,bh in ['0'..'9']) +; in: bx=range +; out: ax=digit (1..9, 10 for 0) + mov ah, 0 + int 16h + cmp al, bl + jb getkey + cmp al, bh + ja getkey + push ax + call putchar + pop ax + and ax, 0Fh + jnz @f + mov al, 10 +@@: + ret + +setcursor: +; in: dl=column, dh=row + mov ah, 2 + mov bh, 0 + int 10h + ret + +macro _setcursor row,column +{ + mov dx, row*256 + column + call setcursor +} + +boot_read_floppy: + push si + xor si, si + mov ah, 2 ; read +@@: + push ax + int 0x13 + pop ax + jnc @f + inc si + cmp si, 10 + jb @b +sayerr_badsect: + mov si, badsect +sayerr_plain: + call printplain + jmp $ +@@: + pop si + ret + +; convert abs. sector number (AX) to BIOS T:H:S +; sector number = (abs.sector%BPB_SecPerTrk)+1 +; pre.track number = (abs.sector/BPB_SecPerTrk) +; head number = pre.track number%BPB_NumHeads +; track number = pre.track number/BPB_NumHeads +; Return: cl - sector number +; ch - track number +; dl - drive number (0 = a:) +; dh - head number +conv_abs_to_THS: + push bx + mov bx, word [BPB_SecPerTrk] + xor dx, dx + div bx + inc dx + mov cl, dl ; cl = sector number + mov bx, word [BPB_NumHeads] + xor dx, dx + div bx + ; !!!!!!! ax = track number, dx = head number + mov ch, al ; ch=track number + xchg dh, dl ; dh=head number + mov dl, 0 ; dl=0 (drive 0 (a:)) + pop bx + retn +; needed variables +BPB_SecPerTrk dw 0 ; sectors per track +BPB_NumHeads dw 0 ; number of heads +BPB_FATSz16 dw 0 ; size of FAT +BPB_RootEntCnt dw 0 ; count of root dir. entries +BPB_BytsPerSec dw 0 ; bytes per sector +BPB_RsvdSecCnt dw 0 ; number of reserved sectors +BPB_TotSec16 dw 0 ; count of the sectors on the volume +BPB_SecPerClus db 0 ; number of sectors per cluster +BPB_NumFATs db 0 ; number of FAT tables +abs_sector_adj dw 0 ; adjustment to make abs. sector number +end_of_FAT dw 0 ; end of FAT table +FirstDataSector dw 0 ; begin of data + +;========================================================================= +; +; 16 BIT CODE +; +;========================================================================= + +include 'bootvesa.inc' ;Include source for boot vesa +if defined extended_primary_loader +include 'parsers.inc' +end if + +start_of_code: + +if defined extended_primary_loader +; save data from primary loader + mov word [cs:bootcallback], si + mov word [cs:bootcallback+2], ds + push cs + pop ds + mov [bootdevice], ax + mov [bootfs], bx + +; set up stack + mov ax, 3000h + mov ss, ax + mov sp, 0EC00h + +; try to load configuration file + mov ax, 1 + mov di, config_file_struct + call [bootcallback] + cld + push cs + pop es +; bx=0 - ok, bx=1 - part of file loaded, assume this is ok + cmp bx, 1 + ja .config_bad +; configuration file was loaded, parse +; if length is too big, use first 0FFFFh bytes + test dx, dx + jz @f + mov ax, 0FFFFh +@@: +; ds:si will be pointer to current data, dx = limit + xchg ax, dx + push 4000h + pop ds + xor si, si +.parse_loop: +; skip spaces + cmp si, dx + jae .parse_done + lodsb + cmp al, ' ' + jbe .parse_loop + dec si +; loop over all possible configuration values + mov bx, config_file_variables +.find_variant: +; get length + mov cx, [es:bx] +; zero length = end of list + jecxz .find_newline +; skip over length + inc bx + inc bx + mov di, bx +; skip over string + add bx, cx +; test whether we have at least cx symbols left + mov ax, cx + add ax, si + jc .next_variant1 + cmp ax, dx + jae .next_variant1 +; save current position + push si +; compare strings + repz cmpsb + jnz .next_variant2 +; strings are equal; look for "=" with possible spaces before and after +@@: + cmp si, dx + jae .next_variant2 + lodsb + cmp al, ' ' + jbe @b + cmp al, '=' + jnz .next_variant2 +; ok, we found the true variant +; ignore saved position on the stack + pop ax +; call the parser + call word [es:bx] +; line parsed, find next +.find_newline: + cmp si, dx + jae .parse_done + lodsb + cmp al, 13 + jz .parse_loop + cmp al, 10 + jz .parse_loop + jmp .find_newline +.next_variant2: +; continue to the next variant, restoring current position + pop si +.next_variant1: +; continue to the next variant +; skip over the parser + inc bx + inc bx + jmp .find_variant +.parse_done: +.config_bad: + +; set up segment registers + push cs + pop ds +else + cld +; \begin{diamond}[02.12.2005] +; if bootloader sets ax = 'KL', then ds:si points to loader block + cmp ax, 'KL' + jnz @f + mov word [cs:cfgmanager.loader_block], si + mov word [cs:cfgmanager.loader_block+2], ds +@@: +; \end{diamond}[02.12.2005] + +; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk +; (see comment to bx_from_load) + cmp cx, 'HA' + jnz no_hd_load + cmp dx, 'RD' + jnz no_hd_load + mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] +no_hd_load: + +; set up stack + mov ax, 3000h + mov ss, ax + mov sp, 0EC00h +; set up segment registers + push cs + pop ds + push cs + pop es +end if + +; set videomode + mov ax, 3 + int 0x10 + +if lang eq ru + ; Load & set russian VGA font (RU.INC) + mov bp, RU_FNT1 ; RU_FNT1 - First part + mov bx, 1000h ; 768 bytes + mov cx, 30h ; 48 symbols + mov dx, 80h ; 128 - position of first symbol + mov ax, 1100h + int 10h + + mov bp, RU_FNT2 ; RU_FNT2 -Second part + mov bx, 1000h ; 512 bytes + mov cx, 20h ; 32 symbols + mov dx, 0E0h ; 224 - position of first symbol + mov ax, 1100h + int 10h + ; End set VGA russian font +else if lang eq et + mov bp, ET_FNT ; ET_FNT1 + mov bx, 1000h ; + mov cx, 255 ; 256 symbols + xor dx, dx ; 0 - position of first symbol + mov ax, 1100h + int 10h +end if + +; draw frames + push 0xb800 + pop es + xor di, di + mov ah, 1*16+15 + +; draw top + mov si, d80x25_top + mov cx, d80x25_top_num * 80 +@@: + lodsb + stosw + loop @b +; draw spaces + mov si, space_msg + mov dx, 25 - d80x25_top_num - d80x25_bottom_num +dfl1: + push si + mov cx, 80 +@@: + lodsb + stosw + loop @b + pop si + dec dx + jnz dfl1 +; draw bottom + mov si, d80x25_bottom + mov cx, d80x25_bottom_num * 80 +@@: + lodsb + stosw + loop @b + + mov byte [space_msg+80], 0 ; now space_msg is null terminated + + _setcursor d80x25_top_num,0 + + +; TEST FOR 386+ + + mov bx, 0x4000 + pushf + pop ax + mov dx, ax + xor ax, bx + push ax + popf + pushf + pop ax + and ax, bx + and dx, bx + cmp ax, dx + jnz cpugood + mov si, not386 +sayerr: + call print + jmp $ + cpugood: + + push 0 + popf + sti + +; set up esp + movzx esp, sp + + push 0 + pop es + and word [es:0x9031], 0 +; \begin{Mario79} +; find HDD IDE DMA PCI device +; check for PCI BIOS + mov ax, 0xB101 + int 0x1A + jc .nopci + cmp edx, 'PCI ' + jnz .nopci +; find PCI class code +; class 1 = mass storage +; subclass 1 = IDE controller +; a) class 1, subclass 1, programming interface 0x80 + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x80 + xor si, si ; device index = 0 + int 0x1A + jnc .found +; b) class 1, subclass 1, programming interface 0x8A + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x8A + xor si, si ; device index = 0 + int 0x1A + jnc .found +; c) class 1, subclass 1, programming interface 0x85 + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x85 + xor si, si + int 0x1A + jc .nopci +.found: +; get memory base + mov ax, 0xB10A + mov di, 0x20 ; memory base is config register at 0x20 + int 0x1A + jc .nopci + and cx, 0xFFF0 ; clear address decode type + mov [es:0x9031], cx +.nopci: +; \end{Mario79} + + mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование + out 0x60, al + xor cx, cx +wait_loop: ; variant 2 +; reading state of port of 8042 controller + in al, 64h + and al, 00000010b ; ready flag +; wait until 8042 controller is ready + loopnz wait_loop + +;;;/diamond today 5.02.2008 +; set keyboard typematic rate & delay + mov al, 0xf3 + out 0x60, al + xor cx, cx +@@: + in al, 64h + test al, 2 + loopnz @b + mov al, 0 + out 0x60, al + xor cx, cx +@@: + in al, 64h + test al, 2 + loopnz @b +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; --------------- APM --------------------- + and word [es:0x9044], 0 ; ver = 0.0 (APM not found) + mov ax, 0x5300 + xor bx, bx + int 0x15 + jc apm_end ; APM not found + test cx, 2 + jz apm_end ; APM 32-bit protected-mode interface not supported + mov [es:0x9044], ax ; Save APM Version + mov [es:0x9046], cx ; Save APM flags + + ; Write APM ver ---- + and ax, 0xf0f + add ax, '00' + mov si, msg_apm + mov [si + 5], ah + mov [si + 7], al + _setcursor 0, 3 + call printplain + ; ------------------ + + mov ax, 0x5304 ; Disconnect interface + xor bx, bx + int 0x15 + mov ax, 0x5303 ; Connect 32 bit mode interface + xor bx, bx + int 0x15 + + mov [es:0x9040], ebx + mov [es:0x9050], ax + mov [es:0x9052], cx + mov [es:0x9054], dx + +apm_end: + _setcursor d80x25_top_num, 0 + +if ~ defined extended_primary_loader +;CHECK current of code + cmp [cfgmanager.loader_block], -1 + jz noloaderblock + les bx, [cfgmanager.loader_block] + cmp byte [es:bx], 1 + mov si, loader_block_error + jnz sayerr + push 0 + pop es +end if + +noloaderblock: +; DISPLAY VESA INFORMATION + call print_vesa_info + call calc_vmodes_table + call check_first_parm ;check and enable cursor_pos + +; \begin{diamond}[30.11.2005] +cfgmanager: +; settings: +; a) preboot_graph = graphical mode +; preboot_gprobe = probe this mode? +; b) preboot_dma = use DMA access? +; c) preboot_vrrm = use VRR? +; d) preboot_device = from what boot? + +; determine default settings +if ~ defined extended_primary_loader + mov [.bSettingsChanged], 0 +end if + +;.preboot_gr_end: + mov di, preboot_device +; if image in memory is present and [preboot_device] is uninitialized, +; set it to use this preloaded image + cmp byte [di], 0 + jnz .preboot_device_inited +if defined extended_primary_loader + inc byte [di] + cmp byte [bootdevice], 'f' ; floppy? + jz .preboot_device_inited + inc byte [di] +else + cmp [.loader_block], -1 + jz @f + les bx, [.loader_block] + test byte [es:bx+1], 1 + jz @f + mov byte [di], 3 + jmp .preboot_device_inited +@@: +; otherwise, set [preboot_device] to 1 (default value - boot from floppy) + mov byte [di], 1 +end if +.preboot_device_inited: +; following 4 lines set variables to 1 if its current value is 0 + cmp byte [di+preboot_dma-preboot_device], 1 + adc byte [di+preboot_dma-preboot_device], 0 + cmp byte [di+preboot_biosdisk-preboot_device], 1 + adc byte [di+preboot_biosdisk-preboot_device], 0 +;; default value for VRR is OFF +; cmp byte [di+preboot_vrrm-preboot_device], 0 +; jnz @f +; mov byte [di+preboot_vrrm-preboot_device], 2 +;@@: +; notify user + _setcursor 5,2 + + mov si, linef + call printplain + mov si, start_msg + call print + mov si, time_msg + call print +; get start time + call .gettime + mov [.starttime], eax + mov word [.timer], .newtimer + mov word [.timer+2], cs +.printcfg: + + _setcursor 9,0 + mov si, current_cfg_msg + call print + mov si, curvideo_msg + call print + + call draw_current_vmode + + mov si, usebd_msg + cmp [preboot_biosdisk], 1 + call .say_on_off +; mov si, vrrm_msg +; cmp [preboot_vrrm], 1 +; call .say_on_off + mov si, preboot_device_msg + call print + mov al, [preboot_device] +if defined extended_primary_loader + and eax, 3 +else + and eax, 7 +end if + mov si, [preboot_device_msgs+eax*2] + call printplain +.show_remarks: +; show remarks in gray color + mov di, ((21-num_remarks)*80 + 2)*2 + push 0xB800 + pop es + mov cx, num_remarks + mov si, remarks +.write_remarks: + lodsw + push si + xchg ax, si + mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) + push di +.write_remark: + lodsb + test al, al + jz @f + stosw + jmp .write_remark +@@: + pop di + pop si + add di, 80*2 + loop .write_remarks +.wait: + _setcursor 25,0 ; out of screen +; set timer interrupt handler + cli + push 0 + pop es + push dword [es:8*4] + pop dword [.oldtimer] + push dword [.timer] + pop dword [es:8*4] +; mov eax, [es:8*4] +; mov [.oldtimer], eax +; mov eax, [.timer] +; mov [es:8*4], eax + sti +; wait for keypressed + xor ax, ax + int 16h + push ax +; restore timer interrupt +; push 0 +; pop es + mov eax, [.oldtimer] + mov [es:8*4], eax + mov [.timer], eax + + _setcursor 7,0 + mov si, space_msg + call printplain +; clear remarks and restore normal attributes + push es + mov di, ((21-num_remarks)*80 + 2)*2 + push 0xB800 + pop es + mov cx, num_remarks + mov ax, ' ' + (1*16 + 15)*100h +@@: + push cx + mov cx, 76 + rep stosw + pop cx + add di, 4*2 + loop @b + pop es + pop ax +; switch on key + cmp al, 13 + jz .continue + or al, 20h + cmp al, 'a' + jz .change_a + cmp al, 'b' + jz .change_b +; cmp al, 'c' +; jz .change_c + cmp al, 'c' ; 'd' + jnz .show_remarks + _setcursor 15,0 + mov si, bdev + call print +if defined extended_primary_loader + mov bx, '12' +else + mov bx, '14' +end if + call getkey + mov [preboot_device], al + _setcursor 13,0 +.d: +if ~ defined extended_primary_loader + mov [.bSettingsChanged], 1 +end if + call clear_vmodes_table ;clear vmodes_table + jmp .printcfg +.change_a: +.loops: + call draw_vmodes_table + _setcursor 25,0 ; out of screen + xor ax, ax + int 0x16 +; call clear_table_cursor ;clear current position of cursor + + mov si, word [cursor_pos] + + cmp ah, 0x48;x,0x48E0 ; up + jne .down + cmp si, modes_table + jbe .loops + sub word [cursor_pos], size_of_step + jmp .loops + +.down: + cmp ah, 0x50;x,0x50E0 ; down + jne .pgup + cmp word[es:si+10], -1 + je .loops + add word [cursor_pos], size_of_step + jmp .loops + +.pgup: + cmp ah, 0x49 ; page up + jne .pgdn + sub si, size_of_step*long_v_table + cmp si, modes_table + jae @f + mov si, modes_table +@@: + mov word [cursor_pos], si + mov si, word [home_cursor] + sub si, size_of_step*long_v_table + cmp si, modes_table + jae @f + mov si, modes_table +@@: + mov word [home_cursor], si + jmp .loops + +.pgdn: + cmp ah, 0x51 ; page down + jne .enter + mov ax, [end_cursor] + add si, size_of_step*long_v_table + cmp si, ax + jb @f + mov si, ax + sub si, size_of_step +@@: + mov word [cursor_pos], si + mov si, word [home_cursor] + sub ax, size_of_step*long_v_table + add si, size_of_step*long_v_table + cmp si, ax + jb @f + mov si, ax +@@: + mov word [home_cursor], si + jmp .loops + +.enter: + cmp al, 0x0D;x,0x1C0D ; enter + jne .loops + push word [cursor_pos] + pop bp + push word [es:bp] + pop word [x_save] + push word [es:bp+2] + pop word [y_save] + push word [es:bp+6] + pop word [number_vm] + mov word [preboot_graph], bp ;save choose + + jmp .d + +.change_b: + _setcursor 15,0 +; mov si, ask_dma +; call print +; mov bx, '13' +; call getkey +; mov [preboot_dma], al + mov si, ask_bd + call print + mov bx, '12' + call getkey + mov [preboot_biosdisk], al + _setcursor 11,0 + jmp .d +;.change_c: +; _setcursor 15,0 +; mov si, vrrmprint +; call print +; mov bx, '12' +; call getkey +; mov [preboot_vrrm], al +; _setcursor 12,0 +; jmp .d +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.say_on_off: + pushf + call print + mov si, on_msg + popf + jz @f + mov si, off_msg +@@: + jmp printplain +; novesa and vervesa strings are not used at the moment of executing this code +virtual at novesa +.oldtimer dd ? +.starttime dd ? +if ~ defined extended_primary_loader +.bSettingsChanged db ? +end if +.timer dd ? +end virtual +if ~ defined extended_primary_loader +.loader_block dd -1 +end if +.gettime: + mov ah, 0 + int 1Ah + xchg ax, cx + shl eax, 10h + xchg ax, dx + ret +.newtimer: + push ds + push cs + pop ds + pushf + call [.oldtimer] + pushad + call .gettime + sub eax, [.starttime] +if defined extended_primary_loader + sub ax, [preboot_timeout] +else + sub ax, 18*5 +end if + jae .timergo + neg ax + add ax, 18-1 + mov bx, 18 + xor dx, dx + div bx +if lang eq ru +; Ї®¤®¦¤ЁвҐ 5 ᥪ㭤, 4/3/2 ᥪ㭤л, 1 ᥪ㭤г + cmp al, 5 + mov cl, ' ' + jae @f + cmp al, 1 + mov cl, 'г' + jz @f + mov cl, 'л' +@@: + mov [time_str+9], cl +else if lang eq et + cmp al, 1 + ja @f + mov [time_str+9], ' ' + mov [time_str+10], ' ' +@@: +else +; wait 5/4/3/2 seconds, 1 second + cmp al, 1 + mov cl, 's' + ja @f + mov cl, ' ' +@@: + mov [time_str+9], cl +end if + add al, '0' + mov [time_str+1], al + mov si, time_msg + _setcursor 7,0 + call print + _setcursor 25,0 + popad + pop ds + iret +.timergo: + push 0 + pop es + mov eax, [.oldtimer] + mov [es:8*4], eax + mov sp, 0EC00h +.continue: + sti + _setcursor 6,0 + mov si, space_msg + call printplain + call printplain + _setcursor 6,0 + mov si, loading_msg + call print + _setcursor 15,0 +if ~ defined extended_primary_loader + cmp [.bSettingsChanged], 0 + jz .load + cmp [.loader_block], -1 + jz .load + les bx, [.loader_block] + mov eax, [es:bx+3] + push ds + pop es + test eax, eax + jz .load + push eax + mov si, save_quest + call print +.waityn: + mov ah, 0 + int 16h + or al, 20h + cmp al, 'n' + jz .loadc + cmp al, 'y' + jnz .waityn + call putchar + mov byte [space_msg+80], 186 + + pop eax + push cs + push .cont + push eax + retf ;call back +.loadc: + pop eax +.cont: + push cs + pop ds + mov si, space_msg + mov byte [si+80], 0 + _setcursor 15,0 + call printplain + _setcursor 15,0 +.load: +end if +; \end{diamond}[02.12.2005] + +; ASK GRAPHICS MODE + + call set_vmode + +; GRAPHICS ACCELERATION +; force yes + mov [es:0x901C], byte 1 + +; DMA ACCESS TO HD + + mov al, [preboot_dma] + mov [es:0x901F], al + +;; VRR_M USE +; +; mov al,[preboot_vrrm] +; mov [es:0x9030], al + mov [es:0x901E], byte 1 + +; BOOT DEVICE + + mov al, [preboot_device] + dec al + mov [boot_dev], al + +; GET MEMORY MAP +include '../detect/biosmem.inc' + +; READ DISKETTE TO MEMORY + + cmp [boot_dev], 0 + jne no_sys_on_floppy + mov si, diskload + call print + xor ax, ax ; reset drive + xor dx, dx + int 0x13 +; do we boot from CD-ROM? + mov ah, 41h + mov bx, 55AAh + xor dx, dx + int 0x13 + jc .nocd + cmp bx, 0AA55h + jnz .nocd + mov ah, 48h + push ds + push es + pop ds + mov si, 0xa000 + mov word [si], 30 + int 0x13 + pop ds + jc .nocd + push ds + lds si, [es:si+26] + test byte [ds:si+10], 40h + pop ds + jz .nocd +; yes - read all floppy by 18 sectors + +; TODO: !!!! read only first sector and set variables !!!!! +; ... +; TODO: !!! then read flippy image track by track + + mov cx, 0x0001 ; startcyl,startsector +.a1: + push cx dx + mov al, 18 + mov bx, 0xa000 + call boot_read_floppy + mov si, movedesc + push es + push ds + pop es + mov cx, 256*18 + mov ah, 0x87 + int 0x15 + pop es + pop dx cx + test ah, ah + jnz sayerr_floppy + add dword [si+8*3+2], 512*18 + inc dh + cmp dh, 2 + jnz .a1 + mov dh, 0 + inc ch + cmp ch, 80 + jae ok_sys_on_floppy + pusha + mov al, ch + shr ch, 2 + add al, ch + aam + xchg al, ah + add ax, '00' + mov si, pros + mov [si], ax + call printplain + popa + jmp .a1 +.nocd: +; no - read only used sectors from floppy +; now load floppy image to memory +; at first load boot sector and first FAT table + +; read only first sector and fill variables + mov cx, 0x0001 ; first logical sector + xor dx, dx ; head = 0, drive = 0 (a:) + mov al, 1 ; read one sector + mov bx, 0xB000 ; es:bx -> data area + call boot_read_floppy +; fill the necessary parameters to work with a floppy + mov ax, word [es:bx+24] + mov word [BPB_SecPerTrk], ax + mov ax, word [es:bx+26] + mov word [BPB_NumHeads], ax + mov ax, word [es:bx+17] + mov word [BPB_RootEntCnt], ax + mov ax, word [es:bx+14] + mov word [BPB_RsvdSecCnt], ax + mov ax, word [es:bx+19] + mov word [BPB_TotSec16], ax + mov al, byte [es:bx+13] + mov byte [BPB_SecPerClus], al + mov al, byte [es:bx+16] + mov byte [BPB_NumFATs], al +; 18.11.2008 + mov ax, word [es:bx+22] + mov word [BPB_FATSz16], ax + mov cx, word [es:bx+11] + mov word [BPB_BytsPerSec], cx + +; count of clusters in FAT12 ((size_of_FAT*2)/3) +; mov ax, word [BPB_FATSz16] +; mov cx, word [BPB_BytsPerSec] +;end 18.11.2008 + xor dx, dx + mul cx + shl ax, 1 + mov cx, 3 + div cx ; now ax - number of clusters in FAT12 + mov word [end_of_FAT], ax + +; load first FAT table + mov cx, 0x0002 ; startcyl,startsector ; TODO!!!!! + xor dx, dx ; starthead,drive + mov al, byte [BPB_FATSz16] ; no of sectors to read + add bx, word [BPB_BytsPerSec] ; es:bx -> data area + call boot_read_floppy + mov bx, 0xB000 + +; and copy them to extended memory + mov si, movedesc + mov [si+8*2+3], bh ; from + + mov ax, word [BPB_BytsPerSec] + shr ax, 1 ; words per sector + mov cx, word [BPB_RsvdSecCnt] + add cx, word [BPB_FATSz16] + mul cx + push ax ; save to stack count of words in boot+FAT + xchg ax, cx + + push es + push ds + pop es + mov ah, 0x87 + int 0x15 + pop es + test ah, ah + jz @f +sayerr_floppy: + mov dx, 0x3f2 + mov al, 0 + out dx, al +sayerr_memmove: + mov si, memmovefailed + jmp sayerr_plain +@@: + pop ax ; restore from stack count of words in boot+FAT + shl ax, 1 ; make bytes count from count of words + and eax, 0ffffh + add dword [si+8*3+2], eax + +; copy first FAT to second copy +; TODO: BPB_NumFATs !!!!! + add bx, word [BPB_BytsPerSec] ; !!! TODO: may be need multiply by BPB_RsvdSecCnt !!! + mov byte [si+8*2+3], bh ; bx - begin of FAT + + mov ax, word [BPB_BytsPerSec] + shr ax, 1 ; words per sector + mov cx, word [BPB_FATSz16] + mul cx + mov cx, ax ; cx - count of words in FAT + + push es + push ds + pop es + mov ah, 0x87 + int 0x15 + pop es + test ah, ah + jnz sayerr_floppy + + mov ax, cx + shl ax, 1 + and eax, 0ffffh ; ax - count of bytes in FAT + add dword [si+8*3+2], eax + +; reading RootDir +; TODO: BPB_NumFATs + add bx, ax + add bx, 100h + and bx, 0ff00h ; bx - place in buffer to write RootDir + push bx + + mov bx, word [BPB_BytsPerSec] + shr bx, 5 ; divide bx by 32 + mov ax, word [BPB_RootEntCnt] + xor dx, dx + div bx + push ax ; ax - count of RootDir sectors + + mov ax, word [BPB_FATSz16] + xor cx, cx + mov cl, byte [BPB_NumFATs] + mul cx + add ax, word [BPB_RsvdSecCnt] ; ax - first sector of RootDir + + mov word [FirstDataSector], ax + pop bx + push bx + add word [FirstDataSector], bx ; Begin of data region of floppy + +; read RootDir + call conv_abs_to_THS + pop ax + pop bx ; place in buffer to write + push ax + call boot_read_floppy ; read RootDir into buffer +; copy RootDir + mov byte [si+8*2+3], bh ; from buffer + pop ax ; ax = count of RootDir sectors + mov cx, word [BPB_BytsPerSec] + mul cx + shr ax, 1 + mov cx, ax ; count of words to copy + push es + push ds + pop es + mov ah, 0x87 + int 0x15 + pop es + + mov ax, cx + shl ax, 1 + and eax, 0ffffh ; ax - count of bytes in RootDir + add dword [si+8*3+2], eax ; add count of bytes copied + +; Reading data clusters from floppy + mov byte [si+8*2+3], bh + push bx + + mov di, 2 ; First data cluster +.read_loop: + mov bx, di + shr bx, 1 ; bx+di = di*1.5 + jnc .even + test word [es:bx+di+0xB200], 0xFFF0 ; TODO: may not be 0xB200 !!! + jmp @f +.even: + test word [es:bx+di+0xB200], 0xFFF ; TODO: may not be 0xB200 !!! + +@@: + jz .skip +; read cluster di +;.read: + ;conv cluster di to abs. sector ax + ; ax = (N-2) * BPB_SecPerClus + FirstDataSector + mov ax, di + sub ax, 2 + xor bx, bx + mov bl, byte [BPB_SecPerClus] + mul bx + add ax, word [FirstDataSector] + call conv_abs_to_THS + pop bx + push bx + mov al, byte [BPB_SecPerClus] ; number of sectors in cluster + call boot_read_floppy + push es + push ds + pop es + pusha +; + mov ax, word [BPB_BytsPerSec] + xor cx, cx + mov cl, byte [BPB_SecPerClus] + mul cx + shr ax, 1 ; ax = (BPB_BytsPerSec * BPB_SecPerClus)/2 + mov cx, ax ; number of words to copy (count words in cluster) +; + mov ah, 0x87 + int 0x15 ; copy data + test ah, ah + popa + pop es + jnz sayerr_floppy +; skip cluster di +.skip: + mov ax, word [BPB_BytsPerSec] + xor cx, cx + mov cl, byte [BPB_SecPerClus] + mul cx + and eax, 0ffffh ; ax - count of bytes in cluster + add dword [si+8*3+2], eax + + mov ax, word [end_of_FAT] ; max cluster number + pusha +; draw percentage +; total clusters: ax +; read clusters: di + xchg ax, di + mov cx, 100 + mul cx + div di + aam + xchg al, ah + add ax, '00' + mov si, pros + cmp [si], ax + jz @f + mov [si], ax + call printplain +@@: + popa + inc di + cmp di, word [end_of_FAT] ; max number of cluster + jnz .read_loop + pop bx ; clear stack + +ok_sys_on_floppy: + mov si, backspace2 + call printplain + mov si, okt + call printplain +no_sys_on_floppy: + xor ax, ax ; reset drive + xor dx, dx + int 0x13 + mov dx, 0x3f2 ; floppy motor off + mov al, 0 + out dx, al + +if defined extended_primary_loader + cmp [boot_dev], 1 + jne no_sys_from_primary +; load kolibri.img using callback from primary loader + and word [movedesc + 24 + 2], 0 + mov byte [movedesc + 24 + 4], 10h +; read in blocks of 64K until file is fully loaded + mov ax, 1 +.repeat: + mov di, image_file_struct + call [bootcallback] + push cs + pop ds + push cs + pop es + cmp bx, 1 + ja sayerr_badsect + push bx + mov si, movedesc + and word [si + 16 + 2], 0 + mov byte [si + 16 + 4], 4 + mov ah, 87h + mov cx, 8000h + int 15h + pop bx + test ah, ah + jnz sayerr_memmove + inc byte [si + 24 + 4] + test bx, bx + jz no_sys_from_primary + mov ax, 2 + jmp .repeat +no_sys_from_primary: +end if + +; SET GRAPHICS + + xor ax, ax + mov es, ax + + mov ax, [es:0x9008] ; vga & 320x200 + mov bx, ax + cmp ax, 0x13 + je setgr + cmp ax, 0x12 + je setgr + mov ax, 0x4f02 ; Vesa +setgr: + int 0x10 + test ah, ah + mov si, fatalsel + jnz v_mode_error +; set mode 0x12 graphics registers: + cmp bx, 0x12 + jne gmok2 + + mov al, 0x05 + mov dx, 0x03ce + push dx + out dx, al ; select GDC mode register + mov al, 0x02 + inc dx + out dx, al ; set write mode 2 + + mov al, 0x02 + mov dx, 0x03c4 + out dx, al ; select VGA sequencer map mask register + mov al, 0x0f + inc dx + out dx, al ; set mask for all planes 0-3 + + mov al, 0x08 + pop dx + out dx, al ; select GDC bit mask register + ; for writes to 0x03cf +gmok2: + push ds + pop es diff --git a/kernel/trunk/boot/booteng.inc b/kernel/trunk/boot/booteng.inc index ba7184f77..42da32c38 100644 --- a/kernel/trunk/boot/booteng.inc +++ b/kernel/trunk/boot/booteng.inc @@ -1,101 +1,101 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;====================================================================== -; -; BOOT DATA -; -;====================================================================== - -$Revision$ - - -d80x25_bottom: - db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' - db 'NO WARRANTY ',186 - db 186,' See file COPYING for details ' - db ' ',186 - line_full_bottom -d80x25_bottom_num = 3 - -msg_apm db " APM x.x ", 0 -novesa db "Display: EGA/CGA",13,10,0 -s_vesa db "Version of VESA: " - .ver db "?.?",13,10,0 - -gr_mode db "Select a videomode: ",13,10,0 - -ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 - -if defined extended_primary_loader -bdev db "Load ramdisk from [1-floppy; 2-kolibri.img]: ",0 -else -bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-use preloaded ram-image from kernel restart;" - db 13,10,186," " - db "4-create blank image]: ",0 -end if - -prnotfnd db "Fatal - Videomode not found.",0 - -not386 db "Fatal - CPU 386+ required.",0 -fatalsel db "Fatal - Graphics mode not supported by hardware.",0 -pres_key db "Press any key to choose a new videomode.",0 -badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 -memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "Loading diskette: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 ; 0=floppy, 1=hd -start_msg db "Press [abcd] to change settings, press [Enter] to continue booting",13,10,0 -time_msg db " or wait " -time_str db " 5 seconds" - db " before automatical continuation",13,10,0 -current_cfg_msg db "Current settings:",13,10,0 -curvideo_msg db " [a] Videomode: ",0 - -mode0 db "320x200, EGA/CGA 256 colors",13,10,0 -mode9 db "640x480, VGA 16 colors",13,10,0 - -usebd_msg db " [b] Add disks visible by BIOS:",0 -on_msg db " on",13,10,0 -off_msg db " off",13,10,0 - -preboot_device_msg db " [c] Floppy image: ",0 - -if defined extended_primary_loader -preboot_device_msgs dw 0,pdm1,pdm2,0 -pdm1 db "real floppy",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -else -preboot_device_msgs dw 0,pdm1,pdm2,pdm3 -pdm1 db "real floppy",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -pdm3 db "use already loaded image",13,10,0 -pdm4 db "create blank image",13,10,0 -end if - -loading_msg db "Loading KolibriOS...",0 - -if ~ defined extended_primary_loader -save_quest db "Remember current settings? [y/n]: ",0 -loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 -end if - -_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 -_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 -_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 -_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 -_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 - -remark1 db "Default values were selected to match most of configurations, but not all.",0 -remark2 db "If the system does not boot, try to disable the item [b].",0 -remarks dw remark1, remark2 -num_remarks = 2 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + +$Revision$ + + +d80x25_bottom: + db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' + db 'NO WARRANTY ',186 + db 186,' See file COPYING for details ' + db ' ',186 + line_full_bottom +d80x25_bottom_num = 3 + +msg_apm db " APM x.x ", 0 +novesa db "Display: EGA/CGA",13,10,0 +s_vesa db "Version of VESA: " + .ver db "?.?",13,10,0 + +gr_mode db "Select a videomode: ",13,10,0 + +ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 + +if defined extended_primary_loader +bdev db "Load ramdisk from [1-floppy; 2-kolibri.img]: ",0 +else +bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-use preloaded ram-image from kernel restart;" + db 13,10,186," " + db "4-create blank image]: ",0 +end if + +prnotfnd db "Fatal - Videomode not found.",0 + +not386 db "Fatal - CPU 386+ required.",0 +fatalsel db "Fatal - Graphics mode not supported by hardware.",0 +pres_key db "Press any key to choose a new videomode.",0 +badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 +memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "Loading diskette: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 ; 0=floppy, 1=hd +start_msg db "Press [abcd] to change settings, press [Enter] to continue booting",13,10,0 +time_msg db " or wait " +time_str db " 5 seconds" + db " before automatical continuation",13,10,0 +current_cfg_msg db "Current settings:",13,10,0 +curvideo_msg db " [a] Videomode: ",0 + +mode0 db "320x200, EGA/CGA 256 colors",13,10,0 +mode9 db "640x480, VGA 16 colors",13,10,0 + +usebd_msg db " [b] Add disks visible by BIOS:",0 +on_msg db " on",13,10,0 +off_msg db " off",13,10,0 + +preboot_device_msg db " [c] Floppy image: ",0 + +if defined extended_primary_loader +preboot_device_msgs dw 0,pdm1,pdm2,0 +pdm1 db "real floppy",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +else +preboot_device_msgs dw 0,pdm1,pdm2,pdm3 +pdm1 db "real floppy",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +pdm3 db "use already loaded image",13,10,0 +pdm4 db "create blank image",13,10,0 +end if + +loading_msg db "Loading KolibriOS...",0 + +if ~ defined extended_primary_loader +save_quest db "Remember current settings? [y/n]: ",0 +loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 +end if + +_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 +_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 +_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 +_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 +_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 + +remark1 db "Default values were selected to match most of configurations, but not all.",0 +remark2 db "If the system does not boot, try to disable the item [b].",0 +remarks dw remark1, remark2 +num_remarks = 2 diff --git a/kernel/trunk/boot/bootet.inc b/kernel/trunk/boot/bootet.inc index 51c6bbcc3..0386d5e91 100644 --- a/kernel/trunk/boot/bootet.inc +++ b/kernel/trunk/boot/bootet.inc @@ -1,101 +1,101 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;====================================================================== -; -; BOOT DATA -; -;====================================================================== - -$Revision$ - - -d80x25_bottom: - db 186,' KolibriOS pohineb MenuetOS ja kaasas IGASUGUSE GARANTI' - db 'ITA ',186 - db 186,' Naha faili COPYING detailid ' - db ' ',186 - line_full_bottom -d80x25_bottom_num = 3 - -msg_apm db " APM x.x ", 0 -novesa db "Ekraan: EGA/CGA",13,10,0 -s_vesa db "Vesa versioon: " - .ver db "?.?",13,10,0 - -gr_mode db "Vali videomode: ",13,10,0 - -ask_bd db "Lisa kettad nahtavaks BIOS reziim V86? [1-jah, 2-no]: ",0 - -if defined extended_primary_loader -bdev db "Paigalda mдluketas [1-diskett; 2-kolibri.img]: ",0 -else -bdev db "Paigalda mдluketas [1-diskett; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-kasuta eellaaditud mдluketast kerneli restardist;" - db 13,10,186," " - db "4-loo tьhi pilt]: ",0 -end if - -prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 - -not386 db "Fataalne - CPU 386+ on vajalik.",0 -fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 -pres_key db "Vajutage suvalist klahvi, et valida uus videomode.",0 -badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 -memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaхnnestus.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "Loen disketti: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 ; 0=floppy, 1=hd -start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jдtkamiseks",13,10,0 -time_msg db " vхi oota " -time_str db " 5 sekundit" - db " automaatseks jдtkamiseks",13,10,0 -current_cfg_msg db "Praegused seaded:",13,10,0 -curvideo_msg db " [a] Videoreziim: ",0 - -mode0 db "320x200, EGA/CGA 256 vдrvi",0 -mode9 db "640x480, VGA 16 vдrvi",0 - -usebd_msg db " [b] Lisa kettad nahtavaks BIOS:",0 -on_msg db " sees",13,10,0 -off_msg db " vдljas",13,10,0 - -preboot_device_msg db " [c] Disketi kujutis: ",0 - -if defined extended_primary_loader -preboot_device_msgs dw 0,pdm1,pdm2,0 -pdm1 db "reaalne diskett",13,10,0 -pdm2 db "kolibri.img",13,10,0 -else -preboot_device_msgs dw 0,pdm1,pdm2,pdm3 -pdm1 db "reaalne diskett",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -pdm3 db "kasuta juba laaditud kujutist",13,10,0 -pdm4 db "loo tьhi pilt",13,10,0 -end if - -loading_msg db "Laadin KolibriOS...",0 - -if ~ defined extended_primary_loader -save_quest db "Jдta meelde praegused seaded? [y/n]: ",0 -loader_block_error db "Alglaaduri andmed vigased, ei saa jдtkata. Peatatud.",0 -end if - -_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 -_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 -_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 -_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 -_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 - -remark1 db "Vaikimisi maaratud vaartused on valitud mugavuse enamikes, kuid mitte koik.",0 -remark2 db "Kui susteem ei kaivitu, proovige lulitada kirje [b].",0 -remarks dw remark1, remark2 -num_remarks = 2 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + +$Revision$ + + +d80x25_bottom: + db 186,' KolibriOS pohineb MenuetOS ja kaasas IGASUGUSE GARANTI' + db 'ITA ',186 + db 186,' Naha faili COPYING detailid ' + db ' ',186 + line_full_bottom +d80x25_bottom_num = 3 + +msg_apm db " APM x.x ", 0 +novesa db "Ekraan: EGA/CGA",13,10,0 +s_vesa db "Vesa versioon: " + .ver db "?.?",13,10,0 + +gr_mode db "Vali videomode: ",13,10,0 + +ask_bd db "Lisa kettad nahtavaks BIOS reziim V86? [1-jah, 2-no]: ",0 + +if defined extended_primary_loader +bdev db "Paigalda mдluketas [1-diskett; 2-kolibri.img]: ",0 +else +bdev db "Paigalda mдluketas [1-diskett; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-kasuta eellaaditud mдluketast kerneli restardist;" + db 13,10,186," " + db "4-loo tьhi pilt]: ",0 +end if + +prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 + +not386 db "Fataalne - CPU 386+ on vajalik.",0 +fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 +pres_key db "Vajutage suvalist klahvi, et valida uus videomode.",0 +badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 +memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaхnnestus.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "Loen disketti: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 ; 0=floppy, 1=hd +start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jдtkamiseks",13,10,0 +time_msg db " vхi oota " +time_str db " 5 sekundit" + db " automaatseks jдtkamiseks",13,10,0 +current_cfg_msg db "Praegused seaded:",13,10,0 +curvideo_msg db " [a] Videoreziim: ",0 + +mode0 db "320x200, EGA/CGA 256 vдrvi",0 +mode9 db "640x480, VGA 16 vдrvi",0 + +usebd_msg db " [b] Lisa kettad nahtavaks BIOS:",0 +on_msg db " sees",13,10,0 +off_msg db " vдljas",13,10,0 + +preboot_device_msg db " [c] Disketi kujutis: ",0 + +if defined extended_primary_loader +preboot_device_msgs dw 0,pdm1,pdm2,0 +pdm1 db "reaalne diskett",13,10,0 +pdm2 db "kolibri.img",13,10,0 +else +preboot_device_msgs dw 0,pdm1,pdm2,pdm3 +pdm1 db "reaalne diskett",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +pdm3 db "kasuta juba laaditud kujutist",13,10,0 +pdm4 db "loo tьhi pilt",13,10,0 +end if + +loading_msg db "Laadin KolibriOS...",0 + +if ~ defined extended_primary_loader +save_quest db "Jдta meelde praegused seaded? [y/n]: ",0 +loader_block_error db "Alglaaduri andmed vigased, ei saa jдtkata. Peatatud.",0 +end if + +_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 +_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 +_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 +_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 +_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 + +remark1 db "Vaikimisi maaratud vaartused on valitud mugavuse enamikes, kuid mitte koik.",0 +remark2 db "Kui susteem ei kaivitu, proovige lulitada kirje [b].",0 +remarks dw remark1, remark2 +num_remarks = 2 diff --git a/kernel/trunk/boot/bootge.inc b/kernel/trunk/boot/bootge.inc index 9db178f05..3cfd296ed 100644 --- a/kernel/trunk/boot/bootge.inc +++ b/kernel/trunk/boot/bootge.inc @@ -1,101 +1,101 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;====================================================================== -; -; BOOT DATA -; -;====================================================================== - -$Revision$ - - -d80x25_bottom: - db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' - db ' Garantie vertrieben ',186 - db 186,' Details stehen in der Datei COPYING ' - db ' ',186 - line_full_bottom -d80x25_bottom_num = 3 - -msg_apm db " APM x.x ", 0 -novesa db "Anzeige: EGA/CGA ",13,10,0 -s_vesa db "Vesa-Version: " - .ver db "?.?",13,10,0 - -gr_mode db "Wahlen Sie einen videomode: ",13,10,0 - -ask_bd db "Add-Festplatten sichtbar BIOS in V86-Modus emuliert? [1-ja, 2 nein]: ",0 - -if defined extended_primary_loader -bdev db "Lade die Ramdisk von [1-Diskette; 2-kolibri.img]: ",0 -else -bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-benutze ein bereits geladenes Kernel image;" - db 13,10,186," " - db "4-create blank image]: ",0 -end if - -prnotfnd db "Fatal - Videomodus nicht gefunden.",0 - -not386 db "Fatal - CPU 386+ benoetigt.",0 -fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 -pres_key db "Drucken Sie eine beliebige Taste, um eine neue videomode wahlen.",0 -badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 -memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "Lade Diskette: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 ; 0=floppy, 1=hd -start_msg db "Druecke [abcd], um die Einstellungen zu aendern, druecke [Enter] zum starten",13,10,0 -time_msg db " oder warte " -time_str db " 5 Sekunden" - db " bis zum automatischen Start",13,10,0 -current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 -curvideo_msg db " [a] Videomodus: ",0 - -mode0 db "320x200, EGA/CGA 256 colors",13,10,0 -mode9 db "640x480, VGA 16 colors",13,10,0 - -usebd_msg db " [b] Add-Festplatten sichtbar durch das BIOS:",0 -on_msg db " an",13,10,0 -off_msg db " aus",13,10,0 - -preboot_device_msg db " [c] Diskettenimage: ",0 - -if defined extended_primary_loader -preboot_device_msgs dw 0,pdm1,pdm2,0 -pdm1 db "Echte Diskette",13,10,0 -pdm2 db "kolibri.img",13,10,0 -else -preboot_device_msgs dw 0,pdm1,pdm2,pdm3 -pdm1 db "Echte Diskette",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -pdm3 db "Nutze bereits geladenes Image",13,10,0 -pdm4 db "create blank image",13,10,0 -end if - -loading_msg db "Lade KolibriOS...",0 - -if ~ defined extended_primary_loader -save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 -loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 -end if - -_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 -_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 -_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 -_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 -_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 - -remark1 db "Die Standardwerte sind fur die meisten gewahlt, aber nicht fur jedermann.",0 -remark2 db "Wenn das System nicht bootet, versuchen, das Element [b] deaktivieren.",0 -remarks dw remark1, remark2 -num_remarks = 2 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + +$Revision$ + + +d80x25_bottom: + db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' + db ' Garantie vertrieben ',186 + db 186,' Details stehen in der Datei COPYING ' + db ' ',186 + line_full_bottom +d80x25_bottom_num = 3 + +msg_apm db " APM x.x ", 0 +novesa db "Anzeige: EGA/CGA ",13,10,0 +s_vesa db "Vesa-Version: " + .ver db "?.?",13,10,0 + +gr_mode db "Wahlen Sie einen videomode: ",13,10,0 + +ask_bd db "Add-Festplatten sichtbar BIOS in V86-Modus emuliert? [1-ja, 2 nein]: ",0 + +if defined extended_primary_loader +bdev db "Lade die Ramdisk von [1-Diskette; 2-kolibri.img]: ",0 +else +bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-benutze ein bereits geladenes Kernel image;" + db 13,10,186," " + db "4-create blank image]: ",0 +end if + +prnotfnd db "Fatal - Videomodus nicht gefunden.",0 + +not386 db "Fatal - CPU 386+ benoetigt.",0 +fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 +pres_key db "Drucken Sie eine beliebige Taste, um eine neue videomode wahlen.",0 +badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 +memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "Lade Diskette: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 ; 0=floppy, 1=hd +start_msg db "Druecke [abcd], um die Einstellungen zu aendern, druecke [Enter] zum starten",13,10,0 +time_msg db " oder warte " +time_str db " 5 Sekunden" + db " bis zum automatischen Start",13,10,0 +current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 +curvideo_msg db " [a] Videomodus: ",0 + +mode0 db "320x200, EGA/CGA 256 colors",13,10,0 +mode9 db "640x480, VGA 16 colors",13,10,0 + +usebd_msg db " [b] Add-Festplatten sichtbar durch das BIOS:",0 +on_msg db " an",13,10,0 +off_msg db " aus",13,10,0 + +preboot_device_msg db " [c] Diskettenimage: ",0 + +if defined extended_primary_loader +preboot_device_msgs dw 0,pdm1,pdm2,0 +pdm1 db "Echte Diskette",13,10,0 +pdm2 db "kolibri.img",13,10,0 +else +preboot_device_msgs dw 0,pdm1,pdm2,pdm3 +pdm1 db "Echte Diskette",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +pdm3 db "Nutze bereits geladenes Image",13,10,0 +pdm4 db "create blank image",13,10,0 +end if + +loading_msg db "Lade KolibriOS...",0 + +if ~ defined extended_primary_loader +save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 +loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 +end if + +_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 +_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 +_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 +_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 +_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 + +remark1 db "Die Standardwerte sind fur die meisten gewahlt, aber nicht fur jedermann.",0 +remark2 db "Wenn das System nicht bootet, versuchen, das Element [b] deaktivieren.",0 +remarks dw remark1, remark2 +num_remarks = 2 diff --git a/kernel/trunk/boot/bootru.inc b/kernel/trunk/boot/bootru.inc index 03203c29e..5945a260c 100644 --- a/kernel/trunk/boot/bootru.inc +++ b/kernel/trunk/boot/bootru.inc @@ -1,101 +1,101 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;================================================================= -; -; BOOT DATA -; -;================================================================= - -$Revision$ - - -d80x25_bottom: - db 186,' KolibriOS ®б­®ў ­  ­  MenuetOS Ё Ќ… Џђ…„Ћ‘’Ђ‚‹џ…’ Ќ€' - db 'ЉЂЉ€• ѓЂђAЌ’€‰. ',186 - db 186,' Џ®¤а®Ў­ҐҐ ᬮваЁвҐ ў д ©«Ґ COPYING.TXT ' - db ' ',186 - line_full_bottom -d80x25_bottom_num = 3 - -msg_apm db " APM x.x ", 0 -novesa db "‚Ё¤Ґ®Є ав : EGA/CGA",13,10,0 -s_vesa db "‚ҐабЁп VESA: " - .ver db "?.?",13,10,0 - -gr_mode db "‚лЎҐаЁвҐ ўЁ¤Ґ®аҐ¦Ё¬: ",13,10,0 - -ask_bd db "„®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS ў ०Ё¬Ґ V86? [1-¤ , 2-­Ґв]: ",0 - -if defined extended_primary_loader -bdev db "‡ Јаг§Ёвм ®Ўа § Ё§ [1-¤ЁбЄҐв ; 2-kolibri.img Ё§ Ї ЇЄЁ § Јаг§ЄЁ]: ",0 -else -bdev db "‡ Јаг§Ёвм ®Ўа § Ё§ [1-¤ЁбЄҐв ; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §;" - db 13,10,186," " - db "4-б®§¤ вм зЁбвл© ®Ўа §]: ",0 -end if - -prnotfnd db "ЋиЁЎЄ  - ‚Ё¤Ґ®аҐ¦Ё¬ ­Ґ ­ ©¤Ґ­.",0 - -not386 db "ЋиЁЎЄ  - ’ॡгҐвбп Їа®жҐбб®а 386+.",0 -fatalsel db "ЋиЁЎЄ  - ‚лЎа ­­л© ўЁ¤Ґ®аҐ¦Ё¬ ­Ґ Ї®¤¤Ґа¦Ёў Ґвбп.",0 -pres_key db "Ќ ¦Ё¬ЁвҐ «оЎго Є« ўЁиг, ¤«п ЇҐаҐе®¤  ў ўлЎ®а ०Ё¬®ў.",0 -badsect db 13,10,186," ЋиЁЎЄ  - „ЁбЄҐв  Ї®ўаҐ¦¤Ґ­ . Џ®Їа®Ўг©вҐ ¤агЈго.",0 -memmovefailed db 13,10,186," ЋиЁЎЄ  - Int 0x15 move failed.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "‡ Јаг§Є  ¤ЁбЄҐвл: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 -start_msg db "Ќ ¦¬ЁвҐ [abcd] ¤«п Ё§¬Ґ­Ґ­Ёп ­ бв஥Є, [Enter] ¤«п Їа®¤®«¦Ґ­Ёп § Јаг§ЄЁ",13,10,0 -time_msg db " Ё«Ё Ї®¤®¦¤ЁвҐ " -time_str db " 5 ᥪ㭤 " - db " ¤®  ўв®¬ вЁзҐбЄ®Ј® Їа®¤®«¦Ґ­Ёп",13,10,0 -current_cfg_msg db "’ҐЄгйЁҐ ­ бва®©ЄЁ:",13,10,0 -curvideo_msg db " [a] ‚Ё¤Ґ®аҐ¦Ё¬: ",0 - -mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 -mode9 db "640x480, VGA 16 梥⮢",13,10,0 - -usebd_msg db " [b] „®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS:",0 -on_msg db " ўЄ«",13,10,0 -off_msg db " ўлЄ«",13,10,0 - -preboot_device_msg db " [c] ЋЎа § ¤ЁбЄҐвл: ",0 - -if defined extended_primary_loader -preboot_device_msgs dw 0,pdm1,pdm2,0 -pdm1 db "­ бв®пй п ¤ЁбЄҐв ",13,10,0 -pdm2 db "kolibri.img Ё§ Ї ЇЄЁ § Јаг§ЄЁ",13,10,0 -else -preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 -pdm1 db "­ бв®пй п ¤ЁбЄҐв ",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -pdm3 db "ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §",13,10,0 -pdm4 db "б®§¤ вм зЁбвл© ®Ўа §",13,10,0 -end if - -loading_msg db "€¤св § Јаг§Є  KolibriOS...",0 - -if ~ defined extended_primary_loader ; saving not supported in this case -save_quest db "‡ Ї®¬­Ёвм ⥪гйЁҐ ­ бва®©ЄЁ? [y/n]: ",0 -loader_block_error db "ЋиЁЎЄ  ў ¤ ­­ле ­ з «м­®Ј® § Јаг§зЁЄ , Їа®¤®«¦Ґ­ЁҐ ­Ґў®§¬®¦­®.",0 -end if - -_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї ',13,10,0 -_r1 db 186,' і 320x200 EGA/CGA 256 梥⮢ і і ',13,10,0 -_r2 db 186,' і 640x480 VGA 16 梥⮢ і і ',13,10,0 -_rs db 186,' і ????x????@?? SVGA VESA і і ',13,10,0 -_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ ',13,10,0 - -remark1 db "‡­ зҐ­Ёп Ї® 㬮«з ­Ёо ўлЎа ­л ¤«п 㤮Ўбвў  Ў®«миЁ­бвў , ­® ­Ґ ўбҐе.",0 -remark2 db "…б«Ё г ‚ б ­Ґ Јаг§Ёвбп бЁб⥬ , Ї®Їа®Ўг©вҐ ®вЄ«озЁвм Їг­Єв [b].",0 -remarks dw remark1, remark2 -num_remarks = 2 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;================================================================= +; +; BOOT DATA +; +;================================================================= + +$Revision$ + + +d80x25_bottom: + db 186,' KolibriOS ®б­®ў ­  ­  MenuetOS Ё Ќ… Џђ…„Ћ‘’Ђ‚‹џ…’ Ќ€' + db 'ЉЂЉ€• ѓЂђAЌ’€‰. ',186 + db 186,' Џ®¤а®Ў­ҐҐ ᬮваЁвҐ ў д ©«Ґ COPYING.TXT ' + db ' ',186 + line_full_bottom +d80x25_bottom_num = 3 + +msg_apm db " APM x.x ", 0 +novesa db "‚Ё¤Ґ®Є ав : EGA/CGA",13,10,0 +s_vesa db "‚ҐабЁп VESA: " + .ver db "?.?",13,10,0 + +gr_mode db "‚лЎҐаЁвҐ ўЁ¤Ґ®аҐ¦Ё¬: ",13,10,0 + +ask_bd db "„®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS ў ०Ё¬Ґ V86? [1-¤ , 2-­Ґв]: ",0 + +if defined extended_primary_loader +bdev db "‡ Јаг§Ёвм ®Ўа § Ё§ [1-¤ЁбЄҐв ; 2-kolibri.img Ё§ Ї ЇЄЁ § Јаг§ЄЁ]: ",0 +else +bdev db "‡ Јаг§Ёвм ®Ўа § Ё§ [1-¤ЁбЄҐв ; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §;" + db 13,10,186," " + db "4-б®§¤ вм зЁбвл© ®Ўа §]: ",0 +end if + +prnotfnd db "ЋиЁЎЄ  - ‚Ё¤Ґ®аҐ¦Ё¬ ­Ґ ­ ©¤Ґ­.",0 + +not386 db "ЋиЁЎЄ  - ’ॡгҐвбп Їа®жҐбб®а 386+.",0 +fatalsel db "ЋиЁЎЄ  - ‚лЎа ­­л© ўЁ¤Ґ®аҐ¦Ё¬ ­Ґ Ї®¤¤Ґа¦Ёў Ґвбп.",0 +pres_key db "Ќ ¦Ё¬ЁвҐ «оЎго Є« ўЁиг, ¤«п ЇҐаҐе®¤  ў ўлЎ®а ०Ё¬®ў.",0 +badsect db 13,10,186," ЋиЁЎЄ  - „ЁбЄҐв  Ї®ўаҐ¦¤Ґ­ . Џ®Їа®Ўг©вҐ ¤агЈго.",0 +memmovefailed db 13,10,186," ЋиЁЎЄ  - Int 0x15 move failed.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "‡ Јаг§Є  ¤ЁбЄҐвл: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 +start_msg db "Ќ ¦¬ЁвҐ [abcd] ¤«п Ё§¬Ґ­Ґ­Ёп ­ бв஥Є, [Enter] ¤«п Їа®¤®«¦Ґ­Ёп § Јаг§ЄЁ",13,10,0 +time_msg db " Ё«Ё Ї®¤®¦¤ЁвҐ " +time_str db " 5 ᥪ㭤 " + db " ¤®  ўв®¬ вЁзҐбЄ®Ј® Їа®¤®«¦Ґ­Ёп",13,10,0 +current_cfg_msg db "’ҐЄгйЁҐ ­ бва®©ЄЁ:",13,10,0 +curvideo_msg db " [a] ‚Ё¤Ґ®аҐ¦Ё¬: ",0 + +mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 +mode9 db "640x480, VGA 16 梥⮢",13,10,0 + +usebd_msg db " [b] „®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS:",0 +on_msg db " ўЄ«",13,10,0 +off_msg db " ўлЄ«",13,10,0 + +preboot_device_msg db " [c] ЋЎа § ¤ЁбЄҐвл: ",0 + +if defined extended_primary_loader +preboot_device_msgs dw 0,pdm1,pdm2,0 +pdm1 db "­ бв®пй п ¤ЁбЄҐв ",13,10,0 +pdm2 db "kolibri.img Ё§ Ї ЇЄЁ § Јаг§ЄЁ",13,10,0 +else +preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 +pdm1 db "­ бв®пй п ¤ЁбЄҐв ",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +pdm3 db "ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §",13,10,0 +pdm4 db "б®§¤ вм зЁбвл© ®Ўа §",13,10,0 +end if + +loading_msg db "€¤св § Јаг§Є  KolibriOS...",0 + +if ~ defined extended_primary_loader ; saving not supported in this case +save_quest db "‡ Ї®¬­Ёвм ⥪гйЁҐ ­ бва®©ЄЁ? [y/n]: ",0 +loader_block_error db "ЋиЁЎЄ  ў ¤ ­­ле ­ з «м­®Ј® § Јаг§зЁЄ , Їа®¤®«¦Ґ­ЁҐ ­Ґў®§¬®¦­®.",0 +end if + +_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї ',13,10,0 +_r1 db 186,' і 320x200 EGA/CGA 256 梥⮢ і і ',13,10,0 +_r2 db 186,' і 640x480 VGA 16 梥⮢ і і ',13,10,0 +_rs db 186,' і ????x????@?? SVGA VESA і і ',13,10,0 +_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ ',13,10,0 + +remark1 db "‡­ зҐ­Ёп Ї® 㬮«з ­Ёо ўлЎа ­л ¤«п 㤮Ўбвў  Ў®«миЁ­бвў , ­® ­Ґ ўбҐе.",0 +remark2 db "…б«Ё г ‚ б ­Ґ Јаг§Ёвбп бЁб⥬ , Ї®Їа®Ўг©вҐ ®вЄ«озЁвм Їг­Єв [b].",0 +remarks dw remark1, remark2 +num_remarks = 2 diff --git a/kernel/trunk/boot/bootstr.inc b/kernel/trunk/boot/bootstr.inc index bf71fb7a9..6a88c203c 100644 --- a/kernel/trunk/boot/bootstr.inc +++ b/kernel/trunk/boot/bootstr.inc @@ -1,62 +1,63 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; boot data: common strings (for all languages) -macro line_full_top { - db 201 - times 78 db 205 - db 187 -} -macro line_full_bottom { - db 200 - times 78 db 205 - db 188 -} -macro line_half { - db 186,' ' - times 76 db 0xc4 - db ' ',186 -} -macro line_space { - db 186 - times 78 db 32 - db 186 -} -d80x25_top: - line_full_top -cur_line_pos = 75 - store byte ' ' at d80x25_top+cur_line_pos+1 -rev_var = __REV__ -while rev_var > 0 - store byte rev_var mod 10 + '0' at d80x25_top+cur_line_pos - cur_line_pos = cur_line_pos - 1 - rev_var = rev_var / 10 -end while - store byte ' ' at d80x25_top+cur_line_pos - store dword ' SVN' at d80x25_top+cur_line_pos-4 - -space_msg: line_space -verstr: -; line_space -; version string - db 186,32 - repeat 78 - load a byte from version+%-1 - if a = 13 - break - end if - db a - end repeat - repeat 78 - ($-verstr) - db ' ' - end repeat - db 32,186 - line_half -d80x25_top_num = 4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; boot data: common strings (for all languages) +macro line_full_top { + db 201 + times 78 db 205 + db 187 +} +macro line_full_bottom { + db 200 + times 78 db 205 + db 188 +} +macro line_half { + db 186,' ' + times 76 db 0xc4 + db ' ',186 +} +macro line_space { + db 186 + times 78 db 32 + db 186 +} +d80x25_top: + line_full_top +cur_line_pos = 75 + store byte ' ' at d80x25_top+cur_line_pos+1 +rev_var = __REV__ +while rev_var > 0 + store byte rev_var mod 10 + '0' at d80x25_top+cur_line_pos + cur_line_pos = cur_line_pos - 1 + rev_var = rev_var / 10 +end while + store byte ' ' at d80x25_top+cur_line_pos + store dword ' SVN' at d80x25_top+cur_line_pos-4 + +space_msg: + line_space +verstr: +; line_space +; version string + db 186,32 + repeat 78 + load a byte from version+%-1 + if a = 13 + break + end if + db a + end repeat + repeat 78 - ($-verstr) + db ' ' + end repeat + db 32,186 + line_half +d80x25_top_num = 4 diff --git a/kernel/trunk/boot/bootvesa.inc b/kernel/trunk/boot/bootvesa.inc index 16e856e5b..b20058427 100644 --- a/kernel/trunk/boot/bootvesa.inc +++ b/kernel/trunk/boot/bootvesa.inc @@ -1,790 +1,799 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -struc VBE_VGAInfo { - .VESASignature dd ? ; char - .VESAVersion dw ? ; short - .OemStringPtr dd ? ; char * - .Capabilities dd ? ; ulong - .VideoModePtr dd ? ; ulong - .TotalMemory dw ? ; short - ; VBE 2.0+ - .OemSoftwareRev db ? ; short - .OemVendorNamePtr dw ? ; char * - .OemProductNamePtr dw ? ; char * - .OemProductRevPtr dw ? ; char * - .reserved rb 222 ; char - .OemData rb 256 ; char -} - -struc VBE_ModeInfo { - .ModeAttributes dw ? ; short - .WinAAttributes db ? ; char - .WinBAttributes db ? ; char - .WinGranularity dw ? ; short - .WinSize dw ? ; short - .WinASegment dw ? ; ushort - .WinBSegment dw ? ; ushort - .WinFuncPtr dd ? ; void * - .BytesPerScanLine dw ? ; short - .XRes dw ? ; short - .YRes dw ? ; short - .XCharSize db ? ; char - .YCharSize db ? ; char - .NumberOfPlanes db ? ; char - .BitsPerPixel db ? ; char - .NumberOfBanks db ? ; char - .MemoryModel db ? ; char - .BankSize db ? ; char - .NumberOfImagePages db ? ; char - .res1 db ? ; char - .RedMaskSize db ? ; char - .RedFieldPosition db ? ; char - .GreenMaskSize db ? ; char - .GreenFieldPosition db ? ; char - .BlueMaskSize db ? ; char - .BlueFieldPosition db ? ; char - .RsvedMaskSize db ? ; char - .RsvedFieldPosition db ? ; char - .DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE - ; VBE 2.0+ - .PhysBasePtr dd ? ; ulong - .OffScreenMemOffset dd ? ; ulong - .OffScreenMemSize dw ? ; short - ; VBE 3.0+ - .LinbytesPerScanLine dw ? ; short - .BankNumberOfImagePages db ? ; char - .LinNumberOfImagePages db ? ; char - .LinRedMaskSize db ? ; char - .LinRedFieldPosition db ? ; char - .LingreenMaskSize db ? ; char - .LinGreenFieldPosition db ? ; char - .LinBlueMaskSize db ? ; char - .LinBlueFieldPosition db ? ; char - .LinRsvdMaskSize db ? ; char - .LinRsvdFieldPosition db ? ; char - .MaxPixelClock dd ? ; ulong - .res2 rb 190 ; char -} - -virtual at $A000 - vi VBE_VGAInfo - mi VBE_ModeInfo -modes_table: -end virtual -cursor_pos dw 0 ;временное хранение курсора. -home_cursor dw 0 ;current shows rows a table -end_cursor dw 0 ;end of position current shows rows a table -scroll_start dw 0 ;start position of scroll bar -scroll_end dw 0 ;end position of scroll bar -long_v_table equ 9 ;long of visible video table -size_of_step equ 10 -scroll_area_size equ (long_v_table-2) -int2str: - dec bl - jz @f - xor edx,edx - div ecx - push edx - call int2str - pop eax - @@: or al,0x30 - mov [ds:di],al - inc di - ret - -int2strnz: - cmp eax,ecx - jb @f - xor edx,edx - div ecx - push edx - call int2strnz - pop eax - @@: or al,0x30 - mov [es:di],al - inc di - ret - -;------------------------------------------------------- -;Write message about incorrect v_mode and write message about jmp on swith v_mode -v_mode_error: - _setcursor 19,2 - mov si, fatalsel - call printplain - _setcursor 20,2 - mov si,pres_key - call printplain - xor eax,eax - int 16h - jmp cfgmanager.d -;------------------------------------------------------- -; - - - -;------------------------------------------------------- -print_vesa_info: - _setcursor 5,2 - - mov [es:vi.VESASignature],'VBE2' - mov ax,0x4F00 - mov di,vi ;0xa000 - int 0x10 - or ah,ah - jz @f - mov [es:vi.VESASignature],'VESA' - mov ax,$4F00 - mov di,vi - int 0x10 - or ah,ah - jnz .exit - @@: - cmp [es:vi.VESASignature],'VESA' - jne .exit - cmp [es:vi.VESAVersion],0x0100 - jb .exit - jmp .vesaok2 - - .exit: - mov si,novesa - call printplain - ret - - .vesaok2: - mov ax,[es:vi.VESAVersion] - add ax,'00' - - mov [s_vesa.ver], ah - mov [s_vesa.ver+2], al - mov si,s_vesa - call printplain - - _setcursor 4,2 - mov si,word[es:vi.OemStringPtr] - mov di,si - - push ds - mov ds,word[es:vi.OemStringPtr+2] - call printplain - pop ds - - ret -;----------------------------------------------------------------------------- - -calc_vmodes_table: - pushad - -; push 0 -; pop es - - lfs si, [es:vi.VideoModePtr] - - mov bx,modes_table -;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ - mov word [es:bx],640 - mov word [es:bx+2],480 - mov word [es:bx+6],0x13 - - mov word [es:bx+10],640 - mov word [es:bx+12],480 - mov word [es:bx+16],0x12 - add bx,20 - .next_mode: - mov cx,word [fs:si] ; mode number - cmp cx,-1 - je .modes_ok.2 - - mov ax,0x4F01 - mov di,mi - int 0x10 - - or ah,ah - jnz .modes_ok.2;vesa_info.exit - - test [es:mi.ModeAttributes],00000001b ;videomode support ? - jz @f - test [es:mi.ModeAttributes],00010000b ;picture ? - jz @f - test [es:mi.ModeAttributes],10000000b ;LFB ? - jz @f - - cmp [es:mi.BitsPerPixel], 24 ;It show only videomodes to have support 24 and 32 bpp - jb @f - -; cmp [es:mi.BitsPerPixel],16 -; jne .l0 -; cmp [es:mi.GreenMaskSize],5 -; jne .l0 -; mov [es:mi.BitsPerPixel],15 - - -.l0: - cmp [es:mi.XRes],640 - jb @f - cmp [es:mi.YRes],480 - jb @f -; cmp [es:mi.BitsPerPixel],8 -; jb @f - - mov ax,[es:mi.XRes] - mov [es:bx+0],ax ; +0[2] : resolution X - mov ax,[es:mi.YRes] - mov [es:bx+2],ax ; +2[2] : resolution Y - mov ax,[es:mi.ModeAttributes] - mov [es:bx+4],ax ; +4[2] : attributes - - cmp [s_vesa.ver],'2' - jb .lp1 - - or cx,0x4000 ; use LFB -.lp1: mov [es:bx+6],cx ; +6 : mode number - movzx ax,byte [es:mi.BitsPerPixel] - mov word [es:bx+8],ax ; +8 : bits per pixel - add bx,size_of_step ; size of record - - @@: - add si,2 - jmp .next_mode - - .modes_ok.2: - - mov word[es:bx],-1 ;end video table - mov word[end_cursor],bx ;save end cursor position -;;;;;;;;;;;;;;;;;; -;Sort array -; mov si,modes_table -;.new_mode: -; mov ax,word [es:si] -; cmp ax,-1 -; je .exxit -; add ax,word [es:si+2] -; add ax,word [es:si+8] -; mov bp,si -;.again: -; add bp,12 -; mov bx,word [es:bp] -; cmp bx,-1 -; je .exit -; add bx,word [es:bp+2] -; add bx,word [es:bp+8] -; -; cmp ax,bx -; ja .loops -; jmp .again -;.loops: -; push dword [es:si] -; push dword [es:si+4] -; push dword [es:si+8] -; push dword [es:bp] -; push dword [es:bp+4] -; push dword [es:bp+8] -; -; pop dword [es:si+8] -; pop dword [es:si+4] -; pop dword [es:si] -; pop dword [es:bp+8] -; pop dword [es:bp+4] -; pop dword [es:bp] -; jmp .new_mode -; -;.exit: add si,12 -; jmp .new_mode -;.exxit: - popad - ret - -;----------------------------------------------------------------------------- - -draw_current_vmode: - push 0 - pop es - - mov si,word [cursor_pos] - - cmp word [es:si+6],0x12 - je .no_vesa_0x12 - - cmp word [es:si+6],0x13 - je .no_vesa_0x13 - -if defined extended_primary_loader - mov di,config_file_variables -else - mov di,loader_block_error -end if - movzx eax,word[es:si+0] - mov ecx,10 - call int2strnz - mov byte[es:di],'x' - inc di - movzx eax,word[es:si+2] - call int2strnz - mov byte[es:di],'x' - inc di - movzx eax,word[es:si+8] - call int2strnz - mov dword[es:di],0x00000d0a -if defined extended_primary_loader - mov si,config_file_variables -else - mov si,loader_block_error -end if - push ds - push es - pop ds - call printplain - pop ds - ret -.no_vesa_0x13: - mov si,mode0 - jmp .print -.no_vesa_0x12: - mov si,mode9 -.print: - call printplain - ret -;----------------------------------------------------------------------------- -check_first_parm: -if defined extended_primary_loader - mov cx, [number_vm] - jcxz .novbemode - mov si, modes_table -.findvbemode: - cmp [es:si+6], cx - jnz @f - cmp word [es:si+8],32 - je .ok_found_mode - cmp word [es:si+8],24 - je .ok_found_mode -@@: add si,size_of_step - cmp word [es:si],-1 - jnz .findvbemode -.novbemode: - mov ax, [x_save] - test ax, ax - jz .zerro - mov bx, [y_save] - mov si, modes_table - call .loops - test ax, ax - jz .ok_found_mode -else - mov si,word [preboot_graph] - test si,si - jnz .no_zero ;if no zero -end if -.zerro: -; mov ax,modes_table -; mov word [cursor_pos],ax -; mov word [home_cursor],ax -; mov word [preboot_graph],ax -;SET default video of mode first probe will fined a move of work 1024x768@32 - - mov ax,1024 - mov bx,768 - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - mov ax,800 - mov bx,600 - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - mov ax,640 - mov bx,480 - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - - mov si,modes_table -if ~ defined extended_primary_loader - jmp .ok_found_mode - - - -.no_zero: - mov bp,word [number_vm] - cmp bp,word [es:si+6] - jz .ok_found_mode - mov ax,word [x_save] - mov bx,word [y_save] - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - - mov si,modes_table -; cmp ax,modes_table -; jb .zerro ;check on correct if bellow -; cmp ax,word [end_cursor] -; ja .zerro ;check on correct if anymore -end if - -.ok_found_mode: - mov word [home_cursor],si -; mov word [cursor_pos],si - mov word [preboot_graph],si - mov ax,si - - mov ecx,long_v_table - -.loop: add ax,size_of_step - cmp ax,word [end_cursor] - jae .next_step - loop .loop -.next_step: - sub ax,size_of_step*long_v_table - cmp ax,modes_table - jae @f - mov ax,modes_table -@@: - - mov word [home_cursor],ax - mov si,[preboot_graph] - mov word [cursor_pos],si - - push word [es:si] - pop word [x_save] - push word [es:si+2] - pop word [y_save] - push word [es:si+6] - pop word [number_vm] - - ret -;;;;;;;;;;;;;;;;;;;;;;;;;;; -.loops: - cmp ax,word [es:si] - jne .next - cmp bx,word [es:si+2] - jne .next - cmp word [es:si+8],32 - je .ok - cmp word [es:si+8],24 - je .ok -.next: add si,size_of_step - cmp word [es:si],-1 - je .exit - jmp .loops -.ok: xor ax,ax - ret -.exit: or ax,-1 - ret - - -;----------------------------------------------------------------------------- - -;default_vmode: - -;----------------------------------------------------------------------------- -draw_vmodes_table: - _setcursor 9, 2 - mov si,gr_mode - call printplain - - mov si,_st - call printplain - - push word [cursor_pos] - pop ax - push word [home_cursor] - pop si - mov cx,si - - cmp ax,si - je .ok - jb .low - - - add cx,size_of_step*long_v_table - - cmp ax,cx - jb .ok - - sub cx,size_of_step*long_v_table - add cx,size_of_step - cmp cx,word[end_cursor] - jae .ok - add si,size_of_step - push si - pop word [home_cursor] - jmp .ok - - -.low: sub cx,size_of_step - cmp cx,modes_table - jb .ok - push cx - push cx - pop word [home_cursor] - pop si - - -.ok: -; calculate scroll position - push si - mov ax, [end_cursor] - sub ax, modes_table - mov bx, size_of_step - cwd - div bx - mov si, ax ; si = size of list - mov ax, [home_cursor] - sub ax, modes_table - cwd - div bx - mov di, ax - mov ax, scroll_area_size*long_v_table - cwd - div si - test ax, ax - jnz @f - inc ax -@@: - cmp al, scroll_area_size - jb @f - mov al, scroll_area_size -@@: - mov cx, ax -; cx = scroll height -; calculate scroll pos - xor bx, bx ; initialize scroll pos - sub al, scroll_area_size+1 - neg al - sub si, long_v_table-1 - jbe @f - mul di - div si - mov bx, ax -@@: - inc bx - imul ax, bx, size_of_step - add ax, [home_cursor] - mov [scroll_start], ax - imul cx, size_of_step - add ax, cx - mov [scroll_end], ax - pop si - mov bp,long_v_table ;show rows -.@@_next_bit: -;clear cursor - mov ax,' ' - mov word[ds:_r1+21],ax - mov word[ds:_r1+50],ax - - mov word[ds:_r2+21],ax - mov word[ds:_r2+45],ax - - mov word[ds:_rs+21],ax - mov word[ds:_rs+46],ax -; draw string - cmp word [es:si+6],0x12 - je .show_0x12 - cmp word [es:si+6],0x13 - je .show_0x13 - - movzx eax,word[es:si] - cmp ax,-1 - je .@@_end - mov di,_rs+23 - mov ecx,10 - mov bl,4 - call int2str - movzx eax,word[es:si+2] - inc di - mov bl,4 - call int2str - - movzx eax,word[es:si+8] - inc di - mov bl,2 - call int2str - - cmp si, word [cursor_pos] - jne .next -;draw cursor - mov word[ds:_rs+21],'>>' - mov word[ds:_rs+46],'<<' - - - -.next: - push si - mov si,_rs -.@@_sh: -; add to the string pseudographics for scrollbar - pop bx - push bx - mov byte [si+53], ' ' - cmp bx, [scroll_start] - jb @f - cmp bx, [scroll_end] - jae @f - mov byte [si+53], 0xDB ; filled bar -@@: - push bx - add bx, size_of_step - cmp bx, [end_cursor] - jnz @f - mov byte [si+53], 31 ; 'down arrow' symbol -@@: - sub bx, [home_cursor] - cmp bx, size_of_step*long_v_table - jnz @f - mov byte [si+53], 31 ; 'down arrow' symbol -@@: - pop bx - cmp bx, [home_cursor] - jnz @f - mov byte [si+53], 30 ; 'up arrow' symbol -@@: - call printplain - pop si - add si,size_of_step - - dec bp - jnz .@@_next_bit - -.@@_end: - mov si,_bt - call printplain - ret -.show_0x13: - push si - - cmp si, word [cursor_pos] - jne @f - mov word[ds:_r1+21],'>>' - mov word[ds:_r1+50],'<<' -@@: - mov si,_r1 - jmp .@@_sh -.show_0x12: - push si - cmp si, word [cursor_pos] - jne @f - - mov word[ds:_r2+21],'>>' - mov word[ds:_r2+45],'<<' -@@: - mov si,_r2 - jmp .@@_sh - -;----------------------------------------------------------------------------- -;Clear arrea of current video page (0xb800) -clear_vmodes_table: - pusha - ; draw frames - push es - push 0xb800 - pop es - mov di,1444 - xor ax,ax - mov ah, 1*16+15 - mov cx,70 - mov bp,12 -.loop_start: - rep stosw - mov cx,70 - add di,20 - dec bp - jns .loop_start - pop es - popa - ret - -;----------------------------------------------------------------------------- - -set_vmode: - push 0 ;0;x1000 - pop es - - mov si,word [preboot_graph] ;[preboot_graph] - mov cx,word [es:si+6] ; number of mode - - - mov ax,word [es:si+0] ; resolution X - mov bx,word [es:si+2] ; resolution Y - - - mov word [es:0x900A],ax ; resolution X - mov word [es:0x900C],bx ; resolution Y - mov word [es:0x9008],cx ; number of mode - - cmp cx,0x12 - je .mode0x12_0x13 - cmp cx,0x13 - je .mode0x12_0x13 - - - cmp byte [s_vesa.ver],'2' - jb .vesa12 - -; VESA 2 and Vesa 3 - - mov ax,0x4f01 - and cx,0xfff - mov di,mi;0xa000 - int 0x10 - ; LFB - mov eax,[es:mi.PhysBasePtr];di+0x28] - mov [es:0x9018],eax - ; ---- vbe voodoo - BytesPerLine equ 0x10 - mov ax, [es:di+BytesPerLine] - mov [es:0x9001], ax - ; BPP - cmp [es:mi.BitsPerPixel],16 - jne .l0 - cmp [es:mi.GreenMaskSize],5 - jne .l0 - mov [es:mi.BitsPerPixel],15 -.l0: - mov al, byte [es:di+0x19] - mov [es:0x9000], al - jmp .exit - -.mode0x12_0x13: - mov byte [es:0x9000], 32 - or dword [es:0x9018], 0xFFFFFFFF; 0x800000 - - -; VESA 1.2 PM BANK SWITCH ADDRESS - -.vesa12: - - - mov ax,0x4f0A - xor bx,bx - int 0x10 - xor eax,eax - xor ebx,ebx - mov ax,es - shl eax,4 - mov bx,di - add eax,ebx - movzx ebx,word[es:di] - add eax,ebx - push 0x0000 - pop es - mov [es:0x9014],eax - .exit: - ret - - -; mov dword[es:0x9018],0x000A0000 -; ret - -;============================================================================= -;============================================================================= -;============================================================================= - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +struc VBE_VGAInfo { + .VESASignature dd ? ; char + .VESAVersion dw ? ; short + .OemStringPtr dd ? ; char * + .Capabilities dd ? ; ulong + .VideoModePtr dd ? ; ulong + .TotalMemory dw ? ; short + ; VBE 2.0+ + .OemSoftwareRev db ? ; short + .OemVendorNamePtr dw ? ; char * + .OemProductNamePtr dw ? ; char * + .OemProductRevPtr dw ? ; char * + .reserved rb 222 ; char + .OemData rb 256 ; char +} + +struc VBE_ModeInfo { + .ModeAttributes dw ? ; short + .WinAAttributes db ? ; char + .WinBAttributes db ? ; char + .WinGranularity dw ? ; short + .WinSize dw ? ; short + .WinASegment dw ? ; ushort + .WinBSegment dw ? ; ushort + .WinFuncPtr dd ? ; void * + .BytesPerScanLine dw ? ; short + .XRes dw ? ; short + .YRes dw ? ; short + .XCharSize db ? ; char + .YCharSize db ? ; char + .NumberOfPlanes db ? ; char + .BitsPerPixel db ? ; char + .NumberOfBanks db ? ; char + .MemoryModel db ? ; char + .BankSize db ? ; char + .NumberOfImagePages db ? ; char + .res1 db ? ; char + .RedMaskSize db ? ; char + .RedFieldPosition db ? ; char + .GreenMaskSize db ? ; char + .GreenFieldPosition db ? ; char + .BlueMaskSize db ? ; char + .BlueFieldPosition db ? ; char + .RsvedMaskSize db ? ; char + .RsvedFieldPosition db ? ; char + .DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE + ; VBE 2.0+ + .PhysBasePtr dd ? ; ulong + .OffScreenMemOffset dd ? ; ulong + .OffScreenMemSize dw ? ; short + ; VBE 3.0+ + .LinbytesPerScanLine dw ? ; short + .BankNumberOfImagePages db ? ; char + .LinNumberOfImagePages db ? ; char + .LinRedMaskSize db ? ; char + .LinRedFieldPosition db ? ; char + .LingreenMaskSize db ? ; char + .LinGreenFieldPosition db ? ; char + .LinBlueMaskSize db ? ; char + .LinBlueFieldPosition db ? ; char + .LinRsvdMaskSize db ? ; char + .LinRsvdFieldPosition db ? ; char + .MaxPixelClock dd ? ; ulong + .res2 rb 190 ; char +} + +virtual at $A000 + vi VBE_VGAInfo + mi VBE_ModeInfo +modes_table: +end virtual +cursor_pos dw 0 ;временное хранение курсора. +home_cursor dw 0 ;current shows rows a table +end_cursor dw 0 ;end of position current shows rows a table +scroll_start dw 0 ;start position of scroll bar +scroll_end dw 0 ;end position of scroll bar +long_v_table equ 9 ;long of visible video table +size_of_step equ 10 +scroll_area_size equ (long_v_table-2) +int2str: + dec bl + jz @f + xor edx, edx + div ecx + push edx + call int2str + pop eax + @@: + or al, 0x30 + mov [ds:di], al + inc di + ret + +int2strnz: + cmp eax, ecx + jb @f + xor edx, edx + div ecx + push edx + call int2strnz + pop eax + @@: + or al, 0x30 + mov [es:di], al + inc di + ret + +;------------------------------------------------------- +;Write message about incorrect v_mode and write message about jmp on swith v_mode +v_mode_error: + _setcursor 19,2 + mov si, fatalsel + call printplain + _setcursor 20,2 + mov si, pres_key + call printplain + xor eax, eax + int 16h + jmp cfgmanager.d +;------------------------------------------------------- +; + + + +;------------------------------------------------------- +print_vesa_info: + _setcursor 5,2 + + mov [es:vi.VESASignature], 'VBE2' + mov ax, 0x4F00 + mov di, vi ;0xa000 + int 0x10 + or ah, ah + jz @f + mov [es:vi.VESASignature], 'VESA' + mov ax, $4F00 + mov di, vi + int 0x10 + or ah, ah + jnz .exit + @@: + cmp [es:vi.VESASignature], 'VESA' + jne .exit + cmp [es:vi.VESAVersion], 0x0100 + jb .exit + jmp .vesaok2 + + .exit: + mov si, novesa + call printplain + ret + + .vesaok2: + mov ax, [es:vi.VESAVersion] + add ax, '00' + + mov [s_vesa.ver], ah + mov [s_vesa.ver+2], al + mov si, s_vesa + call printplain + + _setcursor 4,2 + mov si, word[es:vi.OemStringPtr] + mov di, si + + push ds + mov ds, word[es:vi.OemStringPtr+2] + call printplain + pop ds + + ret +;----------------------------------------------------------------------------- + +calc_vmodes_table: + pushad + +; push 0 +; pop es + + lfs si, [es:vi.VideoModePtr] + + mov bx, modes_table +;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ + mov word [es:bx], 640 + mov word [es:bx+2], 480 + mov word [es:bx+6], 0x13 + + mov word [es:bx+10], 640 + mov word [es:bx+12], 480 + mov word [es:bx+16], 0x12 + add bx, 20 + .next_mode: + mov cx, word [fs:si]; mode number + cmp cx, -1 + je .modes_ok.2 + + mov ax, 0x4F01 + mov di, mi + int 0x10 + + or ah, ah + jnz .modes_ok.2;vesa_info.exit + + test [es:mi.ModeAttributes], 00000001b ;videomode support ? + jz @f + test [es:mi.ModeAttributes], 00010000b ;picture ? + jz @f + test [es:mi.ModeAttributes], 10000000b ;LFB ? + jz @f + + cmp [es:mi.BitsPerPixel], 24 ;It show only videomodes to have support 24 and 32 bpp + jb @f + +; cmp [es:mi.BitsPerPixel],16 +; jne .l0 +; cmp [es:mi.GreenMaskSize],5 +; jne .l0 +; mov [es:mi.BitsPerPixel],15 + + +.l0: + cmp [es:mi.XRes], 640 + jb @f + cmp [es:mi.YRes], 480 + jb @f +; cmp [es:mi.BitsPerPixel],8 +; jb @f + + mov ax, [es:mi.XRes] + mov [es:bx+0], ax ; +0[2] : resolution X + mov ax, [es:mi.YRes] + mov [es:bx+2], ax ; +2[2] : resolution Y + mov ax, [es:mi.ModeAttributes] + mov [es:bx+4], ax ; +4[2] : attributes + + cmp [s_vesa.ver], '2' + jb .lp1 + + or cx, 0x4000 ; use LFB +.lp1: + mov [es:bx+6], cx ; +6 : mode number + movzx ax, byte [es:mi.BitsPerPixel] + mov word [es:bx+8], ax ; +8 : bits per pixel + add bx, size_of_step ; size of record + + @@: + add si, 2 + jmp .next_mode + + .modes_ok.2: + + mov word[es:bx], -1 ;end video table + mov word[end_cursor], bx ;save end cursor position +;;;;;;;;;;;;;;;;;; +;Sort array +; mov si,modes_table +;.new_mode: +; mov ax,word [es:si] +; cmp ax,-1 +; je .exxit +; add ax,word [es:si+2] +; add ax,word [es:si+8] +; mov bp,si +;.again: +; add bp,12 +; mov bx,word [es:bp] +; cmp bx,-1 +; je .exit +; add bx,word [es:bp+2] +; add bx,word [es:bp+8] +; +; cmp ax,bx +; ja .loops +; jmp .again +;.loops: +; push dword [es:si] +; push dword [es:si+4] +; push dword [es:si+8] +; push dword [es:bp] +; push dword [es:bp+4] +; push dword [es:bp+8] +; +; pop dword [es:si+8] +; pop dword [es:si+4] +; pop dword [es:si] +; pop dword [es:bp+8] +; pop dword [es:bp+4] +; pop dword [es:bp] +; jmp .new_mode +; +;.exit: add si,12 +; jmp .new_mode +;.exxit: + popad + ret + +;----------------------------------------------------------------------------- + +draw_current_vmode: + push 0 + pop es + + mov si, word [cursor_pos] + + cmp word [es:si+6], 0x12 + je .no_vesa_0x12 + + cmp word [es:si+6], 0x13 + je .no_vesa_0x13 + +if defined extended_primary_loader + mov di, config_file_variables +else + mov di, loader_block_error +end if + movzx eax, word[es:si+0] + mov ecx, 10 + call int2strnz + mov byte[es:di], 'x' + inc di + movzx eax, word[es:si+2] + call int2strnz + mov byte[es:di], 'x' + inc di + movzx eax, word[es:si+8] + call int2strnz + mov dword[es:di], 0x00000d0a +if defined extended_primary_loader + mov si, config_file_variables +else + mov si, loader_block_error +end if + push ds + push es + pop ds + call printplain + pop ds + ret +.no_vesa_0x13: + mov si, mode0 + jmp .print +.no_vesa_0x12: + mov si, mode9 +.print: + call printplain + ret +;----------------------------------------------------------------------------- +check_first_parm: +if defined extended_primary_loader + mov cx, [number_vm] + jcxz .novbemode + mov si, modes_table +.findvbemode: + cmp [es:si+6], cx + jnz @f + cmp word [es:si+8], 32 + je .ok_found_mode + cmp word [es:si+8], 24 + je .ok_found_mode +@@: + add si, size_of_step + cmp word [es:si], -1 + jnz .findvbemode +.novbemode: + mov ax, [x_save] + test ax, ax + jz .zerro + mov bx, [y_save] + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode +else + mov si, word [preboot_graph] + test si, si + jnz .no_zero ;if no zero +end if +.zerro: +; mov ax,modes_table +; mov word [cursor_pos],ax +; mov word [home_cursor],ax +; mov word [preboot_graph],ax +;SET default video of mode first probe will fined a move of work 1024x768@32 + + mov ax, 1024 + mov bx, 768 + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + mov ax, 800 + mov bx, 600 + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + mov ax, 640 + mov bx, 480 + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + + mov si, modes_table +if ~ defined extended_primary_loader + jmp .ok_found_mode + + + +.no_zero: + mov bp, word [number_vm] + cmp bp, word [es:si+6] + jz .ok_found_mode + mov ax, word [x_save] + mov bx, word [y_save] + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + + mov si, modes_table +; cmp ax,modes_table +; jb .zerro ;check on correct if bellow +; cmp ax,word [end_cursor] +; ja .zerro ;check on correct if anymore +end if + +.ok_found_mode: + mov word [home_cursor], si +; mov word [cursor_pos],si + mov word [preboot_graph], si + mov ax, si + + mov ecx, long_v_table + +.loop: + add ax, size_of_step + cmp ax, word [end_cursor] + jae .next_step + loop .loop +.next_step: + sub ax, size_of_step*long_v_table + cmp ax, modes_table + jae @f + mov ax, modes_table +@@: + + mov word [home_cursor], ax + mov si, [preboot_graph] + mov word [cursor_pos], si + + push word [es:si] + pop word [x_save] + push word [es:si+2] + pop word [y_save] + push word [es:si+6] + pop word [number_vm] + + ret +;;;;;;;;;;;;;;;;;;;;;;;;;;; +.loops: + cmp ax, word [es:si] + jne .next + cmp bx, word [es:si+2] + jne .next + cmp word [es:si+8], 32 + je .ok + cmp word [es:si+8], 24 + je .ok +.next: + add si, size_of_step + cmp word [es:si], -1 + je .exit + jmp .loops +.ok: + xor ax, ax + ret +.exit: + or ax, -1 + ret + + +;----------------------------------------------------------------------------- + +;default_vmode: + +;----------------------------------------------------------------------------- +draw_vmodes_table: + _setcursor 9, 2 + mov si, gr_mode + call printplain + + mov si, _st + call printplain + + push word [cursor_pos] + pop ax + push word [home_cursor] + pop si + mov cx, si + + cmp ax, si + je .ok + jb .low + + + add cx, size_of_step*long_v_table + + cmp ax, cx + jb .ok + + sub cx, size_of_step*long_v_table + add cx, size_of_step + cmp cx, word[end_cursor] + jae .ok + add si, size_of_step + push si + pop word [home_cursor] + jmp .ok + + +.low: + sub cx, size_of_step + cmp cx, modes_table + jb .ok + push cx + push cx + pop word [home_cursor] + pop si + + +.ok: +; calculate scroll position + push si + mov ax, [end_cursor] + sub ax, modes_table + mov bx, size_of_step + cwd + div bx + mov si, ax ; si = size of list + mov ax, [home_cursor] + sub ax, modes_table + cwd + div bx + mov di, ax + mov ax, scroll_area_size*long_v_table + cwd + div si + test ax, ax + jnz @f + inc ax +@@: + cmp al, scroll_area_size + jb @f + mov al, scroll_area_size +@@: + mov cx, ax +; cx = scroll height +; calculate scroll pos + xor bx, bx ; initialize scroll pos + sub al, scroll_area_size+1 + neg al + sub si, long_v_table-1 + jbe @f + mul di + div si + mov bx, ax +@@: + inc bx + imul ax, bx, size_of_step + add ax, [home_cursor] + mov [scroll_start], ax + imul cx, size_of_step + add ax, cx + mov [scroll_end], ax + pop si + mov bp, long_v_table ;show rows +.@@_next_bit: +;clear cursor + mov ax, ' ' + mov word[ds:_r1+21], ax + mov word[ds:_r1+50], ax + + mov word[ds:_r2+21], ax + mov word[ds:_r2+45], ax + + mov word[ds:_rs+21], ax + mov word[ds:_rs+46], ax +; draw string + cmp word [es:si+6], 0x12 + je .show_0x12 + cmp word [es:si+6], 0x13 + je .show_0x13 + + movzx eax, word[es:si] + cmp ax, -1 + je .@@_end + mov di, _rs+23 + mov ecx, 10 + mov bl, 4 + call int2str + movzx eax, word[es:si+2] + inc di + mov bl, 4 + call int2str + + movzx eax, word[es:si+8] + inc di + mov bl, 2 + call int2str + + cmp si, word [cursor_pos] + jne .next +;draw cursor + mov word[ds:_rs+21], '>>' + mov word[ds:_rs+46], '<<' + + + +.next: + push si + mov si, _rs +.@@_sh: +; add to the string pseudographics for scrollbar + pop bx + push bx + mov byte [si+53], ' ' + cmp bx, [scroll_start] + jb @f + cmp bx, [scroll_end] + jae @f + mov byte [si+53], 0xDB ; filled bar +@@: + push bx + add bx, size_of_step + cmp bx, [end_cursor] + jnz @f + mov byte [si+53], 31 ; 'down arrow' symbol +@@: + sub bx, [home_cursor] + cmp bx, size_of_step*long_v_table + jnz @f + mov byte [si+53], 31 ; 'down arrow' symbol +@@: + pop bx + cmp bx, [home_cursor] + jnz @f + mov byte [si+53], 30 ; 'up arrow' symbol +@@: + call printplain + pop si + add si, size_of_step + + dec bp + jnz .@@_next_bit + +.@@_end: + mov si, _bt + call printplain + ret +.show_0x13: + push si + + cmp si, word [cursor_pos] + jne @f + mov word[ds:_r1+21], '>>' + mov word[ds:_r1+50], '<<' +@@: + mov si, _r1 + jmp .@@_sh +.show_0x12: + push si + cmp si, word [cursor_pos] + jne @f + + mov word[ds:_r2+21], '>>' + mov word[ds:_r2+45], '<<' +@@: + mov si, _r2 + jmp .@@_sh + +;----------------------------------------------------------------------------- +;Clear arrea of current video page (0xb800) +clear_vmodes_table: + pusha + ; draw frames + push es + push 0xb800 + pop es + mov di, 1444 + xor ax, ax + mov ah, 1*16+15 + mov cx, 70 + mov bp, 12 +.loop_start: + rep stosw + mov cx, 70 + add di, 20 + dec bp + jns .loop_start + pop es + popa + ret + +;----------------------------------------------------------------------------- + +set_vmode: + push 0 ;0;x1000 + pop es + + mov si, word [preboot_graph] ;[preboot_graph] + mov cx, word [es:si+6] ; number of mode + + + mov ax, word [es:si+0] ; resolution X + mov bx, word [es:si+2] ; resolution Y + + + mov word [es:0x900A], ax ; resolution X + mov word [es:0x900C], bx ; resolution Y + mov word [es:0x9008], cx ; number of mode + + cmp cx, 0x12 + je .mode0x12_0x13 + cmp cx, 0x13 + je .mode0x12_0x13 + + + cmp byte [s_vesa.ver], '2' + jb .vesa12 + +; VESA 2 and Vesa 3 + + mov ax, 0x4f01 + and cx, 0xfff + mov di, mi;0xa000 + int 0x10 + ; LFB + mov eax, [es:mi.PhysBasePtr];di+0x28] + mov [es:0x9018], eax + ; ---- vbe voodoo + BytesPerLine equ 0x10 + mov ax, [es:di+BytesPerLine] + mov [es:0x9001], ax + ; BPP + cmp [es:mi.BitsPerPixel], 16 + jne .l0 + cmp [es:mi.GreenMaskSize], 5 + jne .l0 + mov [es:mi.BitsPerPixel], 15 +.l0: + mov al, byte [es:di+0x19] + mov [es:0x9000], al + jmp .exit + +.mode0x12_0x13: + mov byte [es:0x9000], 32 + or dword [es:0x9018], 0xFFFFFFFF; 0x800000 + + +; VESA 1.2 PM BANK SWITCH ADDRESS + +.vesa12: + + + mov ax, 0x4f0A + xor bx, bx + int 0x10 + xor eax, eax + xor ebx, ebx + mov ax, es + shl eax, 4 + mov bx, di + add eax, ebx + movzx ebx, word[es:di] + add eax, ebx + push 0x0000 + pop es + mov [es:0x9014], eax + .exit: + ret + + +; mov dword[es:0x9018],0x000A0000 +; ret + +;============================================================================= +;============================================================================= +;============================================================================= + diff --git a/kernel/trunk/boot/et.inc b/kernel/trunk/boot/et.inc index 83fc44f2b..00df51af6 100644 --- a/kernel/trunk/boot/et.inc +++ b/kernel/trunk/boot/et.inc @@ -1,16 +1,16 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; Full ASCII code font -; only х and д added -; Kaitz -ET_FNT: - fontfile file "ETFONT.FNT" - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; Full ASCII code font +; only х and д added +; Kaitz +ET_FNT: + fontfile file "ETFONT.FNT" + diff --git a/kernel/trunk/boot/parsers.inc b/kernel/trunk/boot/parsers.inc index 2ce8f179a..b0e5c9f67 100644 --- a/kernel/trunk/boot/parsers.inc +++ b/kernel/trunk/boot/parsers.inc @@ -1,170 +1,170 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; All parsers are called with ds:si -> value of the variable, -; possibly with spaces before, and dx = limit of config file. - -; Three subroutines parse_char, parse_number and parse_bool set CF -; if something has failed, otherwise return the value in al/ax. - -parse_timeout: -; timeout is a number not greater than 9 - call parse_number - jc .nothing - cmp ax, 9 - jbe @f - mov ax, 9 -@@: - imul ax, 18 - mov [es:preboot_timeout], ax -.nothing: - ret - -parse_resolution: -; resolution is *, 'x' can be used instead of '*' -; parse width - call parse_number - jc .nothing -; save width - xchg ax, bx -; test for 'x' or '*' - call parse_char - cmp al, 'x' - jz @f - cmp al, '*' - jnz .nothing -@@: -; parse height - call parse_number - jc .nothing -; write width and height - mov [es:x_save], bx - mov [es:y_save], ax -.nothing: - ret - -parse_vbemode: -; vbemode is a number - call parse_number - jc .nothing - mov [es:number_vm], ax -.nothing: - ret - -;parse_vrr: -;; vrr is a boolean setting -; call parse_bool -; jc .nothing -;; convert 0 to 2, 1 to 1 -; inc ax -; xor al, 3 -; mov [es:preboot_vrrm], al -;.nothing: -; ret - -parse_biosdisks: -; using biosdisks is a boolean setting - call parse_bool - jc .nothing -; convert 0 to 2, 1 to 1 - inc ax - xor al, 3 - mov [es:preboot_biosdisk], al -.nothing: - ret - -parse_imgfrom: -; boot device (1-floppy 2-kolibri.img using primary loader) - call parse_number - jc .nothing - cmp al, 1 - jb .nothing - cmp al, 2 - ja .nothing - mov [es:preboot_device], al -.nothing: - ret - -parse_char: -; skip spaces and return the next character or CF if EOF. - cmp si, dx - jae .eof - lodsb - cmp al, ' ' - jbe parse_char - ret -.eof: - stc - ret - -parse_number: -; initialize high part of ax to zero - xor ax, ax -; skip spaces - call parse_char - jc .bad -; al should be a digit - sub al, '0' - cmp al, 9 - ja .bad -; accumulate the value in cx - xchg cx, ax -@@: - cmp si, dx - jae .eof - lodsb - sub al, '0' - cmp al, 9 - ja .end - imul cx, 10 - add cx, ax - jmp @b -; if the end is caused by non-digit, unwind the last character -.end: - dec si -.eof: - xchg cx, ax - clc - ret -.bad: - stc - ret - -parse_bool: -; skip spaces - call parse_char - jc .bad -; Boolean false can be represented as 0=no=off, -; boolean true can be represented as 1=yes=on. - cmp al, '0' - jz .false - cmp al, '1' - jz .true - mov ah, al - cmp si, dx - jae .bad - lodsb - cmp ax, 'n'*256 + 'o' - jz .false - cmp ax, 'o'*256 + 'f' - jz .false - cmp ax, 'y'*256 + 'e' - jz .true - cmp ax, 'o'*256 + 'n' - jz .true -.bad: - stc - ret -.true: - xor ax, ax - inc ax - ret -.false: - xor ax, ax - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; All parsers are called with ds:si -> value of the variable, +; possibly with spaces before, and dx = limit of config file. + +; Three subroutines parse_char, parse_number and parse_bool set CF +; if something has failed, otherwise return the value in al/ax. + +parse_timeout: +; timeout is a number not greater than 9 + call parse_number + jc .nothing + cmp ax, 9 + jbe @f + mov ax, 9 +@@: + imul ax, 18 + mov [es:preboot_timeout], ax +.nothing: + ret + +parse_resolution: +; resolution is *, 'x' can be used instead of '*' +; parse width + call parse_number + jc .nothing +; save width + xchg ax, bx +; test for 'x' or '*' + call parse_char + cmp al, 'x' + jz @f + cmp al, '*' + jnz .nothing +@@: +; parse height + call parse_number + jc .nothing +; write width and height + mov [es:x_save], bx + mov [es:y_save], ax +.nothing: + ret + +parse_vbemode: +; vbemode is a number + call parse_number + jc .nothing + mov [es:number_vm], ax +.nothing: + ret + +;parse_vrr: +;; vrr is a boolean setting +; call parse_bool +; jc .nothing +;; convert 0 to 2, 1 to 1 +; inc ax +; xor al, 3 +; mov [es:preboot_vrrm], al +;.nothing: +; ret + +parse_biosdisks: +; using biosdisks is a boolean setting + call parse_bool + jc .nothing +; convert 0 to 2, 1 to 1 + inc ax + xor al, 3 + mov [es:preboot_biosdisk], al +.nothing: + ret + +parse_imgfrom: +; boot device (1-floppy 2-kolibri.img using primary loader) + call parse_number + jc .nothing + cmp al, 1 + jb .nothing + cmp al, 2 + ja .nothing + mov [es:preboot_device], al +.nothing: + ret + +parse_char: +; skip spaces and return the next character or CF if EOF. + cmp si, dx + jae .eof + lodsb + cmp al, ' ' + jbe parse_char + ret +.eof: + stc + ret + +parse_number: +; initialize high part of ax to zero + xor ax, ax +; skip spaces + call parse_char + jc .bad +; al should be a digit + sub al, '0' + cmp al, 9 + ja .bad +; accumulate the value in cx + xchg cx, ax +@@: + cmp si, dx + jae .eof + lodsb + sub al, '0' + cmp al, 9 + ja .end + imul cx, 10 + add cx, ax + jmp @b +; if the end is caused by non-digit, unwind the last character +.end: + dec si +.eof: + xchg cx, ax + clc + ret +.bad: + stc + ret + +parse_bool: +; skip spaces + call parse_char + jc .bad +; Boolean false can be represented as 0=no=off, +; boolean true can be represented as 1=yes=on. + cmp al, '0' + jz .false + cmp al, '1' + jz .true + mov ah, al + cmp si, dx + jae .bad + lodsb + cmp ax, 'n'*256 + 'o' + jz .false + cmp ax, 'o'*256 + 'f' + jz .false + cmp ax, 'y'*256 + 'e' + jz .true + cmp ax, 'o'*256 + 'n' + jz .true +.bad: + stc + ret +.true: + xor ax, ax + inc ax + ret +.false: + xor ax, ax + ret diff --git a/kernel/trunk/boot/preboot.inc b/kernel/trunk/boot/preboot.inc index b04ea1e36..2d775c5a8 100644 --- a/kernel/trunk/boot/preboot.inc +++ b/kernel/trunk/boot/preboot.inc @@ -1,41 +1,42 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -display_modechg db 0 ; display mode change for text, yes/no (0 or 2) - ; - ; !! Important note !! - ; - ; Must be set to 2, to avoid two screenmode - ; changes within a very short period of time. - -display_atboot db 0 ; show boot screen messages ( 2-no ) - -preboot_graph dw 0 ; graph mode -x_save dw 0 ; x -y_save dw 0 ; y -number_vm dw 0 ; -;pixel_save dw 0 ; per to pixel -preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) -;preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) -preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) -preboot_device db 0 ; boot device - ; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) - ;!!!! 0 - autodetect !!!! -preboot_blogesc = 0 ; start immediately after bootlog -preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) -if defined extended_primary_loader -preboot_timeout dw 5*18 ; timeout in 1/18th of second for config settings screen -end if - - if $>0x200 -ERROR: prebooting parameters must fit in first sector!!! - end if -hdsysimage db 'KOLIBRI IMG' ; load from -image_save db 'KOLIBRI IMG' ; save to +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +display_modechg db 0 ; display mode change for text, yes/no (0 or 2) + ; + ; !! Important note !! + ; + ; Must be set to 2, to avoid two screenmode + ; changes within a very short period of time. + +display_atboot db 0 ; show boot screen messages ( 2-no ) + +preboot_graph dw 0 ; graph mode +x_save dw 0 ; x +y_save dw 0 ; y +number_vm dw 0 ; +;pixel_save dw 0 ; per to pixel +preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) +;preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) +preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) +preboot_device db 0 ; boot device + ; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) + ;!!!! 0 - autodetect !!!! +preboot_blogesc = 0 ; start immediately after bootlog +preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) +if defined extended_primary_loader +preboot_timeout dw 5*18 ; timeout in 1/18th of second for config settings screen +end if + + if $>0x200 +ERROR: + prebooting parameters must fit in first sector!!! + end if +hdsysimage db 'KOLIBRI IMG' ; load from +image_save db 'KOLIBRI IMG' ; save to diff --git a/kernel/trunk/boot/rdload.inc b/kernel/trunk/boot/rdload.inc index b9c9c9656..04fd35585 100644 --- a/kernel/trunk/boot/rdload.inc +++ b/kernel/trunk/boot/rdload.inc @@ -1,125 +1,125 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; READ RAMDISK IMAGE FROM HD - - cmp [boot_dev+OS_BASE+0x10000],1 - jne no_sys_on_hd - - test [DRIVE_DATA+1],byte 0x40 - jz position_2 - mov [hdbase],0x1f0 - mov [hdid],0x0 - mov [hdpos],1 - mov [fat32part],0 - position_1_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+2] - cmp [fat32part],eax - jle position_1_1 - position_2: - test [DRIVE_DATA+1],byte 0x10 - jz position_3 - mov [hdbase],0x1f0 - mov [hdid],0x10 - mov [hdpos],2 - mov [fat32part],0 - position_2_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+3] - cmp eax,[fat32part] - jle position_2_1 - position_3: - test [DRIVE_DATA+1],byte 0x4 - jz position_4 - mov [hdbase],0x170 - mov [hdid],0x0 - mov [hdpos],3 - mov [fat32part],0 - position_3_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+4] - cmp eax,[fat32part] - jle position_3_1 - position_4: - test [DRIVE_DATA+1],byte 0x1 - jz no_sys_on_hd - mov [hdbase],0x170 - mov [hdid],0x10 - mov [hdpos],4 - mov [fat32part],0 - position_4_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+5] - cmp eax,[fat32part] - jle position_4_1 - jmp yes_sys_on_hd - - search_and_read_image: - call set_FAT32_variables - mov edx, bootpath - call read_image - test eax, eax - jz image_present - mov edx, bootpath2 - call read_image - test eax, eax - jz image_present - ret - image_present: - mov [image_retrieved],1 - ret - -read_image: - mov eax, hdsysimage+OS_BASE+0x10000 - mov ebx, 1474560/512 - mov ecx, RAMDISK - mov esi, 0 - mov edi, 12 - call file_read - ret - -image_retrieved db 0 -counter_of_partitions db 0 -no_sys_on_hd: - ; test_to_format_ram_disk (need if not using ram disk) - cmp [boot_dev+OS_BASE+0x10000],3 - jne not_format_ram_disk - ; format_ram_disk - mov edi, RAMDISK - mov ecx, 0x1080 - xor eax,eax -@@: - stosd - loop @b - - mov ecx, 0x58F7F - mov eax,0xF6F6F6F6 -@@: - stosd - loop @b - - mov [RAMDISK+0x200],dword 0xFFFFF0 ; fat table - mov [RAMDISK+0x4200],dword 0xFFFFF0 - -not_format_ram_disk: -yes_sys_on_hd: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; READ RAMDISK IMAGE FROM HD + + cmp [boot_dev+OS_BASE+0x10000], 1 + jne no_sys_on_hd + + test [DRIVE_DATA+1], byte 0x40 + jz position_2 + mov [hdbase], 0x1f0 + mov [hdid], 0x0 + mov [hdpos], 1 + mov [fat32part], 0 + position_1_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+2] + cmp [fat32part], eax + jle position_1_1 + position_2: + test [DRIVE_DATA+1], byte 0x10 + jz position_3 + mov [hdbase], 0x1f0 + mov [hdid], 0x10 + mov [hdpos], 2 + mov [fat32part], 0 + position_2_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+3] + cmp eax, [fat32part] + jle position_2_1 + position_3: + test [DRIVE_DATA+1], byte 0x4 + jz position_4 + mov [hdbase], 0x170 + mov [hdid], 0x0 + mov [hdpos], 3 + mov [fat32part], 0 + position_3_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+4] + cmp eax, [fat32part] + jle position_3_1 + position_4: + test [DRIVE_DATA+1], byte 0x1 + jz no_sys_on_hd + mov [hdbase], 0x170 + mov [hdid], 0x10 + mov [hdpos], 4 + mov [fat32part], 0 + position_4_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+5] + cmp eax, [fat32part] + jle position_4_1 + jmp yes_sys_on_hd + + search_and_read_image: + call set_FAT32_variables + mov edx, bootpath + call read_image + test eax, eax + jz image_present + mov edx, bootpath2 + call read_image + test eax, eax + jz image_present + ret + image_present: + mov [image_retrieved], 1 + ret + +read_image: + mov eax, hdsysimage+OS_BASE+0x10000 + mov ebx, 1474560/512 + mov ecx, RAMDISK + mov esi, 0 + mov edi, 12 + call file_read + ret + +image_retrieved db 0 +counter_of_partitions db 0 +no_sys_on_hd: + ; test_to_format_ram_disk (need if not using ram disk) + cmp [boot_dev+OS_BASE+0x10000], 3 + jne not_format_ram_disk + ; format_ram_disk + mov edi, RAMDISK + mov ecx, 0x1080 + xor eax, eax +@@: + stosd + loop @b + + mov ecx, 0x58F7F + mov eax, 0xF6F6F6F6 +@@: + stosd + loop @b + + mov [RAMDISK+0x200], dword 0xFFFFF0 ; fat table + mov [RAMDISK+0x4200], dword 0xFFFFF0 + +not_format_ram_disk: +yes_sys_on_hd: diff --git a/kernel/trunk/boot/ru.inc b/kernel/trunk/boot/ru.inc index aa59d6f6a..90063f184 100644 --- a/kernel/trunk/boot/ru.inc +++ b/kernel/trunk/boot/ru.inc @@ -1,102 +1,102 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; Generated by RUFNT.EXE -; By BadBugsKiller (C) -; Modifyed by BadBugsKiller 12.01.2004 17:45 -; Шрифт уменьшен в размере и теперь состоит из 2-ух частей, -; содержащих только символы русского алфавита. -; символы в кодировке ASCII (ДОС'овская), кодовая страница 866. -RU_FNT1: - db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - - db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 - - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - -RU_FNT2: - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 - db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 - - db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 - db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; Generated by RUFNT.EXE +; By BadBugsKiller (C) +; Modifyed by BadBugsKiller 12.01.2004 17:45 +; Шрифт уменьшен в размере и теперь состоит из 2-ух частей, +; содержащих только символы русского алфавита. +; символы в кодировке ASCII (ДОС'овская), кодовая страница 866. +RU_FNT1: + db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + + db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 + + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + +RU_FNT2: + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 + db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 + + db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 + db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 diff --git a/kernel/trunk/boot/shutdown.inc b/kernel/trunk/boot/shutdown.inc index 1fbed56b8..aaf7091bc 100644 --- a/kernel/trunk/boot/shutdown.inc +++ b/kernel/trunk/boot/shutdown.inc @@ -1,212 +1,212 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; Shutdown for Menuet ;; -;; ;; -;; Distributed under General Public License ;; -;; See file COPYING for details. ;; -;; Copyright 2003 Ville Turjanmaa ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -align 4 -pr_mode_exit: - -; setup stack - mov ax, 0x3000 - mov ss, ax - mov esp, 0x0EC00 -; setup ds - push cs - pop ds - - lidt [old_ints_h] -;remap IRQs - mov al,0x11 - out 0x20,al - call rdelay - out 0xA0,al - call rdelay - - mov al,0x08 - out 0x21,al - call rdelay - mov al,0x70 - out 0xA1,al - call rdelay - - mov al,0x04 - out 0x21,al - call rdelay - mov al,0x02 - out 0xA1,al - call rdelay - - mov al,0x01 - out 0x21,al - call rdelay - out 0xA1,al - call rdelay - - mov al,0xB8 - out 0x21,al - call rdelay - mov al,0xBD - out 0xA1,al - sti - -temp_3456: - xor ax,ax - mov es,ax - mov al,byte [es:0x9030] - cmp al,1 - jl nbw - cmp al,4 - jle nbw32 - -nbw: - in al,0x60 - cmp al,6 - jae nbw - mov bl,al -nbw2: - in al,0x60 - cmp al,bl - je nbw2 - cmp al,240 ;ax,240 - jne nbw31 - mov al,bl - dec ax - jmp nbw32 -nbw31: - add bl,128 - cmp al,bl - jne nbw - sub al,129 - -nbw32: - - dec ax - dec ax ; 2 = power off - jnz no_apm_off - call APM_PowerOff - jmp $ -no_apm_off: - -if ~ defined extended_primary_loader ; kernel restarting is not supported - dec ax ; 3 = reboot - jnz restart_kernel ; 4 = restart kernel -end if - push 0x40 - pop ds - mov word[0x0072],0x1234 - jmp 0xF000:0xFFF0 - - -rdelay: - ret - -APM_PowerOff: - mov ax, 5304h - xor bx, bx - int 15h -;!!!!!!!!!!!!!!!!!!!!!!!! - mov ax,0x5300 - xor bx,bx - int 0x15 - push ax - - mov ax,0x5301 - xor bx,bx - int 0x15 - - mov ax,0x5308 - mov bx,1 - mov cx,bx - int 0x15 - - mov ax,0x530E - xor bx,bx - pop cx - int 0x15 - - mov ax,0x530D - mov bx,1 - mov cx,bx - int 0x15 - - mov ax,0x530F - mov bx,1 - mov cx,bx - int 0x15 - - mov ax,0x5307 - mov bx,1 - mov cx,3 - int 0x15 -;!!!!!!!!!!!!!!!!!!!!!!!! - ret - -if ~ defined extended_primary_loader -restart_kernel: - - mov ax,0x0003 ; set text mode for screen - int 0x10 - jmp 0x4000:0000 - -restart_kernel_4000: - cli - - push ds - pop es - mov cx, 0x8000 - push cx - push 0x7000 - pop ds - xor si, si - xor di, di - rep movsw - pop cx - mov ds, cx - push 0x2000 - pop es - rep movsw - push 0x9000 - pop ds - push 0x3000 - pop es - mov cx, 0xE000/2 - rep movsw - - wbinvd ; write and invalidate cache - - mov al, 00110100b - out 43h, al - jcxz $+2 - mov al, 0xFF - out 40h, al - jcxz $+2 - out 40h, al - jcxz $+2 - sti - -; (hint by Black_mirror) -; We must read data from keyboard port, -; because there may be situation when previous keyboard interrupt is lost -; (due to return to real mode and IRQ reprogramming) -; and next interrupt will not be generated (as keyboard waits for handling) - in al, 0x60 - -; bootloader interface - push 0x1000 - pop ds - mov si, kernel_restart_bootblock - mov ax, 'KL' - jmp 0x1000:0000 -end if - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; Shutdown for Menuet ;; +;; ;; +;; Distributed under General Public License ;; +;; See file COPYING for details. ;; +;; Copyright 2003 Ville Turjanmaa ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +align 4 +pr_mode_exit: + +; setup stack + mov ax, 0x3000 + mov ss, ax + mov esp, 0x0EC00 +; setup ds + push cs + pop ds + + lidt [old_ints_h] +;remap IRQs + mov al, 0x11 + out 0x20, al + call rdelay + out 0xA0, al + call rdelay + + mov al, 0x08 + out 0x21, al + call rdelay + mov al, 0x70 + out 0xA1, al + call rdelay + + mov al, 0x04 + out 0x21, al + call rdelay + mov al, 0x02 + out 0xA1, al + call rdelay + + mov al, 0x01 + out 0x21, al + call rdelay + out 0xA1, al + call rdelay + + mov al, 0xB8 + out 0x21, al + call rdelay + mov al, 0xBD + out 0xA1, al + sti + +temp_3456: + xor ax, ax + mov es, ax + mov al, byte [es:0x9030] + cmp al, 1 + jl nbw + cmp al, 4 + jle nbw32 + +nbw: + in al, 0x60 + cmp al, 6 + jae nbw + mov bl, al +nbw2: + in al, 0x60 + cmp al, bl + je nbw2 + cmp al, 240;ax,240 + jne nbw31 + mov al, bl + dec ax + jmp nbw32 +nbw31: + add bl, 128 + cmp al, bl + jne nbw + sub al, 129 + +nbw32: + + dec ax + dec ax ; 2 = power off + jnz no_apm_off + call APM_PowerOff + jmp $ +no_apm_off: + +if ~ defined extended_primary_loader ; kernel restarting is not supported + dec ax ; 3 = reboot + jnz restart_kernel ; 4 = restart kernel +end if + push 0x40 + pop ds + mov word[0x0072], 0x1234 + jmp 0xF000:0xFFF0 + + +rdelay: + ret + +APM_PowerOff: + mov ax, 5304h + xor bx, bx + int 15h +;!!!!!!!!!!!!!!!!!!!!!!!! + mov ax, 0x5300 + xor bx, bx + int 0x15 + push ax + + mov ax, 0x5301 + xor bx, bx + int 0x15 + + mov ax, 0x5308 + mov bx, 1 + mov cx, bx + int 0x15 + + mov ax, 0x530E + xor bx, bx + pop cx + int 0x15 + + mov ax, 0x530D + mov bx, 1 + mov cx, bx + int 0x15 + + mov ax, 0x530F + mov bx, 1 + mov cx, bx + int 0x15 + + mov ax, 0x5307 + mov bx, 1 + mov cx, 3 + int 0x15 +;!!!!!!!!!!!!!!!!!!!!!!!! + ret + +if ~ defined extended_primary_loader +restart_kernel: + + mov ax, 0x0003 ; set text mode for screen + int 0x10 + jmp 0x4000:0000 + +restart_kernel_4000: + cli + + push ds + pop es + mov cx, 0x8000 + push cx + push 0x7000 + pop ds + xor si, si + xor di, di + rep movsw + pop cx + mov ds, cx + push 0x2000 + pop es + rep movsw + push 0x9000 + pop ds + push 0x3000 + pop es + mov cx, 0xE000/2 + rep movsw + + wbinvd ; write and invalidate cache + + mov al, 00110100b + out 43h, al + jcxz $+2 + mov al, 0xFF + out 40h, al + jcxz $+2 + out 40h, al + jcxz $+2 + sti + +; (hint by Black_mirror) +; We must read data from keyboard port, +; because there may be situation when previous keyboard interrupt is lost +; (due to return to real mode and IRQ reprogramming) +; and next interrupt will not be generated (as keyboard waits for handling) + in al, 0x60 + +; bootloader interface + push 0x1000 + pop ds + mov si, kernel_restart_bootblock + mov ax, 'KL' + jmp 0x1000:0000 +end if + diff --git a/kernel/trunk/bootloader/boot_fat12.asm b/kernel/trunk/bootloader/boot_fat12.asm index 9f31e383b..96a836f7a 100644 --- a/kernel/trunk/bootloader/boot_fat12.asm +++ b/kernel/trunk/bootloader/boot_fat12.asm @@ -8,15 +8,15 @@ ; ; Version 1.0 -lf equ 0ah -cr equ 0dh +lf equ 0ah +cr equ 0dh -pos_read_tmp equ 0700h ;position for temporary read -boot_program equ 07c00h ;position for boot code -seg_read_kernel equ 01000h ;segment to kernel read +pos_read_tmp equ 0700h ;position for temporary read +boot_program equ 07c00h ;position for boot code +seg_read_kernel equ 01000h ;segment to kernel read - jmp start_program - nop + jmp start_program + nop ; Boot Sector and BPB Structure include 'floppy1440.inc' @@ -26,262 +26,262 @@ include 'floppy1440.inc' start_program: - xor ax,ax - mov ss,ax - mov sp,boot_program - push ss - pop ds + xor ax, ax + mov ss, ax + mov sp, boot_program + push ss + pop ds - ; print loading string - mov si,loading+boot_program + ; print loading string + mov si, loading+boot_program loop_loading: - lodsb - or al,al - jz read_root_directory - mov ah,0eh - mov bx,7 - int 10h - jmp loop_loading + lodsb + or al, al + jz read_root_directory + mov ah, 0eh + mov bx, 7 + int 10h + jmp loop_loading read_root_directory: - push ss - pop es + push ss + pop es - ; calculate some disk parameters - ; - beginning sector of RootDir - mov ax,word [BPB_FATSz16+boot_program] - xor cx,cx - mov cl,byte [BPB_NumFATs+boot_program] - mul cx - add ax,word [BPB_RsvdSecCnt+boot_program] - mov word [FirstRootDirSecNum+boot_program],ax ; 19 - mov si,ax + ; calculate some disk parameters + ; - beginning sector of RootDir + mov ax, word [BPB_FATSz16+boot_program] + xor cx, cx + mov cl, byte [BPB_NumFATs+boot_program] + mul cx + add ax, word [BPB_RsvdSecCnt+boot_program] + mov word [FirstRootDirSecNum+boot_program], ax ; 19 + mov si, ax - ; - count of sectors in RootDir - mov bx,word [BPB_BytsPerSec+boot_program] - mov cl,5 ; divide ax by 32 - shr bx,cl ; bx = directory entries per sector - mov ax,word [BPB_RootEntCnt+boot_program] - xor dx,dx - div bx - mov word [RootDirSecs+boot_program],ax ; 14 + ; - count of sectors in RootDir + mov bx, word [BPB_BytsPerSec+boot_program] + mov cl, 5 ; divide ax by 32 + shr bx, cl ; bx = directory entries per sector + mov ax, word [BPB_RootEntCnt+boot_program] + xor dx, dx + div bx + mov word [RootDirSecs+boot_program], ax ; 14 - ; - data start - add si,ax ; add beginning sector of RootDir and count sectors in RootDir - mov word [data_start+boot_program],si ; 33 - ; reading root directory - ; al=count root dir sectrors !!!! TODO: al, max 255 sectors !!!! - mov ah,2 ; read - push ax + ; - data start + add si, ax ; add beginning sector of RootDir and count sectors in RootDir + mov word [data_start+boot_program], si ; 33 + ; reading root directory + ; al=count root dir sectrors !!!! TODO: al, max 255 sectors !!!! + mov ah, 2 ; read + push ax - mov ax,word [FirstRootDirSecNum+boot_program] - call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) - pop ax - mov bx,pos_read_tmp ; es:bx read buffer - call read_sector + mov ax, word [FirstRootDirSecNum+boot_program] + call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) + pop ax + mov bx, pos_read_tmp ; es:bx read buffer + call read_sector - mov si,bx ; read buffer address: es:si - mov ax,[RootDirSecs+boot_program] - mul word [BPB_BytsPerSec+boot_program] - add ax,si ; AX = end of root dir. in buffer pos_read_tmp + mov si, bx ; read buffer address: es:si + mov ax, [RootDirSecs+boot_program] + mul word [BPB_BytsPerSec+boot_program] + add ax, si ; AX = end of root dir. in buffer pos_read_tmp - ; find kernel file in root directory + ; find kernel file in root directory loop_find_dir_entry: - push si - mov cx,11 - mov di,kernel_name+boot_program - rep cmpsb ; compare es:si and es:di, cx bytes long - pop si - je found_kernel_file - add si,32 ; next dir. entry - cmp si,ax ; end of directory - jb loop_find_dir_entry + push si + mov cx, 11 + mov di, kernel_name+boot_program + rep cmpsb ; compare es:si and es:di, cx bytes long + pop si + je found_kernel_file + add si, 32 ; next dir. entry + cmp si, ax ; end of directory + jb loop_find_dir_entry file_error_message: - mov si,error_message+boot_program + mov si, error_message+boot_program loop_error_message: - lodsb - or al,al - jz freeze_pc - mov ah,0eh - mov bx,7 - int 10h - jmp loop_error_message + lodsb + or al, al + jz freeze_pc + mov ah, 0eh + mov bx, 7 + int 10h + jmp loop_error_message freeze_pc: - jmp $ ; endless loop + jmp $ ; endless loop - ; === KERNEL FOUND. LOADING... === + ; === KERNEL FOUND. LOADING... === found_kernel_file: - mov bp,[si+01ah] ; first cluster of kernel file - ; - mov [cluster1st+boot_program],bp ; starting cluster of kernel file - ; <\diamond> + mov bp, [si+01ah] ; first cluster of kernel file + ; + mov [cluster1st+boot_program], bp ; starting cluster of kernel file + ; <\diamond> - ; reading first FAT table - mov ax,word [BPB_RsvdSecCnt+boot_program] ; begin first FAT abs sector number - call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) - mov bx,pos_read_tmp ; es:bx read position - mov ah,2 ; ah=2 (read) - mov al, byte [BPB_FATSz16+boot_program] ; FAT size in sectors (TODO: max 255 sectors) - call read_sector - jc file_error_message ; read error + ; reading first FAT table + mov ax, word [BPB_RsvdSecCnt+boot_program] ; begin first FAT abs sector number + call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) + mov bx, pos_read_tmp ; es:bx read position + mov ah, 2 ; ah=2 (read) + mov al, byte [BPB_FATSz16+boot_program] ; FAT size in sectors (TODO: max 255 sectors) + call read_sector + jc file_error_message ; read error - mov ax,seg_read_kernel - mov es,ax - xor bx,bx ; es:bx = 1000h:0000h + mov ax, seg_read_kernel + mov es, ax + xor bx, bx ; es:bx = 1000h:0000h - ; reading kernel file + ; reading kernel file loop_obtains_kernel_data: - ; read one cluster of file - call obtain_cluster - jc file_error_message ; read error + ; read one cluster of file + call obtain_cluster + jc file_error_message ; read error - ; add one cluster length to segment:offset - push bx - mov bx,es - mov ax,word [BPB_BytsPerSec+boot_program] ;\ - movsx cx,byte [BPB_SecPerClus+boot_program] ; | !!! TODO: !!! - mul cx ; | out this from loop !!! - shr ax,4 ;/ - add bx,ax - mov es,bx - pop bx + ; add one cluster length to segment:offset + push bx + mov bx, es + mov ax, word [BPB_BytsPerSec+boot_program] ;\ + movsx cx, byte [BPB_SecPerClus+boot_program] ; | !!! TODO: !!! + mul cx ; | out this from loop !!! + shr ax, 4 ;/ + add bx, ax + mov es, bx + pop bx - mov di,bp - shr di,1 - pushf - add di,bp ; di = bp * 1.5 - add di,pos_read_tmp - mov ax,[di] ; read next entry from FAT-chain - popf - jc move_4_right - and ax,0fffh - jmp verify_end_sector + mov di, bp + shr di, 1 + pushf + add di, bp ; di = bp * 1.5 + add di, pos_read_tmp + mov ax, [di] ; read next entry from FAT-chain + popf + jc move_4_right + and ax, 0fffh + jmp verify_end_sector move_4_right: - mov cl,4 - shr ax,cl + mov cl, 4 + shr ax, cl verify_end_sector: - cmp ax,0ff8h ; last cluster - jae execute_kernel - mov bp,ax - jmp loop_obtains_kernel_data + cmp ax, 0ff8h ; last cluster + jae execute_kernel + mov bp, ax + jmp loop_obtains_kernel_data execute_kernel: - ; - mov ax,'KL' - push 0 - pop ds - mov si,loader_block+boot_program - ; - push word seg_read_kernel - push word 0 - retf ; jmp far 1000:0000 + ; + mov ax, 'KL' + push 0 + pop ds + mov si, loader_block+boot_program + ; + push word seg_read_kernel + push word 0 + retf ; jmp far 1000:0000 ;------------------------------------------ - ; loading cluster from file to es:bx + ; loading cluster from file to es:bx obtain_cluster: - ; bp - cluster number to read - ; carry = 0 -> read OK - ; carry = 1 -> read ERROR + ; bp - cluster number to read + ; carry = 0 -> read OK + ; carry = 1 -> read ERROR - ; print one dot - push bx - mov ax,0e2eh ; ah=0eh (teletype), al='.' - xor bh,bh - int 10h - pop bx + ; print one dot + push bx + mov ax, 0e2eh ; ah=0eh (teletype), al='.' + xor bh, bh + int 10h + pop bx writesec: - ; convert cluster number to sector number - mov ax,bp ; data cluster to read - sub ax,2 - xor dx,dx - mov dl,byte [BPB_SecPerClus+boot_program] - mul dx - add ax,word [data_start+boot_program] + ; convert cluster number to sector number + mov ax, bp ; data cluster to read + sub ax, 2 + xor dx, dx + mov dl, byte [BPB_SecPerClus+boot_program] + mul dx + add ax, word [data_start+boot_program] - call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) + call conv_abs_to_THS ; convert abs sector (AX) to BIOS T:H:S (track:head:sector) patchhere: - mov ah,2 ; ah=2 (read) - mov al,byte [BPB_SecPerClus+boot_program] ; al=(one cluster) - call read_sector - retn + mov ah, 2 ; ah=2 (read) + mov al, byte [BPB_SecPerClus+boot_program] ; al=(one cluster) + call read_sector + retn ;------------------------------------------ ;------------------------------------------ - ; read sector from disk + ; read sector from disk read_sector: - push bp - mov bp,20 ; try 20 times + push bp + mov bp, 20 ; try 20 times newread: - dec bp - jz file_error_message - push ax bx cx dx - int 13h - pop dx cx bx ax - jc newread - pop bp - retn + dec bp + jz file_error_message + push ax bx cx dx + int 13h + pop dx cx bx ax + jc newread + pop bp + retn ;------------------------------------------ - ; convert abs. sector number (AX) to BIOS T:H:S - ; sector number = (abs.sector%BPB_SecPerTrk)+1 - ; pre.track number = (abs.sector/BPB_SecPerTrk) - ; head number = pre.track number%BPB_NumHeads - ; track number = pre.track number/BPB_NumHeads - ; Return: cl - sector number - ; ch - track number - ; dl - drive number (0 = a:) - ; dh - head number + ; convert abs. sector number (AX) to BIOS T:H:S + ; sector number = (abs.sector%BPB_SecPerTrk)+1 + ; pre.track number = (abs.sector/BPB_SecPerTrk) + ; head number = pre.track number%BPB_NumHeads + ; track number = pre.track number/BPB_NumHeads + ; Return: cl - sector number + ; ch - track number + ; dl - drive number (0 = a:) + ; dh - head number conv_abs_to_THS: - push bx - mov bx,word [BPB_SecPerTrk+boot_program] - xor dx,dx - div bx - inc dx - mov cl, dl ; cl = sector number - mov bx,word [BPB_NumHeads+boot_program] - xor dx,dx - div bx - ; !!!!!!! ax = track number, dx = head number - mov ch,al ; ch=track number - xchg dh,dl ; dh=head number - mov dl,0 ; dl=0 (drive 0 (a:)) - pop bx - retn + push bx + mov bx, word [BPB_SecPerTrk+boot_program] + xor dx, dx + div bx + inc dx + mov cl, dl ; cl = sector number + mov bx, word [BPB_NumHeads+boot_program] + xor dx, dx + div bx + ; !!!!!!! ax = track number, dx = head number + mov ch, al ; ch=track number + xchg dh, dl ; dh=head number + mov dl, 0 ; dl=0 (drive 0 (a:)) + pop bx + retn ;------------------------------------------ -loading db cr,lf,'Starting system ',00h -error_message db 13,10 -kernel_name db 'KERNEL MNT ?',cr,lf,00h -FirstRootDirSecNum dw ? -RootDirSecs dw ? -data_start dw ? +loading db cr,lf,'Starting system ',00h +error_message db 13,10 +kernel_name db 'KERNEL MNT ?',cr,lf,00h +FirstRootDirSecNum dw ? +RootDirSecs dw ? +data_start dw ? ; write1st: - push cs - pop ds - mov byte [patchhere+1+boot_program], 3 ; change ah=2 to ah=3 - mov bp,[cluster1st+boot_program] - push 1000h - pop es - xor bx,bx - call writesec - mov byte [patchhere+1+boot_program], 2 ; change back ah=3 to ah=2 - retf -cluster1st dw ? + push cs + pop ds + mov byte [patchhere+1+boot_program], 3 ; change ah=2 to ah=3 + mov bp, [cluster1st+boot_program] + push 1000h + pop es + xor bx, bx + call writesec + mov byte [patchhere+1+boot_program], 2 ; change back ah=3 to ah=2 + retf +cluster1st dw ? loader_block: - db 1 - dw 0 - dw write1st+boot_program - dw 0 + db 1 + dw 0 + dw write1st+boot_program + dw 0 ; <\diamond> -times 0x1fe-$ db 00h +times 0x1fe-$ db 00h - db 55h,0aah ;boot signature + db 55h,0aah ;boot signature diff --git a/kernel/trunk/bootloader/extended_primary_loader/after_win/fat.inc b/kernel/trunk/bootloader/extended_primary_loader/after_win/fat.inc index 66130eabd..3f4ccda09 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/after_win/fat.inc +++ b/kernel/trunk/bootloader/extended_primary_loader/after_win/fat.inc @@ -1,509 +1,509 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -; in: ss:bp = 0:dat -; in: es:bx = address to load file -; in: ds:si -> ASCIIZ name -; in: cx = limit in sectors -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) -load_file_fat: - mov eax, [bp + root_clus - dat] - mov [bp + cur_obj - dat], root_string - push es - push bx - push cx -.parse_dir_loop: -; convert name to FAT name - push [bp + cur_obj - dat] - push ax - mov [bp + cur_obj - dat], si - push ss - pop es -; convert ASCIIZ filename to FAT name - mov di, fat_filename - push di - mov cx, 8+3 - mov al, ' ' - rep stosb - pop di - mov cl, 8 ; 8 symbols per name - mov bl, 1 -.nameloop: - lodsb - test al, al - jz .namedone - cmp al, '/' - jz .namedone - cmp al, '.' - jz .namedot - dec cx - js .badname - cmp al, 'a' - jb @f - cmp al, 'z' - ja @f - sub al, 'a'-'A' -@@: - stosb - jmp .nameloop -.namedot: - inc bx - jp .badname - add di, cx - mov cl, 3 - jmp .nameloop -.badname: - mov si, badname_msg - jmp find_error_si -.namedone: -; scan directory - pop ax ; eax = cluster of directory - ; high word of eax is preserved by operations above - push ds - push si -; read a folder sector-by-sector and scan -; first, try to use the cache - push ss - pop ds - mov bx, -2 - mov cx, [bp + rootcache_size - dat] - cmp [bp + root_clus - dat], eax - jz .lookcache_root - mov di, foldcache_mark - xor bx, bx - mov cx, [bp + cachelimit - dat] -@@: - lea si, [di+bx] - mov edx, dword [foldcache_clus+si-foldcache_mark+bx] - cmp edx, eax - jz .cacheok - test edx, edx - jz .cacheadd ; the cache has place for new entry - inc bx - inc bx - dec cx - js @b -; the folder is not present in the cache, so add it -; the cache is full; find the oldest entry and replace it with the new one - mov bx, -2 - mov dx, [bp + cachelimit - dat] -@@: - inc bx - inc bx - cmp word [di+bx], dx ; marks have values 0 through [cachelimit] - jnz @b -.cacheadd: - or word [di+bx], 0xFFFF ; very big value, it will be changed soon - and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet - lea si, [di+bx] - mov dword [foldcache_clus+si-foldcache_mark+bx], eax -.cacheok: -; update cache marks - mov dx, [di+bx] - mov cx, [foldcache_size+di-foldcache_mark+bx] - mov di, [bp + cachelimit - dat] - add di, di -.cacheupdate: - cmp [foldcache_mark+di], dx - adc [foldcache_mark+di], 0 - dec di - dec di - jns .cacheupdate - and [foldcache_mark+bx], 0 -; done, bx contains (position in cache)*2 -.lookcache_root: -; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder - ;mov dx, bx - ;shl dx, 8 - ;add dx, 0x9200 - lea dx, [bx + 0x92] - xchg dl, dh - mov ds, dx - mov si, fat_filename ; ss:si -> filename in FAT style - call fat_scan_for_filename - jz .lookup_done -; cache miss, read folder data from disk -; we are reading parent directory, it can result in disk read errors; restore [cur_obj] - mov di, sp - mov bx, [bp + cur_obj - dat] - xchg bx, [ss:di+4] - mov [bp + cur_obj - dat], bx - mov bx, cx - add bx, 0xF - shr bx, 4 - shl cx, 5 - mov di, cx ; es:di -> free space in cache entry -; external loop: scan clusters -.folder_next_cluster: -; internal loop: scan sectors in cluster - movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus - push eax -; FAT12/16 root - special handling - test eax, eax - jnz .folder_notroot - mov cx, [ss:0x3211] ; BPB_RootEntCnt - mov dx, cx - add cx, 0xF - rcr cx, 1 - shr cx, 3 - mov eax, [bp + root_start - dat] - jmp .folder_next_sector -.folder_notroot: - mul ecx - add eax, [bp + data_start - dat] -.folder_next_sector: - sub dx, 0x10 -; skip first bx sectors - dec bx - jns .folder_skip_sector - push cx - push es di - push 0x8000 - pop es - xor bx, bx - mov cx, 1 - push es - call read - jc ..found_disk_error -; copy data to the cache... - pop ds - pop di es - cmp di, 0x2000 ; ...if there is free space, of course - jae @f - pusha - mov cx, 0x100 - xor si, si - rep movsw - mov di, es - shr di, 8 - cmp di, 0x90 - jz .update_rootcache_size - add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache - jmp .updated_cachesize -.update_rootcache_size: - mov cl, 0x10 - cmp cx, dx - jb @f - mov cx, dx -@@: - add [bp + rootcache_size - dat], cx -.updated_cachesize: - popa -@@: - push es - mov cl, 0x10 ; ch=0 at this point - cmp cx, dx - jb @f - mov cx, dx -@@: - call fat_scan_for_filename - pop es - pop cx - jz .lookup_done_pop -.folder_skip_sector: - inc eax - loop .folder_next_sector - pop eax ; eax = current cluster - test eax, eax - jz @f - call [bp + get_next_cluster_ptr - dat] - jc .folder_next_cluster -@@: - stc - push eax -.lookup_done_pop: - pop eax -.lookup_done: - pop si -; CF=1 <=> failed - jnc .found - pop ds - pop [bp + cur_obj - dat] - mov si, error_not_found - jmp find_error_si -.found: - mov eax, [di+20-2] - mov edx, [di+28] - mov ax, [di+26] ; get cluster - test byte [di+11], 10h ; directory? - pop ds - pop [bp + cur_obj - dat] ; forget old [cur_obj] - jz .regular_file - cmp byte [si-1], 0 - jnz .parse_dir_loop -..directory_error: - mov si, directory_string - jmp find_error_si -.regular_file: - cmp byte [si-1], 0 - jz @f -..notdir_error: - mov si, notdir_string - jmp find_error_si -@@: -; ok, we have found a regular file and the caller requested it -; parse FAT chunk - push ss - pop es - push ss - pop ds - mov di, 0x4005 - mov byte [di-5], 1 ; non-resident attribute - mov dword [di-4], 1 - stosd - pop cx - push cx -.parsefat: - call [bp + get_next_cluster_ptr - dat] - jnc .done - mov esi, [di-8] - add esi, [di-4] - cmp eax, esi - jz .contc - mov dword [di], 1 - scasd - stosd - jmp @f -.contc: - inc dword [di-8] -@@: - sub cl, [0x320D] - sbb ch, 0 - ja .parsefat -.done: - xor eax, eax - stosd - mov si, 0x4000 -load_file_common_end: - xor ecx, ecx - pop cx - pop bx - pop es - mov [bp + filesize - dat], edx - mov [bp + sectors_read - dat], ecx - add edx, 0x1FF - shr edx, 9 - mov [bp + filesize_sectors - dat], edx - cmp edx, ecx - seta al - mov ah, 0 - push ax - call read_file_chunk -continue_load_common_end: - mov [bp + cur_chunk_ptr - dat], si - pop bx - mov ax, word [bp + filesize - dat] - mov dx, word [bp + filesize+2 - dat] - jnc @f - mov bl, 3 ; read error -@@: - ret - -continue_load_file: -; es:bx -> buffer for output, ecx = cx = number of sectors - mov si, [bp + cur_chunk_ptr - dat] - push ecx - add ecx, [bp + sectors_read - dat] - mov [bp + sectors_read - dat], ecx - cmp [bp + filesize_sectors - dat], ecx - pop ecx - seta al - mov ah, 0 - push ax - push continue_load_common_end - push ss - pop ds - cmp [bp + cur_chunk_resident - dat], ah - jnz .nonresident -.resident: - mov ax, word [bp + num_sectors - dat] - jmp read_file_chunk.resident.continue -.nonresident: - mov eax, [bp + cur_cluster - dat] - mov edx, [bp + num_sectors - dat] - add eax, [bp + cur_delta - dat] - jmp read_file_chunk.nonresident.continue - -fat_scan_for_filename: -; in: ss:si -> 11-bytes FAT name -; in: ds:0 -> part of directory data -; in: cx = number of entries -; out: if found: CF=0, ZF=1, es:di -> directory entry -; out: if not found, but continue required: CF=1 and ZF=0 -; out: if not found and zero item reached: CF=1 and ZF=1 - push ds - pop es - xor di, di - push cx - jcxz .noent -.loop: - cmp byte [di], 0 - jz .notfound - test byte [di+11], 8 ; volume label? - jnz .cont ; ignore volume labels - pusha - mov cx, 11 - repz cmps byte [ss:si], byte [es:di] - popa - jz .done -.cont: - add di, 0x20 - loop .loop -.noent: - inc cx ; clear ZF flag -.notfound: - stc -.done: - pop cx - ret - -fat12_get_next_cluster: -; in: ax = cluster (high word of eax is zero) -; out: if there is next cluster: CF=1, ax = next cluster -; out: if there is no next cluster: CF=0 - push si - push ds - push 0x6000 - pop ds - mov si, ax - shr si, 1 - add si, ax - test al, 1 - lodsw - jz @f - shr ax, 4 -@@: - and ax, 0xFFF - cmp ax, 0xFF7 - pop ds si - ret - -fat16_get_next_cluster: -; in: ax = cluster (high word of eax is zero) -; out: if there is next cluster: CF=1, ax = next cluster -; out: if there is no next cluster: CF=0 -; each sector contains 200h bytes = 100h FAT entries -; so ah = # of sector, al = offset in sector - push si - mov si, ax - shr si, 8 -; calculate segment for this sector of FAT table -; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) -; segment = 6000 + 20*si, offset = 0 - push es - push si - shl si, 5 - add si, 0x6000 - mov es, si - pop si - cmp byte [ss:0x3400+si], 0 ; sector already loaded? - jnz .noread -; load corresponding sector, try all FATs if disk read error detected - pusha - movzx di, byte [ss:0x3210] ; BPB_NumFATs - xor bx, bx - mov ax, [ss:0x320E] ; BPB_RsvdSecCnt - xor dx, dx - add ax, si - adc dx, bx -@@: - push es - push dx ax - pop eax - mov cx, 1 ; read 1 sector - call read - pop es - jnc @f - add ax, [ss:0x3216] ; BPB_FATSz16 - adc dx, bx - dec di - jnz @b -..found_disk_error: - mov si, disk_error_msg - jmp find_error_si -@@: - popa -.noread: - mov si, ax - and si, 0xFF - add si, si - mov ax, [es:si] - pop es - cmp ax, 0xFFF7 - pop si - ret - -fat32_get_next_cluster: -; in: eax = cluster -; out: if there is next cluster: CF=1, eax = next cluster -; out: if there is no next cluster: CF=0 - push di - push ax - shr eax, 7 -; eax = FAT sector number; look in cache - push si - mov si, cache1head - call cache_lookup - pop si - jnc .noread -; read FAT, try all FATs if disk read error detected - push es - pushad - movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt - add eax, edx - movzx si, byte [ss:0x3210] ; BPB_NumFATs -@@: - lea cx, [di - 0x3400 + (0x6000 shr (9-3))] - shl cx, 9-3 - mov es, cx - xor bx, bx - mov cx, 1 - call read - jnc @f - add eax, [ss:0x3224] ; BPB_FATSz32 - dec si - jnz @b - jmp ..found_disk_error -@@: - popad - pop es -.noread: -; get requested item - lea ax, [di - 0x3400 + (0x6000 shr (9-3))] - pop di - and di, 0x7F - shl di, 2 - shl ax, 9-3 - push ds - mov ds, ax - and byte [di+3], 0x0F - mov eax, [di] - pop ds - pop di - ;and eax, 0x0FFFFFFF - cmp eax, 0x0FFFFFF7 - ret +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +; in: ss:bp = 0:dat +; in: es:bx = address to load file +; in: ds:si -> ASCIIZ name +; in: cx = limit in sectors +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) +load_file_fat: + mov eax, [bp + root_clus - dat] + mov [bp + cur_obj - dat], root_string + push es + push bx + push cx +.parse_dir_loop: +; convert name to FAT name + push [bp + cur_obj - dat] + push ax + mov [bp + cur_obj - dat], si + push ss + pop es +; convert ASCIIZ filename to FAT name + mov di, fat_filename + push di + mov cx, 8+3 + mov al, ' ' + rep stosb + pop di + mov cl, 8 ; 8 symbols per name + mov bl, 1 +.nameloop: + lodsb + test al, al + jz .namedone + cmp al, '/' + jz .namedone + cmp al, '.' + jz .namedot + dec cx + js .badname + cmp al, 'a' + jb @f + cmp al, 'z' + ja @f + sub al, 'a'-'A' +@@: + stosb + jmp .nameloop +.namedot: + inc bx + jp .badname + add di, cx + mov cl, 3 + jmp .nameloop +.badname: + mov si, badname_msg + jmp find_error_si +.namedone: +; scan directory + pop ax ; eax = cluster of directory + ; high word of eax is preserved by operations above + push ds + push si +; read a folder sector-by-sector and scan +; first, try to use the cache + push ss + pop ds + mov bx, -2 + mov cx, [bp + rootcache_size - dat] + cmp [bp + root_clus - dat], eax + jz .lookcache_root + mov di, foldcache_mark + xor bx, bx + mov cx, [bp + cachelimit - dat] +@@: + lea si, [di+bx] + mov edx, dword [foldcache_clus+si-foldcache_mark+bx] + cmp edx, eax + jz .cacheok + test edx, edx + jz .cacheadd ; the cache has place for new entry + inc bx + inc bx + dec cx + js @b +; the folder is not present in the cache, so add it +; the cache is full; find the oldest entry and replace it with the new one + mov bx, -2 + mov dx, [bp + cachelimit - dat] +@@: + inc bx + inc bx + cmp word [di+bx], dx ; marks have values 0 through [cachelimit] + jnz @b +.cacheadd: + or word [di+bx], 0xFFFF ; very big value, it will be changed soon + and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet + lea si, [di+bx] + mov dword [foldcache_clus+si-foldcache_mark+bx], eax +.cacheok: +; update cache marks + mov dx, [di+bx] + mov cx, [foldcache_size+di-foldcache_mark+bx] + mov di, [bp + cachelimit - dat] + add di, di +.cacheupdate: + cmp [foldcache_mark+di], dx + adc [foldcache_mark+di], 0 + dec di + dec di + jns .cacheupdate + and [foldcache_mark+bx], 0 +; done, bx contains (position in cache)*2 +.lookcache_root: +; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder + ;mov dx, bx + ;shl dx, 8 + ;add dx, 0x9200 + lea dx, [bx + 0x92] + xchg dl, dh + mov ds, dx + mov si, fat_filename ; ss:si -> filename in FAT style + call fat_scan_for_filename + jz .lookup_done +; cache miss, read folder data from disk +; we are reading parent directory, it can result in disk read errors; restore [cur_obj] + mov di, sp + mov bx, [bp + cur_obj - dat] + xchg bx, [ss:di+4] + mov [bp + cur_obj - dat], bx + mov bx, cx + add bx, 0xF + shr bx, 4 + shl cx, 5 + mov di, cx ; es:di -> free space in cache entry +; external loop: scan clusters +.folder_next_cluster: +; internal loop: scan sectors in cluster + movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus + push eax +; FAT12/16 root - special handling + test eax, eax + jnz .folder_notroot + mov cx, [ss:0x3211] ; BPB_RootEntCnt + mov dx, cx + add cx, 0xF + rcr cx, 1 + shr cx, 3 + mov eax, [bp + root_start - dat] + jmp .folder_next_sector +.folder_notroot: + mul ecx + add eax, [bp + data_start - dat] +.folder_next_sector: + sub dx, 0x10 +; skip first bx sectors + dec bx + jns .folder_skip_sector + push cx + push es di + push 0x8000 + pop es + xor bx, bx + mov cx, 1 + push es + call read + jc ..found_disk_error +; copy data to the cache... + pop ds + pop di es + cmp di, 0x2000 ; ...if there is free space, of course + jae @f + pusha + mov cx, 0x100 + xor si, si + rep movsw + mov di, es + shr di, 8 + cmp di, 0x90 + jz .update_rootcache_size + add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache + jmp .updated_cachesize +.update_rootcache_size: + mov cl, 0x10 + cmp cx, dx + jb @f + mov cx, dx +@@: + add [bp + rootcache_size - dat], cx +.updated_cachesize: + popa +@@: + push es + mov cl, 0x10 ; ch=0 at this point + cmp cx, dx + jb @f + mov cx, dx +@@: + call fat_scan_for_filename + pop es + pop cx + jz .lookup_done_pop +.folder_skip_sector: + inc eax + loop .folder_next_sector + pop eax ; eax = current cluster + test eax, eax + jz @f + call [bp + get_next_cluster_ptr - dat] + jc .folder_next_cluster +@@: + stc + push eax +.lookup_done_pop: + pop eax +.lookup_done: + pop si +; CF=1 <=> failed + jnc .found + pop ds + pop [bp + cur_obj - dat] + mov si, error_not_found + jmp find_error_si +.found: + mov eax, [di+20-2] + mov edx, [di+28] + mov ax, [di+26] ; get cluster + test byte [di+11], 10h ; directory? + pop ds + pop [bp + cur_obj - dat] ; forget old [cur_obj] + jz .regular_file + cmp byte [si-1], 0 + jnz .parse_dir_loop +..directory_error: + mov si, directory_string + jmp find_error_si +.regular_file: + cmp byte [si-1], 0 + jz @f +..notdir_error: + mov si, notdir_string + jmp find_error_si +@@: +; ok, we have found a regular file and the caller requested it +; parse FAT chunk + push ss + pop es + push ss + pop ds + mov di, 0x4005 + mov byte [di-5], 1 ; non-resident attribute + mov dword [di-4], 1 + stosd + pop cx + push cx +.parsefat: + call [bp + get_next_cluster_ptr - dat] + jnc .done + mov esi, [di-8] + add esi, [di-4] + cmp eax, esi + jz .contc + mov dword [di], 1 + scasd + stosd + jmp @f +.contc: + inc dword [di-8] +@@: + sub cl, [0x320D] + sbb ch, 0 + ja .parsefat +.done: + xor eax, eax + stosd + mov si, 0x4000 +load_file_common_end: + xor ecx, ecx + pop cx + pop bx + pop es + mov [bp + filesize - dat], edx + mov [bp + sectors_read - dat], ecx + add edx, 0x1FF + shr edx, 9 + mov [bp + filesize_sectors - dat], edx + cmp edx, ecx + seta al + mov ah, 0 + push ax + call read_file_chunk +continue_load_common_end: + mov [bp + cur_chunk_ptr - dat], si + pop bx + mov ax, word [bp + filesize - dat] + mov dx, word [bp + filesize+2 - dat] + jnc @f + mov bl, 3 ; read error +@@: + ret + +continue_load_file: +; es:bx -> buffer for output, ecx = cx = number of sectors + mov si, [bp + cur_chunk_ptr - dat] + push ecx + add ecx, [bp + sectors_read - dat] + mov [bp + sectors_read - dat], ecx + cmp [bp + filesize_sectors - dat], ecx + pop ecx + seta al + mov ah, 0 + push ax + push continue_load_common_end + push ss + pop ds + cmp [bp + cur_chunk_resident - dat], ah + jnz .nonresident +.resident: + mov ax, word [bp + num_sectors - dat] + jmp read_file_chunk.resident.continue +.nonresident: + mov eax, [bp + cur_cluster - dat] + mov edx, [bp + num_sectors - dat] + add eax, [bp + cur_delta - dat] + jmp read_file_chunk.nonresident.continue + +fat_scan_for_filename: +; in: ss:si -> 11-bytes FAT name +; in: ds:0 -> part of directory data +; in: cx = number of entries +; out: if found: CF=0, ZF=1, es:di -> directory entry +; out: if not found, but continue required: CF=1 and ZF=0 +; out: if not found and zero item reached: CF=1 and ZF=1 + push ds + pop es + xor di, di + push cx + jcxz .noent +.loop: + cmp byte [di], 0 + jz .notfound + test byte [di+11], 8 ; volume label? + jnz .cont ; ignore volume labels + pusha + mov cx, 11 + repz cmps byte [ss:si], byte [es:di] + popa + jz .done +.cont: + add di, 0x20 + loop .loop +.noent: + inc cx ; clear ZF flag +.notfound: + stc +.done: + pop cx + ret + +fat12_get_next_cluster: +; in: ax = cluster (high word of eax is zero) +; out: if there is next cluster: CF=1, ax = next cluster +; out: if there is no next cluster: CF=0 + push si + push ds + push 0x6000 + pop ds + mov si, ax + shr si, 1 + add si, ax + test al, 1 + lodsw + jz @f + shr ax, 4 +@@: + and ax, 0xFFF + cmp ax, 0xFF7 + pop ds si + ret + +fat16_get_next_cluster: +; in: ax = cluster (high word of eax is zero) +; out: if there is next cluster: CF=1, ax = next cluster +; out: if there is no next cluster: CF=0 +; each sector contains 200h bytes = 100h FAT entries +; so ah = # of sector, al = offset in sector + push si + mov si, ax + shr si, 8 +; calculate segment for this sector of FAT table +; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) +; segment = 6000 + 20*si, offset = 0 + push es + push si + shl si, 5 + add si, 0x6000 + mov es, si + pop si + cmp byte [ss:0x3400+si], 0 ; sector already loaded? + jnz .noread +; load corresponding sector, try all FATs if disk read error detected + pusha + movzx di, byte [ss:0x3210] ; BPB_NumFATs + xor bx, bx + mov ax, [ss:0x320E] ; BPB_RsvdSecCnt + xor dx, dx + add ax, si + adc dx, bx +@@: + push es + push dx ax + pop eax + mov cx, 1 ; read 1 sector + call read + pop es + jnc @f + add ax, [ss:0x3216] ; BPB_FATSz16 + adc dx, bx + dec di + jnz @b +..found_disk_error: + mov si, disk_error_msg + jmp find_error_si +@@: + popa +.noread: + mov si, ax + and si, 0xFF + add si, si + mov ax, [es:si] + pop es + cmp ax, 0xFFF7 + pop si + ret + +fat32_get_next_cluster: +; in: eax = cluster +; out: if there is next cluster: CF=1, eax = next cluster +; out: if there is no next cluster: CF=0 + push di + push ax + shr eax, 7 +; eax = FAT sector number; look in cache + push si + mov si, cache1head + call cache_lookup + pop si + jnc .noread +; read FAT, try all FATs if disk read error detected + push es + pushad + movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt + add eax, edx + movzx si, byte [ss:0x3210] ; BPB_NumFATs +@@: + lea cx, [di - 0x3400 + (0x6000 shr (9-3))] + shl cx, 9-3 + mov es, cx + xor bx, bx + mov cx, 1 + call read + jnc @f + add eax, [ss:0x3224] ; BPB_FATSz32 + dec si + jnz @b + jmp ..found_disk_error +@@: + popad + pop es +.noread: +; get requested item + lea ax, [di - 0x3400 + (0x6000 shr (9-3))] + pop di + and di, 0x7F + shl di, 2 + shl ax, 9-3 + push ds + mov ds, ax + and byte [di+3], 0x0F + mov eax, [di] + pop ds + pop di + ;and eax, 0x0FFFFFFF + cmp eax, 0x0FFFFFF7 + ret diff --git a/kernel/trunk/bootloader/extended_primary_loader/after_win/kordldr.win.asm b/kernel/trunk/bootloader/extended_primary_loader/after_win/kordldr.win.asm index 37c798e0d..460e3b7c3 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/after_win/kordldr.win.asm +++ b/kernel/trunk/bootloader/extended_primary_loader/after_win/kordldr.win.asm @@ -1,921 +1,924 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond -; It is used when main bootloader is Windows loader. - -; this code is loaded: -; NT/2k/XP: by ntldr to 0D00:0000 -; 9x: by io.sys from config.sys to xxxx:0100 -; Vista: by bootmgr to 0000:7C00 - format binary - use16 - -; in any case, we relocate this code to 0000:0600 - org 0x600 -; entry point for 9x and Vista booting - call @f - db 'NTFS' -@@: - pop si - sub si, 3 - cmp si, 100h - jnz boot_vista - mov si, load_question + 100h - 600h - call out_string -; mov si, answer + 100h - 0600h ; already is -xxy: mov ah, 0 - int 16h - or al, 20h - mov [si], al - cmp al, 'y' - jz xxz - cmp al, 'n' - jnz xxy -; continue load Windows -; call out_string -; ret -out_string: - push bx -@@: - lodsb - test al, al - jz @f - mov ah, 0Eh - mov bx, 7 - int 10h - jmp @b -@@: - pop bx - ret -xxz: -; boot KordOS - call out_string -; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, -; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached - xor di, di - mov ds, di - mov word [di+4], new01handler + 100h - 600h - mov [di+6], cs - pushf - pop ax - or ah, 1 - push ax - popf -; we cannot issue INT 19h directly, because INT command clears TF -; int 19h ; don't issue it directly, because INT command clears TF -; so instead we use direct call -; pushf ; there will be no IRET - call far [di + 19h*4] -xxt: - xor di, di - mov ds, di - cmp word [di + 8*4+2], 0F000h - jz @f - les bx, [di + 8*4] - mov eax, [es:bx+1] - mov [di + 8*4], eax -@@: - mov si, 100h -boot_vista: -; relocate cs:si -> 0000:0600 - push cs - pop ds - xor ax, ax - mov es, ax - mov di, 0x600 - mov cx, 2000h/2 - rep movsw - jmp 0:real_entry - -load_question db 'Load KordOS? [y/n]: ',0 -answer db ? - db 13,10,0 - -new01handler: -; [sp]=ip, [sp+2]=cs, [sp+4]=flags - push bp - mov bp, sp - push ds - lds bp, [bp+2] - cmp word [ds:bp], 19cdh - jz xxt - pop ds - pop bp - iret - -; read from hard disk -; in: eax = absolute sector -; cx = number of sectors -; es:bx -> buffer -; out: CF=1 if error -read: - pushad - add eax, [bp + partition_start - dat] - cmp [bp + use_lba - dat], 0 - jz .chs -; LBA read - push ds -.lbado: - push ax - push cx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - push 0 - push 0 - push eax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [bp + boot_drive - dat] - mov ah, 42h - int 13h - jc .disk_error_lba - add sp, 10h ; restore stack -; increase current sector & buffer; decrease number of sectors - movzx esi, cx - mov ax, es - shl cx, 5 - add ax, cx - mov es, ax - pop cx - pop ax - add eax, esi - sub cx, si - jnz .lbado - pop ds - popad - ret -.disk_error_lba: - add sp, 14h - pop ds - popad - stc - ret - -.chs: - pusha - pop edi ; loword(edi) = di, hiword(edi) = si - push bx - -; eax / (SectorsPerTrack) -> eax, remainder bx - movzx esi, [bp + sectors - dat] - xor edx, edx - div esi - mov bx, dx ; bx = sector-1 - -; eax -> dx:ax - push eax - pop ax - pop dx -; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx - div [bp + heads - dat] - -; number of sectors: read no more than to end of track - sub si, bx - cmp cx, si - jbe @f - mov cx, si -@@: - - inc bx -; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector -; convert to int13 format - movzx edi, cx - mov dh, dl - mov dl, [bp + boot_drive - dat] - shl ah, 6 - mov ch, al - mov al, cl - mov cl, bl - or cl, ah - pop bx - mov si, 3 - mov ah, 2 -@@: - push ax - int 13h - jnc @f - xor ax, ax - int 13h ; reset drive - pop ax - dec si - jnz @b - add sp, 12 - popad - stc - ret -@@: - pop ax - mov ax, es - mov cx, di - shl cx, 5 - add ax, cx - mov es, ax - push edi - popa - add eax, edi - sub cx, di - jnz .chs - popad - ret - -disk_error2 db 'Fatal: cannot read partitions info: ' -disk_error_msg db 'disk read error',0 -disk_params_msg db 'Fatal: cannot get drive parameters',0 -start_msg db 2,' KordOS bootloader',13,10,0 -part_msg db 'looking at partition ' -part_char db '0' ; will be incremented before writing message - db ' ... ',0 -errfs_msg db 'unknown filesystem',13,10,0 -fatxx_msg db 'FATxx' -newline db 13,10,0 -ntfs_msg db 'NTFS',13,10,0 -error_msg db 'Error' -colon db ': ',0 -root_string db '\',0 -nomem_msg db 'No memory',0 -filesys_string db '(filesystem)',0 -directory_string db 'is a directory',0 -notdir_string db 'not a directory',0 - -; entry point for NT/2k/XP booting -; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 - repeat 600h + 256h - $ - db 1 ; any data can be here; 1 in ASCII is a nice face :) - end repeat -; cs=es=0D00, ds=07C0, ss=0 -; esi=edi=ebp=0, esp=7C00 - xor si, si - jmp boot_vista - -real_entry: -; ax = 0 - mov ds, ax - mov es, ax -; our stack is 4 Kb: memory range 2000-3000 - mov ss, ax - mov sp, 3000h - mov bp, dat - sti ; just for case -; say hi to user - mov si, start_msg - call out_string -; we are booting from hard disk identified by [boot_drive] - mov dl, [bp + boot_drive - dat] -; is LBA supported? - mov [bp + use_lba - dat], 0 - mov ah, 41h - mov bx, 55AAh - int 13h - jc .no_lba - cmp bx, 0AA55h - jnz .no_lba - test cl, 1 - jz .no_lba - inc [bp + use_lba - dat] - jmp disk_params_ok -.no_lba: -; get drive geometry - mov ah, 8 - mov dl, [bp + boot_drive - dat] - int 13h - jnc @f - mov si, disk_params_msg - call out_string - jmp $ -@@: - movzx ax, dh - inc ax - mov [bp + heads - dat], ax - and cx, 3Fh - mov [bp + sectors - dat], cx -disk_params_ok: -; determine size of cache for folders - int 12h ; ax = size of available base memory in Kb - sub ax, 94000h / 1024 - jc nomem - shr ax, 3 - mov [bp + cachelimit - dat], ax ; size of cache - 1 -; scan all partitions -new_partition_ex: - xor eax, eax ; read first sector of current disk area - mov [bp + extended_part_cur - dat], eax ; no extended partition yet - mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition - push es - mov cx, 1 - mov bx, 3000h - call read - pop es - jnc new_partition - mov si, disk_error2 - call out_string - jmp $ -new_partition: - mov bx, [bp + cur_partition_ofs - dat] - mov al, [bx+4] ; partition type - test al, al - jz next_partition - cmp al, 5 - jz @f - cmp al, 0xF - jnz not_extended -@@: -; extended partition - mov eax, [bx+8] ; partition start - add eax, [bp + extended_part_start - dat] - mov [bp + extended_part_cur - dat], eax -next_partition: - add [bp + cur_partition_ofs - dat], 10h - cmp [bp + cur_partition_ofs - dat], 31FEh - jb new_partition - mov eax, [bp + extended_part_cur - dat] - test eax, eax - jz partitions_done - cmp [bp + extended_part_start - dat], 0 - jnz @f - mov [bp + extended_part_start - dat], eax -@@: - mov [bp + extended_parent - dat], eax - mov [bp + partition_start - dat], eax - jmp new_partition_ex -partitions_done: - mov si, total_kaput - call out_string - jmp $ -not_extended: - mov eax, [bx+8] - add eax, [bp + extended_parent - dat] - mov [bp + partition_start - dat], eax -; try to load from current partition -; inform user - mov si, part_msg - inc [si + part_char - part_msg] - call out_string -; read bootsector - xor eax, eax - mov [bp + cur_obj - dat], filesys_string - push es - mov cx, 1 - mov bx, 3200h - call read - pop es - mov si, disk_error_msg - jc find_error_si - movzx si, byte [bx+13] - mov word [bp + sect_per_clust - dat], si - test si, si - jz unknown_fs - lea ax, [si-1] - test si, ax - jnz unknown_fs -; determine file system -; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) - cmp word [bx+11], 0x200 - jnz unknown_fs -; is it NTFS? - cmp dword [bx+3], 'NTFS' - jnz not_ntfs - cmp byte [bx+16], bl - jz ntfs -not_ntfs: -; is it FAT? FAT12/FAT16/FAT32? -; get count of sectors to dword in cx:si - mov si, [bx+19] - xor cx, cx - test si, si - jnz @f - mov si, [bx+32] - mov cx, [bx+34] -@@: - xor eax, eax -; subtract size of system area - sub si, [bx+14] ; BPB_ResvdSecCnt - sbb cx, ax - mov ax, [bx+17] ; BPB_RootEntCnt - add ax, 0xF - rcr ax, 1 - shr ax, 3 - sub si, ax - sbb cx, 0 - push cx - push si - mov ax, word [bx+22] - test ax, ax - jnz @f - mov eax, [bx+36] -@@: - movzx ecx, byte [bx+16] - imul ecx, eax - pop eax - sub eax, ecx -; now eax = count of sectors in the data region - xor edx, edx - div [bp + sect_per_clust - dat] -; now eax = count of clusters in the data region - mov si, fatxx_msg - cmp eax, 0xFFF5 - jae test_fat32 -; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 - cmp byte [bx+38], 0x29 - jnz not_fat - cmp ax, 0xFF5 - jae fat16 -fat12: - mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster - mov di, cx ; BPB_NumFATs - mov ax, '12' - push ax ; save for secondary loader - mov word [si+3], ax - call out_string - movzx ecx, word [bx+22] ; BPB_FATSz16 -; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) -.fatloop: -; if first copy is not readable, try to switch to other copies - push 0x6000 - pop es - xor bx, bx - movzx eax, word [0x320E] ; BPB_RsvdSecCnt - push cx - cmp cx, 12 - jb @f - mov cx, 12 -@@: - call read - pop cx - jnc fat1x_common - add eax, ecx ; switch to next copy of FAT - dec di - jnz .fatloop - mov si, disk_error_msg - jmp find_error_si -fat16: - mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster - mov ax, '16' - push ax ; save for secondary loader - mov word [si+3], ax - call out_string -; FAT16: init FAT cache - no sectors loaded - mov di, 0x3400 - xor ax, ax - mov cx, 0x100/2 - rep stosw -fat1x_common: - mov bx, 0x3200 - movzx eax, word [bx+22] ; BPB_FATSz16 - xor esi, esi ; no root cluster - jmp fat_common -test_fat32: -; FAT32 bootsector has it at the offset +66 - cmp byte [bx+66], 0x29 - jnz not_fat - mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster - mov ax, '32' - push ax ; save for secondary loader - mov word [si+3], ax - call out_string -; FAT32 - init cache for FAT table: no sectors loaded - lea si, [bp + cache1head - dat] - mov [si], si ; no sectors in cache: - mov [si+2], si ; 'prev' & 'next' links point to self - mov [bp + cache1end - dat], 3400h ; first free item = 3400h - mov [bp + cache1limit - dat], 3C00h - mov eax, [bx+36] ; BPB_FATSz32 - mov esi, [bx+44] ; BPB_RootClus - jmp fat_common -not_fat: -unknown_fs: - mov si, errfs_msg - call out_string - jmp next_partition -fat_common: - push ss - pop es - movzx edx, byte [bx+16] ; BPB_NumFATs - mul edx - mov [bp + root_start - dat], eax ; this is for FAT1x -; eax = total size of all FAT tables, in sectors - movzx ecx, word [bx+17] ; BPB_RootEntCnt - add ecx, 0xF - shr ecx, 4 - add eax, ecx - mov cx, word [bx+14] ; BPB_RsvdSecCnt - add [bp + root_start - dat], ecx ; this is for FAT1x - add eax, ecx -; cluster 2 begins from sector eax - movzx ebx, byte [bx+13] ; BPB_SecPerClus - sub eax, ebx - sub eax, ebx - mov [bp + data_start - dat], eax -; no clusters in folders cache - mov di, foldcache_clus - 2 - xor ax, ax - mov cx, 7*8/2 + 1 - rep stosw - mov [bp + root_clus - dat], esi -; load secondary loader - mov [bp + load_file_ptr - dat], load_file_fat -load_secondary: - push 0x1000 - pop es - xor bx, bx - mov si, kernel_name - mov cx, 0x30000 / 0x200 - call [bp + load_file_ptr - dat] -; say error if needed - mov si, error_too_big - dec bx - js @f - jz find_error_si - mov si, disk_error_msg - jmp find_error_si -@@: -; fill loader information and jump to secondary loader - mov al, 'h' ; boot device: hard drive - mov ah, [bp + boot_drive - dat] - sub ah, 80h ; boot device: identifier - pop bx ; restore file system ID ('12'/'16'/'32'/'nt') - mov si, callback - jmp 1000h:0000h - -nomem: - mov si, nomem_msg - call out_string - jmp $ - -ntfs: - push 'nt' ; save for secondary loader - mov si, ntfs_msg - call out_string - xor eax, eax - mov [bp + data_start - dat], eax - mov ecx, [bx+40h] ; frs_size - cmp cl, al - jg .1 - neg cl - inc ax - shl eax, cl - jmp .2 -.1: - mov eax, ecx - shl eax, 9 -.2: - mov [bp + frs_size - dat], ax -; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different -; (at least with standard tools) -; we allow extra size, but no more than 0x1000 bytes = 4 Kb - mov si, invalid_volume_msg - cmp eax, 0x1000 - ja find_error_si -; must be multiple of sector size - test ax, 0x1FF - jnz find_error_si - shr ax, 9 - xchg cx, ax -; initialize cache - no data loaded - lea si, [bp + cache1head - dat] - mov [si], si - mov [si+2], si - mov word [si+4], 3400h ; first free item = 3400h - mov word [si+6], 3400h + 8*8 ; 8 items in this cache -; read first MFT record - description of MFT itself - mov [bp + cur_obj - dat], mft_string - mov eax, [bx+30h] ; mft_cluster - mul [bp + sect_per_clust - dat] - push 0x8000 - pop es - xor bx, bx - push es - call read - pop ds - call restore_usa -; scan for unnamed $DATA attribute - mov [bp + freeattr - dat], 4000h - mov ax, 80h - call load_attr - push ss - pop ds - mov si, nodata_string - jc find_error_si -; load secondary loader - mov [bp + load_file_ptr - dat], load_file_ntfs - jmp load_secondary - -find_error_si: - push si -find_error_sp: - cmp [bp + in_callback - dat], 0 - jnz error_in_callback - push ss - pop ds - push ss - pop es - mov si, error_msg - call out_string - mov si, [bp + cur_obj - dat] -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jz @f - mov ah, 0Eh - mov bx, 7 - int 10h - jmp @b -@@: - mov si, colon - call out_string - pop si - call out_string - mov si, newline - call out_string - mov sp, 0x3000 - jmp next_partition -error_in_callback: -; return status: file not found, except for read errors - mov bx, 2 - cmp si, disk_error_msg - jnz @f - inc bx -@@: - mov ax, 0xFFFF - mov dx, ax - mov sp, 3000h - 6 - ret - -callback: -; in: ax = function number; only functions 1 and 2 are defined for now -; save caller's stack - mov dx, ss - mov cx, sp -; set our stack (required because we need ss=0) - xor si, si - mov ss, si - mov sp, 3000h - mov bp, dat - mov [bp + in_callback - dat], 1 - push dx - push cx -; set ds:si -> ASCIIZ name - lea si, [di+6] -; set cx = limit in sectors; 4Kb = 8 sectors - movzx ecx, word [di+4] - shl cx, 3 -; set es:bx = pointer to buffer - les bx, [di] -; call our function - stc ; unsupported function - dec ax - jz callback_readfile - dec ax - jnz callback_ret - call continue_load_file - jmp callback_ret_succ -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call [bp + load_file_ptr - dat] -callback_ret_succ: - clc -callback_ret: -; restore caller's stack - pop cx - pop ss - mov sp, cx -; return to caller - retf - -read_file_chunk.resident: -; auxiliary label for read_file_chunk procedure - mov di, bx - lodsw -read_file_chunk.resident.continue: - mov dx, ax - add dx, 0x1FF - shr dx, 9 - cmp dx, cx - jbe @f - mov ax, cx - shl ax, 9 -@@: - xchg ax, cx - rep movsb - xchg ax, cx - clc ; no disk error if no disk requests - mov word [bp + num_sectors - dat], ax - ret - -read_file_chunk: -; in: ds:si -> file chunk -; in: es:bx -> buffer for output -; in: ecx = maximum number of sectors to read (high word must be 0) -; out: CF=1 <=> disk read error - lodsb - mov [bp + cur_chunk_resident - dat], al - test al, al - jz .resident -; normal case: load (non-resident) attribute from disk -.read_block: - lodsd - xchg eax, edx - test edx, edx - jz .ret - lodsd -; eax = start cluster, edx = number of clusters, cx = limit in sectors - imul eax, [bp + sect_per_clust - dat] - add eax, [bp + data_start - dat] - mov [bp + cur_cluster - dat], eax - imul edx, [bp + sect_per_clust - dat] - mov [bp + num_sectors - dat], edx - and [bp + cur_delta - dat], 0 -.nonresident.continue: - cmp edx, ecx - jb @f - mov edx, ecx -@@: - test dx, dx - jz .read_block - add [bp + cur_delta - dat], edx - sub [bp + num_sectors - dat], edx - sub ecx, edx - push cx - mov cx, dx - call read - pop cx - jc .ret - test cx, cx - jnz .read_block -.ret: - ret - -cache_lookup: -; in: eax = value to look, si = pointer to cache structure -; out: di->cache entry; CF=1 <=> the value was not found - push ds bx - push ss - pop ds - mov di, [si+2] -.look: - cmp di, si - jz .not_in_cache - cmp eax, [di+4] - jz .in_cache - mov di, [di+2] - jmp .look -.not_in_cache: -; cache miss -; cache is full? - mov di, [si+4] - cmp di, [si+6] - jnz .cache_not_full -; yes, delete the oldest entry - mov di, [si] - mov bx, [di] - mov [si], bx - push word [di+2] - pop word [bx+2] - jmp .cache_append -.cache_not_full: -; no, allocate new item - add word [si+4], 8 -.cache_append: - mov [di+4], eax - stc - jmp @f -.in_cache: -; delete this sector from the list - push si - mov si, [di] - mov bx, [di+2] - mov [si+2], bx - mov [bx], si - pop si -@@: -; add new sector to the end of list - mov bx, di - xchg bx, [si+2] - push word [bx] - pop word [di] - mov [bx], di - mov [di+2], bx - pop bx ds - ret - -include 'fat.inc' -include 'ntfs.inc' - -total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 -error_too_big db 'file is too big',0 -nodata_string db '$DATA ' -error_not_found db 'not found',0 -noindex_string db '$INDEX_ROOT not found',0 -badname_msg db 'bad name for FAT',0 -invalid_volume_msg db 'invalid volume',0 -mft_string db '$MFT',0 -fragmented_string db 'too fragmented file',0 -invalid_read_request_string db 'cannot read attribute',0 - -kernel_name db 'kernel.mnt',0 - -align 4 -dat: - -extended_part_start dd 0 ; start sector for main extended partition -extended_part_cur dd ? ; start sector for current extended child -extended_parent dd 0 ; start sector for current extended parent -partition_start dd 0 ; start sector for current logical disk -cur_partition_ofs dw ? ; offset in MBR data for current partition -sect_per_clust dd 0 -; change this variable if you want to boot from other physical drive -boot_drive db 80h -in_callback db 0 - -; uninitialized data -use_lba db ? -cur_chunk_resident db ? -align 2 -heads dw ? -sectors dw ? -cache1head rw 2 -cache1end dw ? -cache1limit dw ? -data_start dd ? -cachelimit dw ? -load_file_ptr dw ? -cur_obj dw ? -missing_slash dw ? -root_clus dd ? -root_start dd ? -get_next_cluster_ptr dw ? -frs_size dw ? -freeattr dw ? -index_root dw ? -index_alloc dw ? -cur_index_seg dw ? -cur_index_cache dw ? -filesize dd ? -filesize_sectors dd ? -cur_cluster dd ? -cur_delta dd ? -num_sectors dd ? -sectors_read dd ? -cur_chunk_ptr dw ? - -rootcache_size dw ? ; must be immediately before foldcache_clus -if $-dat >= 0x80 -warning: unoptimal data displacement! -end if -foldcache_clus rd 7 -foldcache_mark rw 7 -foldcache_size rw 7 -fat_filename rb 11 - -if $ > 2000h -error: file is too big -end if - -; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long -repeat 0x2600 - $ - db 2 ; any data can be here; 2 is another nice face in ASCII :) -end repeat +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond +; It is used when main bootloader is Windows loader. + +; this code is loaded: +; NT/2k/XP: by ntldr to 0D00:0000 +; 9x: by io.sys from config.sys to xxxx:0100 +; Vista: by bootmgr to 0000:7C00 + format binary + use16 + +; in any case, we relocate this code to 0000:0600 + org 0x600 +; entry point for 9x and Vista booting + call @f + db 'NTFS' +@@: + pop si + sub si, 3 + cmp si, 100h + jnz boot_vista + mov si, load_question + 100h - 600h + call out_string +; mov si, answer + 100h - 0600h ; already is +xxy: + mov ah, 0 + int 16h + or al, 20h + mov [si], al + cmp al, 'y' + jz xxz + cmp al, 'n' + jnz xxy +; continue load Windows +; call out_string +; ret +out_string: + push bx +@@: + lodsb + test al, al + jz @f + mov ah, 0Eh + mov bx, 7 + int 10h + jmp @b +@@: + pop bx + ret +xxz: +; boot KordOS + call out_string +; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, +; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached + xor di, di + mov ds, di + mov word [di+4], new01handler + 100h - 600h + mov [di+6], cs + pushf + pop ax + or ah, 1 + push ax + popf +; we cannot issue INT 19h directly, because INT command clears TF +; int 19h ; don't issue it directly, because INT command clears TF +; so instead we use direct call +; pushf ; there will be no IRET + call far [di + 19h*4] +xxt: + xor di, di + mov ds, di + cmp word [di + 8*4+2], 0F000h + jz @f + les bx, [di + 8*4] + mov eax, [es:bx+1] + mov [di + 8*4], eax +@@: + mov si, 100h +boot_vista: +; relocate cs:si -> 0000:0600 + push cs + pop ds + xor ax, ax + mov es, ax + mov di, 0x600 + mov cx, 2000h/2 + rep movsw + jmp 0:real_entry + +load_question db 'Load KordOS? [y/n]: ',0 +answer db ? + db 13,10,0 + +new01handler: +; [sp]=ip, [sp+2]=cs, [sp+4]=flags + push bp + mov bp, sp + push ds + lds bp, [bp+2] + cmp word [ds:bp], 19cdh + jz xxt + pop ds + pop bp + iret + +; read from hard disk +; in: eax = absolute sector +; cx = number of sectors +; es:bx -> buffer +; out: CF=1 if error +read: + pushad + add eax, [bp + partition_start - dat] + cmp [bp + use_lba - dat], 0 + jz .chs +; LBA read + push ds +.lbado: + push ax + push cx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + push 0 + push 0 + push eax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [bp + boot_drive - dat] + mov ah, 42h + int 13h + jc .disk_error_lba + add sp, 10h ; restore stack +; increase current sector & buffer; decrease number of sectors + movzx esi, cx + mov ax, es + shl cx, 5 + add ax, cx + mov es, ax + pop cx + pop ax + add eax, esi + sub cx, si + jnz .lbado + pop ds + popad + ret +.disk_error_lba: + add sp, 14h + pop ds + popad + stc + ret + +.chs: + pusha + pop edi ; loword(edi) = di, hiword(edi) = si + push bx + +; eax / (SectorsPerTrack) -> eax, remainder bx + movzx esi, [bp + sectors - dat] + xor edx, edx + div esi + mov bx, dx ; bx = sector-1 + +; eax -> dx:ax + push eax + pop ax + pop dx +; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx + div [bp + heads - dat] + +; number of sectors: read no more than to end of track + sub si, bx + cmp cx, si + jbe @f + mov cx, si +@@: + + inc bx +; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector +; convert to int13 format + movzx edi, cx + mov dh, dl + mov dl, [bp + boot_drive - dat] + shl ah, 6 + mov ch, al + mov al, cl + mov cl, bl + or cl, ah + pop bx + mov si, 3 + mov ah, 2 +@@: + push ax + int 13h + jnc @f + xor ax, ax + int 13h ; reset drive + pop ax + dec si + jnz @b + add sp, 12 + popad + stc + ret +@@: + pop ax + mov ax, es + mov cx, di + shl cx, 5 + add ax, cx + mov es, ax + push edi + popa + add eax, edi + sub cx, di + jnz .chs + popad + ret + +disk_error2 db 'Fatal: cannot read partitions info: ' +disk_error_msg db 'disk read error',0 +disk_params_msg db 'Fatal: cannot get drive parameters',0 +start_msg db 2,' KordOS bootloader',13,10,0 +part_msg db 'looking at partition ' +part_char db '0' ; will be incremented before writing message + db ' ... ',0 +errfs_msg db 'unknown filesystem',13,10,0 +fatxx_msg db 'FATxx' +newline db 13,10,0 +ntfs_msg db 'NTFS',13,10,0 +error_msg db 'Error' +colon db ': ',0 +root_string db '\',0 +nomem_msg db 'No memory',0 +filesys_string db '(filesystem)',0 +directory_string db 'is a directory',0 +notdir_string db 'not a directory',0 + +; entry point for NT/2k/XP booting +; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 + repeat 600h + 256h - $ + db 1 ; any data can be here; 1 in ASCII is a nice face :) + end repeat +; cs=es=0D00, ds=07C0, ss=0 +; esi=edi=ebp=0, esp=7C00 + xor si, si + jmp boot_vista + +real_entry: +; ax = 0 + mov ds, ax + mov es, ax +; our stack is 4 Kb: memory range 2000-3000 + mov ss, ax + mov sp, 3000h + mov bp, dat + sti ; just for case +; say hi to user + mov si, start_msg + call out_string +; we are booting from hard disk identified by [boot_drive] + mov dl, [bp + boot_drive - dat] +; is LBA supported? + mov [bp + use_lba - dat], 0 + mov ah, 41h + mov bx, 55AAh + int 13h + jc .no_lba + cmp bx, 0AA55h + jnz .no_lba + test cl, 1 + jz .no_lba + inc [bp + use_lba - dat] + jmp disk_params_ok +.no_lba: +; get drive geometry + mov ah, 8 + mov dl, [bp + boot_drive - dat] + int 13h + jnc @f + mov si, disk_params_msg + call out_string + jmp $ +@@: + movzx ax, dh + inc ax + mov [bp + heads - dat], ax + and cx, 3Fh + mov [bp + sectors - dat], cx +disk_params_ok: +; determine size of cache for folders + int 12h ; ax = size of available base memory in Kb + sub ax, 94000h / 1024 + jc nomem + shr ax, 3 + mov [bp + cachelimit - dat], ax ; size of cache - 1 +; scan all partitions +new_partition_ex: + xor eax, eax ; read first sector of current disk area + mov [bp + extended_part_cur - dat], eax ; no extended partition yet + mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition + push es + mov cx, 1 + mov bx, 3000h + call read + pop es + jnc new_partition + mov si, disk_error2 + call out_string + jmp $ +new_partition: + mov bx, [bp + cur_partition_ofs - dat] + mov al, [bx+4] ; partition type + test al, al + jz next_partition + cmp al, 5 + jz @f + cmp al, 0xF + jnz not_extended +@@: +; extended partition + mov eax, [bx+8] ; partition start + add eax, [bp + extended_part_start - dat] + mov [bp + extended_part_cur - dat], eax +next_partition: + add [bp + cur_partition_ofs - dat], 10h + cmp [bp + cur_partition_ofs - dat], 31FEh + jb new_partition + mov eax, [bp + extended_part_cur - dat] + test eax, eax + jz partitions_done + cmp [bp + extended_part_start - dat], 0 + jnz @f + mov [bp + extended_part_start - dat], eax +@@: + mov [bp + extended_parent - dat], eax + mov [bp + partition_start - dat], eax + jmp new_partition_ex +partitions_done: + mov si, total_kaput + call out_string + jmp $ +not_extended: + mov eax, [bx+8] + add eax, [bp + extended_parent - dat] + mov [bp + partition_start - dat], eax +; try to load from current partition +; inform user + mov si, part_msg + inc [si + part_char - part_msg] + call out_string +; read bootsector + xor eax, eax + mov [bp + cur_obj - dat], filesys_string + push es + mov cx, 1 + mov bx, 3200h + call read + pop es + mov si, disk_error_msg + jc find_error_si + movzx si, byte [bx+13] + mov word [bp + sect_per_clust - dat], si + test si, si + jz unknown_fs + lea ax, [si-1] + test si, ax + jnz unknown_fs +; determine file system +; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) + cmp word [bx+11], 0x200 + jnz unknown_fs +; is it NTFS? + cmp dword [bx+3], 'NTFS' + jnz not_ntfs + cmp byte [bx+16], bl + jz ntfs +not_ntfs: +; is it FAT? FAT12/FAT16/FAT32? +; get count of sectors to dword in cx:si + mov si, [bx+19] + xor cx, cx + test si, si + jnz @f + mov si, [bx+32] + mov cx, [bx+34] +@@: + xor eax, eax +; subtract size of system area + sub si, [bx+14] ; BPB_ResvdSecCnt + sbb cx, ax + mov ax, [bx+17] ; BPB_RootEntCnt + add ax, 0xF + rcr ax, 1 + shr ax, 3 + sub si, ax + sbb cx, 0 + push cx + push si + mov ax, word [bx+22] + test ax, ax + jnz @f + mov eax, [bx+36] +@@: + movzx ecx, byte [bx+16] + imul ecx, eax + pop eax + sub eax, ecx +; now eax = count of sectors in the data region + xor edx, edx + div [bp + sect_per_clust - dat] +; now eax = count of clusters in the data region + mov si, fatxx_msg + cmp eax, 0xFFF5 + jae test_fat32 +; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 + cmp byte [bx+38], 0x29 + jnz not_fat + cmp ax, 0xFF5 + jae fat16 +fat12: + mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster + mov di, cx ; BPB_NumFATs + mov ax, '12' + push ax ; save for secondary loader + mov word [si+3], ax + call out_string + movzx ecx, word [bx+22] ; BPB_FATSz16 +; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) +.fatloop: +; if first copy is not readable, try to switch to other copies + push 0x6000 + pop es + xor bx, bx + movzx eax, word [0x320E] ; BPB_RsvdSecCnt + push cx + cmp cx, 12 + jb @f + mov cx, 12 +@@: + call read + pop cx + jnc fat1x_common + add eax, ecx ; switch to next copy of FAT + dec di + jnz .fatloop + mov si, disk_error_msg + jmp find_error_si +fat16: + mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster + mov ax, '16' + push ax ; save for secondary loader + mov word [si+3], ax + call out_string +; FAT16: init FAT cache - no sectors loaded + mov di, 0x3400 + xor ax, ax + mov cx, 0x100/2 + rep stosw +fat1x_common: + mov bx, 0x3200 + movzx eax, word [bx+22] ; BPB_FATSz16 + xor esi, esi ; no root cluster + jmp fat_common +test_fat32: +; FAT32 bootsector has it at the offset +66 + cmp byte [bx+66], 0x29 + jnz not_fat + mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster + mov ax, '32' + push ax ; save for secondary loader + mov word [si+3], ax + call out_string +; FAT32 - init cache for FAT table: no sectors loaded + lea si, [bp + cache1head - dat] + mov [si], si ; no sectors in cache: + mov [si+2], si ; 'prev' & 'next' links point to self + mov [bp + cache1end - dat], 3400h ; first free item = 3400h + mov [bp + cache1limit - dat], 3C00h + mov eax, [bx+36] ; BPB_FATSz32 + mov esi, [bx+44] ; BPB_RootClus + jmp fat_common +not_fat: +unknown_fs: + mov si, errfs_msg + call out_string + jmp next_partition +fat_common: + push ss + pop es + movzx edx, byte [bx+16] ; BPB_NumFATs + mul edx + mov [bp + root_start - dat], eax ; this is for FAT1x +; eax = total size of all FAT tables, in sectors + movzx ecx, word [bx+17] ; BPB_RootEntCnt + add ecx, 0xF + shr ecx, 4 + add eax, ecx + mov cx, word [bx+14] ; BPB_RsvdSecCnt + add [bp + root_start - dat], ecx ; this is for FAT1x + add eax, ecx +; cluster 2 begins from sector eax + movzx ebx, byte [bx+13] ; BPB_SecPerClus + sub eax, ebx + sub eax, ebx + mov [bp + data_start - dat], eax +; no clusters in folders cache + mov di, foldcache_clus - 2 + xor ax, ax + mov cx, 7*8/2 + 1 + rep stosw + mov [bp + root_clus - dat], esi +; load secondary loader + mov [bp + load_file_ptr - dat], load_file_fat +load_secondary: + push 0x1000 + pop es + xor bx, bx + mov si, kernel_name + mov cx, 0x30000 / 0x200 + call [bp + load_file_ptr - dat] +; say error if needed + mov si, error_too_big + dec bx + js @f + jz find_error_si + mov si, disk_error_msg + jmp find_error_si +@@: +; fill loader information and jump to secondary loader + mov al, 'h' ; boot device: hard drive + mov ah, [bp + boot_drive - dat] + sub ah, 80h ; boot device: identifier + pop bx ; restore file system ID ('12'/'16'/'32'/'nt') + mov si, callback + jmp 1000h:0000h + +nomem: + mov si, nomem_msg + call out_string + jmp $ + +ntfs: + push 'nt' ; save for secondary loader + mov si, ntfs_msg + call out_string + xor eax, eax + mov [bp + data_start - dat], eax + mov ecx, [bx+40h] ; frs_size + cmp cl, al + jg .1 + neg cl + inc ax + shl eax, cl + jmp .2 +.1: + mov eax, ecx + shl eax, 9 +.2: + mov [bp + frs_size - dat], ax +; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different +; (at least with standard tools) +; we allow extra size, but no more than 0x1000 bytes = 4 Kb + mov si, invalid_volume_msg + cmp eax, 0x1000 + ja find_error_si +; must be multiple of sector size + test ax, 0x1FF + jnz find_error_si + shr ax, 9 + xchg cx, ax +; initialize cache - no data loaded + lea si, [bp + cache1head - dat] + mov [si], si + mov [si+2], si + mov word [si+4], 3400h ; first free item = 3400h + mov word [si+6], 3400h + 8*8 ; 8 items in this cache +; read first MFT record - description of MFT itself + mov [bp + cur_obj - dat], mft_string + mov eax, [bx+30h] ; mft_cluster + mul [bp + sect_per_clust - dat] + push 0x8000 + pop es + xor bx, bx + push es + call read + pop ds + call restore_usa +; scan for unnamed $DATA attribute + mov [bp + freeattr - dat], 4000h + mov ax, 80h + call load_attr + push ss + pop ds + mov si, nodata_string + jc find_error_si +; load secondary loader + mov [bp + load_file_ptr - dat], load_file_ntfs + jmp load_secondary + +find_error_si: + push si +find_error_sp: + cmp [bp + in_callback - dat], 0 + jnz error_in_callback + push ss + pop ds + push ss + pop es + mov si, error_msg + call out_string + mov si, [bp + cur_obj - dat] +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jz @f + mov ah, 0Eh + mov bx, 7 + int 10h + jmp @b +@@: + mov si, colon + call out_string + pop si + call out_string + mov si, newline + call out_string + mov sp, 0x3000 + jmp next_partition +error_in_callback: +; return status: file not found, except for read errors + mov bx, 2 + cmp si, disk_error_msg + jnz @f + inc bx +@@: + mov ax, 0xFFFF + mov dx, ax + mov sp, 3000h - 6 + ret + +callback: +; in: ax = function number; only functions 1 and 2 are defined for now +; save caller's stack + mov dx, ss + mov cx, sp +; set our stack (required because we need ss=0) + xor si, si + mov ss, si + mov sp, 3000h + mov bp, dat + mov [bp + in_callback - dat], 1 + push dx + push cx +; set ds:si -> ASCIIZ name + lea si, [di+6] +; set cx = limit in sectors; 4Kb = 8 sectors + movzx ecx, word [di+4] + shl cx, 3 +; set es:bx = pointer to buffer + les bx, [di] +; call our function + stc ; unsupported function + dec ax + jz callback_readfile + dec ax + jnz callback_ret + call continue_load_file + jmp callback_ret_succ +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call [bp + load_file_ptr - dat] +callback_ret_succ: + clc +callback_ret: +; restore caller's stack + pop cx + pop ss + mov sp, cx +; return to caller + retf + +read_file_chunk.resident: +; auxiliary label for read_file_chunk procedure + mov di, bx + lodsw +read_file_chunk.resident.continue: + mov dx, ax + add dx, 0x1FF + shr dx, 9 + cmp dx, cx + jbe @f + mov ax, cx + shl ax, 9 +@@: + xchg ax, cx + rep movsb + xchg ax, cx + clc ; no disk error if no disk requests + mov word [bp + num_sectors - dat], ax + ret + +read_file_chunk: +; in: ds:si -> file chunk +; in: es:bx -> buffer for output +; in: ecx = maximum number of sectors to read (high word must be 0) +; out: CF=1 <=> disk read error + lodsb + mov [bp + cur_chunk_resident - dat], al + test al, al + jz .resident +; normal case: load (non-resident) attribute from disk +.read_block: + lodsd + xchg eax, edx + test edx, edx + jz .ret + lodsd +; eax = start cluster, edx = number of clusters, cx = limit in sectors + imul eax, [bp + sect_per_clust - dat] + add eax, [bp + data_start - dat] + mov [bp + cur_cluster - dat], eax + imul edx, [bp + sect_per_clust - dat] + mov [bp + num_sectors - dat], edx + and [bp + cur_delta - dat], 0 +.nonresident.continue: + cmp edx, ecx + jb @f + mov edx, ecx +@@: + test dx, dx + jz .read_block + add [bp + cur_delta - dat], edx + sub [bp + num_sectors - dat], edx + sub ecx, edx + push cx + mov cx, dx + call read + pop cx + jc .ret + test cx, cx + jnz .read_block +.ret: + ret + +cache_lookup: +; in: eax = value to look, si = pointer to cache structure +; out: di->cache entry; CF=1 <=> the value was not found + push ds bx + push ss + pop ds + mov di, [si+2] +.look: + cmp di, si + jz .not_in_cache + cmp eax, [di+4] + jz .in_cache + mov di, [di+2] + jmp .look +.not_in_cache: +; cache miss +; cache is full? + mov di, [si+4] + cmp di, [si+6] + jnz .cache_not_full +; yes, delete the oldest entry + mov di, [si] + mov bx, [di] + mov [si], bx + push word [di+2] + pop word [bx+2] + jmp .cache_append +.cache_not_full: +; no, allocate new item + add word [si+4], 8 +.cache_append: + mov [di+4], eax + stc + jmp @f +.in_cache: +; delete this sector from the list + push si + mov si, [di] + mov bx, [di+2] + mov [si+2], bx + mov [bx], si + pop si +@@: +; add new sector to the end of list + mov bx, di + xchg bx, [si+2] + push word [bx] + pop word [di] + mov [bx], di + mov [di+2], bx + pop bx ds + ret + +include 'fat.inc' +include 'ntfs.inc' + +total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 +error_too_big db 'file is too big',0 +nodata_string db '$DATA ' +error_not_found db 'not found',0 +noindex_string db '$INDEX_ROOT not found',0 +badname_msg db 'bad name for FAT',0 +invalid_volume_msg db 'invalid volume',0 +mft_string db '$MFT',0 +fragmented_string db 'too fragmented file',0 +invalid_read_request_string db 'cannot read attribute',0 + +kernel_name db 'kernel.mnt',0 + +align 4 +dat: + +extended_part_start dd 0 ; start sector for main extended partition +extended_part_cur dd ? ; start sector for current extended child +extended_parent dd 0 ; start sector for current extended parent +partition_start dd 0 ; start sector for current logical disk +cur_partition_ofs dw ? ; offset in MBR data for current partition +sect_per_clust dd 0 +; change this variable if you want to boot from other physical drive +boot_drive db 80h +in_callback db 0 + +; uninitialized data +use_lba db ? +cur_chunk_resident db ? +align 2 +heads dw ? +sectors dw ? +cache1head rw 2 +cache1end dw ? +cache1limit dw ? +data_start dd ? +cachelimit dw ? +load_file_ptr dw ? +cur_obj dw ? +missing_slash dw ? +root_clus dd ? +root_start dd ? +get_next_cluster_ptr dw ? +frs_size dw ? +freeattr dw ? +index_root dw ? +index_alloc dw ? +cur_index_seg dw ? +cur_index_cache dw ? +filesize dd ? +filesize_sectors dd ? +cur_cluster dd ? +cur_delta dd ? +num_sectors dd ? +sectors_read dd ? +cur_chunk_ptr dw ? + +rootcache_size dw ? ; must be immediately before foldcache_clus +if $-dat >= 0x80 +warning: + unoptimal data displacement! +end if +foldcache_clus rd 7 +foldcache_mark rw 7 +foldcache_size rw 7 +fat_filename rb 11 + +if $ > 2000h +error: + file is too big +end if + +; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long +repeat 0x2600 - $ + db 2 ; any data can be here; 2 is another nice face in ASCII :) +end repeat diff --git a/kernel/trunk/bootloader/extended_primary_loader/after_win/ntfs.inc b/kernel/trunk/bootloader/extended_primary_loader/after_win/ntfs.inc index f92f13caa..413fe9907 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/after_win/ntfs.inc +++ b/kernel/trunk/bootloader/extended_primary_loader/after_win/ntfs.inc @@ -1,587 +1,587 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -restore_usa: -; Update Sequence Array restore -; in: ds:bx -> USA-protected structure - push bx - lea di, [bx+1feh] - mov cx, [bx+6] - add bx, [bx+4] - dec cx -@@: - mov ax, [bx+2] - mov [di], ax - inc bx - inc bx - add di, 200h - loop @b - pop bx - ret - -find_attr: -; in: ds:di->file record, ax=attribute -; out: ds:di->attribute or di=0 if not found - add di, [di+14h] -.1: -; attributes' codes are formally dwords, but all of them fit in word - cmp word [di], -1 - jz .notfound - cmp word [di], ax - jnz .continue -; for $DATA attribute, scan only unnamed - cmp ax, 80h - jnz .found - cmp byte [di+9], 0 - jz .found -.continue: - add di, [di+4] - jmp .1 -.notfound: - xor di, di -.found: - ret - -process_mcb_nonres: -; in: ds:si->attribute, es:di->buffer -; out: es:di->buffer end - pushad - pop di - add si, [si+20h] - xor ebx, ebx -.loop: - lodsb - test al, al - jz .done - push invalid_read_request_string - movzx cx, al - shr cx, 4 - jz find_error_sp - xchg ax, dx - and dx, 0Fh - jz find_error_sp - add si, cx - add si, dx - pop ax - push si - dec si - movsx eax, byte [si] - dec cx - jz .l1e -.l1: - dec si - shl eax, 8 - mov al, [si] - loop .l1 -.l1e: - xchg ebp, eax - dec si - movsx eax, byte [si] - mov cx, dx - dec cx - jz .l2e -.l2: - dec si - shl eax, 8 - mov al, byte [si] - loop .l2 -.l2e: - pop si - add ebx, ebp -; eax=length, ebx=disk block - stosd - mov eax, ebx - stosd - cmp di, 0x8000 - 12 - jbe .loop -..attr_overflow: - mov si, fragmented_string - jmp find_error_si -.done: - xor ax, ax - stosw - stosw - push di - popad - ret - -load_attr: -; in: ax=attribute, ds:bx->base record -; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, -; edx=size of attribute in bytes -; out: if not found: CF=1 - mov di, [bp + freeattr - dat] - push ss - pop es - mov byte [es:di], 1 - inc di - cmp di, 0x8000 - 12 - ja ..attr_overflow - or edx, -1 ; file size is not known yet -; scan for attribute - push di - mov di, bx - add di, [di+14h] -@@: - call find_attr.1 - test di, di - jz .notfound1 - cmp byte [di+8], 0 - jnz .nonresident - mov si, di - pop di - push ds - jmp .resident -.aux_resident: - mov ax, ds - mov si, di - pop di ds bx ds edx - push ss - pop es - push ds - mov ds, ax -; resident attribute -.resident: - dec di - mov al, 0 - stosb - mov ax, [si+10h] - stosw - push di - add di, ax - cmp di, 0x8000 - 12 - pop di - ja ..attr_overflow - movzx edx, ax ; length of attribute - xchg ax, cx - add si, [si+14h] - rep movsb - mov [bp + freeattr - dat], di - pop ds - ret -.nonresident: -; nonresident attribute - cmp dword [di+10h], 0 - jnz @b -; read start of data - mov si, di - mov edx, [di+30h] ; size of attribute - pop di - call process_mcb_nonres - sub di, 4 - push di -.notfound1: - pop di - push edx -; $ATTRIBUTE_LIST is always in base file record - cmp ax, 20h - jz .nofragmented -; try to load $ATTRIBUTE_LIST = 20h - push ax - mov ax, 20h - push [bp + freeattr - dat] - mov [bp + freeattr - dat], di - push di - call load_attr - pop di - pop [bp + freeattr - dat] - pop ax - jc .nofragmented - push ds bx - pusha - mov si, di - push ss - pop ds - push 0x8100 - pop es - xor ecx, ecx - mov cl, 0x78 - xor bx, bx - push es - call read_file_chunk - pop ds - jc ..found_disk_error - test cx, cx - jz ..attr_overflow - popa - push ss - pop es - xor bx, bx -.1: - cmp [bx], ax - jnz .continue1 -; only unnamed $DATA attributes! - cmp ax, 80h - jnz @f - cmp byte [bx+6], 0 - jnz .continue1 -@@: - cmp dword [bx+10h], 0 - jz .continue1 - cmp dword [bx+8], 0 - jnz @f - dec di - cmp di, [bp + freeattr - dat] - lea di, [di+1] - jnz .continue1 -@@: - push ds di - push ax - mov eax, [bx+10h] - mov ecx, [bx+8] - call read_file_record - pop ax - mov di, [14h] -.2: - call find_attr.1 - cmp byte [di+8], 0 - jz .aux_resident - cmp dword [di+10h], ecx - jnz .2 - mov si, di - mov di, sp - cmp dword [ss:di+8], -1 - jnz @f - push dword [si+30h] ; size of attribute - pop dword [ss:di+8] -@@: - pop di - call process_mcb_nonres - sub di, 4 - pop ds -.continue1: - add bx, [bx+4] - cmp bx, dx - jb .1 - pop bx ds -.nofragmented: - pop edx - dec di - cmp di, [bp + freeattr - dat] - jnz @f - stc - ret -@@: - inc di - xor ax, ax - stosw - stosw - mov [bp + freeattr - dat], di - ret - -read_file_record: -; in: eax = index of record -; out: ds:0 -> record -; find place in cache - push di - push si - mov si, cache1head - call cache_lookup - pop si - pushf - sub di, 3400h - shl di, 10-3 - add di, 0x6000 - mov ds, di - popf - pop di - jnc .noread -; read file record to ds:0 - pushad - push ds - push es - movzx ecx, [bp + frs_size - dat] - shr cx, 9 - mul ecx - push ds - pop es - push ss - pop ds - mov si, 0x4000 - xor bx, bx - push [bp + cur_obj - dat] - mov [bp + cur_obj - dat], mft_string - push es - call read_attr -; initialize cache for $INDEX_ALLOCATION for this record - pop si - push si - sub si, 0x6000 - mov ax, si - shr si, 10-3 - shr ax, 2 - add si, 3480h - add ax, 3500h - mov [si], si - mov [si+2], si - mov [si+4], ax - pop ds - call restore_usa - pop [bp + cur_obj - dat] - pop es - pop ds - popad -.noread: - ret - -read_attr: -; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute - push invalid_read_request_string - cmp byte [si], 0 - jnz .nonresident - cmp eax, 10000h shr 9 - jae find_error_sp - shl ax, 9 - shl cx, 9 - cmp ax, [si+2] - jae find_error_sp - cmp cx, [si+2] - ja find_error_sp - add si, 3 - add si, ax - mov di, bx - rep movsb - pop ax - ret -.nonresident: - inc si -.loop: - mov edx, dword [si] - add si, 8 - test edx, edx - jz find_error_sp - imul edx, [bp + sect_per_clust - dat] - sub eax, edx - jnc .loop - add eax, edx - sub edx, eax - push cx - cmp ecx, edx - jb @f - mov cx, dx -@@: - push bx - mov ebx, [si-4] - imul ebx, [bp + sect_per_clust - dat] - add eax, ebx - pop bx - call read - jc ..found_disk_error - mov dx, cx - pop cx - xor eax, eax - sub cx, dx - jnz .loop - pop ax - ret - -load_file_ntfs: -; in: ss:bp = 0:dat -; in: es:bx = address to load file -; in: ds:si -> ASCIIZ name -; in: cx = limit in sectors -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) - push es bx cx - mov eax, 5 ; root cluster - mov [bp + cur_obj - dat], root_string -.parse_dir_loop: - push ds si - call read_file_record -; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP - mov ax, [bp + freeattr - dat] - mov [bp + index_root - dat], ax - mov ax, 90h ; $INDEX_ROOT - xor bx, bx - call load_attr - mov si, noindex_string - jc find_error_si - mov ax, [bp + freeattr - dat] - mov [bp + index_alloc - dat], ax - mov ax, 0A0h ; $INDEX_ALLOCATION - call load_attr - jnc @f - mov [bp + index_alloc - dat], bx -@@: - push ds -; search for entry - mov si, [bp + index_root - dat] - push ss - pop ds - push 0x8100 - pop es - xor ecx, ecx - mov cl, 0x78 - xor bx, bx - push es - call read_file_chunk - pop ds - jc ..found_disk_error - test cx, cx - jz ..attr_overflow - mov si, invalid_read_request_string - cmp word [bx+10], 0 - jnz find_error_si -; calculate number of items in cache - mov di, [bx+8] ; subnode_size - mov ax, 0x4000 - sub ax, word [bp + frs_size - dat] - cwd - div di - test ax, ax - jz find_error_si - mov si, invalid_volume_msg - test di, 0x1FF - jnz find_error_si - pop cx - mov [bp + cur_index_seg - dat], cx - shl ax, 3 - sub cx, 6000h - mov si, cx - shr cx, 2 - shr si, 10-3 - add cx, ax - add si, 3480h - mov [bp + cur_index_cache - dat], si - add cx, 3500h - mov [ss:si+6], cx - mov dx, di - add bx, 10h -.scan_record: - add bx, [bx] -.scan: - test byte [bx+0Ch], 2 - jnz .look_child - movzx cx, byte [bx+50h] ; namelen - lea di, [bx+52h] ; name - push ds - pop es - pop si ds - push ds si - xor ax, ax -.1: - lodsb - cmp al, '/' - jnz @f - mov al, 0 -@@: - cmp al, 'A' - jb .nocapital - cmp al, 'Z' - ja .nocapital - or al, 20h -.nocapital: - cmp al, 'a' - jb .notletter - cmp al, 'z' - ja .notletter - or byte [es:di], 20h -.notletter: - scasw - loopz .1 - jb .look_child - ja @f - cmp byte [si], 0 - jz .file_found - cmp byte [si], '/' - jz .file_found -@@: - push es - pop ds - add bx, [bx+8] - jmp .scan -.look_child: - push es - pop ds - test byte [bx+0Ch], 1 - jz .not_found - mov si, [bp + index_alloc - dat] - test si, si - jz .not_found - add bx, [bx+8] - mov eax, [bx-8] - mov es, [bp + cur_index_seg - dat] - push si - mov si, [bp + cur_index_cache - dat] - call cache_lookup - pop si - pushf - mov bx, di - mov bh, 0 - shr bx, 3 - imul bx, dx - add bx, [bp + frs_size - dat] - popf - jnc .noread - push es - push dx - push ss - pop ds - movzx ecx, dx - shr cx, 9 - mul [bp + sect_per_clust - dat] - call read_attr - pop dx - pop es - push es - pop ds - call restore_usa -.noread: - push es - pop ds - add bx, 18h - jmp .scan_record -.not_found: - pop [bp + cur_obj - dat] - mov si, error_not_found - jmp find_error_si -.file_found: - pop [bp + cur_obj - dat] - pop cx - mov ax, [bp + index_root - dat] - mov [bp + freeattr - dat], ax - mov eax, [es:bx] - test byte [es:bx+48h+3], 10h - jz .regular_file - cmp byte [si], 0 - jz ..directory_error - inc si - jmp .parse_dir_loop -.regular_file: - cmp byte [si], 0 - jnz ..notdir_error -; read entry - call read_file_record - xor bx, bx - mov ax, 80h - call load_attr - mov si, nodata_string - jc find_error_si - mov si, [bp + index_root - dat] - mov [bp + freeattr - dat], si - push ss - pop ds - jmp load_file_common_end +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +restore_usa: +; Update Sequence Array restore +; in: ds:bx -> USA-protected structure + push bx + lea di, [bx+1feh] + mov cx, [bx+6] + add bx, [bx+4] + dec cx +@@: + mov ax, [bx+2] + mov [di], ax + inc bx + inc bx + add di, 200h + loop @b + pop bx + ret + +find_attr: +; in: ds:di->file record, ax=attribute +; out: ds:di->attribute or di=0 if not found + add di, [di+14h] +.1: +; attributes' codes are formally dwords, but all of them fit in word + cmp word [di], -1 + jz .notfound + cmp word [di], ax + jnz .continue +; for $DATA attribute, scan only unnamed + cmp ax, 80h + jnz .found + cmp byte [di+9], 0 + jz .found +.continue: + add di, [di+4] + jmp .1 +.notfound: + xor di, di +.found: + ret + +process_mcb_nonres: +; in: ds:si->attribute, es:di->buffer +; out: es:di->buffer end + pushad + pop di + add si, [si+20h] + xor ebx, ebx +.loop: + lodsb + test al, al + jz .done + push invalid_read_request_string + movzx cx, al + shr cx, 4 + jz find_error_sp + xchg ax, dx + and dx, 0Fh + jz find_error_sp + add si, cx + add si, dx + pop ax + push si + dec si + movsx eax, byte [si] + dec cx + jz .l1e +.l1: + dec si + shl eax, 8 + mov al, [si] + loop .l1 +.l1e: + xchg ebp, eax + dec si + movsx eax, byte [si] + mov cx, dx + dec cx + jz .l2e +.l2: + dec si + shl eax, 8 + mov al, byte [si] + loop .l2 +.l2e: + pop si + add ebx, ebp +; eax=length, ebx=disk block + stosd + mov eax, ebx + stosd + cmp di, 0x8000 - 12 + jbe .loop +..attr_overflow: + mov si, fragmented_string + jmp find_error_si +.done: + xor ax, ax + stosw + stosw + push di + popad + ret + +load_attr: +; in: ax=attribute, ds:bx->base record +; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, +; edx=size of attribute in bytes +; out: if not found: CF=1 + mov di, [bp + freeattr - dat] + push ss + pop es + mov byte [es:di], 1 + inc di + cmp di, 0x8000 - 12 + ja ..attr_overflow + or edx, -1 ; file size is not known yet +; scan for attribute + push di + mov di, bx + add di, [di+14h] +@@: + call find_attr.1 + test di, di + jz .notfound1 + cmp byte [di+8], 0 + jnz .nonresident + mov si, di + pop di + push ds + jmp .resident +.aux_resident: + mov ax, ds + mov si, di + pop di ds bx ds edx + push ss + pop es + push ds + mov ds, ax +; resident attribute +.resident: + dec di + mov al, 0 + stosb + mov ax, [si+10h] + stosw + push di + add di, ax + cmp di, 0x8000 - 12 + pop di + ja ..attr_overflow + movzx edx, ax ; length of attribute + xchg ax, cx + add si, [si+14h] + rep movsb + mov [bp + freeattr - dat], di + pop ds + ret +.nonresident: +; nonresident attribute + cmp dword [di+10h], 0 + jnz @b +; read start of data + mov si, di + mov edx, [di+30h] ; size of attribute + pop di + call process_mcb_nonres + sub di, 4 + push di +.notfound1: + pop di + push edx +; $ATTRIBUTE_LIST is always in base file record + cmp ax, 20h + jz .nofragmented +; try to load $ATTRIBUTE_LIST = 20h + push ax + mov ax, 20h + push [bp + freeattr - dat] + mov [bp + freeattr - dat], di + push di + call load_attr + pop di + pop [bp + freeattr - dat] + pop ax + jc .nofragmented + push ds bx + pusha + mov si, di + push ss + pop ds + push 0x8100 + pop es + xor ecx, ecx + mov cl, 0x78 + xor bx, bx + push es + call read_file_chunk + pop ds + jc ..found_disk_error + test cx, cx + jz ..attr_overflow + popa + push ss + pop es + xor bx, bx +.1: + cmp [bx], ax + jnz .continue1 +; only unnamed $DATA attributes! + cmp ax, 80h + jnz @f + cmp byte [bx+6], 0 + jnz .continue1 +@@: + cmp dword [bx+10h], 0 + jz .continue1 + cmp dword [bx+8], 0 + jnz @f + dec di + cmp di, [bp + freeattr - dat] + lea di, [di+1] + jnz .continue1 +@@: + push ds di + push ax + mov eax, [bx+10h] + mov ecx, [bx+8] + call read_file_record + pop ax + mov di, [14h] +.2: + call find_attr.1 + cmp byte [di+8], 0 + jz .aux_resident + cmp dword [di+10h], ecx + jnz .2 + mov si, di + mov di, sp + cmp dword [ss:di+8], -1 + jnz @f + push dword [si+30h] ; size of attribute + pop dword [ss:di+8] +@@: + pop di + call process_mcb_nonres + sub di, 4 + pop ds +.continue1: + add bx, [bx+4] + cmp bx, dx + jb .1 + pop bx ds +.nofragmented: + pop edx + dec di + cmp di, [bp + freeattr - dat] + jnz @f + stc + ret +@@: + inc di + xor ax, ax + stosw + stosw + mov [bp + freeattr - dat], di + ret + +read_file_record: +; in: eax = index of record +; out: ds:0 -> record +; find place in cache + push di + push si + mov si, cache1head + call cache_lookup + pop si + pushf + sub di, 3400h + shl di, 10-3 + add di, 0x6000 + mov ds, di + popf + pop di + jnc .noread +; read file record to ds:0 + pushad + push ds + push es + movzx ecx, [bp + frs_size - dat] + shr cx, 9 + mul ecx + push ds + pop es + push ss + pop ds + mov si, 0x4000 + xor bx, bx + push [bp + cur_obj - dat] + mov [bp + cur_obj - dat], mft_string + push es + call read_attr +; initialize cache for $INDEX_ALLOCATION for this record + pop si + push si + sub si, 0x6000 + mov ax, si + shr si, 10-3 + shr ax, 2 + add si, 3480h + add ax, 3500h + mov [si], si + mov [si+2], si + mov [si+4], ax + pop ds + call restore_usa + pop [bp + cur_obj - dat] + pop es + pop ds + popad +.noread: + ret + +read_attr: +; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute + push invalid_read_request_string + cmp byte [si], 0 + jnz .nonresident + cmp eax, 10000h shr 9 + jae find_error_sp + shl ax, 9 + shl cx, 9 + cmp ax, [si+2] + jae find_error_sp + cmp cx, [si+2] + ja find_error_sp + add si, 3 + add si, ax + mov di, bx + rep movsb + pop ax + ret +.nonresident: + inc si +.loop: + mov edx, dword [si] + add si, 8 + test edx, edx + jz find_error_sp + imul edx, [bp + sect_per_clust - dat] + sub eax, edx + jnc .loop + add eax, edx + sub edx, eax + push cx + cmp ecx, edx + jb @f + mov cx, dx +@@: + push bx + mov ebx, [si-4] + imul ebx, [bp + sect_per_clust - dat] + add eax, ebx + pop bx + call read + jc ..found_disk_error + mov dx, cx + pop cx + xor eax, eax + sub cx, dx + jnz .loop + pop ax + ret + +load_file_ntfs: +; in: ss:bp = 0:dat +; in: es:bx = address to load file +; in: ds:si -> ASCIIZ name +; in: cx = limit in sectors +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) + push es bx cx + mov eax, 5 ; root cluster + mov [bp + cur_obj - dat], root_string +.parse_dir_loop: + push ds si + call read_file_record +; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP + mov ax, [bp + freeattr - dat] + mov [bp + index_root - dat], ax + mov ax, 90h ; $INDEX_ROOT + xor bx, bx + call load_attr + mov si, noindex_string + jc find_error_si + mov ax, [bp + freeattr - dat] + mov [bp + index_alloc - dat], ax + mov ax, 0A0h ; $INDEX_ALLOCATION + call load_attr + jnc @f + mov [bp + index_alloc - dat], bx +@@: + push ds +; search for entry + mov si, [bp + index_root - dat] + push ss + pop ds + push 0x8100 + pop es + xor ecx, ecx + mov cl, 0x78 + xor bx, bx + push es + call read_file_chunk + pop ds + jc ..found_disk_error + test cx, cx + jz ..attr_overflow + mov si, invalid_read_request_string + cmp word [bx+10], 0 + jnz find_error_si +; calculate number of items in cache + mov di, [bx+8] ; subnode_size + mov ax, 0x4000 + sub ax, word [bp + frs_size - dat] + cwd + div di + test ax, ax + jz find_error_si + mov si, invalid_volume_msg + test di, 0x1FF + jnz find_error_si + pop cx + mov [bp + cur_index_seg - dat], cx + shl ax, 3 + sub cx, 6000h + mov si, cx + shr cx, 2 + shr si, 10-3 + add cx, ax + add si, 3480h + mov [bp + cur_index_cache - dat], si + add cx, 3500h + mov [ss:si+6], cx + mov dx, di + add bx, 10h +.scan_record: + add bx, [bx] +.scan: + test byte [bx+0Ch], 2 + jnz .look_child + movzx cx, byte [bx+50h] ; namelen + lea di, [bx+52h] ; name + push ds + pop es + pop si ds + push ds si + xor ax, ax +.1: + lodsb + cmp al, '/' + jnz @f + mov al, 0 +@@: + cmp al, 'A' + jb .nocapital + cmp al, 'Z' + ja .nocapital + or al, 20h +.nocapital: + cmp al, 'a' + jb .notletter + cmp al, 'z' + ja .notletter + or byte [es:di], 20h +.notletter: + scasw + loopz .1 + jb .look_child + ja @f + cmp byte [si], 0 + jz .file_found + cmp byte [si], '/' + jz .file_found +@@: + push es + pop ds + add bx, [bx+8] + jmp .scan +.look_child: + push es + pop ds + test byte [bx+0Ch], 1 + jz .not_found + mov si, [bp + index_alloc - dat] + test si, si + jz .not_found + add bx, [bx+8] + mov eax, [bx-8] + mov es, [bp + cur_index_seg - dat] + push si + mov si, [bp + cur_index_cache - dat] + call cache_lookup + pop si + pushf + mov bx, di + mov bh, 0 + shr bx, 3 + imul bx, dx + add bx, [bp + frs_size - dat] + popf + jnc .noread + push es + push dx + push ss + pop ds + movzx ecx, dx + shr cx, 9 + mul [bp + sect_per_clust - dat] + call read_attr + pop dx + pop es + push es + pop ds + call restore_usa +.noread: + push es + pop ds + add bx, 18h + jmp .scan_record +.not_found: + pop [bp + cur_obj - dat] + mov si, error_not_found + jmp find_error_si +.file_found: + pop [bp + cur_obj - dat] + pop cx + mov ax, [bp + index_root - dat] + mov [bp + freeattr - dat], ax + mov eax, [es:bx] + test byte [es:bx+48h+3], 10h + jz .regular_file + cmp byte [si], 0 + jz ..directory_error + inc si + jmp .parse_dir_loop +.regular_file: + cmp byte [si], 0 + jnz ..notdir_error +; read entry + call read_file_record + xor bx, bx + mov ax, 80h + call load_attr + mov si, nodata_string + jc find_error_si + mov si, [bp + index_root - dat] + mov [bp + freeattr - dat], si + push ss + pop ds + jmp load_file_common_end diff --git a/kernel/trunk/bootloader/extended_primary_loader/cdfs/bootsect.asm b/kernel/trunk/bootloader/extended_primary_loader/cdfs/bootsect.asm index c89becbda..4694e005e 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/cdfs/bootsect.asm +++ b/kernel/trunk/bootloader/extended_primary_loader/cdfs/bootsect.asm @@ -1,1024 +1,1024 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - - jmp far 0:real_start -; special text -org $+0x7C00 -real_start: -; initialize - xor ax, ax - mov ss, ax - mov sp, 0x7C00 - mov ds, ax - mov es, ax - cld - sti - mov [bootdrive], dl -; check LBA support - mov ah, 41h - mov bx, 55AAh - int 13h - mov si, aNoLBA - jc err_ - cmp bx, 0AA55h - jnz err_ - test cl, 1 - jz err_ -; get file system information -; scan for Primary Volume Descriptor - db 66h - push 10h-1 - pop eax -pvd_scan_loop: - mov cx, 1 - inc eax - mov bx, 0x1000 - call read_sectors - jnc @f -fatal_read_err: - mov si, aReadError -err_: - call out_string - mov si, aPressAnyKey - call out_string - xor ax, ax - int 16h - int 18h - jmp $ -@@: - push ds - pop es - cmp word [bx+1], 'CD' - jnz pvd_scan_loop - cmp word [bx+3], '00' - jnz pvd_scan_loop - cmp byte [bx+5], '1' - jnz pvd_scan_loop -; we have found ISO9660 descriptor, look for type - cmp byte [bx], 1 ; Primary Volume Descriptor? - jz pvd_found - cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? - jnz pvd_scan_loop -; Volume Descriptor Set Terminator reached, no PVD found - fatal error - mov si, no_pvd - jmp err_ -pvd_found: - add bx, 80h - mov ax, [bx] - mov [lb_size], ax -; calculate number of logical blocks in one sector - mov ax, 800h - cwd - div word [bx] - mov [lb_per_sec], ax -; get location of root directory - mov di, root_location - movzx eax, byte [bx+1Dh] - add eax, [bx+1Eh] - stosd -; get memory size - int 12h - mov si, nomem_str - cmp ax, 71000h / 400h - jb err_ - shr ax, 1 - sub ax, 60000h / 800h - mov [size_rest], ax - mov [free_ptr], 60000h / 800h -; load path table -; if size > 62K => it's very strange, avoid using it -; if size > (size of cache)/2 => avoid using it too - mov ecx, [bx+4] - cmp ecx, 0x10000 - 0x800 - ja nopathtable - shr ax, 1 - cmp ax, 0x20 - jae @f - shl ax, 11 - cmp cx, ax - ja nopathtable -@@: -; size is ok, try to load it - mov [pathtable_size], cx - mov eax, [bx+12] - xor edx, edx - div dword [lb_per_sec] - imul dx, [bx] - mov [pathtable_start], dx - add cx, dx - call cx_to_sectors - xor bx, bx - push 6000h - pop es - call read_sectors - jc nopathtable -; path table has been loaded - inc [use_path_table] - sub [size_rest], cx - add [free_ptr], cx -nopathtable: -; init cache - mov ax, [size_rest] - mov [cache_size], ax - mov ax, [free_ptr] - mov [cache_start], ax -; load secondary loader - mov di, secondary_loader_info - call load_file - test bx, bx - jnz noloader -; set registers for secondary loader - mov ah, [bootdrive] - mov al, 'c' - mov bx, 'is' - mov si, callback - jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 - -noloader: - mov si, aKernelNotFound - jmp err_ - -read_sectors: -; es:bx = pointer to data -; eax = first sector -; cx = number of sectors - pushad - push ds -do_read_sectors: - push ax - push cx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - db 66h - push 0 - push eax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [cs:bootdrive] - mov ah, 42h - int 13h - jc diskreaderr -; restore stack - add sp, 10h -; increase current sector & buffer; decrease number of sectors - movzx esi, cx - mov ax, es - shl cx, 7 - add ax, cx - mov es, ax - pop cx - pop ax - add eax, esi - sub cx, si - jnz do_read_sectors - pop ds - popad - ret -diskreaderr: - add sp, 10h + 2*2 - pop ds - popad - stc -out_string.ret: - ret - -out_string: -; in: ds:si -> ASCIIZ string - lodsb - test al, al - jz .ret - mov ah, 0Eh - mov bx, 7 - int 10h - jmp out_string - -aNoLBA db 'The drive does not support LBA!',0 -aReadError db 'Read error',0 -no_pvd db 'Primary Volume Descriptor not found!',0 -nomem_str db 'No memory',0 -aPressAnyKey db 13,10,'Press any key...',13,10,0 - -load_file: -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) -; parse path to the file - lea si, [di+6] - mov eax, [cs:root_location] - cmp [cs:use_path_table], 0 - jz parse_dir -; scan for path in path table - push di - push 6000h - pop es - mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table - mov dx, 1 ; dx = number of current entry in path table, start from 1 - mov cx, [cs:pathtable_size] -pathtable_newparent: - mov bx, dx ; bx = number of current parent in path table: root = 1 -scan_path_table_e: - call is_last_component - jnc path_table_scanned -scan_path_table_i: - cmp word [es:di+6], bx - jb .next - ja path_table_notfound - call test_filename1 - jc .next -@@: - lodsb - cmp al, '/' - jnz @b - jmp pathtable_newparent -.next: -; go to next entry - inc dx - movzx ax, byte [es:di] - add ax, 8+1 - and al, not 1 - add di, ax - sub cx, ax - ja scan_path_table_i -path_table_notfound: - pop di - mov ax, -1 - mov dx, ax - mov bx, 2 ; file not found - ret -path_table_scanned: - movzx eax, byte [es:di+1] - add eax, [es:di+2] - pop di -parse_dir: -; eax = logical block, ds:di -> information structure, ds:si -> file name -; was the folder already read? - push di ds - push cs - pop ds - mov [cur_desc_end], 2000h - mov bx, cachelist -.scan1: - mov bx, [bx+2] - cmp bx, cachelist - jz .notfound - cmp [bx+4], eax - jnz .scan1 -.found: -; yes; delete this item from the list (the following code will append this item to the tail) - mov di, [bx] - push word [bx+2] - pop word [di+2] - mov di, [bx+2] - push word [bx] - pop word [di] - mov di, bx - jmp .scan -.notfound: -; no; load first sector of the folder to get its size - push eax - push si - mov si, 1 - call load_phys_sector_for_lb_force - mov bx, si - pop si - pop eax - jnc @f -; read error - return -.readerr: - pop ds -.readerr2: - pop di - mov ax, -1 - mov dx, ax - mov bx, 3 - ret -@@: -; first item of the folder describes the folder itself -; do not cache too big folders: size < 64K and size <= (total cache size)/2 - cmp word [bx+12], 0 - jnz .nocache - mov cx, [cache_size] ; cx = cache size in sectors - shr cx, 1 ; cx = (cache size)/2 - cmp cx, 0x20 - jae @f - shl cx, 11 - cmp [bx+10], cx - ja .nocache -@@: -; we want to cache this folder; get space for it - mov cx, [bx+10] - call cx_to_sectors - jnz .yescache -.nocache: - push dword [bx+10] - pop dword [cur_nocache_len] - call lb_to_sector - push ds - pop es - pop ds -.nocache_loop: - push eax - mov dx, 1800h - call scan_for_filename_in_sector - mov cx, dx - pop eax - jnc .j_scandone - sub cx, bx - sub word [es:cur_nocache_len], cx - sbb word [es:cur_nocache_len+2], 0 - jb .j_scandone - ja @f - cmp word [es:cur_nocache_len], 0 - jz .j_scandone -@@: - mov cx, 1 - inc eax - push es - mov bx, 1000h - call read_sectors - pop es - jc .readerr2 - jmp .nocache_loop -.j_scandone: - jmp .scandone -.yescache: - push bx - mov bx, [cachelist.head] -.freeloop: - cmp cx, [size_rest] - jbe .sizeok -@@: -; if we are here: there is not enough free space, so we must delete old folders' data -; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). -; one loop iteration: delete data of one folder - pusha - mov dx, [bx+10] - mov es, dx ; es = segment of folder data to be deleted - xor di, di - mov ax, [bx+8] - add ax, 0x7FF - rcr ax, 1 - shr ax, 10 - push ax - shl ax, 11-4 ; get number of paragraphs in folder data to be deleted - mov cx, [cache_size] - add cx, [cache_start] - push ds - push ax - add ax, dx - mov ds, ax - pop ax - shl cx, 11-4 - sub cx, dx ; cx = number of paragraphs to be moved - push si - xor si, si -; move cx paragraphs from ds:si to es:di to get free space in the end of cache -@@: - sub cx, 1000h - jbe @f - push cx - mov cx, 8000h - rep movsw - mov cx, ds - add cx, 1000h - mov ds, cx - mov cx, es - add cx, 1000h - mov es, cx - pop cx - jmp @b -@@: - add cx, 1000h - shl cx, 3 - rep movsw - pop si - pop ds -; correct positions in cache for existing items - mov cx, 80h - mov di, 8400h -.correct: - cmp [di+10], dx - jbe @f - sub [di+10], ax -@@: - add di, 12 - loop .correct -; some additional space is free now - pop ax - add [size_rest], ax - sub [free_ptr], ax -; add cache item to the list of free items - mov dx, [bx] - mov ax, [free_cache_item] - mov [bx], ax - mov [free_cache_item], bx - mov bx, dx -; current iteration done - popa - jmp .freeloop -.sizeok: - mov [cachelist.head], bx - mov word [bx+2], cachelist -; allocate new item in cache - mov di, [free_cache_item] - test di, di - jz .nofree - push word [di] - pop [free_cache_item] - jmp @f -.nofree: - mov di, [last_cache_item] - add [last_cache_item], 12 -@@: - pop bx - push si di -; mov [di+4], eax ; start of folder - scasd - stosd - push ax - mov ax, [free_ptr] - shl ax, 11-4 - mov [di+10-8], ax - mov es, ax - pop ax - add [free_ptr], cx - sub [size_rest], cx -; read folder data -; first sector is already in memory, 0000:bx - pusha - mov cx, [bx+10] - mov [di+8-8], cx ; folder size in bytes - mov si, bx - xor di, di - mov cx, 0x1800 - sub cx, si - rep movsb - pop ax - push di - popa -; read rest of folder - mov esi, dword [lb_per_sec] - add eax, esi - dec si - not si - and ax, si - mov si, word [bx+10] - mov bx, di - pop di - sub si, bx - jbe @f - mov [cur_limit], esi - call read_many_bytes - pop si - jnc .scan - jmp .readerr -@@: - pop si -.scan: -; now we have required cache item; append it to the end of list - mov bx, [cachelist.tail] - mov [cachelist.tail], di - mov [di+2], bx - mov word [di], cachelist - mov [bx], di -; scan for given filename - mov es, [di+10] - mov dx, [di+8] - pop ds - xor bx, bx - call scan_for_filename_in_sector -.scandone: - push cs - pop es - mov bx, 2000h - cmp bx, [es:cur_desc_end] - jnz filefound -j_notfound: - jmp path_table_notfound -filefound: -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jnz @b -@@: - mov cl, [es:bx+8] - test al, al - jz @f -; parse next component of file name - test cl, 2 ; directory? - jz j_notfound - mov eax, [es:bx] - pop di - jmp parse_dir -@@: - test cl, 2 ; directory? - jnz j_notfound ; do not allow read directories as regular files -; ok, now load the file - pop di - les bx, [di] - call normalize - movzx esi, word [di+4] ; esi = limit in 4K blocks - shl esi, 12 ; esi = limit in bytes - push cs - pop ds - mov [cur_limit], esi - mov di, 2000h -loadloop: - and [cur_start], 0 -.loadnew: - mov esi, [cur_limit] - mov eax, [cur_start] - add esi, eax - mov [overflow], 1 - sub esi, [di+4] - jb @f - xor esi, esi - dec [overflow] -@@: - add esi, [di+4] ; esi = number of bytes to read - mov [cur_start], esi - sub esi, eax - jz .loadcontinue - xor edx, edx - div dword [lb_size] ; eax = number of logical blocks to skip, - mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block - cmp byte [di+10], 0 - jnz .interleaved - add eax, [di] -; read esi bytes from logical block eax to buffer es:bx - call read_many_bytes.with_first - jc .readerr3 -.loadcontinue: - mov [cur_chunk], di - add di, 11 - cmp di, [cur_desc_end] - jae @f - cmp [cur_limit], 0 - jnz loadloop -@@: - mov bx, [overflow] -.calclen: -; calculate length of file - xor ax, ax - xor dx, dx - mov di, 2000h -@@: - add ax, [di+4] - adc dx, [di+6] - add di, 11 - cmp di, [cur_desc_end] - jb @b - ret -.interleaved: - mov [cur_unit_limit], esi - push esi -; skip first blocks - movzx ecx, byte [di+9] ; Unit Size - movzx esi, byte [di+10] ; Interleave Gap - add si, cx - mov edx, [di] -@@: - sub eax, ecx - jb @f - add edx, esi - jmp @b -@@: - add ecx, eax ; ecx = number of logical blocks to skip - lea eax, [ecx+edx] ; eax = first logical block - pop esi -.interleaved_loop: -; get number of bytes in current file unit - push eax - movzx eax, byte [di+9] - sub ax, cx - imul eax, dword [lb_size] - cmp eax, esi - ja .i2 -.i1: - xchg esi, eax -.i2: - pop eax - sub [cur_unit_limit], esi - push eax -; read esi bytes from logical block eax to buffer es:bx - call read_many_bytes.with_first - pop eax - jnc @f -.readerr3: - mov bx, 3 - jmp .calclen -@@: - mov esi, [cur_unit_limit] - test esi, esi - jz .loadcontinue - movzx ecx, byte [di+9] ; add Unit Size - add cl, byte [di+10] ; add Interleave Gap - adc ch, 0 - add eax, ecx - xor cx, cx - mov [first_byte], cx - jmp .interleaved_loop - -cx_to_sectors: - add cx, 7FFh - rcr cx, 1 - shr cx, 10 - ret - -is_last_component: -; in: ds:si -> name -; out: CF set <=> current component is not last (=> folder) - push si -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jnz @b - stc -@@: - pop si - ret - -test_filename1: -; in: ds:si -> filename, es:di -> path table item -; out: CF set <=> no match - pusha - mov cl, [es:di] - add di, 8 - jmp test_filename2.start -test_filename2: -; in: ds:si -> filename, es:bx -> directory item -; out: CF set <=> no match - pusha - mov cl, [es:bx+32] - lea di, [bx+33] -.start: - mov ch, 0 -@@: - lodsb - test al, al - jz .test1 - cmp al, '/' - jz .test1 - call toupper - mov ah, al - mov al, [es:di] - call toupper - inc di - cmp al, ah - loopz @b - jnz .next1 -; if we have reached this point: current name is done - lodsb - test al, al - jz .ret - cmp al, '/' - jz .ret -; if we have reached this point: current name is done, but input name continues -; so they do not match - jmp .next1 -.test1: -; if we have reached this point: input name is done, but current name continues -; "filename.ext;version" in ISO-9660 represents file "filename.ext" -; "filename." and "filename.;version" are also possible for "filename" - cmp byte [es:di], '.' - jnz @f - inc di - dec cx - jz .ret -@@: - cmp byte [es:di], ';' - jnz .next1 - jmp .ret -.next1: - stc -.ret: - popa - ret - -toupper: -; in: al=symbol -; out: al=symbol in uppercase - cmp al, 'a' - jb .ret - cmp al, 'z' - ja .ret - sub al, 'a'-'A' -.ret: - ret - -scan_for_filename_in_sector: -; in: ds:si->filename, es:bx->folder data, dx=limit -; out: CF=0 if found - push bx -.loope: - push bx -.loop: - cmp bx, dx - jae .notfound - cmp byte [es:bx], 0 - jz .loopd - test byte [es:bx+25], 4 ; ignore files with Associated bit - jnz .next - call test_filename2 - jc .next - push ds es di - push es - pop ds - push cs - pop es - mov di, [es:cur_desc_end] - movzx eax, byte [bx+1] - add eax, [bx+2] - stosd ; first logical block - mov eax, [bx+10] - stosd ; length - mov al, [bx+25] - stosb ; flags - mov ax, [bx+26] - stosw ; File Unit size, Interleave Gap size - mov [es:cur_desc_end], di - cmp di, 3000h - pop di es ds - jae .done - test byte [es:bx+25], 80h - jz .done -.next: - add bl, [es:bx] - adc bh, 0 - jmp .loop -.loopd: - mov ax, bx - pop bx -@@: - add bx, [cs:lb_size] - jz .done2 - cmp bx, ax - jb @b - jmp .loope -.notfound: - stc -.done: - pop bx -.done2: - pop bx - ret - -lb_to_sector: - xor edx, edx - div dword [lb_per_sec] - ret - -load_phys_sector_for_lb_force: -; in: eax = logical block, ds=0 -; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 -; out: 0000:1000 = physical sector data; si -> logical block -; out: eax = next physical sector -; out: CF=1 if read error -; destroys cx -; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector - call lb_to_sector - or si, dx - jnz @f - mov si, 1800h - jmp .done -@@: - mov si, 1000h - imul dx, [lb_size] - add si, dx - mov cx, 1 - push es bx - push ds - pop es - mov bx, 1000h - call read_sectors - pop bx es - inc eax -.done: - ret - -normalize: -; in: es:bx = far pointer -; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) - push ax bx - mov ax, es - shr bx, 4 - add ax, bx - mov es, ax - pop bx ax - and bx, 0x0F - ret - -read_many_bytes: - and [first_byte], 0 -read_many_bytes.with_first: -; read esi bytes from logical block dx:ax to buffer es:bx -; out: CF=1 <=> disk error - push di -; load first physical sector - push bx si - mov si, [first_byte] - call load_phys_sector_for_lb_force - jnc @f - pop si bx -.ret: - pop di - ret -@@: - add si, [first_byte] - mov ecx, 1800h - sub cx, si - mov ebx, esi - pop bx - sub ebx, ecx - jnc @f - add cx, bx - xor ebx, ebx -@@: - pop di - sub [cur_limit], ecx - rep movsb - mov esi, ebx - mov bx, di - call normalize -; load other physical sectors -; read esi bytes from physical sector eax to buffer es:bx - test esi, esi - jz .ret - push esi - add esi, 0x7FF - and si, not 0x7FF - cmp esi, [cur_limit] - jbe .okplace -.noplace: - sub esi, 800h -.okplace: - shr esi, 11 ; si = number of sectors - mov cx, si - jz @f - call read_sectors -@@: - pop esi - jc .ret - movzx ecx, cx - add eax, ecx - shl ecx, 11 - sub [cur_limit], ecx - sub esi, ecx - jc .big - jz .nopost - push bx es - push ds - pop es - mov bx, 1000h - mov cx, 1 - call read_sectors - pop es di - jc .ret2 - mov cx, si - mov si, 1000h - sub word [cur_limit], cx - sbb word [cur_limit+2], 0 - rep movsb - mov bx, di - call normalize -.nopost: - clc -.ret2: - pop di - ret -.big: - mov ax, es - sub ax, 80h - mov es, ax - add bx, 800h - add bx, si - call normalize - sub [cur_limit], esi - jmp .nopost - -; Callback function for secondary loader -callback: -; in: ax = function number; only function 1 is defined for now - dec ax - jz callback_readfile - dec ax - jz callback_continueread - stc ; unsupported function - retf - -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call load_file - clc ; function is supported - retf - -callback_continueread: -; function 2: continue to read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error -; out: dx:ax = file size - les bx, [di] - call normalize - movzx esi, word [di+4] ; si = limit in 4K blocks - shl esi, 12 ; bp:si = limit in bytes - push cs - pop ds - mov [cur_limit], esi - mov di, [cur_chunk] - call loadloop.loadnew - clc ; function is supported - retf - -secondary_loader_info: - dw 0, 0x1000 - dw 0x30000 / 0x1000 - db 'kernel.mnt',0 -aKernelNotFound db 'Fatal error: cannot load the kernel',0 - -align 2 -cachelist: -.head dw cachelist -.tail dw cachelist -free_cache_item dw 0 -last_cache_item dw 0x8400 - -use_path_table db 0 -bootdrive db ? -align 2 -lb_size dw ? ; Logical Block size in bytes - dw 0 ; to allow access dword [lb_size] -lb_per_sec dw ? ; Logical Blocks per physical sector - dw 0 ; to allow access dword [lb_per_sec] -free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) -size_rest dw ? ; free space in cache (in blocks) -cache_size dw ? -cache_start dw ? -pathtable_size dw ? -pathtable_start dw ? -root_location dd ? -cur_desc_end dw ? -cur_nocache_len dd ? -cur_limit dd ? -cur_unit_limit dd ? -overflow dw ? -cur_chunk dw ? -first_byte dw ? -cur_start dd ? - -times 83FCh-$ db 0 - db 43h -; just to make file 2048 bytes long :) - db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' - - dw 0xAA55 ; this is not required for CD, but to be consistent... +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + + jmp far 0:real_start +; special text +org $+0x7C00 +real_start: +; initialize + xor ax, ax + mov ss, ax + mov sp, 0x7C00 + mov ds, ax + mov es, ax + cld + sti + mov [bootdrive], dl +; check LBA support + mov ah, 41h + mov bx, 55AAh + int 13h + mov si, aNoLBA + jc err_ + cmp bx, 0AA55h + jnz err_ + test cl, 1 + jz err_ +; get file system information +; scan for Primary Volume Descriptor + db 66h + push 10h-1 + pop eax +pvd_scan_loop: + mov cx, 1 + inc eax + mov bx, 0x1000 + call read_sectors + jnc @f +fatal_read_err: + mov si, aReadError +err_: + call out_string + mov si, aPressAnyKey + call out_string + xor ax, ax + int 16h + int 18h + jmp $ +@@: + push ds + pop es + cmp word [bx+1], 'CD' + jnz pvd_scan_loop + cmp word [bx+3], '00' + jnz pvd_scan_loop + cmp byte [bx+5], '1' + jnz pvd_scan_loop +; we have found ISO9660 descriptor, look for type + cmp byte [bx], 1 ; Primary Volume Descriptor? + jz pvd_found + cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? + jnz pvd_scan_loop +; Volume Descriptor Set Terminator reached, no PVD found - fatal error + mov si, no_pvd + jmp err_ +pvd_found: + add bx, 80h + mov ax, [bx] + mov [lb_size], ax +; calculate number of logical blocks in one sector + mov ax, 800h + cwd + div word [bx] + mov [lb_per_sec], ax +; get location of root directory + mov di, root_location + movzx eax, byte [bx+1Dh] + add eax, [bx+1Eh] + stosd +; get memory size + int 12h + mov si, nomem_str + cmp ax, 71000h / 400h + jb err_ + shr ax, 1 + sub ax, 60000h / 800h + mov [size_rest], ax + mov [free_ptr], 60000h / 800h +; load path table +; if size > 62K => it's very strange, avoid using it +; if size > (size of cache)/2 => avoid using it too + mov ecx, [bx+4] + cmp ecx, 0x10000 - 0x800 + ja nopathtable + shr ax, 1 + cmp ax, 0x20 + jae @f + shl ax, 11 + cmp cx, ax + ja nopathtable +@@: +; size is ok, try to load it + mov [pathtable_size], cx + mov eax, [bx+12] + xor edx, edx + div dword [lb_per_sec] + imul dx, [bx] + mov [pathtable_start], dx + add cx, dx + call cx_to_sectors + xor bx, bx + push 6000h + pop es + call read_sectors + jc nopathtable +; path table has been loaded + inc [use_path_table] + sub [size_rest], cx + add [free_ptr], cx +nopathtable: +; init cache + mov ax, [size_rest] + mov [cache_size], ax + mov ax, [free_ptr] + mov [cache_start], ax +; load secondary loader + mov di, secondary_loader_info + call load_file + test bx, bx + jnz noloader +; set registers for secondary loader + mov ah, [bootdrive] + mov al, 'c' + mov bx, 'is' + mov si, callback + jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 + +noloader: + mov si, aKernelNotFound + jmp err_ + +read_sectors: +; es:bx = pointer to data +; eax = first sector +; cx = number of sectors + pushad + push ds +do_read_sectors: + push ax + push cx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + db 66h + push 0 + push eax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [cs:bootdrive] + mov ah, 42h + int 13h + jc diskreaderr +; restore stack + add sp, 10h +; increase current sector & buffer; decrease number of sectors + movzx esi, cx + mov ax, es + shl cx, 7 + add ax, cx + mov es, ax + pop cx + pop ax + add eax, esi + sub cx, si + jnz do_read_sectors + pop ds + popad + ret +diskreaderr: + add sp, 10h + 2*2 + pop ds + popad + stc +out_string.ret: + ret + +out_string: +; in: ds:si -> ASCIIZ string + lodsb + test al, al + jz .ret + mov ah, 0Eh + mov bx, 7 + int 10h + jmp out_string + +aNoLBA db 'The drive does not support LBA!',0 +aReadError db 'Read error',0 +no_pvd db 'Primary Volume Descriptor not found!',0 +nomem_str db 'No memory',0 +aPressAnyKey db 13,10,'Press any key...',13,10,0 + +load_file: +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) +; parse path to the file + lea si, [di+6] + mov eax, [cs:root_location] + cmp [cs:use_path_table], 0 + jz parse_dir +; scan for path in path table + push di + push 6000h + pop es + mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table + mov dx, 1 ; dx = number of current entry in path table, start from 1 + mov cx, [cs:pathtable_size] +pathtable_newparent: + mov bx, dx ; bx = number of current parent in path table: root = 1 +scan_path_table_e: + call is_last_component + jnc path_table_scanned +scan_path_table_i: + cmp word [es:di+6], bx + jb .next + ja path_table_notfound + call test_filename1 + jc .next +@@: + lodsb + cmp al, '/' + jnz @b + jmp pathtable_newparent +.next: +; go to next entry + inc dx + movzx ax, byte [es:di] + add ax, 8+1 + and al, not 1 + add di, ax + sub cx, ax + ja scan_path_table_i +path_table_notfound: + pop di + mov ax, -1 + mov dx, ax + mov bx, 2 ; file not found + ret +path_table_scanned: + movzx eax, byte [es:di+1] + add eax, [es:di+2] + pop di +parse_dir: +; eax = logical block, ds:di -> information structure, ds:si -> file name +; was the folder already read? + push di ds + push cs + pop ds + mov [cur_desc_end], 2000h + mov bx, cachelist +.scan1: + mov bx, [bx+2] + cmp bx, cachelist + jz .notfound + cmp [bx+4], eax + jnz .scan1 +.found: +; yes; delete this item from the list (the following code will append this item to the tail) + mov di, [bx] + push word [bx+2] + pop word [di+2] + mov di, [bx+2] + push word [bx] + pop word [di] + mov di, bx + jmp .scan +.notfound: +; no; load first sector of the folder to get its size + push eax + push si + mov si, 1 + call load_phys_sector_for_lb_force + mov bx, si + pop si + pop eax + jnc @f +; read error - return +.readerr: + pop ds +.readerr2: + pop di + mov ax, -1 + mov dx, ax + mov bx, 3 + ret +@@: +; first item of the folder describes the folder itself +; do not cache too big folders: size < 64K and size <= (total cache size)/2 + cmp word [bx+12], 0 + jnz .nocache + mov cx, [cache_size] ; cx = cache size in sectors + shr cx, 1 ; cx = (cache size)/2 + cmp cx, 0x20 + jae @f + shl cx, 11 + cmp [bx+10], cx + ja .nocache +@@: +; we want to cache this folder; get space for it + mov cx, [bx+10] + call cx_to_sectors + jnz .yescache +.nocache: + push dword [bx+10] + pop dword [cur_nocache_len] + call lb_to_sector + push ds + pop es + pop ds +.nocache_loop: + push eax + mov dx, 1800h + call scan_for_filename_in_sector + mov cx, dx + pop eax + jnc .j_scandone + sub cx, bx + sub word [es:cur_nocache_len], cx + sbb word [es:cur_nocache_len+2], 0 + jb .j_scandone + ja @f + cmp word [es:cur_nocache_len], 0 + jz .j_scandone +@@: + mov cx, 1 + inc eax + push es + mov bx, 1000h + call read_sectors + pop es + jc .readerr2 + jmp .nocache_loop +.j_scandone: + jmp .scandone +.yescache: + push bx + mov bx, [cachelist.head] +.freeloop: + cmp cx, [size_rest] + jbe .sizeok +@@: +; if we are here: there is not enough free space, so we must delete old folders' data +; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). +; one loop iteration: delete data of one folder + pusha + mov dx, [bx+10] + mov es, dx ; es = segment of folder data to be deleted + xor di, di + mov ax, [bx+8] + add ax, 0x7FF + rcr ax, 1 + shr ax, 10 + push ax + shl ax, 11-4 ; get number of paragraphs in folder data to be deleted + mov cx, [cache_size] + add cx, [cache_start] + push ds + push ax + add ax, dx + mov ds, ax + pop ax + shl cx, 11-4 + sub cx, dx ; cx = number of paragraphs to be moved + push si + xor si, si +; move cx paragraphs from ds:si to es:di to get free space in the end of cache +@@: + sub cx, 1000h + jbe @f + push cx + mov cx, 8000h + rep movsw + mov cx, ds + add cx, 1000h + mov ds, cx + mov cx, es + add cx, 1000h + mov es, cx + pop cx + jmp @b +@@: + add cx, 1000h + shl cx, 3 + rep movsw + pop si + pop ds +; correct positions in cache for existing items + mov cx, 80h + mov di, 8400h +.correct: + cmp [di+10], dx + jbe @f + sub [di+10], ax +@@: + add di, 12 + loop .correct +; some additional space is free now + pop ax + add [size_rest], ax + sub [free_ptr], ax +; add cache item to the list of free items + mov dx, [bx] + mov ax, [free_cache_item] + mov [bx], ax + mov [free_cache_item], bx + mov bx, dx +; current iteration done + popa + jmp .freeloop +.sizeok: + mov [cachelist.head], bx + mov word [bx+2], cachelist +; allocate new item in cache + mov di, [free_cache_item] + test di, di + jz .nofree + push word [di] + pop [free_cache_item] + jmp @f +.nofree: + mov di, [last_cache_item] + add [last_cache_item], 12 +@@: + pop bx + push si di +; mov [di+4], eax ; start of folder + scasd + stosd + push ax + mov ax, [free_ptr] + shl ax, 11-4 + mov [di+10-8], ax + mov es, ax + pop ax + add [free_ptr], cx + sub [size_rest], cx +; read folder data +; first sector is already in memory, 0000:bx + pusha + mov cx, [bx+10] + mov [di+8-8], cx ; folder size in bytes + mov si, bx + xor di, di + mov cx, 0x1800 + sub cx, si + rep movsb + pop ax + push di + popa +; read rest of folder + mov esi, dword [lb_per_sec] + add eax, esi + dec si + not si + and ax, si + mov si, word [bx+10] + mov bx, di + pop di + sub si, bx + jbe @f + mov [cur_limit], esi + call read_many_bytes + pop si + jnc .scan + jmp .readerr +@@: + pop si +.scan: +; now we have required cache item; append it to the end of list + mov bx, [cachelist.tail] + mov [cachelist.tail], di + mov [di+2], bx + mov word [di], cachelist + mov [bx], di +; scan for given filename + mov es, [di+10] + mov dx, [di+8] + pop ds + xor bx, bx + call scan_for_filename_in_sector +.scandone: + push cs + pop es + mov bx, 2000h + cmp bx, [es:cur_desc_end] + jnz filefound +j_notfound: + jmp path_table_notfound +filefound: +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jnz @b +@@: + mov cl, [es:bx+8] + test al, al + jz @f +; parse next component of file name + test cl, 2 ; directory? + jz j_notfound + mov eax, [es:bx] + pop di + jmp parse_dir +@@: + test cl, 2 ; directory? + jnz j_notfound ; do not allow read directories as regular files +; ok, now load the file + pop di + les bx, [di] + call normalize + movzx esi, word [di+4] ; esi = limit in 4K blocks + shl esi, 12 ; esi = limit in bytes + push cs + pop ds + mov [cur_limit], esi + mov di, 2000h +loadloop: + and [cur_start], 0 +.loadnew: + mov esi, [cur_limit] + mov eax, [cur_start] + add esi, eax + mov [overflow], 1 + sub esi, [di+4] + jb @f + xor esi, esi + dec [overflow] +@@: + add esi, [di+4] ; esi = number of bytes to read + mov [cur_start], esi + sub esi, eax + jz .loadcontinue + xor edx, edx + div dword [lb_size] ; eax = number of logical blocks to skip, + mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block + cmp byte [di+10], 0 + jnz .interleaved + add eax, [di] +; read esi bytes from logical block eax to buffer es:bx + call read_many_bytes.with_first + jc .readerr3 +.loadcontinue: + mov [cur_chunk], di + add di, 11 + cmp di, [cur_desc_end] + jae @f + cmp [cur_limit], 0 + jnz loadloop +@@: + mov bx, [overflow] +.calclen: +; calculate length of file + xor ax, ax + xor dx, dx + mov di, 2000h +@@: + add ax, [di+4] + adc dx, [di+6] + add di, 11 + cmp di, [cur_desc_end] + jb @b + ret +.interleaved: + mov [cur_unit_limit], esi + push esi +; skip first blocks + movzx ecx, byte [di+9] ; Unit Size + movzx esi, byte [di+10] ; Interleave Gap + add si, cx + mov edx, [di] +@@: + sub eax, ecx + jb @f + add edx, esi + jmp @b +@@: + add ecx, eax ; ecx = number of logical blocks to skip + lea eax, [ecx+edx] ; eax = first logical block + pop esi +.interleaved_loop: +; get number of bytes in current file unit + push eax + movzx eax, byte [di+9] + sub ax, cx + imul eax, dword [lb_size] + cmp eax, esi + ja .i2 +.i1: + xchg esi, eax +.i2: + pop eax + sub [cur_unit_limit], esi + push eax +; read esi bytes from logical block eax to buffer es:bx + call read_many_bytes.with_first + pop eax + jnc @f +.readerr3: + mov bx, 3 + jmp .calclen +@@: + mov esi, [cur_unit_limit] + test esi, esi + jz .loadcontinue + movzx ecx, byte [di+9] ; add Unit Size + add cl, byte [di+10] ; add Interleave Gap + adc ch, 0 + add eax, ecx + xor cx, cx + mov [first_byte], cx + jmp .interleaved_loop + +cx_to_sectors: + add cx, 7FFh + rcr cx, 1 + shr cx, 10 + ret + +is_last_component: +; in: ds:si -> name +; out: CF set <=> current component is not last (=> folder) + push si +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jnz @b + stc +@@: + pop si + ret + +test_filename1: +; in: ds:si -> filename, es:di -> path table item +; out: CF set <=> no match + pusha + mov cl, [es:di] + add di, 8 + jmp test_filename2.start +test_filename2: +; in: ds:si -> filename, es:bx -> directory item +; out: CF set <=> no match + pusha + mov cl, [es:bx+32] + lea di, [bx+33] +.start: + mov ch, 0 +@@: + lodsb + test al, al + jz .test1 + cmp al, '/' + jz .test1 + call toupper + mov ah, al + mov al, [es:di] + call toupper + inc di + cmp al, ah + loopz @b + jnz .next1 +; if we have reached this point: current name is done + lodsb + test al, al + jz .ret + cmp al, '/' + jz .ret +; if we have reached this point: current name is done, but input name continues +; so they do not match + jmp .next1 +.test1: +; if we have reached this point: input name is done, but current name continues +; "filename.ext;version" in ISO-9660 represents file "filename.ext" +; "filename." and "filename.;version" are also possible for "filename" + cmp byte [es:di], '.' + jnz @f + inc di + dec cx + jz .ret +@@: + cmp byte [es:di], ';' + jnz .next1 + jmp .ret +.next1: + stc +.ret: + popa + ret + +toupper: +; in: al=symbol +; out: al=symbol in uppercase + cmp al, 'a' + jb .ret + cmp al, 'z' + ja .ret + sub al, 'a'-'A' +.ret: + ret + +scan_for_filename_in_sector: +; in: ds:si->filename, es:bx->folder data, dx=limit +; out: CF=0 if found + push bx +.loope: + push bx +.loop: + cmp bx, dx + jae .notfound + cmp byte [es:bx], 0 + jz .loopd + test byte [es:bx+25], 4 ; ignore files with Associated bit + jnz .next + call test_filename2 + jc .next + push ds es di + push es + pop ds + push cs + pop es + mov di, [es:cur_desc_end] + movzx eax, byte [bx+1] + add eax, [bx+2] + stosd ; first logical block + mov eax, [bx+10] + stosd ; length + mov al, [bx+25] + stosb ; flags + mov ax, [bx+26] + stosw ; File Unit size, Interleave Gap size + mov [es:cur_desc_end], di + cmp di, 3000h + pop di es ds + jae .done + test byte [es:bx+25], 80h + jz .done +.next: + add bl, [es:bx] + adc bh, 0 + jmp .loop +.loopd: + mov ax, bx + pop bx +@@: + add bx, [cs:lb_size] + jz .done2 + cmp bx, ax + jb @b + jmp .loope +.notfound: + stc +.done: + pop bx +.done2: + pop bx + ret + +lb_to_sector: + xor edx, edx + div dword [lb_per_sec] + ret + +load_phys_sector_for_lb_force: +; in: eax = logical block, ds=0 +; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 +; out: 0000:1000 = physical sector data; si -> logical block +; out: eax = next physical sector +; out: CF=1 if read error +; destroys cx +; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector + call lb_to_sector + or si, dx + jnz @f + mov si, 1800h + jmp .done +@@: + mov si, 1000h + imul dx, [lb_size] + add si, dx + mov cx, 1 + push es bx + push ds + pop es + mov bx, 1000h + call read_sectors + pop bx es + inc eax +.done: + ret + +normalize: +; in: es:bx = far pointer +; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) + push ax bx + mov ax, es + shr bx, 4 + add ax, bx + mov es, ax + pop bx ax + and bx, 0x0F + ret + +read_many_bytes: + and [first_byte], 0 +read_many_bytes.with_first: +; read esi bytes from logical block dx:ax to buffer es:bx +; out: CF=1 <=> disk error + push di +; load first physical sector + push bx si + mov si, [first_byte] + call load_phys_sector_for_lb_force + jnc @f + pop si bx +.ret: + pop di + ret +@@: + add si, [first_byte] + mov ecx, 1800h + sub cx, si + mov ebx, esi + pop bx + sub ebx, ecx + jnc @f + add cx, bx + xor ebx, ebx +@@: + pop di + sub [cur_limit], ecx + rep movsb + mov esi, ebx + mov bx, di + call normalize +; load other physical sectors +; read esi bytes from physical sector eax to buffer es:bx + test esi, esi + jz .ret + push esi + add esi, 0x7FF + and si, not 0x7FF + cmp esi, [cur_limit] + jbe .okplace +.noplace: + sub esi, 800h +.okplace: + shr esi, 11 ; si = number of sectors + mov cx, si + jz @f + call read_sectors +@@: + pop esi + jc .ret + movzx ecx, cx + add eax, ecx + shl ecx, 11 + sub [cur_limit], ecx + sub esi, ecx + jc .big + jz .nopost + push bx es + push ds + pop es + mov bx, 1000h + mov cx, 1 + call read_sectors + pop es di + jc .ret2 + mov cx, si + mov si, 1000h + sub word [cur_limit], cx + sbb word [cur_limit+2], 0 + rep movsb + mov bx, di + call normalize +.nopost: + clc +.ret2: + pop di + ret +.big: + mov ax, es + sub ax, 80h + mov es, ax + add bx, 800h + add bx, si + call normalize + sub [cur_limit], esi + jmp .nopost + +; Callback function for secondary loader +callback: +; in: ax = function number; only function 1 is defined for now + dec ax + jz callback_readfile + dec ax + jz callback_continueread + stc ; unsupported function + retf + +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call load_file + clc ; function is supported + retf + +callback_continueread: +; function 2: continue to read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error +; out: dx:ax = file size + les bx, [di] + call normalize + movzx esi, word [di+4] ; si = limit in 4K blocks + shl esi, 12 ; bp:si = limit in bytes + push cs + pop ds + mov [cur_limit], esi + mov di, [cur_chunk] + call loadloop.loadnew + clc ; function is supported + retf + +secondary_loader_info: + dw 0, 0x1000 + dw 0x30000 / 0x1000 + db 'kernel.mnt',0 +aKernelNotFound db 'Fatal error: cannot load the kernel',0 + +align 2 +cachelist: +.head dw cachelist +.tail dw cachelist +free_cache_item dw 0 +last_cache_item dw 0x8400 + +use_path_table db 0 +bootdrive db ? +align 2 +lb_size dw ? ; Logical Block size in bytes + dw 0 ; to allow access dword [lb_size] +lb_per_sec dw ? ; Logical Blocks per physical sector + dw 0 ; to allow access dword [lb_per_sec] +free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) +size_rest dw ? ; free space in cache (in blocks) +cache_size dw ? +cache_start dw ? +pathtable_size dw ? +pathtable_start dw ? +root_location dd ? +cur_desc_end dw ? +cur_nocache_len dd ? +cur_limit dd ? +cur_unit_limit dd ? +overflow dw ? +cur_chunk dw ? +first_byte dw ? +cur_start dd ? + +times 83FCh-$ db 0 + db 43h +; just to make file 2048 bytes long :) + db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' + + dw 0xAA55 ; this is not required for CD, but to be consistent... diff --git a/kernel/trunk/bootloader/extended_primary_loader/fat1x/bootsect.asm b/kernel/trunk/bootloader/extended_primary_loader/fat1x/bootsect.asm index 772829f06..9b84a85e8 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/fat1x/bootsect.asm +++ b/kernel/trunk/bootloader/extended_primary_loader/fat1x/bootsect.asm @@ -1,392 +1,392 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -use_lba = 0 - org 0x7C00 - jmp start - nop -; FAT parameters, BPB -; note: they can be changed at install, replaced with real values -; these settings are for most typical 1.44M floppies - db 'KOLIBRI ' ; BS_OEMName, ignored - dw 200h ; BPB_BytsPerSec -BPB_SecsPerClus db 1 -BPB_RsvdSecCnt dw 1 -BPB_NumFATs db 2 -BPB_RootEntCnt dw 0xE0 - dw 2880 ; BPB_TotSec16 - db 0xF0 ; BPB_Media -BPB_FATSz16 dw 9 -BPB_SecPerTrk dw 18 -BPB_NumHeads dw 2 -BPB_HiddSec dd 0 - dd 0 ; BPB_TotSec32 -BS_DrvNum db 0 - db 0 ; BS_Reserved1 - db ')' ; BS_BootSig - dd 12344321h ; BS_VolID -filename: - db 'KORD.OS ' ; BS_VolLab - db 'FAT12 ' ; BS_FilSysType -; Used memory map: -; 8000:0000 - current directory -; 9000:0000 - root directory data [cached] -start: - xor ax, ax - mov ss, ax - mov sp, 0x7C00 - mov ds, ax - mov bp, sp - cld - sti - mov [bp+BS_DrvNum-0x7C00], dl -if use_lba - mov ah, 41h - mov bx, 55AAh - int 13h - mov si, aNoLBA - jc err_ - cmp bx, 0AA55h - jnz err_ - test cx, 1 - jz err_ -else - mov ah, 8 - int 13h - jc @f ; on error, assume that BPB geometry is valid - mov al, dh - mov ah, 0 - inc ax - mov [bp+BPB_NumHeads-0x7C00], ax - and cx, 3Fh - mov [bp+BPB_SecPerTrk-0x7C00], cx -@@: -end if -; get FAT parameters - xor bx, bx - mov al, [bp+BPB_NumFATs-0x7C00] - mov ah, 0 - mul [bp+BPB_FATSz16-0x7C00] - add ax, [bp+BPB_RsvdSecCnt-0x7C00] - adc dx, bx - push dx - push ax ; root directory start = dword [bp-4] - mov cx, [bp+BPB_RootEntCnt-0x7C00] - add cx, 0xF - rcr cx, 1 - shr cx, 3 ; cx = size of root directory in sectors - add ax, cx - adc dx, bx - push dx - push ax ; data start = dword [bp-8] -; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) - cmp cx, 0x10 - jb @f - mov cx, 0x10 -@@: - mov ax, [bp-4] - mov dx, [bp-2] - push 0x9000 - pop es - call read_sectors - add word [bp-4], cx ; dword [bp-4] = start of non-cached root data - adc word [bp-2], bx -; load kordldr.f12 - mov si, main_loader - call lookup_in_root_dir - jc noloader - test byte [es:di+11], 10h ; directory? - jz kordldr_ok -noloader: - mov si, aLoaderNotFound -err_: - call out_string - mov si, aPressAnyKey - call out_string - xor ax, ax - int 16h - int 18h - jmp $ -kordldr_ok: - mov ax, [es:di+26] ; get file cluster - mov bx, 0x7E00 - xor cx, cx - mov es, cx - sub ax, 2 - jc noloader - push bx ; save return address: bx = 7E00 - mov cl, [bp+BPB_SecsPerClus-0x7C00] - mul cx -; fall through - 'ret' in read_sectors will return to 7E00 - -read_sectors2: -; same as read_sectors, but dx:ax is relative to start of data - add ax, [bp-8] - adc dx, [bp-6] -read_sectors: -; ss:bp = 0:7C00 -; es:bx = pointer to data -; dx:ax = first sector -; cx = number of sectors - pusha - add ax, word [bp+BPB_HiddSec-0x7C00] - adc dx, word [bp+BPB_HiddSec+2-0x7C00] -if use_lba - push ds -do_read_sectors: - push ax - push cx - push dx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - push 0 - push 0 - push dx - push ax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [bp+BS_DrvNum-0x7C00] - mov ah, 42h - int 13h - mov si, aReadError - jc err_ -; restore stack - add sp, 10h -; increase current sector & buffer; decrease number of sectors - mov si, cx - mov ax, es - shl cx, 5 - add ax, cx - mov es, ax - pop dx - pop cx - pop ax - add ax, si - adc dx, 0 - sub cx, si - jnz do_read_sectors - pop ds - popa - ret -else -do_read_sectors: - pusha - pop di - push bx - -; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx - mov si, ax - xchg ax, dx - xor dx, dx - div [bp+BPB_SecPerTrk-0x7C00] - push ax - mov ax, si - div [bp+BPB_SecPerTrk-0x7C00] - mov bx, dx ; bx=sector-1 - pop dx - -; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx - div [bp+BPB_NumHeads-0x7C00] - -; number of sectors: read no more than to end of track - push bx - sub bx, [bp+BPB_SecPerTrk-0x7C00] - neg bx - cmp cx, bx - jbe @f - mov cx, bx -@@: - pop bx - - inc bx -; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format - mov di, cx - mov dh, dl - mov dl, [bp+BS_DrvNum-0x7C00] - shl ah, 6 - mov ch, al - mov al, cl - mov cl, bl - or cl, ah - pop bx - mov si, 3 - mov ah, 2 -@@: - push ax - int 13h - jnc @f - xor ax, ax - int 13h ; reset drive - pop ax - dec si - jnz @b - mov si, aReadError - jmp err_ -@@: - pop ax - mov ax, es - mov cx, di - shl cx, 5 - add ax, cx - mov es, ax - push di - popa - add ax, di - adc dx, 0 - sub cx, di - jnz do_read_sectors - popa - ret -end if - -scan_for_filename: -; in: ds:si -> 11-bytes FAT name -; in: es:0 -> part of directory data -; in: cx = number of entries -; out: if found: CF=0, ZF=1, es:di -> directory entry -; out: if not found, but continue required: CF=1 and ZF=0 -; out: if not found and zero item reached: CF=1 and ZF=1 - xor di, di - push cx -sloop: - cmp byte [es:di], 0 - jz snotfound - test byte [es:di+11], 8 ; volume label? - jnz scont ; ignore volume labels - pusha - mov cx, 11 - repz cmpsb - popa - jz sdone -scont: - add di, 0x20 - loop sloop - inc cx ; clear ZF flag -snotfound: - stc -sdone: - pop cx -lrdret: - ret - -lookup_in_root_dir: -; ss:bp = 0:7C00 -; in: ds:si -> 11-bytes FAT name -; out: if found: CF=0, es:di -> directory entry -; out: if not found: CF=1 - mov cx, [bp+BPB_RootEntCnt-0x7C00] - push cx -; first, look in root directory cache - push 0x9000 - pop es - test ch, ch - jz @f - mov cx, 0x100 -@@: - mov ax, [bp-4] - mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory -lrdloop: - call scan_for_filename - pop bx - jz lrdret - sub bx, cx - mov cx, bx - stc - jz lrdret -; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries - push cx - cmp ch, 0x8 - jb @f - mov cx, 0x800 -@@: - push 0x8000 - pop es - push cx - push es - xor bx, bx - add cx, 0xF - shr cx, 4 - call read_sectors - pop es - add ax, cx - adc dx, bx - pop cx - jmp lrdloop - -out_string: -; in: ds:si -> ASCIIZ string - lodsb - test al, al - jz lrdret - mov ah, 0Eh - mov bx, 7 - int 10h - jmp out_string - -aReadError db 'Read error',0 -if use_lba -aNoLBA db 'The drive does not support LBA!',0 -end if -aLoaderNotFound db 'Loader not found',0 -aPressAnyKey db 13,10,'Press any key...',13,10,0 -main_loader db 'KORDLDR F1X' - -if use_lba - db 0 ; make bootsector 512 bytes in length -end if - -; bootsector signature - dw 0xAA55 - -; display offsets of all procedures used by kordldr.f12.asm -macro show [procedure] -{ - bits = 16 - display `procedure,' = ' - repeat bits/4 - d = '0' + procedure shr (bits - %*4) and 0Fh - if d > '9' - d = d + 'A'-'9'-1 - end if - display d - end repeat - display 13,10 -} - -show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +use_lba = 0 + org 0x7C00 + jmp start + nop +; FAT parameters, BPB +; note: they can be changed at install, replaced with real values +; these settings are for most typical 1.44M floppies + db 'KOLIBRI ' ; BS_OEMName, ignored + dw 200h ; BPB_BytsPerSec +BPB_SecsPerClus db 1 +BPB_RsvdSecCnt dw 1 +BPB_NumFATs db 2 +BPB_RootEntCnt dw 0xE0 + dw 2880 ; BPB_TotSec16 + db 0xF0 ; BPB_Media +BPB_FATSz16 dw 9 +BPB_SecPerTrk dw 18 +BPB_NumHeads dw 2 +BPB_HiddSec dd 0 + dd 0 ; BPB_TotSec32 +BS_DrvNum db 0 + db 0 ; BS_Reserved1 + db ')' ; BS_BootSig + dd 12344321h ; BS_VolID +filename: + db 'KORD.OS ' ; BS_VolLab + db 'FAT12 ' ; BS_FilSysType +; Used memory map: +; 8000:0000 - current directory +; 9000:0000 - root directory data [cached] +start: + xor ax, ax + mov ss, ax + mov sp, 0x7C00 + mov ds, ax + mov bp, sp + cld + sti + mov [bp+BS_DrvNum-0x7C00], dl +if use_lba + mov ah, 41h + mov bx, 55AAh + int 13h + mov si, aNoLBA + jc err_ + cmp bx, 0AA55h + jnz err_ + test cx, 1 + jz err_ +else + mov ah, 8 + int 13h + jc @f ; on error, assume that BPB geometry is valid + mov al, dh + mov ah, 0 + inc ax + mov [bp+BPB_NumHeads-0x7C00], ax + and cx, 3Fh + mov [bp+BPB_SecPerTrk-0x7C00], cx +@@: +end if +; get FAT parameters + xor bx, bx + mov al, [bp+BPB_NumFATs-0x7C00] + mov ah, 0 + mul [bp+BPB_FATSz16-0x7C00] + add ax, [bp+BPB_RsvdSecCnt-0x7C00] + adc dx, bx + push dx + push ax ; root directory start = dword [bp-4] + mov cx, [bp+BPB_RootEntCnt-0x7C00] + add cx, 0xF + rcr cx, 1 + shr cx, 3 ; cx = size of root directory in sectors + add ax, cx + adc dx, bx + push dx + push ax ; data start = dword [bp-8] +; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) + cmp cx, 0x10 + jb @f + mov cx, 0x10 +@@: + mov ax, [bp-4] + mov dx, [bp-2] + push 0x9000 + pop es + call read_sectors + add word [bp-4], cx ; dword [bp-4] = start of non-cached root data + adc word [bp-2], bx +; load kordldr.f12 + mov si, main_loader + call lookup_in_root_dir + jc noloader + test byte [es:di+11], 10h ; directory? + jz kordldr_ok +noloader: + mov si, aLoaderNotFound +err_: + call out_string + mov si, aPressAnyKey + call out_string + xor ax, ax + int 16h + int 18h + jmp $ +kordldr_ok: + mov ax, [es:di+26] ; get file cluster + mov bx, 0x7E00 + xor cx, cx + mov es, cx + sub ax, 2 + jc noloader + push bx ; save return address: bx = 7E00 + mov cl, [bp+BPB_SecsPerClus-0x7C00] + mul cx +; fall through - 'ret' in read_sectors will return to 7E00 + +read_sectors2: +; same as read_sectors, but dx:ax is relative to start of data + add ax, [bp-8] + adc dx, [bp-6] +read_sectors: +; ss:bp = 0:7C00 +; es:bx = pointer to data +; dx:ax = first sector +; cx = number of sectors + pusha + add ax, word [bp+BPB_HiddSec-0x7C00] + adc dx, word [bp+BPB_HiddSec+2-0x7C00] +if use_lba + push ds +do_read_sectors: + push ax + push cx + push dx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + push 0 + push 0 + push dx + push ax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [bp+BS_DrvNum-0x7C00] + mov ah, 42h + int 13h + mov si, aReadError + jc err_ +; restore stack + add sp, 10h +; increase current sector & buffer; decrease number of sectors + mov si, cx + mov ax, es + shl cx, 5 + add ax, cx + mov es, ax + pop dx + pop cx + pop ax + add ax, si + adc dx, 0 + sub cx, si + jnz do_read_sectors + pop ds + popa + ret +else +do_read_sectors: + pusha + pop di + push bx + +; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx + mov si, ax + xchg ax, dx + xor dx, dx + div [bp+BPB_SecPerTrk-0x7C00] + push ax + mov ax, si + div [bp+BPB_SecPerTrk-0x7C00] + mov bx, dx ; bx=sector-1 + pop dx + +; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx + div [bp+BPB_NumHeads-0x7C00] + +; number of sectors: read no more than to end of track + push bx + sub bx, [bp+BPB_SecPerTrk-0x7C00] + neg bx + cmp cx, bx + jbe @f + mov cx, bx +@@: + pop bx + + inc bx +; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format + mov di, cx + mov dh, dl + mov dl, [bp+BS_DrvNum-0x7C00] + shl ah, 6 + mov ch, al + mov al, cl + mov cl, bl + or cl, ah + pop bx + mov si, 3 + mov ah, 2 +@@: + push ax + int 13h + jnc @f + xor ax, ax + int 13h ; reset drive + pop ax + dec si + jnz @b + mov si, aReadError + jmp err_ +@@: + pop ax + mov ax, es + mov cx, di + shl cx, 5 + add ax, cx + mov es, ax + push di + popa + add ax, di + adc dx, 0 + sub cx, di + jnz do_read_sectors + popa + ret +end if + +scan_for_filename: +; in: ds:si -> 11-bytes FAT name +; in: es:0 -> part of directory data +; in: cx = number of entries +; out: if found: CF=0, ZF=1, es:di -> directory entry +; out: if not found, but continue required: CF=1 and ZF=0 +; out: if not found and zero item reached: CF=1 and ZF=1 + xor di, di + push cx +sloop: + cmp byte [es:di], 0 + jz snotfound + test byte [es:di+11], 8 ; volume label? + jnz scont ; ignore volume labels + pusha + mov cx, 11 + repz cmpsb + popa + jz sdone +scont: + add di, 0x20 + loop sloop + inc cx ; clear ZF flag +snotfound: + stc +sdone: + pop cx +lrdret: + ret + +lookup_in_root_dir: +; ss:bp = 0:7C00 +; in: ds:si -> 11-bytes FAT name +; out: if found: CF=0, es:di -> directory entry +; out: if not found: CF=1 + mov cx, [bp+BPB_RootEntCnt-0x7C00] + push cx +; first, look in root directory cache + push 0x9000 + pop es + test ch, ch + jz @f + mov cx, 0x100 +@@: + mov ax, [bp-4] + mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory +lrdloop: + call scan_for_filename + pop bx + jz lrdret + sub bx, cx + mov cx, bx + stc + jz lrdret +; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries + push cx + cmp ch, 0x8 + jb @f + mov cx, 0x800 +@@: + push 0x8000 + pop es + push cx + push es + xor bx, bx + add cx, 0xF + shr cx, 4 + call read_sectors + pop es + add ax, cx + adc dx, bx + pop cx + jmp lrdloop + +out_string: +; in: ds:si -> ASCIIZ string + lodsb + test al, al + jz lrdret + mov ah, 0Eh + mov bx, 7 + int 10h + jmp out_string + +aReadError db 'Read error',0 +if use_lba +aNoLBA db 'The drive does not support LBA!',0 +end if +aLoaderNotFound db 'Loader not found',0 +aPressAnyKey db 13,10,'Press any key...',13,10,0 +main_loader db 'KORDLDR F1X' + +if use_lba + db 0 ; make bootsector 512 bytes in length +end if + +; bootsector signature + dw 0xAA55 + +; display offsets of all procedures used by kordldr.f12.asm +macro show [procedure] +{ + bits = 16 + display `procedure,' = ' + repeat bits/4 + d = '0' + procedure shr (bits - %*4) and 0Fh + if d > '9' + d = d + 'A'-'9'-1 + end if + display d + end repeat + display 13,10 +} + +show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader diff --git a/kernel/trunk/bootloader/extended_primary_loader/fat1x/kordldr.f1x.asm b/kernel/trunk/bootloader/extended_primary_loader/fat1x/kordldr.f1x.asm index cd73e48a3..d5724bc89 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/fat1x/kordldr.f1x.asm +++ b/kernel/trunk/bootloader/extended_primary_loader/fat1x/kordldr.f1x.asm @@ -1,688 +1,689 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - - org 0x7E00 -; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here -; ss:bp = 0:7C00 -virtual at bp - rb 3 ; BS_jmpBoot - rb 8 ; BS_OEMName, ignored - dw ? ; BPB_BytsPerSec -BPB_SecsPerClus db ? -BPB_RsvdSecCnt dw ? -BPB_NumFATs db ? -BPB_RootEntCnt dw ? -BPB_TotSec16 dw ? - db ? ; BPB_Media -BPB_FATSz16 dw ? -BPB_SecPerTrk dw ? -BPB_NumHeads dw ? -BPB_HiddSec dd ? -BPB_TotSec32 dd ? -BS_DrvNum db ? -fat_type db ? ; this is BS_Reserved1, - ; we use it to save FS type: 0=FAT12, 1=FAT16 - db ? ; BS_BootSig -num_sectors dd ? ; BS_VolID -; rb 11 ; BS_VolLab -; rb 3 ; BS_FilSysType, first 3 bytes -read_sectors dw ? -read_sectors2 dw ? -lookup_in_root_dir dw ? -scan_for_filename dw ? -err_ dw ? -noloader dw ? -cachelimit dw ? -filesize: ; will be used to save file size - rb 5 ; BS_FilSysType, last 5 bytes -; following variables are located in the place of starting code; -; starting code is no more used at this point -sect_per_clus dw ? -cur_cluster dw ? -next_cluster dw ? -flags dw ? -cur_delta dd ? -end virtual - -; procedures from boot sector -; LBA version -lba_read_sectors = 7CE2h -lba_read_sectors2 = 7CDCh -lba_lookup_in_root_dir = 7D4Fh -lba_scan_for_filename = 7D2Dh -lba_err = 7CB5h -lba_noloader = 7CB2h -; CHS version -chs_read_sectors = 7CDEh -chs_read_sectors2 = 7CD8h -chs_lookup_in_root_dir = 7D70h -chs_scan_for_filename = 7D4Eh -chs_err = 7CB1h -chs_noloader = 7CAEh - - push ax cx ; save our position on disk - push ss - pop es -; determine version of bootsector (LBA vs CHS) -; mov [read_sectors], chs_read_sectors -; mov [read_sectors2], chs_read_sectors2 -; mov [lookup_in_root_dir], chs_lookup_in_root_dir -; mov [scan_for_filename], chs_scan_for_filename -; mov [err], chs_err -; mov [noloader], chs_noloader - lea di, [read_sectors] - mov si, chs_proc_addresses - mov cx, 6*2 - cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' - jz @f - add si, cx -; mov [read_sectors], lba_read_sectors -; mov [read_sectors2], lba_read_sectors2 -; mov [lookup_in_root_dir], lba_lookup_in_root_dir -; mov [scan_for_filename], lba_scan_for_filename -; mov [err], lba_err -; mov [noloader], lba_noloader -@@: - rep movsb - mov cl, [BPB_SecsPerClus] - mov [sect_per_clus], cx - xor bx, bx -; determine size of cache for folders - int 12h ; ax = size of available base memory in Kb - sub ax, 94000h / 1024 - jae @f -nomem: - mov si, nomem_str - jmp [err_] -@@: - shr ax, 3 - mov [cachelimit], ax ; size of cache - 1 -; get type of file system - FAT12 or FAT16? -; calculate number of clusters - mov ax, [BPB_TotSec16] - xor dx, dx - test ax, ax - jnz @f - mov ax, word [BPB_TotSec32] - mov dx, word [BPB_TotSec32+2] -@@: - sub ax, [bp-8] ; dword [bp-8] = first data sector - sbb dx, [bp-6] - jb j_noloader - div [sect_per_clus] -; ax = number of clusters -; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes - mov [fat_type], ch - cmp ax, 0xFF5 - jb init_fat12 - inc [fat_type] -init_fat16: -; no sectors loaded - mov di, 0x8200 - xor ax, ax - mov cx, 0x100/2 - rep stosw - jmp init_fat_done -init_fat12: -; read FAT - push 0x6000 - pop es - mov ax, [BPB_RsvdSecCnt] - mov cx, [BPB_FATSz16] - cmp cx, 12 - jb @f - mov cx, 12 -@@: - xor dx, dx - call [read_sectors] -init_fat_done: -; if cluster = sector, we need to read second part of our file -; (bootsector loads only first cluster of kordldr.f1x) - pop cx ax ; restore our position on disk - cmp cx, 1 - ja kordldr_full - sub ax, [bp-8] - inc ax - inc ax ; ax = first cluster of kordldr.f12 - call get_next_cluster - jc @f -j_noloader: - jmp [noloader] -@@: - dec ax - dec ax - push 0x800 - pop es - call [read_sectors2] -kordldr_full: -; ...continue loading... - mov di, secondary_loader_info - call load_file - test bx, bx - mov bx, [err_] - jz @f - mov si, aKernelNotFound - jmp bx -@@: -; for subsequent calls to callback function, hook error handler -; mov byte [bx], 0xE9 ; 'jmp' opcode -; mov ax, hooked_err - 3 -; sub ax, bx -; mov word [bx+1], ax -; push hooked_err / ret - mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) - mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) -; set registers for secondary loader - mov ah, [BS_DrvNum] - mov al, 'f' - test ah, ah - jns @f - sub ah, 80h - mov al, 'h' -@@: - mov bx, '12' - cmp [fat_type], 0 - jz @f - mov bh, '6' -@@: - mov si, callback ; ds:si = far pointer to callback procedure - jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 - -nomem_str db 'No memory',0 - -chs_proc_addresses: - dw chs_read_sectors - dw chs_read_sectors2 - dw chs_lookup_in_root_dir - dw chs_scan_for_filename - dw chs_err - dw chs_noloader -lba_proc_addresses: - dw lba_read_sectors - dw lba_read_sectors2 - dw lba_lookup_in_root_dir - dw lba_scan_for_filename - dw lba_err - dw lba_noloader - -get_next_cluster: -; in: ax = cluster -; out: if there is next cluster: CF=1, ax = next cluster -; out: if there is no next cluster: CF=0 - push si - cmp [fat_type], 0 - jnz gnc16 -; for FAT12 - push ds - push 0x6000 - pop ds - mov si, ax - shr si, 1 - add si, ax - test al, 1 - lodsw - jz @f - shr ax, 4 -@@: - and ax, 0xFFF - cmp ax, 0xFF7 - pop ds si - ret -; for FAT16 -gnc16: -; each sector contains 200h bytes = 100h FAT entries -; so ah = # of sector, al = offset in sector - mov si, ax - mov ah, 0 - shr si, 8 -; calculate segment for this sector of FAT table -; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) -; segment = 6000 + 20*si, offset = 0 - push es - push si - shl si, 5 - add si, 0x6000 - mov es, si - pop si - cmp byte [ss:0x8200+si], ah ; sector already loaded? - jnz @f -; load corresponding sector - pusha - push es - xor bx, bx - mov ax, [BPB_RsvdSecCnt] - xor dx, dx - add ax, si - adc dx, bx - mov cx, 1 ; read 1 sector - call [read_sectors] - pop es - popa -@@: - mov si, ax - add si, si -; mov ax, [es:si] - lods word [es:si] - pop es - cmp ax, 0xFFF7 - pop si - ret - -if $ > 0x8000 -error 'get_next_cluster must fit in first sector of kordldr.f1x!' -end if - -load_file: -; in: ss:bp = 0:7C00 -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) - xor ax, ax ; start from root directory - mov dx, -1 - mov word [filesize], dx - mov word [filesize+2], dx ; initialize file size with invalid value - lea si, [di+6] -parse_dir_loop: -; convert name to FAT name - push di - push ax - push ss - pop es -; convert ASCIIZ filename to FAT name - mov di, filename - push di - mov cx, 8+3 - mov al, ' ' - rep stosb - pop di - mov cl, 8 ; 8 symbols per name - mov bl, 1 -nameloop: - lodsb - test al, al - jz namedone - cmp al, '/' - jz namedone - cmp al, '.' - jz namedot - dec cx - js badname - cmp al, 'a' - jb @f - cmp al, 'z' - ja @f - sub al, 'a'-'A' -@@: - stosb - jmp nameloop -namedot: - inc bx - jp badname - add di, cx - mov cl, 3 - jmp nameloop -badname: ; do not make direct js/jp to notfound_pop: - ; this generates long forms of conditional jumps and results in longer code - jmp notfound_pop -namedone: -; scan directory - pop ax ; ax = cluster of directory or 0 for root - push ds - push si - push es - pop ds - mov si, filename ; ds:si -> filename in FAT style - test ax, ax - jnz lookup_in_notroot_dir -; for root directory, use the subroutine from bootsector - call [lookup_in_root_dir] - jmp lookup_done -lookup_in_notroot_dir: -; for other directories, read a folder sector-by-sector and scan -; first, try to use the cache - push ds - push cs - pop ds - mov bx, [cachelimit] - add bx, bx - mov di, foldcache_mark -@@: - mov dx, [foldcache_clus+di-foldcache_mark+bx] - cmp dx, ax - jz cacheok - test dx, dx - jz cacheadd ; the cache has place for new entry - dec bx - dec bx - jns @b -; the folder is not present in the cache, so add it -; the cache is full; find the oldest entry and replace it with the new one - mov dx, [cachelimit] -@@: - inc bx - inc bx - cmp word [di+bx], dx ; marks have values 0 through [cachelimit] - jnz @b -cacheadd: - or word [di+bx], 0xFFFF ; very big value, it will be changed soon - mov [foldcache_clus+di-foldcache_mark+bx], ax - and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet -cacheok: -; update cache marks - mov dx, [di+bx] - mov cx, [foldcache_size+di-foldcache_mark+bx] - mov di, [cachelimit] - add di, di -cacheupdate: - cmp [foldcache_mark+di], dx - adc [foldcache_mark+di], 0 - dec di - dec di - jns cacheupdate - and [foldcache_mark+bx], 0 -; done, bx contains (position in cache)*2 - pop ds -; mov dx, bx -; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 -; add dx, 0x9200 - lea dx, [bx+0x92] - xchg dl, dh - mov es, dx - jcxz not_in_cache - call [scan_for_filename] - jz lookup_done -not_in_cache: -; cache miss, read folder data from disk - mov bx, cx - shr bx, 4 - shl cx, 5 - mov di, cx ; es:di -> free space in cache entry -; external loop: scan clusters -folder_next_cluster: -; internal loop: scan sectors in cluster - mov cx, [sect_per_clus] - push ax - dec ax - dec ax - mul cx - add ax, [bp-8] - adc dx, [bp-6] ; dx:ax = absolute sector -folder_next_sector: -; skip first bx sectors - dec bx - jns folder_skip_sector - push cx - push es di - push 0x8000 - pop es - xor bx, bx - mov cx, 1 - push es - call [read_sectors] -; copy data to the cache... - pop ds - pop di es - cmp di, 0x2000 ; ...if there is free space, of course - jae @f - push si di - mov cx, 0x100 - xor si, si - rep movsw - mov di, es - shr di, 8 - add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache - pop di si -@@: - push es - push 0x8000 - pop es - push cs - pop ds - mov cx, 0x10 - call [scan_for_filename] - pop es - pop cx - jz lookup_done_pop -folder_skip_sector: - inc ax - jnz @f - inc dx -@@: - loop folder_next_sector - pop ax ; ax = current cluster - call get_next_cluster - jc folder_next_cluster - stc - push ax -lookup_done_pop: - pop ax -lookup_done: - pop si - pop ds -; CF=1 <=> failed - jnc found -notfound: - pop di - mov bx, 2 ; file not found - mov ax, 0xFFFF - mov dx, ax ; invalid file size - ret -notfound_pop: - pop ax - jmp notfound -found: - mov ax, [es:di+26] ; get cluster - test byte [es:di+11], 10h ; directory? - jz regular_file - cmp byte [si-1], 0 - jz notfound ; don't read directories as a regular files -; ok, we have found a directory and the caller requested a file into it - pop di - jmp parse_dir_loop ; restart with new cluster in ax -regular_file: - cmp byte [si-1], 0 - jnz notfound ; file does not contain another files -; ok, we have found a regular file and the caller requested it -; save file size - mov dx, [es:di+28] - mov [filesize], dx - mov dx, [es:di+30] - mov [filesize+2], dx - pop di - mov si, [di+4] - shl si, 3 - push si ; [ds:di+4] = limit in 4K blocks - les bx, [di] ; es:bx -> buffer -clusloop: -; ax = first cluster, top of stack contains limit in sectors - mov si, ax ; remember current cluster - xor cx, cx ; cx will contain number of consecutive clusters - mov word [cur_delta], cx - mov word [cur_delta+2], cx - mov di, ax -clusfind: - inc di - inc cx - call get_next_cluster - jnc clusread - cmp ax, di - jz clusfind - stc -clusread: - pop di ; limit in sectors - push ax ; save next cluster - pushf ; save flags -; read cx clusters, starting from si -; calculate number of sectors - xchg ax, cx - mul [sect_per_clus] -; dx:ax = number of sectors; compare with limit - mov word [num_sectors], ax - mov word [num_sectors+2], dx - jmp @f -continue_load_file: - les bx, [di] ; es:bx -> buffer - mov di, [di+4] ; ds:di = limit in 4K blocks - shl di, 3 ; now di = limit in sectors - mov ax, word [num_sectors] - mov dx, word [num_sectors+2] - mov si, [cur_cluster] - push [next_cluster] - push [flags] - or ax, dx - jz nextclus -@@: - test dx, dx - jnz clusdecrease - push dx ; limit was not exceeded - cmp ax, di - jbe @f - pop ax -clusdecrease: - push 1 ; limit was exceeded - mov ax, di -@@: - sub di, ax ; calculate new limit - sub word [num_sectors], ax - sbb word [num_sectors+2], 0 -readloop: - push ax -; buffer should not cross a 64K boundary - push bx - shr bx, 4 - mov cx, es - add bx, cx - neg bx - and bh, 0xF - shr bx, 5 - jnz @f - mov bl, 0x80 -@@: - cmp ax, bx - jbe @f - xchg ax, bx -@@: - pop bx - xchg ax, cx -; calculate starting sector - lea ax, [si-2] - mul [sect_per_clus] - add ax, word [cur_delta] - adc dx, word [cur_delta+2] - add word [cur_delta], cx - adc word [cur_delta+2], 0 -; read - call [read_sectors2] - pop ax - sub ax, cx - jnz readloop - pop dx -; next cluster? -nextclus: - popf - pop ax - mov [cur_cluster], si - mov [next_cluster], ax - pushf - pop [flags] - jnc @f ; no next cluster => return - mov dl, 1 ; dh=0 in any case - test di, di - jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded - push di - jmp clusloop ; all is ok, continue -hooked_err: - mov sp, 7C00h-12-2 ; restore stack - mov dx, 3 ; return: read error -@@: - mov bx, dx - mov ax, [filesize] - mov dx, [filesize+2] - ret - -; Callback function for secondary loader -callback: -; in: ax = function number; only functions 1 and 2 are defined for now -; save caller's stack - mov dx, ss - mov cx, sp -; set our stack (required because we need ss=0) - xor si, si - mov ss, si - mov sp, 7C00h-8 - mov bp, 7C00h - push dx - push cx -; call our function - stc ; unsupported function - dec ax - jz callback_readfile - dec ax - jnz callback_ret -; function 2: continue loading file -; can be called only after function 1 returned value bx=1 (only part of file was loaded) -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error -; out: dx:ax = file size - call continue_load_file - jmp callback_ret_succ -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call load_file -callback_ret_succ: - clc ; function is supported -callback_ret: -; restore caller's stack - pop cx - pop ss - mov sp, cx -; return to caller - retf - -secondary_loader_info: - dw 0, 0x1000 - dw 0x30000 / 0x1000 - db 'kernel.mnt',0 -aKernelNotFound db 'Fatal error: cannot load the kernel',0 - -foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache -foldcache_mark rw 7 -foldcache_size rw 7 -filename rb 11 -if $ > 0x8200 -error: table overwritten -end if +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + + org 0x7E00 +; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here +; ss:bp = 0:7C00 +virtual at bp + rb 3 ; BS_jmpBoot + rb 8 ; BS_OEMName, ignored + dw ? ; BPB_BytsPerSec +BPB_SecsPerClus db ? +BPB_RsvdSecCnt dw ? +BPB_NumFATs db ? +BPB_RootEntCnt dw ? +BPB_TotSec16 dw ? + db ? ; BPB_Media +BPB_FATSz16 dw ? +BPB_SecPerTrk dw ? +BPB_NumHeads dw ? +BPB_HiddSec dd ? +BPB_TotSec32 dd ? +BS_DrvNum db ? +fat_type db ? ; this is BS_Reserved1, + ; we use it to save FS type: 0=FAT12, 1=FAT16 + db ? ; BS_BootSig +num_sectors dd ? ; BS_VolID +; rb 11 ; BS_VolLab +; rb 3 ; BS_FilSysType, first 3 bytes +read_sectors dw ? +read_sectors2 dw ? +lookup_in_root_dir dw ? +scan_for_filename dw ? +err_ dw ? +noloader dw ? +cachelimit dw ? +filesize: ; will be used to save file size + rb 5 ; BS_FilSysType, last 5 bytes +; following variables are located in the place of starting code; +; starting code is no more used at this point +sect_per_clus dw ? +cur_cluster dw ? +next_cluster dw ? +flags dw ? +cur_delta dd ? +end virtual + +; procedures from boot sector +; LBA version +lba_read_sectors = 7CE2h +lba_read_sectors2 = 7CDCh +lba_lookup_in_root_dir = 7D4Fh +lba_scan_for_filename = 7D2Dh +lba_err = 7CB5h +lba_noloader = 7CB2h +; CHS version +chs_read_sectors = 7CDEh +chs_read_sectors2 = 7CD8h +chs_lookup_in_root_dir = 7D70h +chs_scan_for_filename = 7D4Eh +chs_err = 7CB1h +chs_noloader = 7CAEh + + push ax cx ; save our position on disk + push ss + pop es +; determine version of bootsector (LBA vs CHS) +; mov [read_sectors], chs_read_sectors +; mov [read_sectors2], chs_read_sectors2 +; mov [lookup_in_root_dir], chs_lookup_in_root_dir +; mov [scan_for_filename], chs_scan_for_filename +; mov [err], chs_err +; mov [noloader], chs_noloader + lea di, [read_sectors] + mov si, chs_proc_addresses + mov cx, 6*2 + cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' + jz @f + add si, cx +; mov [read_sectors], lba_read_sectors +; mov [read_sectors2], lba_read_sectors2 +; mov [lookup_in_root_dir], lba_lookup_in_root_dir +; mov [scan_for_filename], lba_scan_for_filename +; mov [err], lba_err +; mov [noloader], lba_noloader +@@: + rep movsb + mov cl, [BPB_SecsPerClus] + mov [sect_per_clus], cx + xor bx, bx +; determine size of cache for folders + int 12h ; ax = size of available base memory in Kb + sub ax, 94000h / 1024 + jae @f +nomem: + mov si, nomem_str + jmp [err_] +@@: + shr ax, 3 + mov [cachelimit], ax ; size of cache - 1 +; get type of file system - FAT12 or FAT16? +; calculate number of clusters + mov ax, [BPB_TotSec16] + xor dx, dx + test ax, ax + jnz @f + mov ax, word [BPB_TotSec32] + mov dx, word [BPB_TotSec32+2] +@@: + sub ax, [bp-8] ; dword [bp-8] = first data sector + sbb dx, [bp-6] + jb j_noloader + div [sect_per_clus] +; ax = number of clusters +; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes + mov [fat_type], ch + cmp ax, 0xFF5 + jb init_fat12 + inc [fat_type] +init_fat16: +; no sectors loaded + mov di, 0x8200 + xor ax, ax + mov cx, 0x100/2 + rep stosw + jmp init_fat_done +init_fat12: +; read FAT + push 0x6000 + pop es + mov ax, [BPB_RsvdSecCnt] + mov cx, [BPB_FATSz16] + cmp cx, 12 + jb @f + mov cx, 12 +@@: + xor dx, dx + call [read_sectors] +init_fat_done: +; if cluster = sector, we need to read second part of our file +; (bootsector loads only first cluster of kordldr.f1x) + pop cx ax ; restore our position on disk + cmp cx, 1 + ja kordldr_full + sub ax, [bp-8] + inc ax + inc ax ; ax = first cluster of kordldr.f12 + call get_next_cluster + jc @f +j_noloader: + jmp [noloader] +@@: + dec ax + dec ax + push 0x800 + pop es + call [read_sectors2] +kordldr_full: +; ...continue loading... + mov di, secondary_loader_info + call load_file + test bx, bx + mov bx, [err_] + jz @f + mov si, aKernelNotFound + jmp bx +@@: +; for subsequent calls to callback function, hook error handler +; mov byte [bx], 0xE9 ; 'jmp' opcode +; mov ax, hooked_err - 3 +; sub ax, bx +; mov word [bx+1], ax +; push hooked_err / ret + mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) + mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) +; set registers for secondary loader + mov ah, [BS_DrvNum] + mov al, 'f' + test ah, ah + jns @f + sub ah, 80h + mov al, 'h' +@@: + mov bx, '12' + cmp [fat_type], 0 + jz @f + mov bh, '6' +@@: + mov si, callback ; ds:si = far pointer to callback procedure + jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 + +nomem_str db 'No memory',0 + +chs_proc_addresses: + dw chs_read_sectors + dw chs_read_sectors2 + dw chs_lookup_in_root_dir + dw chs_scan_for_filename + dw chs_err + dw chs_noloader +lba_proc_addresses: + dw lba_read_sectors + dw lba_read_sectors2 + dw lba_lookup_in_root_dir + dw lba_scan_for_filename + dw lba_err + dw lba_noloader + +get_next_cluster: +; in: ax = cluster +; out: if there is next cluster: CF=1, ax = next cluster +; out: if there is no next cluster: CF=0 + push si + cmp [fat_type], 0 + jnz gnc16 +; for FAT12 + push ds + push 0x6000 + pop ds + mov si, ax + shr si, 1 + add si, ax + test al, 1 + lodsw + jz @f + shr ax, 4 +@@: + and ax, 0xFFF + cmp ax, 0xFF7 + pop ds si + ret +; for FAT16 +gnc16: +; each sector contains 200h bytes = 100h FAT entries +; so ah = # of sector, al = offset in sector + mov si, ax + mov ah, 0 + shr si, 8 +; calculate segment for this sector of FAT table +; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) +; segment = 6000 + 20*si, offset = 0 + push es + push si + shl si, 5 + add si, 0x6000 + mov es, si + pop si + cmp byte [ss:0x8200+si], ah ; sector already loaded? + jnz @f +; load corresponding sector + pusha + push es + xor bx, bx + mov ax, [BPB_RsvdSecCnt] + xor dx, dx + add ax, si + adc dx, bx + mov cx, 1 ; read 1 sector + call [read_sectors] + pop es + popa +@@: + mov si, ax + add si, si +; mov ax, [es:si] + lods word [es:si] + pop es + cmp ax, 0xFFF7 + pop si + ret + +if $ > 0x8000 +error 'get_next_cluster must fit in first sector of kordldr.f1x!' +end if + +load_file: +; in: ss:bp = 0:7C00 +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) + xor ax, ax ; start from root directory + mov dx, -1 + mov word [filesize], dx + mov word [filesize+2], dx ; initialize file size with invalid value + lea si, [di+6] +parse_dir_loop: +; convert name to FAT name + push di + push ax + push ss + pop es +; convert ASCIIZ filename to FAT name + mov di, filename + push di + mov cx, 8+3 + mov al, ' ' + rep stosb + pop di + mov cl, 8 ; 8 symbols per name + mov bl, 1 +nameloop: + lodsb + test al, al + jz namedone + cmp al, '/' + jz namedone + cmp al, '.' + jz namedot + dec cx + js badname + cmp al, 'a' + jb @f + cmp al, 'z' + ja @f + sub al, 'a'-'A' +@@: + stosb + jmp nameloop +namedot: + inc bx + jp badname + add di, cx + mov cl, 3 + jmp nameloop +badname: ; do not make direct js/jp to notfound_pop: + ; this generates long forms of conditional jumps and results in longer code + jmp notfound_pop +namedone: +; scan directory + pop ax ; ax = cluster of directory or 0 for root + push ds + push si + push es + pop ds + mov si, filename ; ds:si -> filename in FAT style + test ax, ax + jnz lookup_in_notroot_dir +; for root directory, use the subroutine from bootsector + call [lookup_in_root_dir] + jmp lookup_done +lookup_in_notroot_dir: +; for other directories, read a folder sector-by-sector and scan +; first, try to use the cache + push ds + push cs + pop ds + mov bx, [cachelimit] + add bx, bx + mov di, foldcache_mark +@@: + mov dx, [foldcache_clus+di-foldcache_mark+bx] + cmp dx, ax + jz cacheok + test dx, dx + jz cacheadd ; the cache has place for new entry + dec bx + dec bx + jns @b +; the folder is not present in the cache, so add it +; the cache is full; find the oldest entry and replace it with the new one + mov dx, [cachelimit] +@@: + inc bx + inc bx + cmp word [di+bx], dx ; marks have values 0 through [cachelimit] + jnz @b +cacheadd: + or word [di+bx], 0xFFFF ; very big value, it will be changed soon + mov [foldcache_clus+di-foldcache_mark+bx], ax + and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet +cacheok: +; update cache marks + mov dx, [di+bx] + mov cx, [foldcache_size+di-foldcache_mark+bx] + mov di, [cachelimit] + add di, di +cacheupdate: + cmp [foldcache_mark+di], dx + adc [foldcache_mark+di], 0 + dec di + dec di + jns cacheupdate + and [foldcache_mark+bx], 0 +; done, bx contains (position in cache)*2 + pop ds +; mov dx, bx +; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 +; add dx, 0x9200 + lea dx, [bx+0x92] + xchg dl, dh + mov es, dx + jcxz not_in_cache + call [scan_for_filename] + jz lookup_done +not_in_cache: +; cache miss, read folder data from disk + mov bx, cx + shr bx, 4 + shl cx, 5 + mov di, cx ; es:di -> free space in cache entry +; external loop: scan clusters +folder_next_cluster: +; internal loop: scan sectors in cluster + mov cx, [sect_per_clus] + push ax + dec ax + dec ax + mul cx + add ax, [bp-8] + adc dx, [bp-6] ; dx:ax = absolute sector +folder_next_sector: +; skip first bx sectors + dec bx + jns folder_skip_sector + push cx + push es di + push 0x8000 + pop es + xor bx, bx + mov cx, 1 + push es + call [read_sectors] +; copy data to the cache... + pop ds + pop di es + cmp di, 0x2000 ; ...if there is free space, of course + jae @f + push si di + mov cx, 0x100 + xor si, si + rep movsw + mov di, es + shr di, 8 + add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache + pop di si +@@: + push es + push 0x8000 + pop es + push cs + pop ds + mov cx, 0x10 + call [scan_for_filename] + pop es + pop cx + jz lookup_done_pop +folder_skip_sector: + inc ax + jnz @f + inc dx +@@: + loop folder_next_sector + pop ax ; ax = current cluster + call get_next_cluster + jc folder_next_cluster + stc + push ax +lookup_done_pop: + pop ax +lookup_done: + pop si + pop ds +; CF=1 <=> failed + jnc found +notfound: + pop di + mov bx, 2 ; file not found + mov ax, 0xFFFF + mov dx, ax ; invalid file size + ret +notfound_pop: + pop ax + jmp notfound +found: + mov ax, [es:di+26] ; get cluster + test byte [es:di+11], 10h ; directory? + jz regular_file + cmp byte [si-1], 0 + jz notfound ; don't read directories as a regular files +; ok, we have found a directory and the caller requested a file into it + pop di + jmp parse_dir_loop ; restart with new cluster in ax +regular_file: + cmp byte [si-1], 0 + jnz notfound ; file does not contain another files +; ok, we have found a regular file and the caller requested it +; save file size + mov dx, [es:di+28] + mov [filesize], dx + mov dx, [es:di+30] + mov [filesize+2], dx + pop di + mov si, [di+4] + shl si, 3 + push si ; [ds:di+4] = limit in 4K blocks + les bx, [di] ; es:bx -> buffer +clusloop: +; ax = first cluster, top of stack contains limit in sectors + mov si, ax ; remember current cluster + xor cx, cx ; cx will contain number of consecutive clusters + mov word [cur_delta], cx + mov word [cur_delta+2], cx + mov di, ax +clusfind: + inc di + inc cx + call get_next_cluster + jnc clusread + cmp ax, di + jz clusfind + stc +clusread: + pop di ; limit in sectors + push ax ; save next cluster + pushf ; save flags +; read cx clusters, starting from si +; calculate number of sectors + xchg ax, cx + mul [sect_per_clus] +; dx:ax = number of sectors; compare with limit + mov word [num_sectors], ax + mov word [num_sectors+2], dx + jmp @f +continue_load_file: + les bx, [di] ; es:bx -> buffer + mov di, [di+4] ; ds:di = limit in 4K blocks + shl di, 3 ; now di = limit in sectors + mov ax, word [num_sectors] + mov dx, word [num_sectors+2] + mov si, [cur_cluster] + push [next_cluster] + push [flags] + or ax, dx + jz nextclus +@@: + test dx, dx + jnz clusdecrease + push dx ; limit was not exceeded + cmp ax, di + jbe @f + pop ax +clusdecrease: + push 1 ; limit was exceeded + mov ax, di +@@: + sub di, ax ; calculate new limit + sub word [num_sectors], ax + sbb word [num_sectors+2], 0 +readloop: + push ax +; buffer should not cross a 64K boundary + push bx + shr bx, 4 + mov cx, es + add bx, cx + neg bx + and bh, 0xF + shr bx, 5 + jnz @f + mov bl, 0x80 +@@: + cmp ax, bx + jbe @f + xchg ax, bx +@@: + pop bx + xchg ax, cx +; calculate starting sector + lea ax, [si-2] + mul [sect_per_clus] + add ax, word [cur_delta] + adc dx, word [cur_delta+2] + add word [cur_delta], cx + adc word [cur_delta+2], 0 +; read + call [read_sectors2] + pop ax + sub ax, cx + jnz readloop + pop dx +; next cluster? +nextclus: + popf + pop ax + mov [cur_cluster], si + mov [next_cluster], ax + pushf + pop [flags] + jnc @f ; no next cluster => return + mov dl, 1 ; dh=0 in any case + test di, di + jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded + push di + jmp clusloop ; all is ok, continue +hooked_err: + mov sp, 7C00h-12-2 ; restore stack + mov dx, 3 ; return: read error +@@: + mov bx, dx + mov ax, [filesize] + mov dx, [filesize+2] + ret + +; Callback function for secondary loader +callback: +; in: ax = function number; only functions 1 and 2 are defined for now +; save caller's stack + mov dx, ss + mov cx, sp +; set our stack (required because we need ss=0) + xor si, si + mov ss, si + mov sp, 7C00h-8 + mov bp, 7C00h + push dx + push cx +; call our function + stc ; unsupported function + dec ax + jz callback_readfile + dec ax + jnz callback_ret +; function 2: continue loading file +; can be called only after function 1 returned value bx=1 (only part of file was loaded) +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error +; out: dx:ax = file size + call continue_load_file + jmp callback_ret_succ +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call load_file +callback_ret_succ: + clc ; function is supported +callback_ret: +; restore caller's stack + pop cx + pop ss + mov sp, cx +; return to caller + retf + +secondary_loader_info: + dw 0, 0x1000 + dw 0x30000 / 0x1000 + db 'kernel.mnt',0 +aKernelNotFound db 'Fatal error: cannot load the kernel',0 + +foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache +foldcache_mark rw 7 +foldcache_size rw 7 +filename rb 11 +if $ > 0x8200 +error: + table overwritten +end if diff --git a/kernel/trunk/bootloader/extended_primary_loader/fat32/bootsect.asm b/kernel/trunk/bootloader/extended_primary_loader/fat32/bootsect.asm index 3dbee8865..69f16c459 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/fat32/bootsect.asm +++ b/kernel/trunk/bootloader/extended_primary_loader/fat32/bootsect.asm @@ -1,358 +1,358 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -use_lba = 0 - org 0x7C00 - jmp start - nop -; FAT parameters, BPB -; they must be changed at install, replaced with real values - rb 8 ; BS_OEMName, ignored - dw 200h ; BPB_BytsPerSec -BPB_SecsPerClus db ? -BPB_RsvdSecCnt dw ? -BPB_NumFATs db ? -BPB_RootEntCnt dw ? - dw ? ; BPB_TotSec16 - db ? ; BPB_Media - dw ? ; BPB_FATSz16 = 0 for FAT32 -BPB_SecPerTrk dw ? -BPB_NumHeads dw ? -BPB_HiddSec dd ? - dd ? ; BPB_TotSec32 -BPB_FATSz32 dd ? -BPB_ExtFlags dw ? - dw ? ; BPB_FSVer -BPB_RootClus dd ? - dw ? ; BPB_FSInfo -BPB_BkBootSec dw ? - rb 12 ; BPB_Reserved -BS_DrvNum db ? - db ? ; BS_Reserved1 - db ? ; BS_BootSig - dd ? ; BS_VolID - rb 11 ; BS_VolLab - rb 8 ; - -curseg dw 0x8000 - -start: - xor ax, ax - mov ss, ax - mov sp, 0x7C00 - mov ds, ax - mov bp, sp - cld - sti - push dx ; byte [bp-2] = boot drive -if use_lba - mov ah, 41h - mov bx, 55AAh - int 13h - mov si, aNoLBA - jc err_ - cmp bx, 0AA55h - jnz err_ - test cl, 1 - jz err_ -else - mov ah, 8 - int 13h - jc @f - movzx ax, dh - inc ax - mov [bp+BPB_NumHeads-0x7C00], ax - and cx, 3Fh - mov [bp+BPB_SecPerTrk-0x7C00], cx -@@: -end if -; get FAT parameters - xor bx, bx - movzx eax, [bp+BPB_NumFATs-0x7C00] - mul [bp+BPB_FATSz32-0x7C00] - movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] - push ecx ; FAT start = dword [bp-6] - add eax, ecx - push eax ; data start = dword [bp-10] - ;push dword -1 ; dword [bp-14] = current sector for FAT cache - db 66h - push -1 ; dword [bp-14] = current sector for FAT cache - mov eax, [bp+BPB_RootClus-0x7C00] - mov si, main_loader - call lookup_in_dir - jnc kordldr_ok -noloader: - mov si, aLoaderNotFound -err_: - call out_string - mov si, aPressAnyKey - call out_string - xor ax, ax - int 16h - int 18h - jmp $ -kordldr_ok: - mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) - mov ax, [es:di+26] ; loword(eax) = loword(cluster) - mov es, bx ; es = 0 - mov bx, 0x7E00 - push bx ; save return address: bx = 7E00 -; fall through - 'ret' in read_cluster will return to 7E00 - -read_cluster: -; ss:bp = 0:7C00 -; es:bx = pointer to data -; eax = cluster - sub eax, 2 - movzx ecx, [bp+BPB_SecsPerClus-0x7C00] - mul ecx - -read_sectors2: -; same as read_sectors32, but eax is relative to start of data - add eax, [bp-10] -read_sectors32: -; ss:bp = 0:7C00 -; es:bx = pointer to data -; eax = first sector -; cx = number of sectors -; some high words of 32-bit registers are destroyed! - pusha - add eax, [bp+BPB_HiddSec-0x7C00] -if use_lba - push ds -do_read_sectors: - push ax - push cx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - push 0 - push 0 - push eax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [bp-2] - mov ah, 42h - int 13h - mov si, aReadError - jc err_ -; restore stack - add sp, 10h -; increase current sector & buffer; decrease number of sectors - movzx esi, cx - mov ax, es - shl cx, 5 - add ax, cx - mov es, ax - pop cx - pop ax - add eax, esi - sub cx, si - jnz do_read_sectors - pop ds - popa - ret -else -do_read_sectors: - pusha - pop edi ; loword(edi) = di, hiword(edi) = si - push bx - -; eax / (SectorsPerTrack) -> eax, remainder bx - movzx esi, [bp+BPB_SecPerTrk-0x7C00] - xor edx, edx - div esi - mov bx, dx ; bx=sector-1 - -; eax -> dx:ax - push eax - pop ax - pop dx -; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx - div [bp+BPB_NumHeads-0x7C00] - -; number of sectors: read no more than to end of track - sub si, bx - cmp cx, si - jbe @f - mov cx, si -@@: - - inc bx -; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format - movzx edi, cx - mov dh, dl - mov dl, [bp-2] - shl ah, 6 - mov ch, al - mov al, cl - mov cl, bl - or cl, ah - pop bx - mov si, 3 - mov ah, 2 -@@: - push ax - int 13h - jnc @f - xor ax, ax - int 13h ; reset drive - pop ax - dec si - jnz @b - mov si, aReadError - jmp err_ -@@: - pop ax - mov ax, es - mov cx, di - shl cx, 5 - add ax, cx - mov es, ax - push edi - popa - add eax, edi - sub cx, di - jnz do_read_sectors - popa - ret -end if - -lookup_in_dir: -; in: ds:si -> 11-bytes FAT name -; in: eax = cluster -; in: bx = 0 -; out: if found: CF=0, es:di -> directory entry -; out: if not found: CF=1 -; push 0x8000 -; pop es -; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 - mov es, [bp-7C00h + curseg] - push es - push eax - call read_cluster - mov ax, es - cmp ah, 82h - jb @f - mov ax, 8200h -@@: - mov [bp-7C00h + curseg], ax - pop eax - pop es -; scan for filename - shl cx, 4 - xor di, di -sloop: - cmp byte [es:di], bl - jz snotfound - test byte [es:di+11], 8 ; volume label? - jnz scont ; ignore volume labels - pusha - mov cx, 11 - repz cmpsb - popa - jz sdone -scont: - add di, 0x20 - loop sloop -; next cluster - push 0x6000 - pop es - push es ax - shr eax, 7 - cmp eax, [bp-14] - mov [bp-14], eax - jz @f - add eax, [bp-6] - mov cx, 1 - call read_sectors32 -@@: - pop di es - and di, 0x7F - shl di, 2 - and byte [es:di+3], 0x0F - mov eax, [es:di] - ;and eax, 0x0FFFFFFF - cmp eax, 0x0FFFFFF7 - jb lookup_in_dir -snotfound: - stc -sdone: - ret - -out_string: -; in: ds:si -> ASCIIZ string - lodsb - test al, al - jz sdone - mov ah, 0Eh - mov bx, 7 - int 10h - jmp out_string - -aReadError db 'Read error',0 -if use_lba -aNoLBA db 'The drive does not support LBA!',0 -end if -aLoaderNotFound db 'Loader not found',0 -aPressAnyKey db 13,10,'Press any key...',13,10,0 -main_loader db 'KORDLDR F32' - - db 56h -; just to make file 512 bytes long :) - db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' - -; bootsector signature - dw 0xAA55 - -; display offsets of all procedures used by kordldr.f12.asm -macro show [procedure] -{ - bits = 16 - display `procedure,' = ' - repeat bits/4 - d = '0' + procedure shr (bits - %*4) and 0Fh - if d > '9' - d = d + 'A'-'9'-1 - end if - display d - end repeat - display 13,10 -} - -show read_sectors32, read_sectors2, err_, noloader +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +use_lba = 0 + org 0x7C00 + jmp start + nop +; FAT parameters, BPB +; they must be changed at install, replaced with real values + rb 8 ; BS_OEMName, ignored + dw 200h ; BPB_BytsPerSec +BPB_SecsPerClus db ? +BPB_RsvdSecCnt dw ? +BPB_NumFATs db ? +BPB_RootEntCnt dw ? + dw ? ; BPB_TotSec16 + db ? ; BPB_Media + dw ? ; BPB_FATSz16 = 0 for FAT32 +BPB_SecPerTrk dw ? +BPB_NumHeads dw ? +BPB_HiddSec dd ? + dd ? ; BPB_TotSec32 +BPB_FATSz32 dd ? +BPB_ExtFlags dw ? + dw ? ; BPB_FSVer +BPB_RootClus dd ? + dw ? ; BPB_FSInfo +BPB_BkBootSec dw ? + rb 12 ; BPB_Reserved +BS_DrvNum db ? + db ? ; BS_Reserved1 + db ? ; BS_BootSig + dd ? ; BS_VolID + rb 11 ; BS_VolLab + rb 8 ; + +curseg dw 0x8000 + +start: + xor ax, ax + mov ss, ax + mov sp, 0x7C00 + mov ds, ax + mov bp, sp + cld + sti + push dx ; byte [bp-2] = boot drive +if use_lba + mov ah, 41h + mov bx, 55AAh + int 13h + mov si, aNoLBA + jc err_ + cmp bx, 0AA55h + jnz err_ + test cl, 1 + jz err_ +else + mov ah, 8 + int 13h + jc @f + movzx ax, dh + inc ax + mov [bp+BPB_NumHeads-0x7C00], ax + and cx, 3Fh + mov [bp+BPB_SecPerTrk-0x7C00], cx +@@: +end if +; get FAT parameters + xor bx, bx + movzx eax, [bp+BPB_NumFATs-0x7C00] + mul [bp+BPB_FATSz32-0x7C00] + movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] + push ecx ; FAT start = dword [bp-6] + add eax, ecx + push eax ; data start = dword [bp-10] + ;push dword -1 ; dword [bp-14] = current sector for FAT cache + db 66h + push -1 ; dword [bp-14] = current sector for FAT cache + mov eax, [bp+BPB_RootClus-0x7C00] + mov si, main_loader + call lookup_in_dir + jnc kordldr_ok +noloader: + mov si, aLoaderNotFound +err_: + call out_string + mov si, aPressAnyKey + call out_string + xor ax, ax + int 16h + int 18h + jmp $ +kordldr_ok: + mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) + mov ax, [es:di+26] ; loword(eax) = loword(cluster) + mov es, bx ; es = 0 + mov bx, 0x7E00 + push bx ; save return address: bx = 7E00 +; fall through - 'ret' in read_cluster will return to 7E00 + +read_cluster: +; ss:bp = 0:7C00 +; es:bx = pointer to data +; eax = cluster + sub eax, 2 + movzx ecx, [bp+BPB_SecsPerClus-0x7C00] + mul ecx + +read_sectors2: +; same as read_sectors32, but eax is relative to start of data + add eax, [bp-10] +read_sectors32: +; ss:bp = 0:7C00 +; es:bx = pointer to data +; eax = first sector +; cx = number of sectors +; some high words of 32-bit registers are destroyed! + pusha + add eax, [bp+BPB_HiddSec-0x7C00] +if use_lba + push ds +do_read_sectors: + push ax + push cx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + push 0 + push 0 + push eax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [bp-2] + mov ah, 42h + int 13h + mov si, aReadError + jc err_ +; restore stack + add sp, 10h +; increase current sector & buffer; decrease number of sectors + movzx esi, cx + mov ax, es + shl cx, 5 + add ax, cx + mov es, ax + pop cx + pop ax + add eax, esi + sub cx, si + jnz do_read_sectors + pop ds + popa + ret +else +do_read_sectors: + pusha + pop edi ; loword(edi) = di, hiword(edi) = si + push bx + +; eax / (SectorsPerTrack) -> eax, remainder bx + movzx esi, [bp+BPB_SecPerTrk-0x7C00] + xor edx, edx + div esi + mov bx, dx ; bx=sector-1 + +; eax -> dx:ax + push eax + pop ax + pop dx +; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx + div [bp+BPB_NumHeads-0x7C00] + +; number of sectors: read no more than to end of track + sub si, bx + cmp cx, si + jbe @f + mov cx, si +@@: + + inc bx +; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format + movzx edi, cx + mov dh, dl + mov dl, [bp-2] + shl ah, 6 + mov ch, al + mov al, cl + mov cl, bl + or cl, ah + pop bx + mov si, 3 + mov ah, 2 +@@: + push ax + int 13h + jnc @f + xor ax, ax + int 13h ; reset drive + pop ax + dec si + jnz @b + mov si, aReadError + jmp err_ +@@: + pop ax + mov ax, es + mov cx, di + shl cx, 5 + add ax, cx + mov es, ax + push edi + popa + add eax, edi + sub cx, di + jnz do_read_sectors + popa + ret +end if + +lookup_in_dir: +; in: ds:si -> 11-bytes FAT name +; in: eax = cluster +; in: bx = 0 +; out: if found: CF=0, es:di -> directory entry +; out: if not found: CF=1 +; push 0x8000 +; pop es +; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 + mov es, [bp-7C00h + curseg] + push es + push eax + call read_cluster + mov ax, es + cmp ah, 82h + jb @f + mov ax, 8200h +@@: + mov [bp-7C00h + curseg], ax + pop eax + pop es +; scan for filename + shl cx, 4 + xor di, di +sloop: + cmp byte [es:di], bl + jz snotfound + test byte [es:di+11], 8 ; volume label? + jnz scont ; ignore volume labels + pusha + mov cx, 11 + repz cmpsb + popa + jz sdone +scont: + add di, 0x20 + loop sloop +; next cluster + push 0x6000 + pop es + push es ax + shr eax, 7 + cmp eax, [bp-14] + mov [bp-14], eax + jz @f + add eax, [bp-6] + mov cx, 1 + call read_sectors32 +@@: + pop di es + and di, 0x7F + shl di, 2 + and byte [es:di+3], 0x0F + mov eax, [es:di] + ;and eax, 0x0FFFFFFF + cmp eax, 0x0FFFFFF7 + jb lookup_in_dir +snotfound: + stc +sdone: + ret + +out_string: +; in: ds:si -> ASCIIZ string + lodsb + test al, al + jz sdone + mov ah, 0Eh + mov bx, 7 + int 10h + jmp out_string + +aReadError db 'Read error',0 +if use_lba +aNoLBA db 'The drive does not support LBA!',0 +end if +aLoaderNotFound db 'Loader not found',0 +aPressAnyKey db 13,10,'Press any key...',13,10,0 +main_loader db 'KORDLDR F32' + + db 56h +; just to make file 512 bytes long :) + db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' + +; bootsector signature + dw 0xAA55 + +; display offsets of all procedures used by kordldr.f12.asm +macro show [procedure] +{ + bits = 16 + display `procedure,' = ' + repeat bits/4 + d = '0' + procedure shr (bits - %*4) and 0Fh + if d > '9' + d = d + 'A'-'9'-1 + end if + display d + end repeat + display 13,10 +} + +show read_sectors32, read_sectors2, err_, noloader diff --git a/kernel/trunk/bootloader/extended_primary_loader/fat32/kordldr.f32.asm b/kernel/trunk/bootloader/extended_primary_loader/fat32/kordldr.f32.asm index 61c865d82..36bfa6475 100644 --- a/kernel/trunk/bootloader/extended_primary_loader/fat32/kordldr.f32.asm +++ b/kernel/trunk/bootloader/extended_primary_loader/fat32/kordldr.f32.asm @@ -1,673 +1,673 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - - org 0x7E00 -; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here -; ss:bp = 0:7C00 -; ds = 0 -virtual at bp - rb 3 ; BS_jmpBoot - rb 8 ; BS_OEMName, ignored - dw ? ; BPB_BytsPerSec -BPB_SecsPerClus db ? -BPB_RsvdSecCnt dw ? -BPB_NumFATs db ? -BPB_RootEntCnt dw ? - dw ? ; BPB_TotSec16 - db ? ; BPB_Media - dw ? ; BPB_FATSz16 = 0 for FAT32 -BPB_SecPerTrk dw ? -BPB_NumHeads dw ? -BPB_HiddSec dd ? - dd ? ; BPB_TotSec32 -BPB_FATSz32 dd ? -BPB_ExtFlags dw ? - dw ? ; BPB_FSVer -BPB_RootClus dd ? -filesize: - dw ? ; BPB_FSInfo - dw ? ; BPB_BkBootSec - rb 12 ; BPB_Reserved -BS_DrvNum db ? - db ? ; BS_Reserved1 - db ? ; BS_BootSig - dd ? ; BS_VolID -; rb 11 ; BS_VolLab -; rb 5 ; BS_FilSysType, first 5 bytes -read_sectors32 dw ? -read_sectors2 dw ? -err_ dw ? -noloader dw ? -cachelimit dw ? -fatcachehead rw 2 -fatcacheend dw ? - rb 3 ; BS_FilSysType, last 3 bytes -curseg dw ? -num_sectors dd ? -cur_cluster dd ? -next_cluster dd ? -flags dw ? -cur_delta dd ? -end virtual - -; procedures from boot sector -; LBA version -lba_read_sectors2 = 7CD6h -lba_err = 7CAAh -lba_noloader = 7CA7h ; = lba_err - 3 -; CHS version -chs_read_sectors2 = 7CD2h -chs_err = 7CA6h -chs_noloader = 7CA3h ; = chs_err - 3 - - push eax cx ; save our position on disk -; determine version of bootsector (LBA vs CHS) - mov [read_sectors2], chs_read_sectors2 - mov bx, chs_err - mov [err_], bx -; mov [noloader], chs_noloader - cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version - jz @f - add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 - add [err_], lba_err - chs_err -; mov [noloader], lba_noloader -@@: - xor bx, bx -; determine size of cache for folders - int 12h ; ax = size of available base memory in Kb - sub ax, 92000h / 1024 - jae @f -nomem: - mov si, nomem_str - jmp [err_] -@@: - shr ax, 3 - mov [cachelimit], ax ; size of cache - 1 - mov es, bx -; no folders in cache yet - mov di, foldcache_clus - mov cx, 8*4/2 + 1 - xor ax, ax - rep stosw -; bootsector code caches one FAT sector, [bp-14], in 6000:0000 -; initialize our (more advanced) FAT caching from this - mov di, 8400h - mov cx, di - lea si, [fatcachehead] - mov [si], si ; no sectors in cache: - mov [si+2], si ; 'prev' & 'next' links point to self - mov [fatcacheend], di ; first free item = 8400h - stosw ; 'next cached sector' link - stosw ; 'prev cached sector' link - mov eax, [bp-14] - stosd ; first sector number in cache - test eax, eax - js @f - mov [si], cx ; 'first cached sector' link = 8400h - mov [si+2], cx ; 'next cached sector' link = 8400h - mov [fatcacheend], di ; first free item = 8406h -@@: -; if cluster = sector, we need to read second part of our file -; (bootsector loads only first cluster of kordldr.f32) - pop cx eax ; restore our position on disk - cmp cx, 1 - ja kordldr_full - sub eax, [bp-10] - inc eax - inc eax ; eax = first cluster of kordldr.f32 - call get_next_cluster - jc @f -; jmp [noloader] - mov ax, [err_] - sub ax, 3 - jmp ax -@@: - dec eax - dec eax - push 0x800 - pop es - call [read_sectors2] -kordldr_full: -; bootsector code has read some data of root directory to 8000:0000 -; initialize our folder caching from this - mov eax, [BPB_RootClus] - mov [foldcache_clus], eax - mov cx, [curseg] - mov ax, 8000h - sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) - shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) - mov [foldcache_size], cx - shl cx, 4 - push ds - mov ds, ax - push 0x9000 - pop es - xor si, si - xor di, di - rep movsw - pop ds -; ...continue loading... - mov di, secondary_loader_info - call load_file - test bx, bx - mov bx, [err_] - jz @f - mov si, aKernelNotFound - jmp bx -@@: -; for subsequent calls to callback function, hook error handler -; push hooked_err / ret - mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) -; set registers for secondary loader - mov ah, [bp-2] ; drive id - mov al, 'f' - btr ax, 15 - jnc @f - mov al, 'h' -@@: - mov bx, '32' - mov si, callback - jmp far [si+secondary_loader_info-callback] - -nomem_str db 'No memory',0 - -cluster2sector: - sub eax, 2 -clustersz2sectorsz: - movzx ecx, [BPB_SecsPerClus] - mul ecx - ret - -get_next_cluster: -; in: eax = cluster -; out: if there is next cluster: CF=1, eax = next cluster -; out: if there is no next cluster: CF=0 - push di bx - push ds es - push ss - pop ds - push ss - pop es - push ax - shr eax, 7 -; eax = FAT sector number; look in cache - mov di, 8400h -.cache_lookup: - cmp di, [fatcacheend] - jae .not_in_cache - scasd - scasd - jnz .cache_lookup -.in_cache: - sub di, 8 -; delete this sector from the list - push si - mov si, [di] - mov bx, [di+2] - mov [si+2], bx - mov [bx], si - pop si - jmp @f -.not_in_cache: -; cache miss -; cache is full? - mov di, [fatcacheend] - cmp di, 8C00h - jnz .cache_not_full -; yes, delete the oldest entry - mov di, [fatcachehead] - mov bx, [di] - mov [fatcachehead], bx - push word [di+2] - pop word [bx+2] - jmp .cache_append -.cache_not_full: -; no, allocate new sector - add [fatcacheend], 8 -.cache_append: -; read FAT - mov [di+4], eax - pushad - lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] ; +0x10000 - for FASM - shl cx, 9-4-3 - mov es, cx - xor bx, bx - mov cx, 1 - add eax, [bp-6] ; FAT start - sub eax, [bp-10] - call [read_sectors2] - popad -@@: -; add new sector to the end of list - mov bx, di - xchg bx, [fatcachehead+2] - push word [bx] - pop word [di] - mov [bx], di - mov [di+2], bx -; get requested item - lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] - pop di - and di, 0x7F - shl di, 2 - shl ax, 9-4-3 - mov ds, ax - and byte [di+3], 0x0F - mov eax, [di] - pop es ds - pop bx di - ;and eax, 0x0FFFFFFF - cmp eax, 0x0FFFFFF7 - ret - -if $ > 0x8000 -error 'get_next_cluster must fit in first sector of kordldr.f32!' -end if - -load_file: -; in: ss:bp = 0:7C00 -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) - mov eax, [BPB_RootClus] ; start from root directory - or dword [filesize], -1 ; initialize file size with invalid value - lea si, [di+6] -parse_dir_loop: -; convert name to FAT name - push di - push ax - push ss - pop es -; convert ASCIIZ filename to FAT name -filename equ bp - mov di, filename - push di - mov cx, 8+3 - mov al, ' ' - rep stosb - pop di - mov cl, 8 ; 8 symbols per name - mov bl, 1 -nameloop: - lodsb - test al, al - jz namedone - cmp al, '/' - jz namedone - cmp al, '.' - jz namedot - dec cx - js badname - cmp al, 'a' - jb @f - cmp al, 'z' - ja @f - sub al, 'a'-'A' -@@: - stosb - jmp nameloop -namedot: - inc bx - jp badname - add di, cx - mov cl, 3 - jmp nameloop -badname: ; do not make direct js/jp to notfound_pop: - ; this generates long forms of conditional jumps and results in longer code - jmp notfound_pop -namedone: -; scan directory - pop ax ; eax = cluster of directory - ; high word of eax is preserved by operations above - push ds - push si -; read a folder sector-by-sector and scan -; first, try to use the cache - push ss - pop ds - mov di, foldcache_mark - xor bx, bx - mov cx, [cachelimit] -@@: - lea si, [di+bx] - mov edx, dword [foldcache_clus+si-foldcache_mark+bx] - cmp edx, eax - jz cacheok - test edx, edx - jz cacheadd ; the cache has place for new entry - inc bx - inc bx - dec cx - jns @b -; the folder is not present in the cache, so add it -; the cache is full; find the oldest entry and replace it with the new one - mov bx, -2 - mov dx, [cachelimit] -@@: - inc bx - inc bx - cmp word [di+bx], dx ; marks have values 0 through [cachelimit] - jnz @b - lea si, [di+bx] -cacheadd: - or word [di+bx], 0xFFFF ; very big value, it will be changed soon - and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet - mov dword [foldcache_clus+si-foldcache_mark+bx], eax -cacheok: -; update cache marks - mov dx, [di+bx] - mov cx, [foldcache_size+di-foldcache_mark+bx] - mov di, [cachelimit] - add di, di -cacheupdate: - cmp [foldcache_mark+di], dx - adc [foldcache_mark+di], 0 - dec di - dec di - jns cacheupdate - and [foldcache_mark+bx], 0 -; done, bx contains (position in cache)*2 - ;mov dx, bx - ;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 - ;add dx, 0x9000 - lea dx, [bx + 0x90] - xchg dl, dh - mov ds, dx - mov si, filename ; ss:si -> filename in FAT style - call scan_for_filename - jz lookup_done -; cache miss, read folder data from disk - mov bx, cx - shr bx, 4 - shl cx, 5 - mov di, cx ; es:di -> free space in cache entry -; external loop: scan clusters -folder_next_cluster: -; internal loop: scan sectors in cluster - push eax - call cluster2sector -folder_next_sector: -; skip first bx sectors - dec bx - jns folder_skip_sector - push cx - push es di - push 0x8000 - pop es - xor bx, bx - mov cx, 1 - push es - push eax - call [read_sectors2] - pop eax -; copy data to the cache... - pop ds - pop di es - cmp di, 0x2000 ; ...if there is free space, of course - jae @f - pusha - mov cx, 0x100 - xor si, si - rep movsw - mov di, es - shr di, 8 - add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache - popa -@@: - push es - mov cl, 0x10 ; ch=0 at this point - call scan_for_filename - pop es - pop cx - jz lookup_done_pop -folder_skip_sector: - inc eax - loop folder_next_sector - pop eax ; eax = current cluster - call get_next_cluster - jc folder_next_cluster - stc - push eax -lookup_done_pop: - pop eax -lookup_done: - pop si -; CF=1 <=> failed - jnc found - pop ds -notfound: - pop di -notfound2: - mov bx, 2 ; file not found - mov ax, 0xFFFF - mov dx, ax ; invalid file size - ret -notfound_pop: - pop ax - jmp notfound -found: - mov eax, [di+20-2] - mov edx, [di+28] - mov ax, [di+26] ; get cluster - test byte [di+11], 10h ; directory? - pop ds - pop di - jz regular_file - cmp byte [si-1], 0 - jz notfound2 ; don't read directories as regular files -; ok, we have found a directory and the caller requested a file into it - jmp parse_dir_loop ; restart with new cluster in ax -regular_file: - cmp byte [si-1], 0 - jnz notfound2 ; file does not contain another files -; ok, we have found a regular file and the caller requested it -; save file size - mov [filesize], edx - mov si, [di+4] ; [ds:di+4] = limit in 4K blocks - shl si, 3 - push si - les bx, [di] ; es:bx -> buffer -clusloop: -; eax = first cluster, top of stack contains limit in sectors - mov esi, eax ; remember current cluster - xor ecx, ecx ; ecx will contain number of consecutive clusters - mov [cur_delta], ecx - mov edi, eax -clusfind: - inc edi - inc ecx - call get_next_cluster - jnc clusread - cmp eax, edi - jz clusfind - stc -clusread: - pop di ; limit in sectors - movzx edi, di - push eax ; save next cluster - pushf ; save flags -; read cx clusters, starting from si -; calculate number of sectors - xchg eax, ecx - call clustersz2sectorsz - mov [num_sectors], eax - jmp @f -continue_load_file: - les bx, [di] ; es:bx -> buffer - movzx edi, word [di+4] ; di = limit in 4K blocks - shl di, 3 ; now di = limit in sectors - mov eax, [num_sectors] - mov esi, [cur_cluster] - push [next_cluster] - push [flags] - test eax, eax - jz nextclus -@@: -; eax = number of sectors; compare with limit - cmp eax, edi - seta dl - push dx ; limit was exceeded? - jbe @f - mov eax, edi -@@: - sub di, ax ; calculate new limit - sub [num_sectors], eax - mov [cur_cluster], esi -; calculate starting sector - push ax - xchg eax, esi - call cluster2sector - pop cx - add eax, [cur_delta] - add [cur_delta], ecx -; read - call [read_sectors2] - pop dx -; next cluster? -nextclus: - popf - pop eax - mov [next_cluster], eax - pushf - pop [flags] - jnc @f ; no next cluster => return - mov dl, 1 - test di, di - jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded - push di - jmp clusloop ; all is ok, continue -hooked_err: - mov sp, 7C00h-14-2 ; restore stack - mov dl, 3 ; return: read error -@@: - mov bl, dl - mov bh, 0 - mov ax, [filesize] - mov dx, [filesize+2] - ret - -scan_for_filename: -; in: ss:si -> 11-bytes FAT name -; in: ds:0 -> part of directory data -; in: cx = number of entries -; in: bh = 0 -; out: if found: CF=0, ZF=1, es:di -> directory entry -; out: if not found, but continue required: CF=1 and ZF=0 -; out: if not found and zero item reached: CF=1 and ZF=1 - push ds - pop es - xor di, di - push cx - jcxz snoent -sloop: - cmp byte [di], bh - jz snotfound - test byte [di+11], 8 ; volume label? - jnz scont ; ignore volume labels - pusha - mov cx, 11 - repz cmps byte [ss:si], byte [es:di] - popa - jz sdone -scont: - add di, 0x20 - loop sloop -snoent: - inc cx ; clear ZF flag -snotfound: - stc -sdone: - pop cx -lrdret: - ret - -; Callback function for secondary loader -callback: -; in: ax = function number; only functions 1 and 2 are defined for now -; save caller's stack - mov dx, ss - mov cx, sp -; set our stack (required because we need ss=0) - xor si, si - mov ss, si - mov sp, 7C00h-10 - mov bp, 7C00h - push dx - push cx -; call our function - stc ; unsupported function - dec ax - jz callback_readfile - dec ax - jnz callback_ret -; function 2: continue loading file -; can be called only after function 1 returned value bx=1 (only part of file was loaded) -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error -; out: dx:ax = file size - call continue_load_file - jmp callback_ret_succ -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call load_file -callback_ret_succ: - clc ; function is supported -callback_ret: -; restore caller's stack - pop cx - pop ss - mov sp, cx -; return to caller - retf - -secondary_loader_info: - dw 0, 0x1000 - dw 0x30000 / 0x1000 - db 'kernel.mnt',0 -aKernelNotFound db 'Fatal error: cannot load the kernel',0 - -;if $ > 0x8200 -;error 'total size of kordldr.f32 must not exceed 1024 bytes!' -;end if - -;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache -;foldcache_mark dw 0 -; rw 7 -;foldcache_size rw 8 -foldcache_clus rd 8 -foldcache_mark rw 8 -foldcache_size rw 8 +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + + org 0x7E00 +; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here +; ss:bp = 0:7C00 +; ds = 0 +virtual at bp + rb 3 ; BS_jmpBoot + rb 8 ; BS_OEMName, ignored + dw ? ; BPB_BytsPerSec +BPB_SecsPerClus db ? +BPB_RsvdSecCnt dw ? +BPB_NumFATs db ? +BPB_RootEntCnt dw ? + dw ? ; BPB_TotSec16 + db ? ; BPB_Media + dw ? ; BPB_FATSz16 = 0 for FAT32 +BPB_SecPerTrk dw ? +BPB_NumHeads dw ? +BPB_HiddSec dd ? + dd ? ; BPB_TotSec32 +BPB_FATSz32 dd ? +BPB_ExtFlags dw ? + dw ? ; BPB_FSVer +BPB_RootClus dd ? +filesize: + dw ? ; BPB_FSInfo + dw ? ; BPB_BkBootSec + rb 12 ; BPB_Reserved +BS_DrvNum db ? + db ? ; BS_Reserved1 + db ? ; BS_BootSig + dd ? ; BS_VolID +; rb 11 ; BS_VolLab +; rb 5 ; BS_FilSysType, first 5 bytes +read_sectors32 dw ? +read_sectors2 dw ? +err_ dw ? +noloader dw ? +cachelimit dw ? +fatcachehead rw 2 +fatcacheend dw ? + rb 3 ; BS_FilSysType, last 3 bytes +curseg dw ? +num_sectors dd ? +cur_cluster dd ? +next_cluster dd ? +flags dw ? +cur_delta dd ? +end virtual + +; procedures from boot sector +; LBA version +lba_read_sectors2 = 7CD6h +lba_err = 7CAAh +lba_noloader = 7CA7h ; = lba_err - 3 +; CHS version +chs_read_sectors2 = 7CD2h +chs_err = 7CA6h +chs_noloader = 7CA3h ; = chs_err - 3 + + push eax cx ; save our position on disk +; determine version of bootsector (LBA vs CHS) + mov [read_sectors2], chs_read_sectors2 + mov bx, chs_err + mov [err_], bx +; mov [noloader], chs_noloader + cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version + jz @f + add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 + add [err_], lba_err - chs_err +; mov [noloader], lba_noloader +@@: + xor bx, bx +; determine size of cache for folders + int 12h ; ax = size of available base memory in Kb + sub ax, 92000h / 1024 + jae @f +nomem: + mov si, nomem_str + jmp [err_] +@@: + shr ax, 3 + mov [cachelimit], ax ; size of cache - 1 + mov es, bx +; no folders in cache yet + mov di, foldcache_clus + mov cx, 8*4/2 + 1 + xor ax, ax + rep stosw +; bootsector code caches one FAT sector, [bp-14], in 6000:0000 +; initialize our (more advanced) FAT caching from this + mov di, 8400h + mov cx, di + lea si, [fatcachehead] + mov [si], si ; no sectors in cache: + mov [si+2], si ; 'prev' & 'next' links point to self + mov [fatcacheend], di ; first free item = 8400h + stosw ; 'next cached sector' link + stosw ; 'prev cached sector' link + mov eax, [bp-14] + stosd ; first sector number in cache + test eax, eax + js @f + mov [si], cx ; 'first cached sector' link = 8400h + mov [si+2], cx ; 'next cached sector' link = 8400h + mov [fatcacheend], di ; first free item = 8406h +@@: +; if cluster = sector, we need to read second part of our file +; (bootsector loads only first cluster of kordldr.f32) + pop cx eax ; restore our position on disk + cmp cx, 1 + ja kordldr_full + sub eax, [bp-10] + inc eax + inc eax ; eax = first cluster of kordldr.f32 + call get_next_cluster + jc @f +; jmp [noloader] + mov ax, [err_] + sub ax, 3 + jmp ax +@@: + dec eax + dec eax + push 0x800 + pop es + call [read_sectors2] +kordldr_full: +; bootsector code has read some data of root directory to 8000:0000 +; initialize our folder caching from this + mov eax, [BPB_RootClus] + mov [foldcache_clus], eax + mov cx, [curseg] + mov ax, 8000h + sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) + shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) + mov [foldcache_size], cx + shl cx, 4 + push ds + mov ds, ax + push 0x9000 + pop es + xor si, si + xor di, di + rep movsw + pop ds +; ...continue loading... + mov di, secondary_loader_info + call load_file + test bx, bx + mov bx, [err_] + jz @f + mov si, aKernelNotFound + jmp bx +@@: +; for subsequent calls to callback function, hook error handler +; push hooked_err / ret + mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) +; set registers for secondary loader + mov ah, [bp-2] ; drive id + mov al, 'f' + btr ax, 15 + jnc @f + mov al, 'h' +@@: + mov bx, '32' + mov si, callback + jmp far [si+secondary_loader_info-callback] + +nomem_str db 'No memory',0 + +cluster2sector: + sub eax, 2 +clustersz2sectorsz: + movzx ecx, [BPB_SecsPerClus] + mul ecx + ret + +get_next_cluster: +; in: eax = cluster +; out: if there is next cluster: CF=1, eax = next cluster +; out: if there is no next cluster: CF=0 + push di bx + push ds es + push ss + pop ds + push ss + pop es + push ax + shr eax, 7 +; eax = FAT sector number; look in cache + mov di, 8400h +.cache_lookup: + cmp di, [fatcacheend] + jae .not_in_cache + scasd + scasd + jnz .cache_lookup +.in_cache: + sub di, 8 +; delete this sector from the list + push si + mov si, [di] + mov bx, [di+2] + mov [si+2], bx + mov [bx], si + pop si + jmp @f +.not_in_cache: +; cache miss +; cache is full? + mov di, [fatcacheend] + cmp di, 8C00h + jnz .cache_not_full +; yes, delete the oldest entry + mov di, [fatcachehead] + mov bx, [di] + mov [fatcachehead], bx + push word [di+2] + pop word [bx+2] + jmp .cache_append +.cache_not_full: +; no, allocate new sector + add [fatcacheend], 8 +.cache_append: +; read FAT + mov [di+4], eax + pushad + lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] ; +0x10000 - for FASM + shl cx, 9-4-3 + mov es, cx + xor bx, bx + mov cx, 1 + add eax, [bp-6] ; FAT start + sub eax, [bp-10] + call [read_sectors2] + popad +@@: +; add new sector to the end of list + mov bx, di + xchg bx, [fatcachehead+2] + push word [bx] + pop word [di] + mov [bx], di + mov [di+2], bx +; get requested item + lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-4-3))] + pop di + and di, 0x7F + shl di, 2 + shl ax, 9-4-3 + mov ds, ax + and byte [di+3], 0x0F + mov eax, [di] + pop es ds + pop bx di + ;and eax, 0x0FFFFFFF + cmp eax, 0x0FFFFFF7 + ret + +if $ > 0x8000 +error 'get_next_cluster must fit in first sector of kordldr.f32!' +end if + +load_file: +; in: ss:bp = 0:7C00 +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) + mov eax, [BPB_RootClus] ; start from root directory + or dword [filesize], -1 ; initialize file size with invalid value + lea si, [di+6] +parse_dir_loop: +; convert name to FAT name + push di + push ax + push ss + pop es +; convert ASCIIZ filename to FAT name +filename equ bp + mov di, filename + push di + mov cx, 8+3 + mov al, ' ' + rep stosb + pop di + mov cl, 8 ; 8 symbols per name + mov bl, 1 +nameloop: + lodsb + test al, al + jz namedone + cmp al, '/' + jz namedone + cmp al, '.' + jz namedot + dec cx + js badname + cmp al, 'a' + jb @f + cmp al, 'z' + ja @f + sub al, 'a'-'A' +@@: + stosb + jmp nameloop +namedot: + inc bx + jp badname + add di, cx + mov cl, 3 + jmp nameloop +badname: ; do not make direct js/jp to notfound_pop: + ; this generates long forms of conditional jumps and results in longer code + jmp notfound_pop +namedone: +; scan directory + pop ax ; eax = cluster of directory + ; high word of eax is preserved by operations above + push ds + push si +; read a folder sector-by-sector and scan +; first, try to use the cache + push ss + pop ds + mov di, foldcache_mark + xor bx, bx + mov cx, [cachelimit] +@@: + lea si, [di+bx] + mov edx, dword [foldcache_clus+si-foldcache_mark+bx] + cmp edx, eax + jz cacheok + test edx, edx + jz cacheadd ; the cache has place for new entry + inc bx + inc bx + dec cx + jns @b +; the folder is not present in the cache, so add it +; the cache is full; find the oldest entry and replace it with the new one + mov bx, -2 + mov dx, [cachelimit] +@@: + inc bx + inc bx + cmp word [di+bx], dx ; marks have values 0 through [cachelimit] + jnz @b + lea si, [di+bx] +cacheadd: + or word [di+bx], 0xFFFF ; very big value, it will be changed soon + and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet + mov dword [foldcache_clus+si-foldcache_mark+bx], eax +cacheok: +; update cache marks + mov dx, [di+bx] + mov cx, [foldcache_size+di-foldcache_mark+bx] + mov di, [cachelimit] + add di, di +cacheupdate: + cmp [foldcache_mark+di], dx + adc [foldcache_mark+di], 0 + dec di + dec di + jns cacheupdate + and [foldcache_mark+bx], 0 +; done, bx contains (position in cache)*2 + ;mov dx, bx + ;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 + ;add dx, 0x9000 + lea dx, [bx + 0x90] + xchg dl, dh + mov ds, dx + mov si, filename ; ss:si -> filename in FAT style + call scan_for_filename + jz lookup_done +; cache miss, read folder data from disk + mov bx, cx + shr bx, 4 + shl cx, 5 + mov di, cx ; es:di -> free space in cache entry +; external loop: scan clusters +folder_next_cluster: +; internal loop: scan sectors in cluster + push eax + call cluster2sector +folder_next_sector: +; skip first bx sectors + dec bx + jns folder_skip_sector + push cx + push es di + push 0x8000 + pop es + xor bx, bx + mov cx, 1 + push es + push eax + call [read_sectors2] + pop eax +; copy data to the cache... + pop ds + pop di es + cmp di, 0x2000 ; ...if there is free space, of course + jae @f + pusha + mov cx, 0x100 + xor si, si + rep movsw + mov di, es + shr di, 8 + add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache + popa +@@: + push es + mov cl, 0x10 ; ch=0 at this point + call scan_for_filename + pop es + pop cx + jz lookup_done_pop +folder_skip_sector: + inc eax + loop folder_next_sector + pop eax ; eax = current cluster + call get_next_cluster + jc folder_next_cluster + stc + push eax +lookup_done_pop: + pop eax +lookup_done: + pop si +; CF=1 <=> failed + jnc found + pop ds +notfound: + pop di +notfound2: + mov bx, 2 ; file not found + mov ax, 0xFFFF + mov dx, ax ; invalid file size + ret +notfound_pop: + pop ax + jmp notfound +found: + mov eax, [di+20-2] + mov edx, [di+28] + mov ax, [di+26] ; get cluster + test byte [di+11], 10h ; directory? + pop ds + pop di + jz regular_file + cmp byte [si-1], 0 + jz notfound2 ; don't read directories as regular files +; ok, we have found a directory and the caller requested a file into it + jmp parse_dir_loop ; restart with new cluster in ax +regular_file: + cmp byte [si-1], 0 + jnz notfound2 ; file does not contain another files +; ok, we have found a regular file and the caller requested it +; save file size + mov [filesize], edx + mov si, [di+4] ; [ds:di+4] = limit in 4K blocks + shl si, 3 + push si + les bx, [di] ; es:bx -> buffer +clusloop: +; eax = first cluster, top of stack contains limit in sectors + mov esi, eax ; remember current cluster + xor ecx, ecx ; ecx will contain number of consecutive clusters + mov [cur_delta], ecx + mov edi, eax +clusfind: + inc edi + inc ecx + call get_next_cluster + jnc clusread + cmp eax, edi + jz clusfind + stc +clusread: + pop di ; limit in sectors + movzx edi, di + push eax ; save next cluster + pushf ; save flags +; read cx clusters, starting from si +; calculate number of sectors + xchg eax, ecx + call clustersz2sectorsz + mov [num_sectors], eax + jmp @f +continue_load_file: + les bx, [di] ; es:bx -> buffer + movzx edi, word [di+4] ; di = limit in 4K blocks + shl di, 3 ; now di = limit in sectors + mov eax, [num_sectors] + mov esi, [cur_cluster] + push [next_cluster] + push [flags] + test eax, eax + jz nextclus +@@: +; eax = number of sectors; compare with limit + cmp eax, edi + seta dl + push dx ; limit was exceeded? + jbe @f + mov eax, edi +@@: + sub di, ax ; calculate new limit + sub [num_sectors], eax + mov [cur_cluster], esi +; calculate starting sector + push ax + xchg eax, esi + call cluster2sector + pop cx + add eax, [cur_delta] + add [cur_delta], ecx +; read + call [read_sectors2] + pop dx +; next cluster? +nextclus: + popf + pop eax + mov [next_cluster], eax + pushf + pop [flags] + jnc @f ; no next cluster => return + mov dl, 1 + test di, di + jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded + push di + jmp clusloop ; all is ok, continue +hooked_err: + mov sp, 7C00h-14-2 ; restore stack + mov dl, 3 ; return: read error +@@: + mov bl, dl + mov bh, 0 + mov ax, [filesize] + mov dx, [filesize+2] + ret + +scan_for_filename: +; in: ss:si -> 11-bytes FAT name +; in: ds:0 -> part of directory data +; in: cx = number of entries +; in: bh = 0 +; out: if found: CF=0, ZF=1, es:di -> directory entry +; out: if not found, but continue required: CF=1 and ZF=0 +; out: if not found and zero item reached: CF=1 and ZF=1 + push ds + pop es + xor di, di + push cx + jcxz snoent +sloop: + cmp byte [di], bh + jz snotfound + test byte [di+11], 8 ; volume label? + jnz scont ; ignore volume labels + pusha + mov cx, 11 + repz cmps byte [ss:si], byte [es:di] + popa + jz sdone +scont: + add di, 0x20 + loop sloop +snoent: + inc cx ; clear ZF flag +snotfound: + stc +sdone: + pop cx +lrdret: + ret + +; Callback function for secondary loader +callback: +; in: ax = function number; only functions 1 and 2 are defined for now +; save caller's stack + mov dx, ss + mov cx, sp +; set our stack (required because we need ss=0) + xor si, si + mov ss, si + mov sp, 7C00h-10 + mov bp, 7C00h + push dx + push cx +; call our function + stc ; unsupported function + dec ax + jz callback_readfile + dec ax + jnz callback_ret +; function 2: continue loading file +; can be called only after function 1 returned value bx=1 (only part of file was loaded) +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error +; out: dx:ax = file size + call continue_load_file + jmp callback_ret_succ +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call load_file +callback_ret_succ: + clc ; function is supported +callback_ret: +; restore caller's stack + pop cx + pop ss + mov sp, cx +; return to caller + retf + +secondary_loader_info: + dw 0, 0x1000 + dw 0x30000 / 0x1000 + db 'kernel.mnt',0 +aKernelNotFound db 'Fatal error: cannot load the kernel',0 + +;if $ > 0x8200 +;error 'total size of kordldr.f32 must not exceed 1024 bytes!' +;end if + +;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache +;foldcache_mark dw 0 +; rw 7 +;foldcache_size rw 8 +foldcache_clus rd 8 +foldcache_mark rw 8 +foldcache_size rw 8 diff --git a/kernel/trunk/bootloader/floppy1440.inc b/kernel/trunk/bootloader/floppy1440.inc index 678e2d35f..5be3accba 100644 --- a/kernel/trunk/bootloader/floppy1440.inc +++ b/kernel/trunk/bootloader/floppy1440.inc @@ -1,19 +1,19 @@ - BS_OEMName db 'KOLIBRI ' ; db 8 - BPB_BytsPerSec dw 512 ; bytes per sector - BPB_SecPerClus db 1 ; sectors per cluster - BPB_RsvdSecCnt dw 1 ; number of reserver sectors - BPB_NumFATs db 2 ; count of FAT data structures - BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) - BPB_TotSec16 dw 2880 ; count of sectors on the volume (2880 for 1.44 mbytes disk) - BPB_Media db 0f0h ; f0 - used for removable media - BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT - BPB_SecPerTrk dw 18 ; sectors per track - BPB_NumHeads dw 2 ; number of heads - BPB_HiddSec dd 0 ; count of hidden sectors - BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) - BS_DrvNum db 0 ; int 13h drive number - BS_Reserved db 0 ; reserved - BS_BootSig db 29h ; Extended boot signature - BS_VolID dd 0 ; Volume serial number - BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) - BS_FilSysType db 'FAT12 ' ; file system type (db 8) + BS_OEMName db 'KOLIBRI ' ; db 8 + BPB_BytsPerSec dw 512 ; bytes per sector + BPB_SecPerClus db 1 ; sectors per cluster + BPB_RsvdSecCnt dw 1 ; number of reserver sectors + BPB_NumFATs db 2 ; count of FAT data structures + BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) + BPB_TotSec16 dw 2880 ; count of sectors on the volume (2880 for 1.44 mbytes disk) + BPB_Media db 0f0h ; f0 - used for removable media + BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT + BPB_SecPerTrk dw 18 ; sectors per track + BPB_NumHeads dw 2 ; number of heads + BPB_HiddSec dd 0 ; count of hidden sectors + BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) + BS_DrvNum db 0 ; int 13h drive number + BS_Reserved db 0 ; reserved + BS_BootSig db 29h ; Extended boot signature + BS_VolID dd 0 ; Volume serial number + BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) + BS_FilSysType db 'FAT12 ' ; file system type (db 8) diff --git a/kernel/trunk/bootloader/floppy1680.inc b/kernel/trunk/bootloader/floppy1680.inc index ef754de8d..bf796d57b 100644 --- a/kernel/trunk/bootloader/floppy1680.inc +++ b/kernel/trunk/bootloader/floppy1680.inc @@ -1,19 +1,19 @@ - BS_OEMName db 'KOLIBRI ' ; db 8 - BPB_BytsPerSec dw 512 ; bytes per sector - BPB_SecPerClus db 1 ; sectors per cluster - BPB_RsvdSecCnt dw 1 ; number of reserver sectors - BPB_NumFATs db 2 ; count of FAT data structures - BPB_RootEntCnt dw 112 ; count of 32-byte dir. entries (112*32 = 7 sectors) - BPB_TotSec16 dw 3360 ; count of sectors on the volume (3360 for 1.68 mbytes disk) - BPB_Media db 0f0h ; f0 - used for removable media - BPB_FATSz16 dw 10 ; count of sectors by one copy of FAT - BPB_SecPerTrk dw 21 ; sectors per track - BPB_NumHeads dw 2 ; number of heads - BPB_HiddSec dd 0 ; count of hidden sectors - BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) - BS_DrvNum db 0 ; int 13h drive number - BS_Reserved db 0 ; reserved - BS_BootSig db 29h ; Extended boot signature - BS_VolID dd 0 ; Volume serial number - BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) - BS_FilSysType db 'FAT12 ' ; file system type (db 8) + BS_OEMName db 'KOLIBRI ' ; db 8 + BPB_BytsPerSec dw 512 ; bytes per sector + BPB_SecPerClus db 1 ; sectors per cluster + BPB_RsvdSecCnt dw 1 ; number of reserver sectors + BPB_NumFATs db 2 ; count of FAT data structures + BPB_RootEntCnt dw 112 ; count of 32-byte dir. entries (112*32 = 7 sectors) + BPB_TotSec16 dw 3360 ; count of sectors on the volume (3360 for 1.68 mbytes disk) + BPB_Media db 0f0h ; f0 - used for removable media + BPB_FATSz16 dw 10 ; count of sectors by one copy of FAT + BPB_SecPerTrk dw 21 ; sectors per track + BPB_NumHeads dw 2 ; number of heads + BPB_HiddSec dd 0 ; count of hidden sectors + BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) + BS_DrvNum db 0 ; int 13h drive number + BS_Reserved db 0 ; reserved + BS_BootSig db 29h ; Extended boot signature + BS_VolID dd 0 ; Volume serial number + BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) + BS_FilSysType db 'FAT12 ' ; file system type (db 8) diff --git a/kernel/trunk/bootloader/floppy1743.inc b/kernel/trunk/bootloader/floppy1743.inc index bd777301f..3a6e3e5a3 100644 --- a/kernel/trunk/bootloader/floppy1743.inc +++ b/kernel/trunk/bootloader/floppy1743.inc @@ -1,19 +1,19 @@ - BS_OEMName db 'KOLIBRI ' ; db 8 - BPB_BytsPerSec dw 512 ; bytes per sector - BPB_SecPerClus db 1 ; sectors per cluster - BPB_RsvdSecCnt dw 1 ; number of reserver sectors - BPB_NumFATs db 2 ; count of FAT data structures - BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) - BPB_TotSec16 dw 3486 ; count of sectors on the volume (3486 for 1.74 mbytes disk) - BPB_Media db 0f0h ; f0 - used for removable media - BPB_FATSz16 dw 11 ; count of sectors by one copy of FAT - BPB_SecPerTrk dw 21 ; sectors per track - BPB_NumHeads dw 2 ; number of heads - BPB_HiddSec dd 0 ; count of hidden sectors - BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) - BS_DrvNum db 0 ; int 13h drive number - BS_Reserved db 0 ; reserved - BS_BootSig db 29h ; Extended boot signature - BS_VolID dd 0 ; Volume serial number - BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) - BS_FilSysType db 'FAT12 ' ; file system type (db 8) + BS_OEMName db 'KOLIBRI ' ; db 8 + BPB_BytsPerSec dw 512 ; bytes per sector + BPB_SecPerClus db 1 ; sectors per cluster + BPB_RsvdSecCnt dw 1 ; number of reserver sectors + BPB_NumFATs db 2 ; count of FAT data structures + BPB_RootEntCnt dw 224 ; count of 32-byte dir. entries (224*32 = 14 sectors) + BPB_TotSec16 dw 3486 ; count of sectors on the volume (3486 for 1.74 mbytes disk) + BPB_Media db 0f0h ; f0 - used for removable media + BPB_FATSz16 dw 11 ; count of sectors by one copy of FAT + BPB_SecPerTrk dw 21 ; sectors per track + BPB_NumHeads dw 2 ; number of heads + BPB_HiddSec dd 0 ; count of hidden sectors + BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) + BS_DrvNum db 0 ; int 13h drive number + BS_Reserved db 0 ; reserved + BS_BootSig db 29h ; Extended boot signature + BS_VolID dd 0 ; Volume serial number + BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) + BS_FilSysType db 'FAT12 ' ; file system type (db 8) diff --git a/kernel/trunk/bootloader/floppy2880.inc b/kernel/trunk/bootloader/floppy2880.inc index 8a52c059c..34da06085 100644 --- a/kernel/trunk/bootloader/floppy2880.inc +++ b/kernel/trunk/bootloader/floppy2880.inc @@ -1,19 +1,19 @@ - BS_OEMName db 'KOLIBRI ' ; db 8 - BPB_BytsPerSec dw 512 ; bytes per sector - BPB_SecPerClus db 2 ; sectors per cluster - BPB_RsvdSecCnt dw 1 ; number of reserver sectors - BPB_NumFATs db 2 ; count of FAT data structures - BPB_RootEntCnt dw 240 ; count of 32-byte dir. entries (240*32 = 15 sectors) - BPB_TotSec16 dw 5760 ; count of sectors on the volume (5760 for 2.88 mbytes disk) - BPB_Media db 0f0h ; f0 - used for removable media - BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT - BPB_SecPerTrk dw 36 ; sectors per track - BPB_NumHeads dw 2 ; number of heads - BPB_HiddSec dd 0 ; count of hidden sectors - BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) - BS_DrvNum db 0 ; int 13h drive number - BS_Reserved db 0 ; reserved - BS_BootSig db 29h ; Extended boot signature - BS_VolID dd 0 ; Volume serial number - BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) - BS_FilSysType db 'FAT12 ' ; file system type (db 8) + BS_OEMName db 'KOLIBRI ' ; db 8 + BPB_BytsPerSec dw 512 ; bytes per sector + BPB_SecPerClus db 2 ; sectors per cluster + BPB_RsvdSecCnt dw 1 ; number of reserver sectors + BPB_NumFATs db 2 ; count of FAT data structures + BPB_RootEntCnt dw 240 ; count of 32-byte dir. entries (240*32 = 15 sectors) + BPB_TotSec16 dw 5760 ; count of sectors on the volume (5760 for 2.88 mbytes disk) + BPB_Media db 0f0h ; f0 - used for removable media + BPB_FATSz16 dw 9 ; count of sectors by one copy of FAT + BPB_SecPerTrk dw 36 ; sectors per track + BPB_NumHeads dw 2 ; number of heads + BPB_HiddSec dd 0 ; count of hidden sectors + BPB_TotSec32 dd 0 ; count of sectors on the volume (if > 65535) + BS_DrvNum db 0 ; int 13h drive number + BS_Reserved db 0 ; reserved + BS_BootSig db 29h ; Extended boot signature + BS_VolID dd 0 ; Volume serial number + BS_VolLab db 'KOLIBRI ' ; Volume label (db 11) + BS_FilSysType db 'FAT12 ' ; file system type (db 8) diff --git a/kernel/trunk/bus/pci/PCIe.inc b/kernel/trunk/bus/pci/PCIe.inc index 4284b18c4..d1ea8c6ec 100644 --- a/kernel/trunk/bus/pci/PCIe.inc +++ b/kernel/trunk/bus/pci/PCIe.inc @@ -1,119 +1,119 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) 2010 KolibriOS team. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ;; -;; PCIe.INC ;; -;; ;; -;; Extended PCI express services ;; -;; ;; -;; art_zh ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision: 1463 $ - -;*************************************************************************** -; Function -; pci_ext_config: -; -; Description -; PCIe extended (memory-mapped) config space detection -; -; WARNINGs: -; 1) Very Experimental! -; 2) direct HT-detection (no ACPI or BIOS service used) -; 3) Only AMD/HT processors currently supported -; -;*************************************************************************** - -PCIe_CONFIG_SPACE equ 0xF0000000 ; to be moved to const.inc -mmio_pcie_cfg_addr dd 0x0 ; intel pcie space may be defined here -mmio_pcie_cfg_lim dd 0x0 ; upper pcie space address - - -align 4 - -pci_ext_config: - - mov ebx, [mmio_pcie_cfg_addr] - or ebx,ebx - jz @f - or ebx, 0x7FFFFFFF ; required by PCI-SIG standards - jnz .pcie_failed - add ebx, 0x0FFFFC - cmp ebx, [mmio_pcie_cfg_lim]; is the space limit correct? - ja .pcie_failed - jmp .pcie_cfg_mapped -@@: - mov ebx, [cpu_vendor] - cmp ebx, dword [AMD_str] - jne .pcie_failed - mov bx, 0xC184 ; dev = 24, fn = 01, reg = 84h - -.check_HT_mmio: - mov cx, bx - mov ax, 0x0002 ; bus = 0, 1dword to read - call pci_read_reg - mov bx, cx - sub bl, 4 - and al, 0x80 ; check the NP bit - jz .no_pcie_cfg - shl eax, 8 ; bus:[27..20], dev:[19:15] - or eax, 0x00007FFC ; fun:[14..12], reg:[11:2] - mov [mmio_pcie_cfg_lim], eax - mov cl, bl - mov ax, 0x0002 ; bus = 0, 1dword to read - call pci_read_reg - mov bx, cx - test al, 0x03 ; MMIO Base RW enabled? - jz .no_pcie_cfg - test al, 0x0C ; MMIO Base locked? - jnz .no_pcie_cfg - xor al, al - shl eax, 8 - test eax, 0x000F0000 ; MMIO Base must be bus0-aligned - jnz .no_pcie_cfg - mov [mmio_pcie_cfg_addr], eax - add eax, 0x000FFFFC - sub eax,[mmio_pcie_cfg_lim] ; MMIO must cover at least one bus - ja .no_pcie_cfg - -; -- it looks like a true PCIe config space; - mov eax,[mmio_pcie_cfg_addr] ; physical address - or eax, (PG_SHARED + PG_LARGE + PG_USER) - mov ebx, PCIe_CONFIG_SPACE ; linear address - mov ecx, ebx - shr ebx, 20 - add ebx, sys_pgdir ; PgDir entry @ -@@: - mov dword[ebx], eax ; map 4 buses - invlpg [ecx] - cmp bl, 4 - jz .pcie_cfg_mapped ; fix it later - add bl, 4 ; next PgDir entry - add eax, 0x400000 ; eax += 4M - add ecx, 0x400000 - jmp @b - -.pcie_cfg_mapped: - -; -- glad to have the extended PCIe config field found -; mov esi, boot_pcie_ok -; call boot_log - ret ; <<<<<<<<<<< OK >>>>>>>>>>> - -.no_pcie_cfg: - - xor eax, eax - mov [mmio_pcie_cfg_addr], eax - mov [mmio_pcie_cfg_lim], eax - add bl, 12 - cmp bl, 0xC0 ; MMIO regs lay below this offset - jb .check_HT_mmio -.pcie_failed: -; mov esi, boot_pcie_fail -; call boot_log - ret ; <<<<<<<<< FAILURE >>>>>>>>> - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) 2010 KolibriOS team. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; PCIe.INC ;; +;; ;; +;; Extended PCI express services ;; +;; ;; +;; art_zh ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision: 1463 $ + +;*************************************************************************** +; Function +; pci_ext_config: +; +; Description +; PCIe extended (memory-mapped) config space detection +; +; WARNINGs: +; 1) Very Experimental! +; 2) direct HT-detection (no ACPI or BIOS service used) +; 3) Only AMD/HT processors currently supported +; +;*************************************************************************** + +PCIe_CONFIG_SPACE equ 0xF0000000 ; to be moved to const.inc +mmio_pcie_cfg_addr dd 0x0 ; intel pcie space may be defined here +mmio_pcie_cfg_lim dd 0x0 ; upper pcie space address + + +align 4 + +pci_ext_config: + + mov ebx, [mmio_pcie_cfg_addr] + or ebx, ebx + jz @f + or ebx, 0x7FFFFFFF ; required by PCI-SIG standards + jnz .pcie_failed + add ebx, 0x0FFFFC + cmp ebx, [mmio_pcie_cfg_lim]; is the space limit correct? + ja .pcie_failed + jmp .pcie_cfg_mapped +@@: + mov ebx, [cpu_vendor] + cmp ebx, dword [AMD_str] + jne .pcie_failed + mov bx, 0xC184 ; dev = 24, fn = 01, reg = 84h + +.check_HT_mmio: + mov cx, bx + mov ax, 0x0002 ; bus = 0, 1dword to read + call pci_read_reg + mov bx, cx + sub bl, 4 + and al, 0x80 ; check the NP bit + jz .no_pcie_cfg + shl eax, 8 ; bus:[27..20], dev:[19:15] + or eax, 0x00007FFC ; fun:[14..12], reg:[11:2] + mov [mmio_pcie_cfg_lim], eax + mov cl, bl + mov ax, 0x0002 ; bus = 0, 1dword to read + call pci_read_reg + mov bx, cx + test al, 0x03 ; MMIO Base RW enabled? + jz .no_pcie_cfg + test al, 0x0C ; MMIO Base locked? + jnz .no_pcie_cfg + xor al, al + shl eax, 8 + test eax, 0x000F0000 ; MMIO Base must be bus0-aligned + jnz .no_pcie_cfg + mov [mmio_pcie_cfg_addr], eax + add eax, 0x000FFFFC + sub eax, [mmio_pcie_cfg_lim]; MMIO must cover at least one bus + ja .no_pcie_cfg + +; -- it looks like a true PCIe config space; + mov eax, [mmio_pcie_cfg_addr] ; physical address + or eax, (PG_SHARED + PG_LARGE + PG_USER) + mov ebx, PCIe_CONFIG_SPACE ; linear address + mov ecx, ebx + shr ebx, 20 + add ebx, sys_pgdir ; PgDir entry @ +@@: + mov dword[ebx], eax ; map 4 buses + invlpg [ecx] + cmp bl, 4 + jz .pcie_cfg_mapped ; fix it later + add bl, 4 ; next PgDir entry + add eax, 0x400000 ; eax += 4M + add ecx, 0x400000 + jmp @b + +.pcie_cfg_mapped: + +; -- glad to have the extended PCIe config field found +; mov esi, boot_pcie_ok +; call boot_log + ret ; <<<<<<<<<<< OK >>>>>>>>>>> + +.no_pcie_cfg: + + xor eax, eax + mov [mmio_pcie_cfg_addr], eax + mov [mmio_pcie_cfg_lim], eax + add bl, 12 + cmp bl, 0xC0 ; MMIO regs lay below this offset + jb .check_HT_mmio +.pcie_failed: +; mov esi, boot_pcie_fail +; call boot_log + ret ; <<<<<<<<< FAILURE >>>>>>>>> + diff --git a/kernel/trunk/bus/pci/pci16.inc b/kernel/trunk/bus/pci/pci16.inc index 211fabf2f..197e7303d 100644 --- a/kernel/trunk/bus/pci/pci16.inc +++ b/kernel/trunk/bus/pci/pci16.inc @@ -1,51 +1,51 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; PCI16.INC ;; -;; ;; -;; 16 bit PCI driver code ;; -;; ;; -;; Version 0.2 December 21st, 2002 ;; -;; ;; -;; Author: Victor Prodan, victorprodan@yahoo.com ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -init_pci_16: - - pushad - - xor ax,ax - mov es,ax - mov byte [es:0x9020],1 ;default mechanism:1 - mov ax,0xb101 - int 0x1a - or ah,ah - jnz pci16skip - - mov [es:0x9021],cl ;last PCI bus in system - mov [es:0x9022],bx - mov [es:0x9024],edi - -; we have a PCI BIOS, so check which configuration mechanism(s) -; it supports -; AL = PCI hardware characteristics (bit0 => mechanism1, bit1 => mechanism2) - test al,1 - jnz pci16skip - test al,2 - jz pci16skip - mov byte [es:0x9020],2 ; if (al&3)==2 => mechanism 2 - -pci16skip: - - mov ax,0x1000 - mov es,ax - - popad +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; PCI16.INC ;; +;; ;; +;; 16 bit PCI driver code ;; +;; ;; +;; Version 0.2 December 21st, 2002 ;; +;; ;; +;; Author: Victor Prodan, victorprodan@yahoo.com ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +init_pci_16: + + pushad + + xor ax, ax + mov es, ax + mov byte [es:0x9020], 1;default mechanism:1 + mov ax, 0xb101 + int 0x1a + or ah, ah + jnz pci16skip + + mov [es:0x9021], cl;last PCI bus in system + mov [es:0x9022], bx + mov [es:0x9024], edi + +; we have a PCI BIOS, so check which configuration mechanism(s) +; it supports +; AL = PCI hardware characteristics (bit0 => mechanism1, bit1 => mechanism2) + test al, 1 + jnz pci16skip + test al, 2 + jz pci16skip + mov byte [es:0x9020], 2; if (al&3)==2 => mechanism 2 + +pci16skip: + + mov ax, 0x1000 + mov es, ax + + popad diff --git a/kernel/trunk/bus/pci/pci32.inc b/kernel/trunk/bus/pci/pci32.inc index e67afcea9..410373cd7 100644 --- a/kernel/trunk/bus/pci/pci32.inc +++ b/kernel/trunk/bus/pci/pci32.inc @@ -1,654 +1,660 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ;; -;; PCI32.INC ;; -;; ;; -;; 32 bit PCI driver code ;; -;; ;; -;; Version 0.3 April 9, 2007 ;; -;; Version 0.2 December 21st, 2002 ;; -;; ;; -;; Author: Victor Prodan, victorprodan@yahoo.com ;; -;; Mihailov Ilia, ghost.nsk@gmail.com ;; -;; Credits: ;; -;; Ralf Brown ;; -;; Mike Hibbett, mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -;*************************************************************************** -; Function -; pci_api: -; -; Description -; entry point for system PCI calls -;*************************************************************************** -;mmio_pci_addr equ 0x400 ; set actual PCI address here to activate user-MMIO - -iglobal -align 4 -f62call: - dd pci_fn_0 - dd pci_fn_1 - dd pci_fn_2 - dd pci_service_not_supported ;3 - dd pci_read_reg ;4 byte - dd pci_read_reg ;5 word - dd pci_read_reg ;6 dword - dd pci_service_not_supported ;7 - dd pci_write_reg ;8 byte - dd pci_write_reg ;9 word - dd pci_write_reg ;10 dword -if defined mmio_pci_addr - dd pci_mmio_init ;11 - dd pci_mmio_map ;12 - dd pci_mmio_unmap ;13 -end if - -endg - -align 4 - -pci_api: - -;cross - mov eax,ebx - mov ebx,ecx - mov ecx,edx - - cmp [pci_access_enabled],1 - jne pci_service_not_supported - - movzx edx, al - -if defined mmio_pci_addr - cmp al, 13 - ja pci_service_not_supported -else - cmp al, 10 - ja pci_service_not_supported -end if - - call dword [f62call+edx*4] - mov dword [esp+32],eax - ret - - -align 4 -pci_api_drv: - - cmp [pci_access_enabled],1 - jne .fail - - cmp eax, 2 - ja .fail - - jmp dword [f62call+eax*4] - -.fail: - or eax,-1 - ret - - -;; ============================================ - -pci_fn_0: -; PCI function 0: get pci version (AH.AL) - movzx eax,word [BOOT_VAR+0x9022] - ret - -pci_fn_1: -; PCI function 1: get last bus in AL - mov al,[BOOT_VAR+0x9021] - ret - -pci_fn_2: -; PCI function 2: get pci access mechanism - mov al,[BOOT_VAR+0x9020] - ret - -pci_service_not_supported: - or eax,-1 - mov dword [esp+32],eax - ret - -;*************************************************************************** -; Function -; pci_make_config_cmd -; -; Description -; creates a command dword for use with the PCI bus -; bus # in ah -; device+func in bh (dddddfff) -; register in bl -; -; command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 ) -;*************************************************************************** - -align 4 - -pci_make_config_cmd: - shl eax,8 ; move bus to bits 16-23 - mov ax,bx ; combine all - and eax,0xffffff - or eax,0x80000000 - ret - -;*************************************************************************** -; Function -; pci_read_reg: -; -; Description -; read a register from the PCI config space into EAX/AX/AL -; IN: ah=bus,device+func=bh,register address=bl -; number of bytes to read (1,2,4) coded into AL, bits 0-1 -; (0 - byte, 1 - word, 2 - dword) -;*************************************************************************** - -align 4 - -pci_read_reg: - cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? - je pci_read_reg_2 - - ; mechanism 1 - push esi ; save register size into ESI - mov esi,eax - and esi,3 - - call pci_make_config_cmd - mov ebx,eax - ; get current state - mov dx,0xcf8 - in eax, dx - push eax - ; set up addressing to config data - mov eax,ebx - and al,0xfc ; make address dword-aligned - out dx,eax - ; get requested DWORD of config data - mov dl,0xfc - and bl,3 - or dl,bl ; add to port address first 2 bits of register address - - or esi,esi - jz pci_read_byte1 - cmp esi,1 - jz pci_read_word1 - cmp esi,2 - jz pci_read_dword1 - jmp pci_fin_read1 - -pci_read_byte1: - in al,dx - jmp pci_fin_read1 -pci_read_word1: - in ax,dx - jmp pci_fin_read1 -pci_read_dword1: - in eax,dx - jmp pci_fin_read1 -pci_fin_read1: - ; restore configuration control - xchg eax,[esp] - mov dx,0xcf8 - out dx,eax - - pop eax - pop esi - ret -pci_read_reg_2: - - test bh,128 ;mech#2 only supports 16 devices per bus - jnz pci_read_reg_err - - push esi ; save register size into ESI - mov esi,eax - and esi,3 - - push eax - ;store current state of config space - mov dx,0xcf8 - in al,dx - mov ah,al - mov dl,0xfa - in al,dx - - xchg eax,[esp] - ; out 0xcfa,bus - mov al,ah - out dx,al - ; out 0xcf8,0x80 - mov dl,0xf8 - mov al,0x80 - out dx,al - ; compute addr - shr bh,3 ; func is ignored in mechanism 2 - or bh,0xc0 - mov dx,bx - - or esi,esi - jz pci_read_byte2 - cmp esi,1 - jz pci_read_word2 - cmp esi,2 - jz pci_read_dword2 - jmp pci_fin_read2 - -pci_read_byte2: - in al,dx - jmp pci_fin_read2 -pci_read_word2: - in ax,dx - jmp pci_fin_read2 -pci_read_dword2: - in eax,dx -; jmp pci_fin_read2 -pci_fin_read2: - - ; restore configuration space - xchg eax,[esp] - mov dx,0xcfa - out dx,al - mov dl,0xf8 - mov al,ah - out dx,al - - pop eax - pop esi - ret - -pci_read_reg_err: - xor eax,eax - dec eax - ret - - -;*************************************************************************** -; Function -; pci_write_reg: -; -; Description -; write a register from ECX/CX/CL into the PCI config space -; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, -; value to write in ecx -; number of bytes to write (1,2,4) coded into AL, bits 0-1 -; (0 - byte, 1 - word, 2 - dword) -;*************************************************************************** - -align 4 - -pci_write_reg: - cmp byte [BOOT_VAR+0x9020],2 ;what mechanism will we use? - je pci_write_reg_2 - - ; mechanism 1 - push esi ; save register size into ESI - mov esi,eax - and esi,3 - - call pci_make_config_cmd - mov ebx,eax - ; get current state into ecx - mov dx,0xcf8 - in eax, dx - push eax - ; set up addressing to config data - mov eax,ebx - and al,0xfc ; make address dword-aligned - out dx,eax - ; write DWORD of config data - mov dl,0xfc - and bl,3 - or dl,bl - mov eax,ecx - - or esi,esi - jz pci_write_byte1 - cmp esi,1 - jz pci_write_word1 - cmp esi,2 - jz pci_write_dword1 - jmp pci_fin_write1 - -pci_write_byte1: - out dx,al - jmp pci_fin_write1 -pci_write_word1: - out dx,ax - jmp pci_fin_write1 -pci_write_dword1: - out dx,eax - jmp pci_fin_write1 -pci_fin_write1: - - ; restore configuration control - pop eax - mov dl,0xf8 - out dx,eax - - xor eax,eax - pop esi - - ret -pci_write_reg_2: - - test bh,128 ;mech#2 only supports 16 devices per bus - jnz pci_write_reg_err - - - push esi ; save register size into ESI - mov esi,eax - and esi,3 - - push eax - ;store current state of config space - mov dx,0xcf8 - in al,dx - mov ah,al - mov dl,0xfa - in al,dx - xchg eax,[esp] - ; out 0xcfa,bus - mov al,ah - out dx,al - ; out 0xcf8,0x80 - mov dl,0xf8 - mov al,0x80 - out dx,al - ; compute addr - shr bh,3 ; func is ignored in mechanism 2 - or bh,0xc0 - mov dx,bx - ; write register - mov eax,ecx - - or esi,esi - jz pci_write_byte2 - cmp esi,1 - jz pci_write_word2 - cmp esi,2 - jz pci_write_dword2 - jmp pci_fin_write2 - -pci_write_byte2: - out dx,al - jmp pci_fin_write2 -pci_write_word2: - out dx,ax - jmp pci_fin_write2 -pci_write_dword2: - out dx,eax - jmp pci_fin_write2 -pci_fin_write2: - ; restore configuration space - pop eax - mov dx,0xcfa - out dx,al - mov dl,0xf8 - mov al,ah - out dx,al - - xor eax,eax - pop esi - ret - -pci_write_reg_err: - xor eax,eax - dec eax - ret - -if defined mmio_pci_addr ; must be set above -;*************************************************************************** -; Function -; pci_mmio_init -; -; Description -; IN: bx = device's PCI bus address (bbbbbbbbdddddfff) -; Returns eax = user heap space available (bytes) -; Error codes -; eax = -1 : PCI user access blocked, -; eax = -2 : device not registered for uMMIO service -; eax = -3 : user heap initialization failure -;*************************************************************************** -pci_mmio_init: - cmp bx, mmio_pci_addr - jz @f - mov eax,-2 - ret -@@: - call init_heap ; (if not initialized yet) - or eax,eax - jz @f - ret -@@: - mov eax,-3 - ret - - -;*************************************************************************** -; Function -; pci_mmio_map -; -; Description -; maps a block of PCI memory to user-accessible linear address -; -; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only! -; The target device address should be set in kernel var mmio_pci_addr -; -; IN: ah = BAR#; -; IN: ebx = block size (bytes); -; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages); -; -; Returns eax = MMIO block's linear address in the userspace (if no error) -; -; -; Error codes -; eax = -1 : user access to PCI blocked, -; eax = -2 : an invalid BAR register referred -; eax = -3 : no i/o space on that BAR -; eax = -4 : a port i/o BAR register referred -; eax = -5 : dynamic userspace allocation problem -;*************************************************************************** - -pci_mmio_map: - and edx,0x0ffff - cmp ah,6 - jc .bar_0_5 - jz .bar_rom - mov eax,-2 - ret -.bar_rom: - mov ah, 8 ; bar6 = Expansion ROM base address -.bar_0_5: - push ecx - add ebx, 4095 - and ebx,-4096 - push ebx - mov bl, ah ; bl = BAR# (0..5), however bl=8 for BAR6 - shl bl, 1 - shl bl, 1 - add bl, 0x10 ; now bl = BAR offset in PCI config. space - mov ax, mmio_pci_addr - mov bh, al ; bh = dddddfff - mov al, 2 ; al : DW to read - call pci_read_reg - or eax, eax - jnz @f - mov eax,-3 ; empty I/O space - jmp mmio_ret_fail -@@: - test eax, 1 - jz @f - mov eax,-4 ; damned ports (not MMIO space) - jmp mmio_ret_fail -@@: - pop ecx ; ecx = block size, bytes (expanded to whole page) - mov ebx, ecx ; user_alloc destroys eax, ecx, edx, but saves ebx - and eax, 0xFFFFFFF0 - push eax ; store MMIO physical address + keep 2DWords in the stack - stdcall user_alloc, ecx - or eax, eax - jnz mmio_map_over - mov eax,-5 ; problem with page allocation - -mmio_ret_fail: - pop ecx - pop edx - ret - -mmio_map_over: - mov ecx, ebx ; ecx = size (bytes, expanded to whole page) - shr ecx, 12 ; ecx = number of pages - mov ebx, eax ; ebx = linear address - pop eax ; eax = MMIO start - pop edx ; edx = MMIO shift (pages) - shl edx, 12 ; edx = MMIO shift (bytes) - add eax, edx ; eax = uMMIO physical address - or eax, PG_SHARED - or eax, PG_UW - or eax, PG_NOCACHE - mov edi, ebx - call commit_pages - mov eax, edi - ret - -;*************************************************************************** -; Function -; pci_mmio_unmap_page -; -; Description -; unmaps the linear space previously tied to a PCI memory block -; -; IN: ebx = linear address of space previously allocated by pci_mmio_map -; returns eax = 1 if successfully unmapped -; -; Error codes -; eax = -1 if no user PCI access allowed, -; eax = 0 if unmapping failed -;*************************************************************************** - -pci_mmio_unmap: - stdcall user_free, ebx - ret - -end if - -;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -uglobal -align 4 -; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1) -pci_emu_dat: times 30*10 db 0 -endg -;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -align 4 -sys_pcibios: - cmp [pci_access_enabled], 1 - jne .unsupported_func - cmp [pci_bios_entry], 0 - jz .emulate_bios - - push ds - mov ax, pci_data_sel - mov ds, ax - mov eax, ebp - mov ah, 0B1h - call pword [cs:pci_bios_entry] - pop ds - - jmp .return - ;-=-=-=-=-=-=-=-= -.emulate_bios: - cmp ebp, 1 ; PCI_FUNCTION_ID - jnz .not_PCI_BIOS_PRESENT - mov edx, 'PCI ' - mov al, [BOOT_VAR + 0x9020] - mov bx, [BOOT_VAR + 0x9022] - mov cl, [BOOT_VAR + 0x9021] - xor ah, ah - jmp .return_abcd - -.not_PCI_BIOS_PRESENT: - cmp ebp, 2 ; FIND_PCI_DEVICE - jne .not_FIND_PCI_DEVICE - mov ebx, pci_emu_dat -..nxt: cmp [ebx], dx - jne ..no - cmp [ebx + 2], cx - jne ..no - dec si - jns ..no - mov bx, [ebx + 4] - xor ah, ah - jmp .return_ab -..no: cmp word[ebx], 0 - je ..dev_not_found - add ebx, 10 - jmp ..nxt -..dev_not_found: - mov ah, 0x86 ; DEVICE_NOT_FOUND - jmp .return_a - -.not_FIND_PCI_DEVICE: - cmp ebp, 3 ; FIND_PCI_CLASS_CODE - jne .not_FIND_PCI_CLASS_CODE - mov esi, pci_emu_dat - shl ecx, 8 -..nxt2: cmp [esi], ecx - jne ..no2 - mov bx, [esi] - xor ah, ah - jmp .return_ab -..no2: cmp dword[esi], 0 - je ..dev_not_found - add esi, 10 - jmp ..nxt2 - -.not_FIND_PCI_CLASS_CODE: - cmp ebp, 8 ; READ_CONFIG_* - jb .not_READ_CONFIG - cmp ebp, 0x0A - ja .not_READ_CONFIG - mov eax, ebp - mov ah, bh - mov edx, edi - mov bh, bl - mov bl, dl - call pci_read_reg - mov ecx, eax - xor ah, ah ; SUCCESSFUL - jmp .return_abc -.not_READ_CONFIG: - cmp ebp, 0x0B ; WRITE_CONFIG_* - jb .not_WRITE_CONFIG - cmp ebp, 0x0D - ja .not_WRITE_CONFIG - lea eax, [ebp+1] - mov ah, bh - mov edx, edi - mov bh, bl - mov bl, dl - call pci_write_reg - xor ah, ah ; SUCCESSFUL - jmp .return_abc -.not_WRITE_CONFIG: -.unsupported_func: - mov ah, 0x81 ; FUNC_NOT_SUPPORTED -.return:mov dword[esp + 4 ], edi - mov dword[esp + 8], esi -.return_abcd: - mov dword[esp + 24], edx -.return_abc: - mov dword[esp + 28], ecx -.return_ab: - mov dword[esp + 20], ebx -.return_a: - mov dword[esp + 32], eax - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; PCI32.INC ;; +;; ;; +;; 32 bit PCI driver code ;; +;; ;; +;; Version 0.3 April 9, 2007 ;; +;; Version 0.2 December 21st, 2002 ;; +;; ;; +;; Author: Victor Prodan, victorprodan@yahoo.com ;; +;; Mihailov Ilia, ghost.nsk@gmail.com ;; +;; Credits: ;; +;; Ralf Brown ;; +;; Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +;*************************************************************************** +; Function +; pci_api: +; +; Description +; entry point for system PCI calls +;*************************************************************************** +;mmio_pci_addr equ 0x400 ; set actual PCI address here to activate user-MMIO + +iglobal +align 4 +f62call: + dd pci_fn_0 + dd pci_fn_1 + dd pci_fn_2 + dd pci_service_not_supported ;3 + dd pci_read_reg ;4 byte + dd pci_read_reg ;5 word + dd pci_read_reg ;6 dword + dd pci_service_not_supported ;7 + dd pci_write_reg ;8 byte + dd pci_write_reg ;9 word + dd pci_write_reg ;10 dword +if defined mmio_pci_addr + dd pci_mmio_init ;11 + dd pci_mmio_map ;12 + dd pci_mmio_unmap ;13 +end if + +endg + +align 4 + +pci_api: + +;cross + mov eax, ebx + mov ebx, ecx + mov ecx, edx + + cmp [pci_access_enabled], 1 + jne pci_service_not_supported + + movzx edx, al + +if defined mmio_pci_addr + cmp al, 13 + ja pci_service_not_supported +else + cmp al, 10 + ja pci_service_not_supported +end if + + call dword [f62call+edx*4] + mov dword [esp+32], eax + ret + + +align 4 +pci_api_drv: + + cmp [pci_access_enabled], 1 + jne .fail + + cmp eax, 2 + ja .fail + + jmp dword [f62call+eax*4] + +.fail: + or eax, -1 + ret + + +;; ============================================ + +pci_fn_0: +; PCI function 0: get pci version (AH.AL) + movzx eax, word [BOOT_VAR+0x9022] + ret + +pci_fn_1: +; PCI function 1: get last bus in AL + mov al, [BOOT_VAR+0x9021] + ret + +pci_fn_2: +; PCI function 2: get pci access mechanism + mov al, [BOOT_VAR+0x9020] + ret + +pci_service_not_supported: + or eax, -1 + mov dword [esp+32], eax + ret + +;*************************************************************************** +; Function +; pci_make_config_cmd +; +; Description +; creates a command dword for use with the PCI bus +; bus # in ah +; device+func in bh (dddddfff) +; register in bl +; +; command dword returned in eax ( 10000000 bbbbbbbb dddddfff rrrrrr00 ) +;*************************************************************************** + +align 4 + +pci_make_config_cmd: + shl eax, 8 ; move bus to bits 16-23 + mov ax, bx ; combine all + and eax, 0xffffff + or eax, 0x80000000 + ret + +;*************************************************************************** +; Function +; pci_read_reg: +; +; Description +; read a register from the PCI config space into EAX/AX/AL +; IN: ah=bus,device+func=bh,register address=bl +; number of bytes to read (1,2,4) coded into AL, bits 0-1 +; (0 - byte, 1 - word, 2 - dword) +;*************************************************************************** + +align 4 + +pci_read_reg: + cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? + je pci_read_reg_2 + + ; mechanism 1 + push esi ; save register size into ESI + mov esi, eax + and esi, 3 + + call pci_make_config_cmd + mov ebx, eax + ; get current state + mov dx, 0xcf8 + in eax, dx + push eax + ; set up addressing to config data + mov eax, ebx + and al, 0xfc; make address dword-aligned + out dx, eax + ; get requested DWORD of config data + mov dl, 0xfc + and bl, 3 + or dl, bl ; add to port address first 2 bits of register address + + or esi, esi + jz pci_read_byte1 + cmp esi, 1 + jz pci_read_word1 + cmp esi, 2 + jz pci_read_dword1 + jmp pci_fin_read1 + +pci_read_byte1: + in al, dx + jmp pci_fin_read1 +pci_read_word1: + in ax, dx + jmp pci_fin_read1 +pci_read_dword1: + in eax, dx + jmp pci_fin_read1 +pci_fin_read1: + ; restore configuration control + xchg eax, [esp] + mov dx, 0xcf8 + out dx, eax + + pop eax + pop esi + ret +pci_read_reg_2: + + test bh, 128 ;mech#2 only supports 16 devices per bus + jnz pci_read_reg_err + + push esi; save register size into ESI + mov esi, eax + and esi, 3 + + push eax + ;store current state of config space + mov dx, 0xcf8 + in al, dx + mov ah, al + mov dl, 0xfa + in al, dx + + xchg eax, [esp] + ; out 0xcfa,bus + mov al, ah + out dx, al + ; out 0xcf8,0x80 + mov dl, 0xf8 + mov al, 0x80 + out dx, al + ; compute addr + shr bh, 3; func is ignored in mechanism 2 + or bh, 0xc0 + mov dx, bx + + or esi, esi + jz pci_read_byte2 + cmp esi, 1 + jz pci_read_word2 + cmp esi, 2 + jz pci_read_dword2 + jmp pci_fin_read2 + +pci_read_byte2: + in al, dx + jmp pci_fin_read2 +pci_read_word2: + in ax, dx + jmp pci_fin_read2 +pci_read_dword2: + in eax, dx +; jmp pci_fin_read2 +pci_fin_read2: + + ; restore configuration space + xchg eax, [esp] + mov dx, 0xcfa + out dx, al + mov dl, 0xf8 + mov al, ah + out dx, al + + pop eax + pop esi + ret + +pci_read_reg_err: + xor eax, eax + dec eax + ret + + +;*************************************************************************** +; Function +; pci_write_reg: +; +; Description +; write a register from ECX/CX/CL into the PCI config space +; IN: ah=bus,device+func=bh,register address (dword aligned)=bl, +; value to write in ecx +; number of bytes to write (1,2,4) coded into AL, bits 0-1 +; (0 - byte, 1 - word, 2 - dword) +;*************************************************************************** + +align 4 + +pci_write_reg: + cmp byte [BOOT_VAR+0x9020], 2;what mechanism will we use? + je pci_write_reg_2 + + ; mechanism 1 + push esi ; save register size into ESI + mov esi, eax + and esi, 3 + + call pci_make_config_cmd + mov ebx, eax + ; get current state into ecx + mov dx, 0xcf8 + in eax, dx + push eax + ; set up addressing to config data + mov eax, ebx + and al, 0xfc; make address dword-aligned + out dx, eax + ; write DWORD of config data + mov dl, 0xfc + and bl, 3 + or dl, bl + mov eax, ecx + + or esi, esi + jz pci_write_byte1 + cmp esi, 1 + jz pci_write_word1 + cmp esi, 2 + jz pci_write_dword1 + jmp pci_fin_write1 + +pci_write_byte1: + out dx, al + jmp pci_fin_write1 +pci_write_word1: + out dx, ax + jmp pci_fin_write1 +pci_write_dword1: + out dx, eax + jmp pci_fin_write1 +pci_fin_write1: + + ; restore configuration control + pop eax + mov dl, 0xf8 + out dx, eax + + xor eax, eax + pop esi + + ret +pci_write_reg_2: + + test bh, 128 ;mech#2 only supports 16 devices per bus + jnz pci_write_reg_err + + + push esi; save register size into ESI + mov esi, eax + and esi, 3 + + push eax + ;store current state of config space + mov dx, 0xcf8 + in al, dx + mov ah, al + mov dl, 0xfa + in al, dx + xchg eax, [esp] + ; out 0xcfa,bus + mov al, ah + out dx, al + ; out 0xcf8,0x80 + mov dl, 0xf8 + mov al, 0x80 + out dx, al + ; compute addr + shr bh, 3; func is ignored in mechanism 2 + or bh, 0xc0 + mov dx, bx + ; write register + mov eax, ecx + + or esi, esi + jz pci_write_byte2 + cmp esi, 1 + jz pci_write_word2 + cmp esi, 2 + jz pci_write_dword2 + jmp pci_fin_write2 + +pci_write_byte2: + out dx, al + jmp pci_fin_write2 +pci_write_word2: + out dx, ax + jmp pci_fin_write2 +pci_write_dword2: + out dx, eax + jmp pci_fin_write2 +pci_fin_write2: + ; restore configuration space + pop eax + mov dx, 0xcfa + out dx, al + mov dl, 0xf8 + mov al, ah + out dx, al + + xor eax, eax + pop esi + ret + +pci_write_reg_err: + xor eax, eax + dec eax + ret + +if defined mmio_pci_addr ; must be set above +;*************************************************************************** +; Function +; pci_mmio_init +; +; Description +; IN: bx = device's PCI bus address (bbbbbbbbdddddfff) +; Returns eax = user heap space available (bytes) +; Error codes +; eax = -1 : PCI user access blocked, +; eax = -2 : device not registered for uMMIO service +; eax = -3 : user heap initialization failure +;*************************************************************************** +pci_mmio_init: + cmp bx, mmio_pci_addr + jz @f + mov eax, -2 + ret +@@: + call init_heap ; (if not initialized yet) + or eax, eax + jz @f + ret +@@: + mov eax, -3 + ret + + +;*************************************************************************** +; Function +; pci_mmio_map +; +; Description +; maps a block of PCI memory to user-accessible linear address +; +; WARNING! This VERY EXPERIMENTAL service is for one chosen PCI device only! +; The target device address should be set in kernel var mmio_pci_addr +; +; IN: ah = BAR#; +; IN: ebx = block size (bytes); +; IN: ecx = offset in MMIO block (in 4K-pages, to avoid misaligned pages); +; +; Returns eax = MMIO block's linear address in the userspace (if no error) +; +; +; Error codes +; eax = -1 : user access to PCI blocked, +; eax = -2 : an invalid BAR register referred +; eax = -3 : no i/o space on that BAR +; eax = -4 : a port i/o BAR register referred +; eax = -5 : dynamic userspace allocation problem +;*************************************************************************** + +pci_mmio_map: + and edx, 0x0ffff + cmp ah, 6 + jc .bar_0_5 + jz .bar_rom + mov eax, -2 + ret +.bar_rom: + mov ah, 8 ; bar6 = Expansion ROM base address +.bar_0_5: + push ecx + add ebx, 4095 + and ebx, -4096 + push ebx + mov bl, ah ; bl = BAR# (0..5), however bl=8 for BAR6 + shl bl, 1 + shl bl, 1 + add bl, 0x10; now bl = BAR offset in PCI config. space + mov ax, mmio_pci_addr + mov bh, al ; bh = dddddfff + mov al, 2 ; al : DW to read + call pci_read_reg + or eax, eax + jnz @f + mov eax, -3 ; empty I/O space + jmp mmio_ret_fail +@@: + test eax, 1 + jz @f + mov eax, -4 ; damned ports (not MMIO space) + jmp mmio_ret_fail +@@: + pop ecx ; ecx = block size, bytes (expanded to whole page) + mov ebx, ecx; user_alloc destroys eax, ecx, edx, but saves ebx + and eax, 0xFFFFFFF0 + push eax ; store MMIO physical address + keep 2DWords in the stack + stdcall user_alloc, ecx + or eax, eax + jnz mmio_map_over + mov eax, -5 ; problem with page allocation + +mmio_ret_fail: + pop ecx + pop edx + ret + +mmio_map_over: + mov ecx, ebx; ecx = size (bytes, expanded to whole page) + shr ecx, 12 ; ecx = number of pages + mov ebx, eax; ebx = linear address + pop eax ; eax = MMIO start + pop edx ; edx = MMIO shift (pages) + shl edx, 12 ; edx = MMIO shift (bytes) + add eax, edx; eax = uMMIO physical address + or eax, PG_SHARED + or eax, PG_UW + or eax, PG_NOCACHE + mov edi, ebx + call commit_pages + mov eax, edi + ret + +;*************************************************************************** +; Function +; pci_mmio_unmap_page +; +; Description +; unmaps the linear space previously tied to a PCI memory block +; +; IN: ebx = linear address of space previously allocated by pci_mmio_map +; returns eax = 1 if successfully unmapped +; +; Error codes +; eax = -1 if no user PCI access allowed, +; eax = 0 if unmapping failed +;*************************************************************************** + +pci_mmio_unmap: + stdcall user_free, ebx + ret + +end if + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +uglobal +align 4 +; VendID (2), DevID (2), Revision = 0 (1), Class Code (3), FNum (1), Bus (1) +pci_emu_dat: + times 30*10 db 0 +endg +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +align 4 +sys_pcibios: + cmp [pci_access_enabled], 1 + jne .unsupported_func + cmp [pci_bios_entry], 0 + jz .emulate_bios + + push ds + mov ax, pci_data_sel + mov ds, ax + mov eax, ebp + mov ah, 0B1h + call pword [cs:pci_bios_entry] + pop ds + + jmp .return + ;-=-=-=-=-=-=-=-= +.emulate_bios: + cmp ebp, 1 ; PCI_FUNCTION_ID + jnz .not_PCI_BIOS_PRESENT + mov edx, 'PCI ' + mov al, [BOOT_VAR + 0x9020] + mov bx, [BOOT_VAR + 0x9022] + mov cl, [BOOT_VAR + 0x9021] + xor ah, ah + jmp .return_abcd + +.not_PCI_BIOS_PRESENT: + cmp ebp, 2 ; FIND_PCI_DEVICE + jne .not_FIND_PCI_DEVICE + mov ebx, pci_emu_dat +..nxt: + cmp [ebx], dx + jne ..no + cmp [ebx + 2], cx + jne ..no + dec si + jns ..no + mov bx, [ebx + 4] + xor ah, ah + jmp .return_ab +..no: + cmp word[ebx], 0 + je ..dev_not_found + add ebx, 10 + jmp ..nxt +..dev_not_found: + mov ah, 0x86 ; DEVICE_NOT_FOUND + jmp .return_a + +.not_FIND_PCI_DEVICE: + cmp ebp, 3 ; FIND_PCI_CLASS_CODE + jne .not_FIND_PCI_CLASS_CODE + mov esi, pci_emu_dat + shl ecx, 8 +..nxt2: + cmp [esi], ecx + jne ..no2 + mov bx, [esi] + xor ah, ah + jmp .return_ab +..no2: + cmp dword[esi], 0 + je ..dev_not_found + add esi, 10 + jmp ..nxt2 + +.not_FIND_PCI_CLASS_CODE: + cmp ebp, 8 ; READ_CONFIG_* + jb .not_READ_CONFIG + cmp ebp, 0x0A + ja .not_READ_CONFIG + mov eax, ebp + mov ah, bh + mov edx, edi + mov bh, bl + mov bl, dl + call pci_read_reg + mov ecx, eax + xor ah, ah ; SUCCESSFUL + jmp .return_abc +.not_READ_CONFIG: + cmp ebp, 0x0B ; WRITE_CONFIG_* + jb .not_WRITE_CONFIG + cmp ebp, 0x0D + ja .not_WRITE_CONFIG + lea eax, [ebp+1] + mov ah, bh + mov edx, edi + mov bh, bl + mov bl, dl + call pci_write_reg + xor ah, ah ; SUCCESSFUL + jmp .return_abc +.not_WRITE_CONFIG: +.unsupported_func: + mov ah, 0x81 ; FUNC_NOT_SUPPORTED +.return: + mov dword[esp + 4 ], edi + mov dword[esp + 8], esi +.return_abcd: + mov dword[esp + 24], edx +.return_abc: + mov dword[esp + 28], ecx +.return_ab: + mov dword[esp + 20], ebx +.return_a: + mov dword[esp + 32], eax + ret diff --git a/kernel/trunk/const.inc b/kernel/trunk/const.inc index ad0a26503..4b6fd5ffb 100644 --- a/kernel/trunk/const.inc +++ b/kernel/trunk/const.inc @@ -1,782 +1,782 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -dpl0 equ 10010000b ; data read dpl0 -drw0 equ 10010010b ; data read/write dpl0 -drw3 equ 11110010b ; data read/write dpl3 -cpl0 equ 10011010b ; code read dpl0 -cpl3 equ 11111010b ; code read dpl3 - -D32 equ 01000000b ; 32bit segment -G32 equ 10000000b ; page gran - - -;;;;;;;;;;;;cpu_caps flags;;;;;;;;;;;;;;;; - -CPU_386 equ 3 -CPU_486 equ 4 -CPU_PENTIUM equ 5 -CPU_P6 equ 6 -CPU_PENTIUM4 equ 0x0F - -CAPS_FPU equ 00 ;on-chip x87 floating point unit -CAPS_VME equ 01 ;virtual-mode enhancements -CAPS_DE equ 02 ;debugging extensions -CAPS_PSE equ 03 ;page-size extensions -CAPS_TSC equ 04 ;time stamp counter -CAPS_MSR equ 05 ;model-specific registers -CAPS_PAE equ 06 ;physical-address extensions -CAPS_MCE equ 07 ;machine check exception -CAPS_CX8 equ 08 ;CMPXCHG8B instruction -CAPS_APIC equ 09 ;on-chip advanced programmable - ; interrupt controller -; 10 ;unused -CAPS_SEP equ 11 ;SYSENTER and SYSEXIT instructions -CAPS_MTRR equ 12 ;memory-type range registers -CAPS_PGE equ 13 ;page global extension -CAPS_MCA equ 14 ;machine check architecture -CAPS_CMOV equ 15 ;conditional move instructions -CAPS_PAT equ 16 ;page attribute table - -CAPS_PSE36 equ 17 ;page-size extensions -CAPS_PSN equ 18 ;processor serial number -CAPS_CLFLUSH equ 19 ;CLFUSH instruction - -CAPS_DS equ 21 ;debug store -CAPS_ACPI equ 22 ;thermal monitor and software - ;controlled clock supported -CAPS_MMX equ 23 ;MMX instructions -CAPS_FXSR equ 24 ;FXSAVE and FXRSTOR instructions -CAPS_SSE equ 25 ;SSE instructions -CAPS_SSE2 equ 26 ;SSE2 instructions -CAPS_SS equ 27 ;self-snoop -CAPS_HTT equ 28 ;hyper-threading technology -CAPS_TM equ 29 ;thermal monitor supported -CAPS_IA64 equ 30 ;IA64 capabilities -CAPS_PBE equ 31 ;pending break enable - -;ecx -CAPS_SSE3 equ 32 ;SSE3 instructions -; 33 -; 34 -CAPS_MONITOR equ 35 ;MONITOR/MWAIT instructions -CAPS_DS_CPL equ 36 ; -CAPS_VMX equ 37 ;virtual mode extensions -; 38 ; -CAPS_EST equ 39 ;enhansed speed step -CAPS_TM2 equ 40 ;thermal monitor2 supported -; 41 -CAPS_CID equ 42 ; -; 43 -; 44 -CAPS_CX16 equ 45 ;CMPXCHG16B instruction -CAPS_xTPR equ 46 ; -; -;reserved -; -;ext edx /ecx -CAPS_SYSCAL equ 64 ; -CAPS_XD equ 65 ;execution disable -CAPS_FFXSR equ 66 ; -CAPS_RDTSCP equ 67 ; -CAPS_X64 equ 68 ; -CAPS_3DNOW equ 69 ; -CAPS_3DNOWEXT equ 70 ; -CAPS_LAHF equ 71 ; -CAPS_CMP_LEG equ 72 ; -CAPS_SVM equ 73 ;secure virual machine -CAPS_ALTMOVCR8 equ 74 ; - -; CPU MSR names -MSR_SYSENTER_CS equ 0x174 -MSR_SYSENTER_ESP equ 0x175 -MSR_SYSENTER_EIP equ 0x176 -MSR_AMD_EFER equ 0xC0000080 ; Extended Feature Enable Register -MSR_AMD_STAR equ 0xC0000081 ; SYSCALL/SYSRET Target Address Register - -CR0_PE equ 0x00000001 ;protected mode -CR0_MP equ 0x00000002 ;monitor fpu -CR0_EM equ 0x00000004 ;fpu emulation -CR0_TS equ 0x00000008 ;task switch -CR0_ET equ 0x00000010 ;extension type hardcoded to 1 -CR0_NE equ 0x00000020 ;numeric error -CR0_WP equ 0x00010000 ;write protect -CR0_AM equ 0x00040000 ;alignment check -CR0_NW equ 0x20000000 ;not write-through -CR0_CD equ 0x40000000 ;cache disable -CR0_PG equ 0x80000000 ;paging - - -CR4_VME equ 0x0001 -CR4_PVI equ 0x0002 -CR4_TSD equ 0x0004 -CR4_DE equ 0x0008 -CR4_PSE equ 0x0010 -CR4_PAE equ 0x0020 -CR4_MCE equ 0x0040 -CR4_PGE equ 0x0080 -CR4_PCE equ 0x0100 -CR4_OSFXSR equ 0x0200 -CR4_OSXMMEXPT equ 0x0400 - -SSE_IE equ 0x0001 -SSE_DE equ 0x0002 -SSE_ZE equ 0x0004 -SSE_OE equ 0x0008 -SSE_UE equ 0x0010 -SSE_PE equ 0x0020 -SSE_DAZ equ 0x0040 -SSE_IM equ 0x0080 -SSE_DM equ 0x0100 -SSE_ZM equ 0x0200 -SSE_OM equ 0x0400 -SSE_UM equ 0x0800 -SSE_PM equ 0x1000 -SSE_FZ equ 0x8000 - -SSE_INIT equ (SSE_IM+SSE_DM+SSE_ZM+SSE_OM+SSE_UM+SSE_PM) - -IRQ_PIC equ 0 -IRQ_APIC equ 1 - -struc TSS -{ - ._back rw 2 - ._esp0 rd 1 - ._ss0 rw 2 - ._esp1 rd 1 - ._ss1 rw 2 - ._esp2 rd 1 - ._ss2 rw 2 - ._cr3 rd 1 - ._eip rd 1 - ._eflags rd 1 - ._eax rd 1 - ._ecx rd 1 - ._edx rd 1 - ._ebx rd 1 - ._esp rd 1 - ._ebp rd 1 - ._esi rd 1 - ._edi rd 1 - ._es rw 2 - ._cs rw 2 - ._ss rw 2 - ._ds rw 2 - ._fs rw 2 - ._gs rw 2 - ._ldt rw 2 - ._trap rw 1 - ._io rw 1 - rb 24 - ._io_map_0 rb 4096 - ._io_map_1 rb 4096 -} - -virtual at 0 - TSS TSS -end virtual - -TSS_SIZE equ (128+8192) - -OS_BASE equ 0x80000000 - -window_data equ (OS_BASE+0x0001000) - -CURRENT_TASK equ (OS_BASE+0x0003000) -TASK_COUNT equ (OS_BASE+0x0003004) -TASK_BASE equ (OS_BASE+0x0003010) -TASK_DATA equ (OS_BASE+0x0003020) -TASK_EVENT equ (OS_BASE+0x0003020) - -mouseunder equ (OS_BASE+0x0006900) -CDDataBuf equ (OS_BASE+0x0007000) -FLOPPY_BUFF equ (OS_BASE+0x0008000) -ACTIVE_PROC_STACK equ (OS_BASE+0x000A400) ;unused -idts equ (OS_BASE+0x000B100) -WIN_STACK equ (OS_BASE+0x000C000) -WIN_POS equ (OS_BASE+0x000C400) -FDD_BUFF equ (OS_BASE+0x000D000) - -;unused ? only one reference -ENABLE_TASKSWITCH equ (OS_BASE+0x000E000) - -PUTPIXEL equ (OS_BASE+0x000E020) -GETPIXEL equ (OS_BASE+0x000E024) - -;unused ? only one reference -BANK_SWITCH equ (OS_BASE+0x000E030) - -;unused ? store mousepointer -MOUSE_PICTURE equ (OS_BASE+0x000F200) - -MOUSE_VISIBLE equ (OS_BASE+0x000F204) -WIN_TEMP_XY equ (OS_BASE+0x000F300) -KEY_COUNT equ (OS_BASE+0x000F400) -KEY_BUFF equ (OS_BASE+0x000F401) - -BTN_COUNT equ (OS_BASE+0x000F500) -BTN_BUFF equ (OS_BASE+0x000F501) - -CPU_FREQ equ (OS_BASE+0x000F600) - -;unused ? no active references -MOUSE_PORT equ (OS_BASE+0x000F604) - -;unused -PS2_CHUNK equ (OS_BASE+0x000FB00) - -MOUSE_SCROLL_H equ (OS_BASE+0x000FB08) -MOUSE_X equ (OS_BASE+0x000FB0A) -MOUSE_Y equ (OS_BASE+0x000FB0C) -MOUSE_SCROLL_V equ (OS_BASE+0x000FB0E) - -MOUSE_COLOR_MEM equ (OS_BASE+0x000FB10) -COLOR_TEMP equ (OS_BASE+0x000FB30) -BTN_DOWN equ (OS_BASE+0x000FB40) -MOUSE_DOWN equ (OS_BASE+0x000FB44) -X_UNDER equ (OS_BASE+0x000FB4A) -Y_UNDER equ (OS_BASE+0x000FB4C) -ScreenBPP equ (OS_BASE+0x000FBF1) - -;unused ? only one reference -MOUSE_BUFF_COUNT equ (OS_BASE+0x000FCFF) - -Screen_Max_X equ (OS_BASE+0x000FE00) -Screen_Max_Y equ (OS_BASE+0x000FE04) -BytesPerScanLine equ (OS_BASE+0x000FE08) -SCR_MODE equ (OS_BASE+0x000FE0C) - -LFBAddress equ (OS_BASE+0x000FE80) -BTN_ADDR equ (OS_BASE+0x000FE88) -MEM_AMOUNT equ (OS_BASE+0x000FE8C) - -SYS_SHUTDOWN equ (OS_BASE+0x000FF00) -TASK_ACTIVATE equ (OS_BASE+0x000FF01) - -REDRAW_BACKGROUND equ (OS_BASE+0x000FFF0) -BACKGROUND_CHANGED equ (OS_BASE+0x000FFF1) -BANK_RW equ (OS_BASE+0x000FFF2) -MOUSE_BACKGROUND equ (OS_BASE+0x000FFF4) -DONT_DRAW_MOUSE equ (OS_BASE+0x000FFF5) -DONT_SWITCH equ (OS_BASE+0x000FFFF) - -TMP_STACK_TOP equ 0x006CC00 - -FONT_II equ (OS_BASE+0x006DC00) -FONT_I equ (OS_BASE+0x006E600) - -sys_pgdir equ (OS_BASE+0x006F000) - -DRIVE_DATA equ (OS_BASE+0x0070000) - -SLOT_BASE equ (OS_BASE+0x0080000) - -;unused -TMP_BUFF equ (OS_BASE+0x0090000) - -VGABasePtr equ (OS_BASE+0x00A0000) - -RAMDISK equ (OS_BASE+0x0100000) -RAMDISK_FAT equ (OS_BASE+0x0280000) -FLOPPY_FAT equ (OS_BASE+0x0282000) - -CLEAN_ZONE equ 0x284000 -IDE_DMA equ 0x284000 - -BgrAuxTable equ (OS_BASE+0x0298000) -; unused? -SB16Buffer equ (OS_BASE+0x02A0000) -SB16_Status equ (OS_BASE+0x02B0000) - -BUTTON_INFO equ (OS_BASE+0x02C0000) -RESERVED_PORTS equ (OS_BASE+0x02D0000) -BOOT_VAR equ (OS_BASE+0x02E0000) - -stack_data_start equ (OS_BASE+0x02F0000) -eth_data_start equ (OS_BASE+0x02F0000) -stack_data equ (OS_BASE+0x02F4000) -stack_data_end equ (OS_BASE+0x030ffff) -resendQ equ (OS_BASE+0x0310000) - -skin_data equ (OS_BASE+0x0318000) -draw_data equ (OS_BASE+0x0320000) - -BgrDrawMode equ (OS_BASE+0x0323FF4) -BgrDataWidth equ (OS_BASE+0x0323FF8) -BgrDataHeight equ (OS_BASE+0x0323FFC) - -sys_pgmap equ (OS_BASE+0x0324000) - -UPPER_KERNEL_PAGES equ (OS_BASE+0x0400000) - -virtual at (OS_BASE+0x05FFF80) - tss TSS -end virtual - -HEAP_BASE equ (OS_BASE+0x0800000) -HEAP_MIN_SIZE equ 0x01000000 - -page_tabs equ 0xFDC00000 -app_page_tabs equ 0xFDC00000 -kernel_tabs equ (page_tabs+ (OS_BASE shr 10)) ;0xFDE00000 -master_tab equ (page_tabs+ (page_tabs shr 10)) ;0xFDFF70000 - -LFB_BASE equ 0xFE000000 - - -new_app_base equ 0; - -twdw equ 0x2000 ;(CURRENT_TASK-window_data) - -std_application_base_address equ new_app_base -RING0_STACK_SIZE equ (0x2000 - 512) ;512 байт для контекста FPU - -REG_SS equ (RING0_STACK_SIZE-4) -REG_APP_ESP equ (RING0_STACK_SIZE-8) -REG_EFLAGS equ (RING0_STACK_SIZE-12) -REG_CS equ (RING0_STACK_SIZE-16) -REG_EIP equ (RING0_STACK_SIZE-20) -REG_EAX equ (RING0_STACK_SIZE-24) -REG_ECX equ (RING0_STACK_SIZE-28) -REG_EDX equ (RING0_STACK_SIZE-32) -REG_EBX equ (RING0_STACK_SIZE-36) -REG_ESP equ (RING0_STACK_SIZE-40) ;RING0_STACK_SIZE-20 -REG_EBP equ (RING0_STACK_SIZE-44) -REG_ESI equ (RING0_STACK_SIZE-48) -REG_EDI equ (RING0_STACK_SIZE-52) -REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return - - -PG_UNMAP equ 0x000 -PG_MAP equ 0x001 -PG_WRITE equ 0x002 -PG_SW equ 0x003 -PG_USER equ 0x005 -PG_UW equ 0x007 -PG_NOCACHE equ 0x018 -PG_LARGE equ 0x080 -PG_GLOBAL equ 0x100 - -PG_SHARED equ 0x200 - -;;;;;;;;;;;boot time variables - -;BOOT_BPP equ 0x9000 ;byte bits per pixel -BOOT_SCANLINE equ 0x9001 ;word scanline length -BOOT_VESA_MODE equ 0x9008 ;word vesa video mode -;;BOOT_X_RES equ 0x900A ;word X res -;;BOOT_Y_RES equ 0x900C ;word Y res -;;BOOT_MOUSE_PORT equ 0x9010 ;byte mouse port - not used -BOOT_BANK_SW equ 0x9014 ;dword Vesa 1.2 pm bank switch -BOOT_LFB equ 0x9018 ;dword Vesa 2.0 LFB address -BOOT_MTRR equ 0x901C ;byte 0 or 1 : enable MTRR graphics acceleration -BOOT_LOG equ 0x901D ;byte not used anymore (0 or 1 : enable system log display) -BOOT_DIRECT_LFB equ 0x901E ;byte 0 or 1 : enable direct lfb write, paging disabled -BOOT_PCI_DATA equ 0x9020 ;8bytes pci data -BOOT_VRR equ 0x9030 ;byte VRR start enabled 1, 2-no -BOOT_IDE_BASE_ADDR equ 0x9031 ;word IDEContrRegsBaseAddr -BOOT_MEM_AMOUNT equ 0x9034 ;dword memory amount - -TMP_FILE_NAME equ 0 -TMP_CMD_LINE equ 1024 -TMP_ICON_OFFS equ 1280 - - -EVENT_REDRAW equ 0x00000001 -EVENT_KEY equ 0x00000002 -EVENT_BUTTON equ 0x00000004 -EVENT_BACKGROUND equ 0x00000010 -EVENT_MOUSE equ 0x00000020 -EVENT_IPC equ 0x00000040 -EVENT_NETWORK equ 0x00000080 -EVENT_DEBUG equ 0x00000100 -EVENT_EXTENDED equ 0x00000200 - -EV_INTR equ 1 - -struc THR_DATA -{ - rb (8192-512) - .pl0_stack: - .fpu_state rb 512 - .tls_page rb 4096 - .pdbr rb 4096 -} - -THR_DATA_SIZE equ 4096*4 - -virtual at (OS_BASE-THR_DATA_SIZE) - thr_data THR_DATA -end virtual - -struc SYS_VARS -{ .bpp dd ? - .scanline dd ? - .vesa_mode dd ? - .x_res dd ? - .y_res dd ? -} - -struc APPOBJ ;common object header -{ - .magic dd ? ; - .destroy dd ? ;internal destructor - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id -}; - -virtual at 0 - APPOBJ APPOBJ -end virtual - -APP_OBJ_OFFSET equ 48 -APP_EV_OFFSET equ 40 - -struc CURSOR -{ -;common object header - .magic dd ? ;'CURS' - .destroy dd ? ;internal destructor - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id - - ;cursor data - .base dd ? ;allocated memory - .hot_x dd ? ;hotspot coords - .hot_y dd ? - - .list_next dd ? ;next cursor in cursor list - .list_prev dd ? ;prev cursor in cursor list - .dev_obj dd ? ;device depended data - - .sizeof: -} -virtual at 0 - CURSOR CURSOR -end virtual - - -struc EVENT -{ - .magic dd ? ;'EVNT' - .destroy dd ? ;internal destructor - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id - - .id dd ? ;event uid - .state dd ? ;internal flags - .code dd ? - rd 5 - .size = $ - .magic - .codesize = $ - .code -} - -virtual at 0 - EVENT EVENT -end virtual - - -struc SMEM -{ - .bk dd ? - .fd dd ? ;+4 - .base dd ? ;+8 - .size dd ? ;+12 - .access dd ? ;+16 - .refcount dd ? ;+20 - .name rb 32 ;+24 - .sizeof: -} - -struc SMAP -{ - .magic dd ? ; SMAP - .destroy dd ? ;internal destructor - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id - - .base dd ? ;mapped base - .parent dd ? ;SMEM - .sizeof: -} - -virtual at 0 - SMEM SMEM -end virtual - -virtual at 0 - SMAP SMAP -end virtual - -struc DLLDESCR -{ - .bk dd ? - .fd dd ? ;+4 - .data dd ? ;+8 - .size dd ? ;+12 - .timestamp dq ? - .refcount dd ? - .defaultbase dd ? - .coff_hdr dd ? - .symbols_ptr dd ? - .symbols_num dd ? - .symbols_lim dd ? - .exports dd ? ;export table - .name: - .sizeof: -} - -struc HDLL -{ - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id - - .base dd ? ;mapped base - .size dd ? ;mapped size - .refcount dd ? ;reference counter for this process and this lib - .parent dd ? ;DLLDESCR - .sizeof: -} - -virtual at 0 - DLLDESCR DLLDESCR -end virtual - -virtual at 0 - HDLL HDLL -end virtual - -struc display_t -{ - .x dd ? - .y dd ? - .width dd ? - .height dd ? - .bpp dd ? - .vrefresh dd ? - .pitch dd ? - .lfb dd ? - - .modes dd ? - .ddev dd ? - .connector dd ? - .crtc dd ? - - .cr_list.next dd ? - .cr_list.prev dd ? - - .cursor dd ? - - .init_cursor dd ? - .select_cursor dd ? - .show_cursor dd ? - .move_cursor dd ? - .restore_cursor dd ? - .disable_mouse dd ? -} - -virtual at 0 - display_t display_t -end virtual - -struc BOOT_DATA -{ .bpp dd ? - .scanline dd ? - .vesa_mode dd ? - .x_res dd ? - .y_res dd ? - .mouse_port dd ? - .bank_switch dd ? - .lfb dd ? - .vesa_mem dd ? - .log dd ? - .direct_lfb dd ? - .pci_data dd ? -; dd ? - .vrr dd ? - .ide_base dd ? - .mem_amount dd ? - .pages_count dd ? - .pagemap_size dd ? - .kernel_max dd ? - .kernel_pages dd ? - .kernel_tables dd ? - - .cpu_vendor dd ? - dd ? - dd ? - .cpu_sign dd ? - .cpu_info dd ? - .cpu_caps dd ? - dd ? - dd ? -} - -virtual at 0 - BOOT_DATA BOOT_DATA -end virtual - -struc MEM_STATE -{ .mutex MUTEX - .smallmap rd 1 - .treemap rd 1 - .topsize rd 1 - .top rd 1 - .smallbins rd 4*32 - .treebins rd 32 -} - -struc PG_DATA -{ .mem_amount dd ? - .vesa_mem dd ? - .pages_count dd ? - .pages_free dd ? - .pages_faults dd ? - .pagemap_size dd ? - .kernel_pages dd ? - .kernel_tables dd ? - .sys_page_dir dd ? - .mutex MUTEX -} - -;struc LIB -;{ .lib_name rb 16 -; .lib_base dd ? -; .lib_start dd ? -; .export dd ? -; .import dd ? -;} - -struc SRV -{ - .srv_name rb 16 ;ASCIIZ string - .magic dd ? ;+0x10 ;'SRV ' - .size dd ? ;+0x14 ;size of structure SRV - .fd dd ? ;+0x18 ;next SRV descriptor - .bk dd ? ;+0x1C ;prev SRV descriptor - .base dd ? ;+0x20 ;service base address - .entry dd ? ;+0x24 ;service START function - .srv_proc dd ? ;+0x28 ;user mode service handler - .srv_proc_ex dd ? ;+0x2C ;kernel mode service handler - .sizeof: -} - -SRV_FD_OFFSET equ 0x18 - -DRV_ENTRY equ 1 -DRV_EXIT equ -1 - -struc COFF_HEADER -{ .machine dw ? - .nSections dw ? - .DataTime dd ? - .pSymTable dd ? - .nSymbols dd ? - .optHeader dw ? - .flags dw ? -}; - - -struc COFF_SECTION -{ .Name rb 8 - .VirtualSize dd ? - .VirtualAddress dd ? - .SizeOfRawData dd ? - .PtrRawData dd ? - .PtrReloc dd ? - .PtrLinenumbers dd ? - .NumReloc dw ? - .NumLinenum dw ? - .Characteristics dd ? -} -COFF_SECTION_SIZE equ 40 - -struc COFF_RELOC -{ .VirtualAddress dd ? - .SymIndex dd ? - .Type dw ? -} - -struc COFF_SYM -{ .Name rb 8 - .Value dd ? - .SectionNumber dw ? - .Type dw ? - .StorageClass db ? - .NumAuxSymbols db ? -} -CSYM_SIZE equ 18 - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -;virtual at 0 -; LIB LIB -;end virtual - -virtual at 0 - SRV SRV -end virtual - -virtual at 0 - CFH COFF_HEADER -end virtual - -virtual at 0 - CFS COFF_SECTION -end virtual - -virtual at 0 - CRELOC COFF_RELOC -end virtual - -virtual at 0 - CSYM COFF_SYM -end virtual - -struc LHEAD -{ - .next dd ? ;next object in list - .prev dd ? ;prev object in list - .sizeof: -} - -virtual at 0 - LHEAD LHEAD -end virtual - -struc IRQH -{ - .list LHEAD - .handler dd ? ;handler roututine - .data dd ? ;user-specific data - .sizeof: -} - -virtual at 0 - IRQH IRQH -end virtual - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +dpl0 equ 10010000b ; data read dpl0 +drw0 equ 10010010b ; data read/write dpl0 +drw3 equ 11110010b ; data read/write dpl3 +cpl0 equ 10011010b ; code read dpl0 +cpl3 equ 11111010b ; code read dpl3 + +D32 equ 01000000b ; 32bit segment +G32 equ 10000000b ; page gran + + +;;;;;;;;;;;;cpu_caps flags;;;;;;;;;;;;;;;; + +CPU_386 equ 3 +CPU_486 equ 4 +CPU_PENTIUM equ 5 +CPU_P6 equ 6 +CPU_PENTIUM4 equ 0x0F + +CAPS_FPU equ 00 ;on-chip x87 floating point unit +CAPS_VME equ 01 ;virtual-mode enhancements +CAPS_DE equ 02 ;debugging extensions +CAPS_PSE equ 03 ;page-size extensions +CAPS_TSC equ 04 ;time stamp counter +CAPS_MSR equ 05 ;model-specific registers +CAPS_PAE equ 06 ;physical-address extensions +CAPS_MCE equ 07 ;machine check exception +CAPS_CX8 equ 08 ;CMPXCHG8B instruction +CAPS_APIC equ 09 ;on-chip advanced programmable + ; interrupt controller +; 10 ;unused +CAPS_SEP equ 11 ;SYSENTER and SYSEXIT instructions +CAPS_MTRR equ 12 ;memory-type range registers +CAPS_PGE equ 13 ;page global extension +CAPS_MCA equ 14 ;machine check architecture +CAPS_CMOV equ 15 ;conditional move instructions +CAPS_PAT equ 16 ;page attribute table + +CAPS_PSE36 equ 17 ;page-size extensions +CAPS_PSN equ 18 ;processor serial number +CAPS_CLFLUSH equ 19 ;CLFUSH instruction + +CAPS_DS equ 21 ;debug store +CAPS_ACPI equ 22 ;thermal monitor and software + ;controlled clock supported +CAPS_MMX equ 23 ;MMX instructions +CAPS_FXSR equ 24 ;FXSAVE and FXRSTOR instructions +CAPS_SSE equ 25 ;SSE instructions +CAPS_SSE2 equ 26 ;SSE2 instructions +CAPS_SS equ 27 ;self-snoop +CAPS_HTT equ 28 ;hyper-threading technology +CAPS_TM equ 29 ;thermal monitor supported +CAPS_IA64 equ 30 ;IA64 capabilities +CAPS_PBE equ 31 ;pending break enable + +;ecx +CAPS_SSE3 equ 32 ;SSE3 instructions +; 33 +; 34 +CAPS_MONITOR equ 35 ;MONITOR/MWAIT instructions +CAPS_DS_CPL equ 36 ; +CAPS_VMX equ 37 ;virtual mode extensions +; 38 ; +CAPS_EST equ 39 ;enhansed speed step +CAPS_TM2 equ 40 ;thermal monitor2 supported +; 41 +CAPS_CID equ 42 ; +; 43 +; 44 +CAPS_CX16 equ 45 ;CMPXCHG16B instruction +CAPS_xTPR equ 46 ; +; +;reserved +; +;ext edx /ecx +CAPS_SYSCAL equ 64 ; +CAPS_XD equ 65 ;execution disable +CAPS_FFXSR equ 66 ; +CAPS_RDTSCP equ 67 ; +CAPS_X64 equ 68 ; +CAPS_3DNOW equ 69 ; +CAPS_3DNOWEXT equ 70 ; +CAPS_LAHF equ 71 ; +CAPS_CMP_LEG equ 72 ; +CAPS_SVM equ 73 ;secure virual machine +CAPS_ALTMOVCR8 equ 74 ; + +; CPU MSR names +MSR_SYSENTER_CS equ 0x174 +MSR_SYSENTER_ESP equ 0x175 +MSR_SYSENTER_EIP equ 0x176 +MSR_AMD_EFER equ 0xC0000080 ; Extended Feature Enable Register +MSR_AMD_STAR equ 0xC0000081 ; SYSCALL/SYSRET Target Address Register + +CR0_PE equ 0x00000001 ;protected mode +CR0_MP equ 0x00000002 ;monitor fpu +CR0_EM equ 0x00000004 ;fpu emulation +CR0_TS equ 0x00000008 ;task switch +CR0_ET equ 0x00000010 ;extension type hardcoded to 1 +CR0_NE equ 0x00000020 ;numeric error +CR0_WP equ 0x00010000 ;write protect +CR0_AM equ 0x00040000 ;alignment check +CR0_NW equ 0x20000000 ;not write-through +CR0_CD equ 0x40000000 ;cache disable +CR0_PG equ 0x80000000 ;paging + + +CR4_VME equ 0x0001 +CR4_PVI equ 0x0002 +CR4_TSD equ 0x0004 +CR4_DE equ 0x0008 +CR4_PSE equ 0x0010 +CR4_PAE equ 0x0020 +CR4_MCE equ 0x0040 +CR4_PGE equ 0x0080 +CR4_PCE equ 0x0100 +CR4_OSFXSR equ 0x0200 +CR4_OSXMMEXPT equ 0x0400 + +SSE_IE equ 0x0001 +SSE_DE equ 0x0002 +SSE_ZE equ 0x0004 +SSE_OE equ 0x0008 +SSE_UE equ 0x0010 +SSE_PE equ 0x0020 +SSE_DAZ equ 0x0040 +SSE_IM equ 0x0080 +SSE_DM equ 0x0100 +SSE_ZM equ 0x0200 +SSE_OM equ 0x0400 +SSE_UM equ 0x0800 +SSE_PM equ 0x1000 +SSE_FZ equ 0x8000 + +SSE_INIT equ (SSE_IM+SSE_DM+SSE_ZM+SSE_OM+SSE_UM+SSE_PM) + +IRQ_PIC equ 0 +IRQ_APIC equ 1 + +struc TSS +{ + ._back rw 2 + ._esp0 rd 1 + ._ss0 rw 2 + ._esp1 rd 1 + ._ss1 rw 2 + ._esp2 rd 1 + ._ss2 rw 2 + ._cr3 rd 1 + ._eip rd 1 + ._eflags rd 1 + ._eax rd 1 + ._ecx rd 1 + ._edx rd 1 + ._ebx rd 1 + ._esp rd 1 + ._ebp rd 1 + ._esi rd 1 + ._edi rd 1 + ._es rw 2 + ._cs rw 2 + ._ss rw 2 + ._ds rw 2 + ._fs rw 2 + ._gs rw 2 + ._ldt rw 2 + ._trap rw 1 + ._io rw 1 + rb 24 + ._io_map_0 rb 4096 + ._io_map_1 rb 4096 +} + +virtual at 0 + TSS TSS +end virtual + +TSS_SIZE equ (128+8192) + +OS_BASE equ 0x80000000 + +window_data equ (OS_BASE+0x0001000) + +CURRENT_TASK equ (OS_BASE+0x0003000) +TASK_COUNT equ (OS_BASE+0x0003004) +TASK_BASE equ (OS_BASE+0x0003010) +TASK_DATA equ (OS_BASE+0x0003020) +TASK_EVENT equ (OS_BASE+0x0003020) + +mouseunder equ (OS_BASE+0x0006900) +CDDataBuf equ (OS_BASE+0x0007000) +FLOPPY_BUFF equ (OS_BASE+0x0008000) +ACTIVE_PROC_STACK equ (OS_BASE+0x000A400) ;unused +idts equ (OS_BASE+0x000B100) +WIN_STACK equ (OS_BASE+0x000C000) +WIN_POS equ (OS_BASE+0x000C400) +FDD_BUFF equ (OS_BASE+0x000D000) + +;unused ? only one reference +ENABLE_TASKSWITCH equ (OS_BASE+0x000E000) + +PUTPIXEL equ (OS_BASE+0x000E020) +GETPIXEL equ (OS_BASE+0x000E024) + +;unused ? only one reference +BANK_SWITCH equ (OS_BASE+0x000E030) + +;unused ? store mousepointer +MOUSE_PICTURE equ (OS_BASE+0x000F200) + +MOUSE_VISIBLE equ (OS_BASE+0x000F204) +WIN_TEMP_XY equ (OS_BASE+0x000F300) +KEY_COUNT equ (OS_BASE+0x000F400) +KEY_BUFF equ (OS_BASE+0x000F401) + +BTN_COUNT equ (OS_BASE+0x000F500) +BTN_BUFF equ (OS_BASE+0x000F501) + +CPU_FREQ equ (OS_BASE+0x000F600) + +;unused ? no active references +MOUSE_PORT equ (OS_BASE+0x000F604) + +;unused +PS2_CHUNK equ (OS_BASE+0x000FB00) + +MOUSE_SCROLL_H equ (OS_BASE+0x000FB08) +MOUSE_X equ (OS_BASE+0x000FB0A) +MOUSE_Y equ (OS_BASE+0x000FB0C) +MOUSE_SCROLL_V equ (OS_BASE+0x000FB0E) + +MOUSE_COLOR_MEM equ (OS_BASE+0x000FB10) +COLOR_TEMP equ (OS_BASE+0x000FB30) +BTN_DOWN equ (OS_BASE+0x000FB40) +MOUSE_DOWN equ (OS_BASE+0x000FB44) +X_UNDER equ (OS_BASE+0x000FB4A) +Y_UNDER equ (OS_BASE+0x000FB4C) +ScreenBPP equ (OS_BASE+0x000FBF1) + +;unused ? only one reference +MOUSE_BUFF_COUNT equ (OS_BASE+0x000FCFF) + +Screen_Max_X equ (OS_BASE+0x000FE00) +Screen_Max_Y equ (OS_BASE+0x000FE04) +BytesPerScanLine equ (OS_BASE+0x000FE08) +SCR_MODE equ (OS_BASE+0x000FE0C) + +LFBAddress equ (OS_BASE+0x000FE80) +BTN_ADDR equ (OS_BASE+0x000FE88) +MEM_AMOUNT equ (OS_BASE+0x000FE8C) + +SYS_SHUTDOWN equ (OS_BASE+0x000FF00) +TASK_ACTIVATE equ (OS_BASE+0x000FF01) + +REDRAW_BACKGROUND equ (OS_BASE+0x000FFF0) +BACKGROUND_CHANGED equ (OS_BASE+0x000FFF1) +BANK_RW equ (OS_BASE+0x000FFF2) +MOUSE_BACKGROUND equ (OS_BASE+0x000FFF4) +DONT_DRAW_MOUSE equ (OS_BASE+0x000FFF5) +DONT_SWITCH equ (OS_BASE+0x000FFFF) + +TMP_STACK_TOP equ 0x006CC00 + +FONT_II equ (OS_BASE+0x006DC00) +FONT_I equ (OS_BASE+0x006E600) + +sys_pgdir equ (OS_BASE+0x006F000) + +DRIVE_DATA equ (OS_BASE+0x0070000) + +SLOT_BASE equ (OS_BASE+0x0080000) + +;unused +TMP_BUFF equ (OS_BASE+0x0090000) + +VGABasePtr equ (OS_BASE+0x00A0000) + +RAMDISK equ (OS_BASE+0x0100000) +RAMDISK_FAT equ (OS_BASE+0x0280000) +FLOPPY_FAT equ (OS_BASE+0x0282000) + +CLEAN_ZONE equ 0x284000 +IDE_DMA equ 0x284000 + +BgrAuxTable equ (OS_BASE+0x0298000) +; unused? +SB16Buffer equ (OS_BASE+0x02A0000) +SB16_Status equ (OS_BASE+0x02B0000) + +BUTTON_INFO equ (OS_BASE+0x02C0000) +RESERVED_PORTS equ (OS_BASE+0x02D0000) +BOOT_VAR equ (OS_BASE+0x02E0000) + +stack_data_start equ (OS_BASE+0x02F0000) +eth_data_start equ (OS_BASE+0x02F0000) +stack_data equ (OS_BASE+0x02F4000) +stack_data_end equ (OS_BASE+0x030ffff) +resendQ equ (OS_BASE+0x0310000) + +skin_data equ (OS_BASE+0x0318000) +draw_data equ (OS_BASE+0x0320000) + +BgrDrawMode equ (OS_BASE+0x0323FF4) +BgrDataWidth equ (OS_BASE+0x0323FF8) +BgrDataHeight equ (OS_BASE+0x0323FFC) + +sys_pgmap equ (OS_BASE+0x0324000) + +UPPER_KERNEL_PAGES equ (OS_BASE+0x0400000) + +virtual at (OS_BASE+0x05FFF80) + tss TSS +end virtual + +HEAP_BASE equ (OS_BASE+0x0800000) +HEAP_MIN_SIZE equ 0x01000000 + +page_tabs equ 0xFDC00000 +app_page_tabs equ 0xFDC00000 +kernel_tabs equ (page_tabs+ (OS_BASE shr 10)) ;0xFDE00000 +master_tab equ (page_tabs+ (page_tabs shr 10)) ;0xFDFF70000 + +LFB_BASE equ 0xFE000000 + + +new_app_base equ 0; + +twdw equ 0x2000 ;(CURRENT_TASK-window_data) + +std_application_base_address equ new_app_base +RING0_STACK_SIZE equ (0x2000 - 512) ;512 байт для контекста FPU + +REG_SS equ (RING0_STACK_SIZE-4) +REG_APP_ESP equ (RING0_STACK_SIZE-8) +REG_EFLAGS equ (RING0_STACK_SIZE-12) +REG_CS equ (RING0_STACK_SIZE-16) +REG_EIP equ (RING0_STACK_SIZE-20) +REG_EAX equ (RING0_STACK_SIZE-24) +REG_ECX equ (RING0_STACK_SIZE-28) +REG_EDX equ (RING0_STACK_SIZE-32) +REG_EBX equ (RING0_STACK_SIZE-36) +REG_ESP equ (RING0_STACK_SIZE-40) ;RING0_STACK_SIZE-20 +REG_EBP equ (RING0_STACK_SIZE-44) +REG_ESI equ (RING0_STACK_SIZE-48) +REG_EDI equ (RING0_STACK_SIZE-52) +REG_RET equ (RING0_STACK_SIZE-56) ;irq0.return + + +PG_UNMAP equ 0x000 +PG_MAP equ 0x001 +PG_WRITE equ 0x002 +PG_SW equ 0x003 +PG_USER equ 0x005 +PG_UW equ 0x007 +PG_NOCACHE equ 0x018 +PG_LARGE equ 0x080 +PG_GLOBAL equ 0x100 + +PG_SHARED equ 0x200 + +;;;;;;;;;;;boot time variables + +;BOOT_BPP equ 0x9000 ;byte bits per pixel +BOOT_SCANLINE equ 0x9001 ;word scanline length +BOOT_VESA_MODE equ 0x9008 ;word vesa video mode +;;BOOT_X_RES equ 0x900A ;word X res +;;BOOT_Y_RES equ 0x900C ;word Y res +;;BOOT_MOUSE_PORT equ 0x9010 ;byte mouse port - not used +BOOT_BANK_SW equ 0x9014 ;dword Vesa 1.2 pm bank switch +BOOT_LFB equ 0x9018 ;dword Vesa 2.0 LFB address +BOOT_MTRR equ 0x901C ;byte 0 or 1 : enable MTRR graphics acceleration +BOOT_LOG equ 0x901D ;byte not used anymore (0 or 1 : enable system log display) +BOOT_DIRECT_LFB equ 0x901E ;byte 0 or 1 : enable direct lfb write, paging disabled +BOOT_PCI_DATA equ 0x9020 ;8bytes pci data +BOOT_VRR equ 0x9030 ;byte VRR start enabled 1, 2-no +BOOT_IDE_BASE_ADDR equ 0x9031 ;word IDEContrRegsBaseAddr +BOOT_MEM_AMOUNT equ 0x9034 ;dword memory amount + +TMP_FILE_NAME equ 0 +TMP_CMD_LINE equ 1024 +TMP_ICON_OFFS equ 1280 + + +EVENT_REDRAW equ 0x00000001 +EVENT_KEY equ 0x00000002 +EVENT_BUTTON equ 0x00000004 +EVENT_BACKGROUND equ 0x00000010 +EVENT_MOUSE equ 0x00000020 +EVENT_IPC equ 0x00000040 +EVENT_NETWORK equ 0x00000080 +EVENT_DEBUG equ 0x00000100 +EVENT_EXTENDED equ 0x00000200 + +EV_INTR equ 1 + +struc THR_DATA +{ + rb (8192-512) + .pl0_stack: + .fpu_state rb 512 + .tls_page rb 4096 + .pdbr rb 4096 +} + +THR_DATA_SIZE equ 4096*4 + +virtual at (OS_BASE-THR_DATA_SIZE) + thr_data THR_DATA +end virtual + +struc SYS_VARS +{ .bpp dd ? + .scanline dd ? + .vesa_mode dd ? + .x_res dd ? + .y_res dd ? +} + +struc APPOBJ ;common object header +{ + .magic dd ? ; + .destroy dd ? ;internal destructor + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id +}; + +virtual at 0 + APPOBJ APPOBJ +end virtual + +APP_OBJ_OFFSET equ 48 +APP_EV_OFFSET equ 40 + +struc CURSOR +{ +;common object header + .magic dd ? ;'CURS' + .destroy dd ? ;internal destructor + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id + + ;cursor data + .base dd ? ;allocated memory + .hot_x dd ? ;hotspot coords + .hot_y dd ? + + .list_next dd ? ;next cursor in cursor list + .list_prev dd ? ;prev cursor in cursor list + .dev_obj dd ? ;device depended data + + .sizeof: +} +virtual at 0 + CURSOR CURSOR +end virtual + + +struc EVENT +{ + .magic dd ? ;'EVNT' + .destroy dd ? ;internal destructor + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id + + .id dd ? ;event uid + .state dd ? ;internal flags + .code dd ? + rd 5 + .size = $ - .magic + .codesize = $ - .code +} + +virtual at 0 + EVENT EVENT +end virtual + + +struc SMEM +{ + .bk dd ? + .fd dd ? ;+4 + .base dd ? ;+8 + .size dd ? ;+12 + .access dd ? ;+16 + .refcount dd ? ;+20 + .name rb 32 ;+24 + .sizeof: +} + +struc SMAP +{ + .magic dd ? ; SMAP + .destroy dd ? ;internal destructor + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id + + .base dd ? ;mapped base + .parent dd ? ;SMEM + .sizeof: +} + +virtual at 0 + SMEM SMEM +end virtual + +virtual at 0 + SMAP SMAP +end virtual + +struc DLLDESCR +{ + .bk dd ? + .fd dd ? ;+4 + .data dd ? ;+8 + .size dd ? ;+12 + .timestamp dq ? + .refcount dd ? + .defaultbase dd ? + .coff_hdr dd ? + .symbols_ptr dd ? + .symbols_num dd ? + .symbols_lim dd ? + .exports dd ? ;export table + .name: + .sizeof: +} + +struc HDLL +{ + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id + + .base dd ? ;mapped base + .size dd ? ;mapped size + .refcount dd ? ;reference counter for this process and this lib + .parent dd ? ;DLLDESCR + .sizeof: +} + +virtual at 0 + DLLDESCR DLLDESCR +end virtual + +virtual at 0 + HDLL HDLL +end virtual + +struc display_t +{ + .x dd ? + .y dd ? + .width dd ? + .height dd ? + .bpp dd ? + .vrefresh dd ? + .pitch dd ? + .lfb dd ? + + .modes dd ? + .ddev dd ? + .connector dd ? + .crtc dd ? + + .cr_list.next dd ? + .cr_list.prev dd ? + + .cursor dd ? + + .init_cursor dd ? + .select_cursor dd ? + .show_cursor dd ? + .move_cursor dd ? + .restore_cursor dd ? + .disable_mouse dd ? +} + +virtual at 0 + display_t display_t +end virtual + +struc BOOT_DATA +{ .bpp dd ? + .scanline dd ? + .vesa_mode dd ? + .x_res dd ? + .y_res dd ? + .mouse_port dd ? + .bank_switch dd ? + .lfb dd ? + .vesa_mem dd ? + .log dd ? + .direct_lfb dd ? + .pci_data dd ? +; dd ? + .vrr dd ? + .ide_base dd ? + .mem_amount dd ? + .pages_count dd ? + .pagemap_size dd ? + .kernel_max dd ? + .kernel_pages dd ? + .kernel_tables dd ? + + .cpu_vendor dd ? + dd ? + dd ? + .cpu_sign dd ? + .cpu_info dd ? + .cpu_caps dd ? + dd ? + dd ? +} + +virtual at 0 + BOOT_DATA BOOT_DATA +end virtual + +struc MEM_STATE +{ .mutex MUTEX + .smallmap rd 1 + .treemap rd 1 + .topsize rd 1 + .top rd 1 + .smallbins rd 4*32 + .treebins rd 32 +} + +struc PG_DATA +{ .mem_amount dd ? + .vesa_mem dd ? + .pages_count dd ? + .pages_free dd ? + .pages_faults dd ? + .pagemap_size dd ? + .kernel_pages dd ? + .kernel_tables dd ? + .sys_page_dir dd ? + .mutex MUTEX +} + +;struc LIB +;{ .lib_name rb 16 +; .lib_base dd ? +; .lib_start dd ? +; .export dd ? +; .import dd ? +;} + +struc SRV +{ + .srv_name rb 16 ;ASCIIZ string + .magic dd ? ;+0x10 ;'SRV ' + .size dd ? ;+0x14 ;size of structure SRV + .fd dd ? ;+0x18 ;next SRV descriptor + .bk dd ? ;+0x1C ;prev SRV descriptor + .base dd ? ;+0x20 ;service base address + .entry dd ? ;+0x24 ;service START function + .srv_proc dd ? ;+0x28 ;user mode service handler + .srv_proc_ex dd ? ;+0x2C ;kernel mode service handler + .sizeof: +} + +SRV_FD_OFFSET equ 0x18 + +DRV_ENTRY equ 1 +DRV_EXIT equ -1 + +struc COFF_HEADER +{ .machine dw ? + .nSections dw ? + .DataTime dd ? + .pSymTable dd ? + .nSymbols dd ? + .optHeader dw ? + .flags dw ? +}; + + +struc COFF_SECTION +{ .Name rb 8 + .VirtualSize dd ? + .VirtualAddress dd ? + .SizeOfRawData dd ? + .PtrRawData dd ? + .PtrReloc dd ? + .PtrLinenumbers dd ? + .NumReloc dw ? + .NumLinenum dw ? + .Characteristics dd ? +} +COFF_SECTION_SIZE equ 40 + +struc COFF_RELOC +{ .VirtualAddress dd ? + .SymIndex dd ? + .Type dw ? +} + +struc COFF_SYM +{ .Name rb 8 + .Value dd ? + .SectionNumber dw ? + .Type dw ? + .StorageClass db ? + .NumAuxSymbols db ? +} +CSYM_SIZE equ 18 + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +;virtual at 0 +; LIB LIB +;end virtual + +virtual at 0 + SRV SRV +end virtual + +virtual at 0 + CFH COFF_HEADER +end virtual + +virtual at 0 + CFS COFF_SECTION +end virtual + +virtual at 0 + CRELOC COFF_RELOC +end virtual + +virtual at 0 + CSYM COFF_SYM +end virtual + +struc LHEAD +{ + .next dd ? ;next object in list + .prev dd ? ;prev object in list + .sizeof: +} + +virtual at 0 + LHEAD LHEAD +end virtual + +struc IRQH +{ + .list LHEAD + .handler dd ? ;handler roututine + .data dd ? ;user-specific data + .sizeof: +} + +virtual at 0 + IRQH IRQH +end virtual + diff --git a/kernel/trunk/core/apic.inc b/kernel/trunk/core/apic.inc index 012887447..47ffc128e 100644 --- a/kernel/trunk/core/apic.inc +++ b/kernel/trunk/core/apic.inc @@ -1,417 +1,417 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -iglobal -IRQ_COUNT dd 24 -endg - -uglobal -irq_mode rd 1 -IOAPIC_base rd 1 -LAPIC_BASE rd 1 -endg - -APIC_ID equ 0x20 -APIC_TPR equ 0x80 -APIC_EOI equ 0xb0 -APIC_LDR equ 0xd0 -APIC_DFR equ 0xe0 -APIC_SVR equ 0xf0 -APIC_ISR equ 0x100 -APIC_ESR equ 0x280 -APIC_ICRL equ 0x300 -APIC_ICRH equ 0x310 -APIC_LVT_LINT0 equ 0x350 -APIC_LVT_LINT1 equ 0x360 -APIC_LVT_err equ 0x370 - -; APIC timer -APIC_LVT_timer equ 0x320 -APIC_timer_div equ 0x3e0 -APIC_timer_init equ 0x380 -APIC_timer_cur equ 0x390 -; IOAPIC -IOAPIC_ID equ 0x0 -IOAPIC_VER equ 0x1 -IOAPIC_ARB equ 0x2 -IOAPIC_REDTBL equ 0x10 - -align 4 -APIC_init: - mov [irq_mode], IRQ_PIC - - cmp [acpi_ioapic_base], 0 - jz .no_apic - - cmp [acpi_lapic_base], 0 - jz .no_apic - - stdcall load_file, dev_data_path - test eax, eax - jz .no_apic - - mov [acpi_dev_data], eax - mov [acpi_dev_size], ebx - - call IRQ_mask_all - -; IOAPIC init - stdcall map_io_mem, [acpi_ioapic_base], 0x20, PG_SW - mov [IOAPIC_base], eax - - mov eax, IOAPIC_VER - call IOAPIC_read - shr eax, 16 - inc al - movzx eax, al - cmp al, IRQ_RESERVED - jbe @f - - mov al, IRQ_RESERVED -@@: - mov [IRQ_COUNT], eax - - ; Reroute IOAPIC & mask all interrupts - xor ecx, ecx - mov eax, IOAPIC_REDTBL -@@: - mov ebx, eax - call IOAPIC_read - mov ah, 0x09 ; Delivery Mode: Lowest Priority, Destination Mode: Logical - mov al, cl - add al, 0x20 ; vector - or eax, 0x10000 ; Mask Interrupt - cmp ecx, 16 - jb .set - - or eax, 0xa000 ;<<< level-triggered active-low for IRQ16+ -.set: - xchg eax, ebx - call IOAPIC_write - inc eax - mov ebx, eax - call IOAPIC_read - or eax, 0xff000000 ; Destination Field - xchg eax, ebx - call IOAPIC_write - inc eax - inc ecx - cmp ecx, [IRQ_COUNT] - jb @b - - call LAPIC_init - - mov [irq_mode], IRQ_APIC - - mov al, 0x70 - out 0x22, al - mov al, 1 - out 0x23, al - - call pci_irq_fixup -.no_apic: - - ret - -;=========================================================== -align 4 -LAPIC_init: - ; Check MSR support - ;.... - ; Get LAPIC base address -; mov ecx, 0x1b -; rdmsr ; it may be replaced to -; and ax, 0xf000 ; mov eax, 0xfee00000 - - stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_SW - mov [LAPIC_BASE], eax - mov esi, eax - - ; Program Destination Format Register for Flat mode. - mov eax, [esi + APIC_DFR] - or eax, 0xf0000000 - mov [esi + APIC_DFR], eax - - ; Program Logical Destination Register. - mov eax, [esi + APIC_LDR] - ;and eax, 0xff000000 - and eax, 0x00ffffff - or eax, 0x01000000 ;!!!!!!!!!!!! - mov [esi + APIC_LDR], eax - - ; Task Priority Register initialization. - mov eax, [esi + APIC_TPR] - and eax, 0xffffff00 - mov [esi + APIC_TPR], eax - - ; Flush the queue - mov edx, 0 -.nxt2: - mov ecx, 32 - mov eax, [esi + APIC_ISR + edx] -.nxt: - shr eax, 1 - jnc @f - mov dword [esi + APIC_EOI], 0 ; EOI -@@: - loop .nxt - - add edx, 0x10 - cmp edx, 0x170 - jbe .nxt2 - - ; Spurious-Interrupt Vector Register initialization. - mov eax, [esi + APIC_SVR] - or eax, 0x1ff - and eax, 0xfffffdff - mov [esi + APIC_SVR], eax - - ; Initialize LVT LINT0 register. (INTR) - mov eax, 0x00700 - ; mov eax, 0x10700 - mov [esi + APIC_LVT_LINT0], eax - - ; Initialize LVT LINT1 register. (NMI) - mov eax, 0x00400 - mov [esi + APIC_LVT_LINT1], eax - - ; Initialize LVT Error register. - mov eax, [esi + APIC_LVT_err] - or eax, 0x10000 ; bit 16 - mov [esi + APIC_LVT_err], eax - - ; LAPIC timer - ; pre init - mov dword[esi + APIC_timer_div], 1011b ; 1 - mov dword[esi + APIC_timer_init], 0xffffffff ; max val - push esi - mov esi, 640 ; wait 0.64 sec - call delay_ms - pop esi - mov eax, [esi + APIC_timer_cur] ; read current tick couner - xor eax, 0xffffffff ; eax = 0xffffffff - eax - shr eax, 6 ; eax /= 64; APIC ticks per 0.01 sec - - ; Start (every 0.01 sec) - mov dword[esi + APIC_LVT_timer], 0x30020 ; periodic int 0x20 - mov dword[esi + APIC_timer_init], eax - ret - -;=========================================================== -; IOAPIC implementation -align 4 -IOAPIC_read: -; in : EAX - IOAPIC register -; out: EAX - readed value - push esi - mov esi, [IOAPIC_base] - mov [esi], eax - mov eax, [esi + 0x10] - pop esi - ret - -align 4 -IOAPIC_write: -; in : EAX - IOAPIC register -; EBX - value -; out: none - push esi - mov esi, [IOAPIC_base] - mov [esi], eax - mov [esi + 0x10], ebx - pop esi - ret -;=========================================================== -; Remap all IRQ to 0x20+ Vectors -; IRQ0 to vector 0x20, IRQ1 to vector 0x21.... -align 4 -PIC_init: - cli - mov al,0x11 ; icw4, edge triggered - out 0x20,al - out 0xA0,al - - mov al,0x20 ; generate 0x20 + - out 0x21,al - mov al,0x28 ; generate 0x28 + - out 0xA1,al - - mov al,0x04 ; slave at irq2 - out 0x21,al - mov al,0x02 ; at irq9 - out 0xA1,al - - mov al,0x01 ; 8086 mode - out 0x21,al - out 0xA1,al - - call IRQ_mask_all - ; mov dword[irq_type_to_set], IRQ_TYPE_PIC - ret - -; ----------------------------------------- -; TIMER SET TO 1/100 S -align 4 -PIT_init: - mov al,0x34 ; set to 100Hz - out 0x43,al - mov al,0x9b ; lsb 1193180 / 1193 - out 0x40,al - mov al,0x2e ; msb - out 0x40,al - ret - -; ----------------------------------------- -align 4 -unmask_timer: - cmp [irq_mode], IRQ_APIC - je @f - - stdcall enable_irq, 0 - ret -@@: - ; use PIT - ; in some systems PIT no connected to IOAPIC - ; mov eax, 0x14 - ; call IOAPIC_read - ; mov ah, 0x09 ; Delivery Mode: Lowest Priority, Destination Mode: Logical - ; mov al, 0x20 - ; or eax, 0x10000 ; Mask Interrupt - ; mov ebx, eax - ; mov eax, 0x14 - ; call IOAPIC_write - ; stdcall enable_irq, 2 - ; ret - - ; use LAPIC timer - mov esi, [LAPIC_BASE] - mov eax, [esi + APIC_LVT_timer] - and eax, 0xfffeffff - mov [esi + APIC_LVT_timer], eax - ret - -; ----------------------------------------- -; Disable all IRQ -align 4 -IRQ_mask_all: - cmp [irq_mode], IRQ_APIC - je .APIC - - mov al, 0xFF - out 0x21, al - out 0xA1, al - mov ecx,0x1000 - ret -.APIC: - mov ecx, [IRQ_COUNT] - mov eax, 0x10 -@@: - mov ebx, eax - call IOAPIC_read - or eax, 0x10000 ; bit 16 - xchg eax, ebx - call IOAPIC_write - inc eax - inc eax - loop @b - ret - -; ----------------------------------------- -; End Of Interrupt -; cl - IRQ number -align 4 -irq_eoi: ; __fastcall - cmp [irq_mode], IRQ_APIC - je .APIC - - cmp cl, 8 - mov al, 0x20 - jb @f - out 0xa0, al -@@: - out 0x20, al - ret - -.APIC: - mov eax, [LAPIC_BASE] - mov dword [eax + APIC_EOI], 0 ; EOI - ret - -; ----------------------------------------- -; from dll.inc -align 4 -proc enable_irq stdcall, irq_line:dword - mov ebx, [irq_line] - cmp [irq_mode], IRQ_APIC - je .APIC - - mov edx, 0x21 - cmp ebx, 8 - jb @F - - mov edx, 0xA1 - sub ebx,8 -@@: - in al,dx - btr eax, ebx - out dx, al - ret -.APIC: - shl ebx, 1 - add ebx, 0x10 - mov eax, ebx - call IOAPIC_read - and eax, 0xfffeffff ; bit 16 - xchg eax, ebx - call IOAPIC_write - ret -endp - -align 4 -pci_irq_fixup: - - push ebp - - mov esi, [acpi_dev_data] - mov ebx, [acpi_dev_size] - - lea edi, [esi+ebx] - -.iterate: - - cmp esi, edi - jae .done - - mov eax, [esi] - - cmp eax, -1 - je .done - - movzx ebx, al - movzx ebp, ah - - stdcall pci_read32, ebp, ebx, 0 - - cmp eax, [esi+4] - jne .skip - - mov eax, [esi+8] - stdcall pci_write8, ebp, ebx, 0x3C, eax -.skip: - add esi, 16 - jmp .iterate - -.done: -.fail: - pop ebp - ret - - - - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +iglobal +IRQ_COUNT dd 24 +endg + +uglobal +irq_mode rd 1 +IOAPIC_base rd 1 +LAPIC_BASE rd 1 +endg + +APIC_ID equ 0x20 +APIC_TPR equ 0x80 +APIC_EOI equ 0xb0 +APIC_LDR equ 0xd0 +APIC_DFR equ 0xe0 +APIC_SVR equ 0xf0 +APIC_ISR equ 0x100 +APIC_ESR equ 0x280 +APIC_ICRL equ 0x300 +APIC_ICRH equ 0x310 +APIC_LVT_LINT0 equ 0x350 +APIC_LVT_LINT1 equ 0x360 +APIC_LVT_err equ 0x370 + +; APIC timer +APIC_LVT_timer equ 0x320 +APIC_timer_div equ 0x3e0 +APIC_timer_init equ 0x380 +APIC_timer_cur equ 0x390 +; IOAPIC +IOAPIC_ID equ 0x0 +IOAPIC_VER equ 0x1 +IOAPIC_ARB equ 0x2 +IOAPIC_REDTBL equ 0x10 + +align 4 +APIC_init: + mov [irq_mode], IRQ_PIC + + cmp [acpi_ioapic_base], 0 + jz .no_apic + + cmp [acpi_lapic_base], 0 + jz .no_apic + + stdcall load_file, dev_data_path + test eax, eax + jz .no_apic + + mov [acpi_dev_data], eax + mov [acpi_dev_size], ebx + + call IRQ_mask_all + +; IOAPIC init + stdcall map_io_mem, [acpi_ioapic_base], 0x20, PG_SW + mov [IOAPIC_base], eax + + mov eax, IOAPIC_VER + call IOAPIC_read + shr eax, 16 + inc al + movzx eax, al + cmp al, IRQ_RESERVED + jbe @f + + mov al, IRQ_RESERVED +@@: + mov [IRQ_COUNT], eax + + ; Reroute IOAPIC & mask all interrupts + xor ecx, ecx + mov eax, IOAPIC_REDTBL +@@: + mov ebx, eax + call IOAPIC_read + mov ah, 0x09; Delivery Mode: Lowest Priority, Destination Mode: Logical + mov al, cl + add al, 0x20; vector + or eax, 0x10000; Mask Interrupt + cmp ecx, 16 + jb .set + + or eax, 0xa000;<<< level-triggered active-low for IRQ16+ +.set: + xchg eax, ebx + call IOAPIC_write + inc eax + mov ebx, eax + call IOAPIC_read + or eax, 0xff000000; Destination Field + xchg eax, ebx + call IOAPIC_write + inc eax + inc ecx + cmp ecx, [IRQ_COUNT] + jb @b + + call LAPIC_init + + mov [irq_mode], IRQ_APIC + + mov al, 0x70 + out 0x22, al + mov al, 1 + out 0x23, al + + call pci_irq_fixup +.no_apic: + + ret + +;=========================================================== +align 4 +LAPIC_init: + ; Check MSR support + ;.... + ; Get LAPIC base address +; mov ecx, 0x1b +; rdmsr ; it may be replaced to +; and ax, 0xf000 ; mov eax, 0xfee00000 + + stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_SW + mov [LAPIC_BASE], eax + mov esi, eax + + ; Program Destination Format Register for Flat mode. + mov eax, [esi + APIC_DFR] + or eax, 0xf0000000 + mov [esi + APIC_DFR], eax + + ; Program Logical Destination Register. + mov eax, [esi + APIC_LDR] + ;and eax, 0xff000000 + and eax, 0x00ffffff + or eax, 0x01000000;!!!!!!!!!!!! + mov [esi + APIC_LDR], eax + + ; Task Priority Register initialization. + mov eax, [esi + APIC_TPR] + and eax, 0xffffff00 + mov [esi + APIC_TPR], eax + + ; Flush the queue + mov edx, 0 +.nxt2: + mov ecx, 32 + mov eax, [esi + APIC_ISR + edx] +.nxt: + shr eax, 1 + jnc @f + mov dword [esi + APIC_EOI], 0; EOI +@@: + loop .nxt + + add edx, 0x10 + cmp edx, 0x170 + jbe .nxt2 + + ; Spurious-Interrupt Vector Register initialization. + mov eax, [esi + APIC_SVR] + or eax, 0x1ff + and eax, 0xfffffdff + mov [esi + APIC_SVR], eax + + ; Initialize LVT LINT0 register. (INTR) + mov eax, 0x00700 + ; mov eax, 0x10700 + mov [esi + APIC_LVT_LINT0], eax + + ; Initialize LVT LINT1 register. (NMI) + mov eax, 0x00400 + mov [esi + APIC_LVT_LINT1], eax + + ; Initialize LVT Error register. + mov eax, [esi + APIC_LVT_err] + or eax, 0x10000; bit 16 + mov [esi + APIC_LVT_err], eax + + ; LAPIC timer + ; pre init + mov dword[esi + APIC_timer_div], 1011b; 1 + mov dword[esi + APIC_timer_init], 0xffffffff; max val + push esi + mov esi, 640 ; wait 0.64 sec + call delay_ms + pop esi + mov eax, [esi + APIC_timer_cur]; read current tick couner + xor eax, 0xffffffff ; eax = 0xffffffff - eax + shr eax, 6 ; eax /= 64; APIC ticks per 0.01 sec + + ; Start (every 0.01 sec) + mov dword[esi + APIC_LVT_timer], 0x30020; periodic int 0x20 + mov dword[esi + APIC_timer_init], eax + ret + +;=========================================================== +; IOAPIC implementation +align 4 +IOAPIC_read: +; in : EAX - IOAPIC register +; out: EAX - readed value + push esi + mov esi, [IOAPIC_base] + mov [esi], eax + mov eax, [esi + 0x10] + pop esi + ret + +align 4 +IOAPIC_write: +; in : EAX - IOAPIC register +; EBX - value +; out: none + push esi + mov esi, [IOAPIC_base] + mov [esi], eax + mov [esi + 0x10], ebx + pop esi + ret +;=========================================================== +; Remap all IRQ to 0x20+ Vectors +; IRQ0 to vector 0x20, IRQ1 to vector 0x21.... +align 4 +PIC_init: + cli + mov al, 0x11 ; icw4, edge triggered + out 0x20, al + out 0xA0, al + + mov al, 0x20 ; generate 0x20 + + out 0x21, al + mov al, 0x28 ; generate 0x28 + + out 0xA1, al + + mov al, 0x04 ; slave at irq2 + out 0x21, al + mov al, 0x02 ; at irq9 + out 0xA1, al + + mov al, 0x01 ; 8086 mode + out 0x21, al + out 0xA1, al + + call IRQ_mask_all + ; mov dword[irq_type_to_set], IRQ_TYPE_PIC + ret + +; ----------------------------------------- +; TIMER SET TO 1/100 S +align 4 +PIT_init: + mov al, 0x34 ; set to 100Hz + out 0x43, al + mov al, 0x9b ; lsb 1193180 / 1193 + out 0x40, al + mov al, 0x2e ; msb + out 0x40, al + ret + +; ----------------------------------------- +align 4 +unmask_timer: + cmp [irq_mode], IRQ_APIC + je @f + + stdcall enable_irq, 0 + ret +@@: + ; use PIT + ; in some systems PIT no connected to IOAPIC + ; mov eax, 0x14 + ; call IOAPIC_read + ; mov ah, 0x09 ; Delivery Mode: Lowest Priority, Destination Mode: Logical + ; mov al, 0x20 + ; or eax, 0x10000 ; Mask Interrupt + ; mov ebx, eax + ; mov eax, 0x14 + ; call IOAPIC_write + ; stdcall enable_irq, 2 + ; ret + + ; use LAPIC timer + mov esi, [LAPIC_BASE] + mov eax, [esi + APIC_LVT_timer] + and eax, 0xfffeffff + mov [esi + APIC_LVT_timer], eax + ret + +; ----------------------------------------- +; Disable all IRQ +align 4 +IRQ_mask_all: + cmp [irq_mode], IRQ_APIC + je .APIC + + mov al, 0xFF + out 0x21, al + out 0xA1, al + mov ecx, 0x1000 + ret +.APIC: + mov ecx, [IRQ_COUNT] + mov eax, 0x10 +@@: + mov ebx, eax + call IOAPIC_read + or eax, 0x10000; bit 16 + xchg eax, ebx + call IOAPIC_write + inc eax + inc eax + loop @b + ret + +; ----------------------------------------- +; End Of Interrupt +; cl - IRQ number +align 4 +irq_eoi: ; __fastcall + cmp [irq_mode], IRQ_APIC + je .APIC + + cmp cl, 8 + mov al, 0x20 + jb @f + out 0xa0, al +@@: + out 0x20, al + ret + +.APIC: + mov eax, [LAPIC_BASE] + mov dword [eax + APIC_EOI], 0; EOI + ret + +; ----------------------------------------- +; from dll.inc +align 4 +proc enable_irq stdcall, irq_line:dword + mov ebx, [irq_line] + cmp [irq_mode], IRQ_APIC + je .APIC + + mov edx, 0x21 + cmp ebx, 8 + jb @F + + mov edx, 0xA1 + sub ebx, 8 +@@: + in al, dx + btr eax, ebx + out dx, al + ret +.APIC: + shl ebx, 1 + add ebx, 0x10 + mov eax, ebx + call IOAPIC_read + and eax, 0xfffeffff; bit 16 + xchg eax, ebx + call IOAPIC_write + ret +endp + +align 4 +pci_irq_fixup: + + push ebp + + mov esi, [acpi_dev_data] + mov ebx, [acpi_dev_size] + + lea edi, [esi+ebx] + +.iterate: + + cmp esi, edi + jae .done + + mov eax, [esi] + + cmp eax, -1 + je .done + + movzx ebx, al + movzx ebp, ah + + stdcall pci_read32, ebp, ebx, 0 + + cmp eax, [esi+4] + jne .skip + + mov eax, [esi+8] + stdcall pci_write8, ebp, ebx, 0x3C, eax +.skip: + add esi, 16 + jmp .iterate + +.done: +.fail: + pop ebp + ret + + + + + diff --git a/kernel/trunk/core/conf_lib.inc b/kernel/trunk/core/conf_lib.inc index 1fbe6de68..199ae4ab8 100644 --- a/kernel/trunk/core/conf_lib.inc +++ b/kernel/trunk/core/conf_lib.inc @@ -1,297 +1,298 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;------------------------------------------------------------------------- -;Loading configuration from ini file -; {SPraid.simba} -;------------------------------------------------------------------------- - -$Revision$ - -iglobal -conf_path_sect: db 'path',0 - -conf_fname db '/sys/sys.conf',0 -endg -; set soke kernel configuration -proc set_kernel_conf - locals - par db 30 dup(?) - endl - - pushad -;[gui] -;mouse_speed - - lea eax,[par] - push eax - invoke ini.get_str,conf_fname, ugui, ugui_mouse_speed,\ - eax,30, ugui_mouse_speed_def - pop eax - stdcall strtoint,eax - mov [mouse_speed_factor], ax - -;mouse_delay - lea eax,[par] - push eax - invoke ini.get_str,conf_fname, ugui, ugui_mouse_delay,\ - eax,30, ugui_mouse_delay_def - pop eax - stdcall strtoint,eax - mov [mouse_delay], eax - - -;midibase - lea eax,[par] - push eax - invoke ini.get_str,conf_fname, udev, udev_midibase, eax,30, udev_midibase_def - pop eax - stdcall strtoint,eax - - cmp eax, 0x100 - jb @f - cmp eax, 0x10000 - jae @f - mov [midi_base], ax - mov [mididp], eax - inc eax - mov [midisp], eax -@@: - popad - ret -endp -iglobal -ugui db 'gui',0 -ugui_mouse_speed db 'mouse_speed',0 -ugui_mouse_speed_def db '2',0 -ugui_mouse_delay db 'mouse_delay',0 -ugui_mouse_delay_def db '0x00A',0 - -udev db 'dev',0 -udev_midibase db 'midibase',0 -udev_midibase_def db '0x320',0 -endg -;set up netvork configuration -proc set_network_conf -locals - par db 30 dup(?) -endl - pushad - - ;[net] - ;active - lea eax,[par] - invoke ini.get_int,conf_fname, unet, unet_active, 0 - or eax,eax - jz .do_not_set_net - mov eax, [stack_config] - and eax, 0xFFFFFF80 - add eax, 3 - mov [stack_config], eax - call ash_eth_enable - - ;addr - lea eax,[par] - push eax - invoke ini.get_str,conf_fname, unet, unet_addr, eax,30, unet_def - pop eax - stdcall do_inet_adr,eax - mov [stack_ip], eax - - ;mask - lea eax,[par] - push eax - invoke ini.get_str,conf_fname, unet, unet_mask, eax,30, unet_def - pop eax - stdcall do_inet_adr,eax - mov [subnet_mask], eax - - ;gate - lea eax,[par] - push eax - invoke ini.get_str,conf_fname, unet, unet_gate, eax,30, unet_def - pop eax - stdcall do_inet_adr,eax - mov [gateway_ip], eax -.do_not_set_net: - popad - ret - - -endp -iglobal -unet db 'net',0 -unet_active db 'active',0 -unet_addr db 'addr',0 -unet_mask db 'mask',0 -unet_gate db 'gate',0 -unet_def db 0 -endg -; convert string to DWord -proc strtoint stdcall,strs - pushad - - mov eax,[strs] - inc eax - mov bl,[eax] - cmp bl,'x' - je .hex - cmp bl,'X' - je .hex - jmp .dec -.hex: - inc eax - stdcall strtoint_hex,eax - jmp .exit -.dec: - dec eax - stdcall strtoint_dec,eax -.exit: - mov [esp+28],eax - popad - ret -endp - -; convert string to DWord for decimal value -proc strtoint_dec stdcall,strs - pushad - xor edx,edx - ; Ї®ЁбЄ Є®­ж  - mov esi,[strs] -@@: - lodsb - or al,al - jnz @b - mov ebx,esi - mov esi,[strs] - dec ebx - sub ebx,esi - mov ecx,1 - -@@: - dec ebx - or ebx,ebx - jz @f - imul ecx,ecx,10 ; Ї®а冷Є - jmp @b -@@: - - xchg ebx,ecx - - - xor ecx,ecx - - -@@: - xor eax,eax - lodsb - cmp al,0 - je .eend - - sub al,30h - imul ebx - add ecx,eax - push ecx - xchg eax,ebx - mov ecx,10 - div ecx - xchg eax,ebx - pop ecx - jmp @b - -.eend: - mov [esp+28],ecx - popad - ret -endp - -;convert string to DWord for hex value -proc strtoint_hex stdcall,strs - pushad - xor edx,edx - - mov esi,[strs] - mov ebx,1 - add esi,1 - -@@: - lodsb - or al,al - jz @f - shl ebx,4 - jmp @b -@@: - xor ecx,ecx - mov esi,[strs] - -@@: - xor eax,eax - lodsb - cmp al,0 - je .eend - - cmp al,'a' - jae .bm - cmp al,'A' - jae .bb - jmp .cc -.bm: ; 57h - sub al,57h - jmp .do - -.bb: ; 37h - sub al,37h - jmp .do - -.cc: ; 30h - sub al,30h - -.do: - imul ebx - add ecx,eax - shr ebx,4 - - jmp @b - -.eend: - mov [esp+28],ecx - popad - ret -endp - - -; convert string to DWord for IP addres -proc do_inet_adr stdcall,strs - pushad - - mov esi,[strs] - mov ebx,0 -.next: - push esi -@@: - lodsb - or al,al - jz @f - cmp al,'.' - jz @f - jmp @b -@@: - mov cl, al - mov [esi-1],byte 0 - ;pop eax - call strtoint_dec - rol eax,24 - ror ebx,8 - add ebx,eax - or cl,cl - jz @f - jmp .next -@@: - mov [esp+28],ebx - popad - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;------------------------------------------------------------------------- +;Loading configuration from ini file +; {SPraid.simba} +;------------------------------------------------------------------------- + +$Revision$ + +iglobal +conf_path_sect: + db 'path',0 + +conf_fname db '/sys/sys.conf',0 +endg +; set soke kernel configuration +proc set_kernel_conf + locals + par db 30 dup(?) + endl + + pushad +;[gui] +;mouse_speed + + lea eax, [par] + push eax + invoke ini.get_str, conf_fname, ugui, ugui_mouse_speed, \ + eax,30, ugui_mouse_speed_def + pop eax + stdcall strtoint, eax + mov [mouse_speed_factor], ax + +;mouse_delay + lea eax, [par] + push eax + invoke ini.get_str, conf_fname, ugui, ugui_mouse_delay, \ + eax,30, ugui_mouse_delay_def + pop eax + stdcall strtoint, eax + mov [mouse_delay], eax + + +;midibase + lea eax, [par] + push eax + invoke ini.get_str, conf_fname, udev, udev_midibase, eax, 30, udev_midibase_def + pop eax + stdcall strtoint, eax + + cmp eax, 0x100 + jb @f + cmp eax, 0x10000 + jae @f + mov [midi_base], ax + mov [mididp], eax + inc eax + mov [midisp], eax +@@: + popad + ret +endp +iglobal +ugui db 'gui',0 +ugui_mouse_speed db 'mouse_speed',0 +ugui_mouse_speed_def db '2',0 +ugui_mouse_delay db 'mouse_delay',0 +ugui_mouse_delay_def db '0x00A',0 + +udev db 'dev',0 +udev_midibase db 'midibase',0 +udev_midibase_def db '0x320',0 +endg +;set up netvork configuration +proc set_network_conf +locals + par db 30 dup(?) +endl + pushad + + ;[net] + ;active + lea eax, [par] + invoke ini.get_int, conf_fname, unet, unet_active, 0 + or eax, eax + jz .do_not_set_net + mov eax, [stack_config] + and eax, 0xFFFFFF80 + add eax, 3 + mov [stack_config], eax + call ash_eth_enable + + ;addr + lea eax, [par] + push eax + invoke ini.get_str, conf_fname, unet, unet_addr, eax, 30, unet_def + pop eax + stdcall do_inet_adr, eax + mov [stack_ip], eax + + ;mask + lea eax, [par] + push eax + invoke ini.get_str, conf_fname, unet, unet_mask, eax, 30, unet_def + pop eax + stdcall do_inet_adr, eax + mov [subnet_mask], eax + + ;gate + lea eax, [par] + push eax + invoke ini.get_str, conf_fname, unet, unet_gate, eax, 30, unet_def + pop eax + stdcall do_inet_adr, eax + mov [gateway_ip], eax +.do_not_set_net: + popad + ret + + +endp +iglobal +unet db 'net',0 +unet_active db 'active',0 +unet_addr db 'addr',0 +unet_mask db 'mask',0 +unet_gate db 'gate',0 +unet_def db 0 +endg +; convert string to DWord +proc strtoint stdcall,strs + pushad + + mov eax, [strs] + inc eax + mov bl, [eax] + cmp bl, 'x' + je .hex + cmp bl, 'X' + je .hex + jmp .dec +.hex: + inc eax + stdcall strtoint_hex, eax + jmp .exit +.dec: + dec eax + stdcall strtoint_dec, eax +.exit: + mov [esp+28], eax + popad + ret +endp + +; convert string to DWord for decimal value +proc strtoint_dec stdcall,strs + pushad + xor edx, edx + ; Ї®ЁбЄ Є®­ж  + mov esi, [strs] +@@: + lodsb + or al, al + jnz @b + mov ebx, esi + mov esi, [strs] + dec ebx + sub ebx, esi + mov ecx, 1 + +@@: + dec ebx + or ebx, ebx + jz @f + imul ecx, ecx, 10; Ї®а冷Є + jmp @b +@@: + + xchg ebx, ecx + + + xor ecx, ecx + + +@@: + xor eax, eax + lodsb + cmp al, 0 + je .eend + + sub al, 30h + imul ebx + add ecx, eax + push ecx + xchg eax, ebx + mov ecx, 10 + div ecx + xchg eax, ebx + pop ecx + jmp @b + +.eend: + mov [esp+28], ecx + popad + ret +endp + +;convert string to DWord for hex value +proc strtoint_hex stdcall,strs + pushad + xor edx, edx + + mov esi, [strs] + mov ebx, 1 + add esi, 1 + +@@: + lodsb + or al, al + jz @f + shl ebx, 4 + jmp @b +@@: + xor ecx, ecx + mov esi, [strs] + +@@: + xor eax, eax + lodsb + cmp al, 0 + je .eend + + cmp al, 'a' + jae .bm + cmp al, 'A' + jae .bb + jmp .cc +.bm: ; 57h + sub al, 57h + jmp .do + +.bb: ; 37h + sub al, 37h + jmp .do + +.cc: ; 30h + sub al, 30h + +.do: + imul ebx + add ecx, eax + shr ebx, 4 + + jmp @b + +.eend: + mov [esp+28], ecx + popad + ret +endp + + +; convert string to DWord for IP addres +proc do_inet_adr stdcall,strs + pushad + + mov esi, [strs] + mov ebx, 0 +.next: + push esi +@@: + lodsb + or al, al + jz @f + cmp al, '.' + jz @f + jmp @b +@@: + mov cl, al + mov [esi-1], byte 0 + ;pop eax + call strtoint_dec + rol eax, 24 + ror ebx, 8 + add ebx, eax + or cl, cl + jz @f + jmp .next +@@: + mov [esp+28], ebx + popad + ret +endp diff --git a/kernel/trunk/core/debug.inc b/kernel/trunk/core/debug.inc index 2bfda6b02..da9e2e667 100644 --- a/kernel/trunk/core/debug.inc +++ b/kernel/trunk/core/debug.inc @@ -1,429 +1,435 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; diamond, 2006 -sys_debug_services: - cmp ebx, 9 - ja @f - jmp dword [sys_debug_services_table+ebx*4] -@@: ret -iglobal -align 4 -sys_debug_services_table: - dd debug_set_event_data - dd debug_getcontext - dd debug_setcontext - dd debug_detach - dd debug_suspend - dd debug_resume - dd debug_read_process_memory - dd debug_write_process_memory - dd debug_terminate - dd debug_set_drx -endg -debug_set_event_data: -; in: ecx = pointer -; destroys eax - mov eax, [current_slot] - mov [eax+APPDATA.dbg_event_mem], ecx - ret - -get_debuggee_slot: -; in: ecx=PID -; out: CF=1 if error -; CF=0 and eax=slot*0x20 if ok -; out: interrupts disabled - cli - mov eax, ecx - call pid_to_slot - test eax, eax - jz .ret_bad - shl eax, 5 - push ebx - mov ebx, [CURRENT_TASK] - cmp [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx - pop ebx - jnz .ret_bad -; clc ; automatically - ret -.ret_bad: - stc - ret - -debug_detach: -; in: ecx=pid -; destroys eax,ebx - call get_debuggee_slot - jc .ret - and dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0 - call do_resume -.ret: - sti - ret - -debug_terminate: -; in: ecx=pid - call get_debuggee_slot - jc debug_detach.ret - mov ecx, eax - shr ecx, 5 -; push 2 -; pop ebx - mov edx,esi - jmp sysfn_terminate - -debug_suspend: -; in: ecx=pid -; destroys eax,ecx - cli - mov eax, ecx - call pid_to_slot - shl eax, 5 - jz .ret - mov cl, [CURRENT_TASK+eax+TASKDATA.state] ; process state - test cl, cl - jz .1 - cmp cl, 5 - jnz .ret - mov cl, 2 -.2: mov [CURRENT_TASK+eax+TASKDATA.state], cl -.ret: - sti - ret -.1: - inc ecx - jmp .2 - -do_resume: - mov cl, [CURRENT_TASK+eax+TASKDATA.state] - cmp cl, 1 - jz .1 - cmp cl, 2 - jnz .ret - mov cl, 5 -.2: mov [CURRENT_TASK+eax+TASKDATA.state], cl -.ret: ret -.1: dec ecx - jmp .2 - -debug_resume: -; in: ecx=pid -; destroys eax,ebx - cli - mov eax, ecx - call pid_to_slot - shl eax, 5 - jz .ret - call do_resume -.ret: sti - ret - -debug_getcontext: -; in: -; ecx=pid -; edx=sizeof(CONTEXT) -; esi->CONTEXT -; destroys eax,ecx,edx,esi,edi - cmp edx, 28h - jnz .ret -; push ecx -; mov ecx, esi - call check_region -; pop ecx - dec eax - jnz .ret - call get_debuggee_slot - jc .ret - mov edi, esi - mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] - lea esi, [eax+RING0_STACK_SIZE] - -.ring0: -; note that following code assumes that all interrupt/exception handlers -; saves ring-3 context by pushad in this order -; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), pushad - sub esi, 8+12+20h - lodsd ;edi - mov [edi+24h], eax - lodsd ;esi - mov [edi+20h], eax - lodsd ; ebp - mov [edi+1Ch], eax - lodsd ;esp - lodsd ;ebx - mov [edi+14h], eax - lodsd ;edx - mov [edi+10h], eax - lodsd ;ecx - mov [edi+0Ch], eax - lodsd ;eax - mov [edi+8], eax - lodsd ;eip - mov [edi], eax - lodsd ;cs - lodsd ;eflags - mov [edi+4], eax - lodsd ;esp - mov [edi+18h], eax -.ret: - sti - ret - -debug_setcontext: -; in: -; ecx=pid -; edx=sizeof(CONTEXT) -; esi->CONTEXT -; destroys eax,ecx,edx,esi,edi - cmp edx, 28h - jnz .ret -; push ebx -; mov ebx, edx - call check_region -; pop ebx - dec eax - jnz .ret - call get_debuggee_slot - jc .stiret -; mov esi, edx - mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] - lea edi, [eax+RING0_STACK_SIZE] - -.ring0: - sub edi, 8+12+20h - mov eax, [esi+24h] ;edi - stosd - mov eax, [esi+20h] ;esi - stosd - mov eax, [esi+1Ch] ;ebp - stosd - scasd - mov eax, [esi+14h] ;ebx - stosd - mov eax, [esi+10h] ;edx - stosd - mov eax, [esi+0Ch] ;ecx - stosd - mov eax, [esi+8] ;eax - stosd - mov eax, [esi] ;eip - stosd - scasd - mov eax, [esi+4] ;eflags - stosd - mov eax, [esi+18h] ;esp - stosd -.stiret: - sti -.ret: - ret - -debug_set_drx: - call get_debuggee_slot - jc .errret - mov ebp, eax - lea eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs] -; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3 -; [eax+10]=dr7 - cmp esi, OS_BASE - jae .errret - cmp dl, 3 - ja .errret - mov ecx, dr7 -;fix me - xchg ecx,edx - shr edx, cl - shr edx, cl - xchg ecx,edx - - test ecx, 2 ; bit 1+2*index = G0..G3, global break enable - jnz .errret2 - test dh, dh - jns .new -; clear breakpoint - movzx edx, dl - add edx, edx - and dword [eax+edx*2], 0 ; clear DR - btr dword [eax+10h], edx ; clear L bit - test byte [eax+10h], 55h - jnz .okret -; imul eax, ebp, tss_step/32 -; and byte [eax + tss_data + TSS._trap], not 1 - and [ebp*8 + SLOT_BASE+APPDATA.dbg_state], not 1 -.okret: - and dword [esp+32], 0 - sti - ret -.errret: - sti - mov dword [esp+32], 1 - ret -.errret2: - sti - mov dword [esp+32], 2 - ret -.new: -; add new breakpoint -; dl=index; dh=flags; esi=address - test dh, 0xF0 - jnz .errret - mov cl, dh - and cl, 3 - cmp cl, 2 - jz .errret - mov cl, dh - shr cl, 2 - cmp cl, 2 - jz .errret - - mov ebx,esi - test bl, dl - - jnz .errret - or byte [eax+10h+1], 3 ; set GE and LE flags - - movzx edx, dh - movzx ecx, dl - add ecx, ecx - bts dword [eax+10h], ecx ; set L flag - add ecx, ecx - mov [eax+ecx], ebx;esi ; set DR - shl edx, cl - mov ebx, 0xF - shl ebx, cl - not ebx - and [eax+10h+2], bx - or [eax+10h+2], dx ; set R/W and LEN fields -; imul eax, ebp, tss_step/32 -; or byte [eax + tss_data + TSS._trap], 1 - or [ebp*8 + SLOT_BASE+APPDATA.dbg_state], 1 - jmp .okret - -debug_read_process_memory: -; in: -; ecx=pid -; edx=length -; edi->buffer in debugger -; esi=address in debuggee -; out: [esp+36]=sizeof(read) -; destroys all -; push ebx -; mov ebx, esi - call check_region -; pop ebx - dec eax - jnz .err - call get_debuggee_slot - jc .err - shr eax, 5 - mov ecx, edi - call read_process_memory - sti - mov dword [esp+32], eax - ret -.err: - or dword [esp+32], -1 - ret - -debug_write_process_memory: -; in: -; ecx=pid -; edx=length -; edi->buffer in debugger -; esi=address in debuggee -; out: [esp+36]=sizeof(write) -; destroys all -; push ebx -; mov ebx, esi - call check_region -; pop ebx - dec eax - jnz debug_read_process_memory.err - call get_debuggee_slot - jc debug_read_process_memory.err - shr eax, 5 - mov ecx, edi - call write_process_memory - sti - mov [esp+32], eax - ret - -debugger_notify: -; in: eax=debugger slot -; ecx=size of debug message -; [esp+4]..[esp+4+ecx]=message -; interrupts must be disabled! -; destroys all general registers -; interrupts remain disabled - xchg ebp, eax - mov edi, [timer_ticks] - add edi, 500 ; 5 sec timeout -.1: - mov eax, ebp - shl eax, 8 - mov esi, [SLOT_BASE+eax+APPDATA.dbg_event_mem] - test esi, esi - jz .ret -; read buffer header - push ecx - push eax - push eax - mov eax, ebp - mov ecx, esp - mov edx, 8 - call read_process_memory - cmp eax, edx - jz @f - add esp, 12 - jmp .ret -@@: - cmp dword [ecx], 0 - jg @f -.2: - pop ecx - pop ecx - pop ecx - cmp dword [CURRENT_TASK], 1 - jnz .notos - cmp [timer_ticks], edi - jae .ret -.notos: - sti - call change_task - cli - jmp .1 -@@: - mov edx, [ecx+8] - add edx, [ecx+4] - cmp edx, [ecx] - ja .2 -; advance buffer position - push edx - mov edx, 4 - sub ecx, edx - mov eax, ebp - add esi, edx - call write_process_memory - pop eax -; write message - mov eax, ebp - add esi, edx - add esi, [ecx+8] - add ecx, 20 - pop edx - pop edx - pop edx - call write_process_memory -; new debug event - mov eax, ebp - shl eax, 8 - or byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1 ; set flag 100h -.ret: - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; diamond, 2006 +sys_debug_services: + cmp ebx, 9 + ja @f + jmp dword [sys_debug_services_table+ebx*4] +@@: + ret +iglobal +align 4 +sys_debug_services_table: + dd debug_set_event_data + dd debug_getcontext + dd debug_setcontext + dd debug_detach + dd debug_suspend + dd debug_resume + dd debug_read_process_memory + dd debug_write_process_memory + dd debug_terminate + dd debug_set_drx +endg +debug_set_event_data: +; in: ecx = pointer +; destroys eax + mov eax, [current_slot] + mov [eax+APPDATA.dbg_event_mem], ecx + ret + +get_debuggee_slot: +; in: ecx=PID +; out: CF=1 if error +; CF=0 and eax=slot*0x20 if ok +; out: interrupts disabled + cli + mov eax, ecx + call pid_to_slot + test eax, eax + jz .ret_bad + shl eax, 5 + push ebx + mov ebx, [CURRENT_TASK] + cmp [SLOT_BASE+eax*8+APPDATA.debugger_slot], ebx + pop ebx + jnz .ret_bad +; clc ; automatically + ret +.ret_bad: + stc + ret + +debug_detach: +; in: ecx=pid +; destroys eax,ebx + call get_debuggee_slot + jc .ret + and dword [eax*8+SLOT_BASE+APPDATA.debugger_slot], 0 + call do_resume +.ret: + sti + ret + +debug_terminate: +; in: ecx=pid + call get_debuggee_slot + jc debug_detach.ret + mov ecx, eax + shr ecx, 5 +; push 2 +; pop ebx + mov edx, esi + jmp sysfn_terminate + +debug_suspend: +; in: ecx=pid +; destroys eax,ecx + cli + mov eax, ecx + call pid_to_slot + shl eax, 5 + jz .ret + mov cl, [CURRENT_TASK+eax+TASKDATA.state] ; process state + test cl, cl + jz .1 + cmp cl, 5 + jnz .ret + mov cl, 2 +.2: + mov [CURRENT_TASK+eax+TASKDATA.state], cl +.ret: + sti + ret +.1: + inc ecx + jmp .2 + +do_resume: + mov cl, [CURRENT_TASK+eax+TASKDATA.state] + cmp cl, 1 + jz .1 + cmp cl, 2 + jnz .ret + mov cl, 5 +.2: + mov [CURRENT_TASK+eax+TASKDATA.state], cl +.ret: + ret +.1: + dec ecx + jmp .2 + +debug_resume: +; in: ecx=pid +; destroys eax,ebx + cli + mov eax, ecx + call pid_to_slot + shl eax, 5 + jz .ret + call do_resume +.ret: + sti + ret + +debug_getcontext: +; in: +; ecx=pid +; edx=sizeof(CONTEXT) +; esi->CONTEXT +; destroys eax,ecx,edx,esi,edi + cmp edx, 28h + jnz .ret +; push ecx +; mov ecx, esi + call check_region +; pop ecx + dec eax + jnz .ret + call get_debuggee_slot + jc .ret + mov edi, esi + mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] + lea esi, [eax+RING0_STACK_SIZE] + +.ring0: +; note that following code assumes that all interrupt/exception handlers +; saves ring-3 context by pushad in this order +; top of ring0 stack: ring3 stack ptr (ss+esp), iret data (cs+eip+eflags), pushad + sub esi, 8+12+20h + lodsd ;edi + mov [edi+24h], eax + lodsd ;esi + mov [edi+20h], eax + lodsd ; ebp + mov [edi+1Ch], eax + lodsd ;esp + lodsd ;ebx + mov [edi+14h], eax + lodsd ;edx + mov [edi+10h], eax + lodsd ;ecx + mov [edi+0Ch], eax + lodsd ;eax + mov [edi+8], eax + lodsd ;eip + mov [edi], eax + lodsd ;cs + lodsd ;eflags + mov [edi+4], eax + lodsd ;esp + mov [edi+18h], eax +.ret: + sti + ret + +debug_setcontext: +; in: +; ecx=pid +; edx=sizeof(CONTEXT) +; esi->CONTEXT +; destroys eax,ecx,edx,esi,edi + cmp edx, 28h + jnz .ret +; push ebx +; mov ebx, edx + call check_region +; pop ebx + dec eax + jnz .ret + call get_debuggee_slot + jc .stiret +; mov esi, edx + mov eax, [eax*8+SLOT_BASE+APPDATA.pl0_stack] + lea edi, [eax+RING0_STACK_SIZE] + +.ring0: + sub edi, 8+12+20h + mov eax, [esi+24h] ;edi + stosd + mov eax, [esi+20h] ;esi + stosd + mov eax, [esi+1Ch] ;ebp + stosd + scasd + mov eax, [esi+14h] ;ebx + stosd + mov eax, [esi+10h] ;edx + stosd + mov eax, [esi+0Ch] ;ecx + stosd + mov eax, [esi+8] ;eax + stosd + mov eax, [esi] ;eip + stosd + scasd + mov eax, [esi+4] ;eflags + stosd + mov eax, [esi+18h] ;esp + stosd +.stiret: + sti +.ret: + ret + +debug_set_drx: + call get_debuggee_slot + jc .errret + mov ebp, eax + lea eax, [eax*8+SLOT_BASE+APPDATA.dbg_regs] +; [eax]=dr0, [eax+4]=dr1, [eax+8]=dr2, [eax+C]=dr3 +; [eax+10]=dr7 + cmp esi, OS_BASE + jae .errret + cmp dl, 3 + ja .errret + mov ecx, dr7 +;fix me + xchg ecx, edx + shr edx, cl + shr edx, cl + xchg ecx, edx + + test ecx, 2 ; bit 1+2*index = G0..G3, global break enable + jnz .errret2 + test dh, dh + jns .new +; clear breakpoint + movzx edx, dl + add edx, edx + and dword [eax+edx*2], 0 ; clear DR + btr dword [eax+10h], edx ; clear L bit + test byte [eax+10h], 55h + jnz .okret +; imul eax, ebp, tss_step/32 +; and byte [eax + tss_data + TSS._trap], not 1 + and [ebp*8 + SLOT_BASE+APPDATA.dbg_state], not 1 +.okret: + and dword [esp+32], 0 + sti + ret +.errret: + sti + mov dword [esp+32], 1 + ret +.errret2: + sti + mov dword [esp+32], 2 + ret +.new: +; add new breakpoint +; dl=index; dh=flags; esi=address + test dh, 0xF0 + jnz .errret + mov cl, dh + and cl, 3 + cmp cl, 2 + jz .errret + mov cl, dh + shr cl, 2 + cmp cl, 2 + jz .errret + + mov ebx, esi + test bl, dl + + jnz .errret + or byte [eax+10h+1], 3 ; set GE and LE flags + + movzx edx, dh + movzx ecx, dl + add ecx, ecx + bts dword [eax+10h], ecx ; set L flag + add ecx, ecx + mov [eax+ecx], ebx;esi ; set DR + shl edx, cl + mov ebx, 0xF + shl ebx, cl + not ebx + and [eax+10h+2], bx + or [eax+10h+2], dx ; set R/W and LEN fields +; imul eax, ebp, tss_step/32 +; or byte [eax + tss_data + TSS._trap], 1 + or [ebp*8 + SLOT_BASE+APPDATA.dbg_state], 1 + jmp .okret + +debug_read_process_memory: +; in: +; ecx=pid +; edx=length +; edi->buffer in debugger +; esi=address in debuggee +; out: [esp+36]=sizeof(read) +; destroys all +; push ebx +; mov ebx, esi + call check_region +; pop ebx + dec eax + jnz .err + call get_debuggee_slot + jc .err + shr eax, 5 + mov ecx, edi + call read_process_memory + sti + mov dword [esp+32], eax + ret +.err: + or dword [esp+32], -1 + ret + +debug_write_process_memory: +; in: +; ecx=pid +; edx=length +; edi->buffer in debugger +; esi=address in debuggee +; out: [esp+36]=sizeof(write) +; destroys all +; push ebx +; mov ebx, esi + call check_region +; pop ebx + dec eax + jnz debug_read_process_memory.err + call get_debuggee_slot + jc debug_read_process_memory.err + shr eax, 5 + mov ecx, edi + call write_process_memory + sti + mov [esp+32], eax + ret + +debugger_notify: +; in: eax=debugger slot +; ecx=size of debug message +; [esp+4]..[esp+4+ecx]=message +; interrupts must be disabled! +; destroys all general registers +; interrupts remain disabled + xchg ebp, eax + mov edi, [timer_ticks] + add edi, 500 ; 5 sec timeout +.1: + mov eax, ebp + shl eax, 8 + mov esi, [SLOT_BASE+eax+APPDATA.dbg_event_mem] + test esi, esi + jz .ret +; read buffer header + push ecx + push eax + push eax + mov eax, ebp + mov ecx, esp + mov edx, 8 + call read_process_memory + cmp eax, edx + jz @f + add esp, 12 + jmp .ret +@@: + cmp dword [ecx], 0 + jg @f +.2: + pop ecx + pop ecx + pop ecx + cmp dword [CURRENT_TASK], 1 + jnz .notos + cmp [timer_ticks], edi + jae .ret +.notos: + sti + call change_task + cli + jmp .1 +@@: + mov edx, [ecx+8] + add edx, [ecx+4] + cmp edx, [ecx] + ja .2 +; advance buffer position + push edx + mov edx, 4 + sub ecx, edx + mov eax, ebp + add esi, edx + call write_process_memory + pop eax +; write message + mov eax, ebp + add esi, edx + add esi, [ecx+8] + add ecx, 20 + pop edx + pop edx + pop edx + call write_process_memory +; new debug event + mov eax, ebp + shl eax, 8 + or byte [SLOT_BASE+eax+APPDATA.event_mask+1], 1 ; set flag 100h +.ret: + ret diff --git a/kernel/trunk/core/dll.inc b/kernel/trunk/core/dll.inc index 3623cdd7e..0f13008eb 100644 --- a/kernel/trunk/core/dll.inc +++ b/kernel/trunk/core/dll.inc @@ -1,1447 +1,1447 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -DRV_COMPAT equ 5 ;minimal required drivers version -DRV_CURRENT equ 6 ;current drivers model version - -DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT -PID_KERNEL equ 1 ;os_idle thread - - - -align 4 -proc get_notify stdcall, p_ev:dword - -.wait: - mov ebx,[current_slot] - test dword [ebx+APPDATA.event_mask],EVENT_NOTIFY - jz @f - and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY - mov edi, [p_ev] - mov dword [edi], EV_INTR - mov eax, [ebx+APPDATA.event] - mov dword [edi+4], eax - ret -@@: - call change_task - jmp .wait -endp - -align 4 -proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword - push ebx - xor eax, eax - xor ebx, ebx - mov ah, byte [bus] - mov al, 6 - mov bh, byte [devfn] - mov bl, byte [reg] - call pci_read_reg - pop ebx - ret -endp - -align 4 -proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword - push ebx - xor eax, eax - xor ebx, ebx - mov ah, byte [bus] - mov al, 5 - mov bh, byte [devfn] - mov bl, byte [reg] - call pci_read_reg - pop ebx - ret -endp - -align 4 -proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword - push ebx - xor eax, eax - xor ebx, ebx - mov ah, byte [bus] - mov al, 4 - mov bh, byte [devfn] - mov bl, byte [reg] - call pci_read_reg - pop ebx - ret -endp - -align 4 -proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword - push ebx - xor eax, eax - xor ebx, ebx - mov ah, byte [bus] - mov al, 8 - mov bh, byte [devfn] - mov bl, byte [reg] - mov ecx, [val] - call pci_write_reg - pop ebx - ret -endp - -align 4 -proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword - push ebx - xor eax, eax - xor ebx, ebx - mov ah, byte [bus] - mov al, 9 - mov bh, byte [devfn] - mov bl, byte [reg] - mov ecx, [val] - call pci_write_reg - pop ebx - ret -endp - -align 4 -proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword - push ebx - xor eax, eax - xor ebx, ebx - mov ah, byte [bus] - mov al, 10 - mov bh, byte [devfn] - mov bl, byte [reg] - mov ecx, [val] - call pci_write_reg - pop ebx - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - - -align 4 -proc srv_handler stdcall, ioctl:dword - mov esi, [ioctl] - test esi, esi - jz .err - - mov edi, [esi+handle] - cmp [edi+SRV.magic], ' SRV' - jne .fail - - cmp [edi+SRV.size], SRV.sizeof - jne .fail - - stdcall [edi+SRV.srv_proc], esi - ret -.fail: - xor eax, eax - not eax - mov [esi+output], eax - mov [esi+out_size], 4 - ret -.err: - xor eax, eax - not eax - ret -endp - -; param -; ecx= io_control -; -; retval -; eax= error code - -align 4 -srv_handlerEx: - cmp ecx, OS_BASE - jae .fail - - mov eax, [ecx+handle] - cmp [eax+SRV.magic], ' SRV' - jne .fail - - cmp [eax+SRV.size], SRV.sizeof - jne .fail - - stdcall [eax+SRV.srv_proc], ecx - ret -.fail: - or eax, -1 - ret - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - -align 4 -proc get_service stdcall, sz_name:dword - mov eax, [sz_name] - test eax, eax - jnz @F - ret -@@: - mov edx, [srv.fd] -@@: - cmp edx, srv.fd-SRV_FD_OFFSET - je .not_load - - stdcall strncmp, edx, [sz_name], 16 - test eax, eax - je .ok - - mov edx, [edx+SRV.fd] - jmp @B -.not_load: - pop ebp - jmp load_driver -.ok: - mov eax, edx - ret -endp - -align 4 -proc reg_service stdcall, name:dword, handler:dword - - push ebx - - xor eax, eax - - cmp [name], eax - je .fail - - cmp [handler], eax - je .fail - - mov eax, SRV.sizeof - call malloc - test eax, eax - jz .fail - - push esi - push edi - mov edi, eax - mov esi, [name] - movsd - movsd - movsd - movsd - pop edi - pop esi - - mov [eax+SRV.magic], ' SRV' - mov [eax+SRV.size], SRV.sizeof - - mov ebx, srv.fd-SRV_FD_OFFSET - mov edx, [ebx+SRV.fd] - mov [eax+SRV.fd], edx - mov [eax+SRV.bk], ebx - mov [ebx+SRV.fd], eax - mov [edx+SRV.bk], eax - - mov ecx, [handler] - mov [eax+SRV.srv_proc], ecx - pop ebx - ret -.fail: - xor eax, eax - pop ebx - ret -endp - -align 4 -proc get_proc stdcall, exp:dword, sz_name:dword - - mov edx, [exp] -.next: - mov eax, [edx] - test eax, eax - jz .end - - push edx - stdcall strncmp, eax, [sz_name], 16 - pop edx - test eax, eax - jz .ok - - add edx,8 - jmp .next -.ok: - mov eax, [edx+4] -.end: - ret -endp - -align 4 -proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword - -@@: - stdcall strncmp, [pSym], [sz_sym], 8 - test eax,eax - jz .ok - add [pSym], 18 - dec [count] - jnz @b - xor eax, eax - ret -.ok: - mov eax, [pSym] - mov eax, [eax+8] - ret -endp - -align 4 -proc get_curr_task - mov eax,[CURRENT_TASK] - shl eax, 8 - ret -endp - -align 4 -proc get_fileinfo stdcall, file_name:dword, info:dword - locals - cmd dd ? - offset dd ? - dd ? - count dd ? - buff dd ? - db ? - name dd ? - endl - - xor eax, eax - mov ebx, [file_name] - mov ecx, [info] - - mov [cmd], 5 - mov [offset], eax - mov [offset+4], eax - mov [count], eax - mov [buff], ecx - mov byte [buff+4], al - mov [name], ebx - - mov eax, 70 - lea ebx, [cmd] - int 0x40 - ret -endp - -align 4 -proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\ - bytes:dword - locals - cmd dd ? - offset dd ? - dd ? - count dd ? - buff dd ? - db ? - name dd ? - endl - - xor eax, eax - mov ebx, [file_name] - mov ecx, [off] - mov edx, [bytes] - mov esi, [buffer] - - mov [cmd], eax - mov [offset], ecx - mov [offset+4], eax - mov [count], edx - mov [buff], esi - mov byte [buff+4], al - mov [name], ebx - - pushad - lea ebx, [cmd] - call file_system_lfn - popad - ret -endp - -; description -; allocate kernel memory and loads the specified file -; -; param -; file_name= full path to file -; -; retval -; eax= file image in kernel memory -; ebx= size of file -; -; warging -; You mast call kernel_free() to delete each file -; loaded by the load_file() function - -align 4 -proc load_file stdcall, file_name:dword - locals - attr dd ? - flags dd ? - cr_time dd ? - cr_date dd ? - acc_time dd ? - acc_date dd ? - mod_time dd ? - mod_date dd ? - file_size dd ? - - file dd ? - file2 dd ? - endl - - push esi - push edi - - lea eax, [attr] - stdcall get_fileinfo, [file_name], eax - test eax, eax - jnz .fail - - mov eax, [file_size] - cmp eax, 1024*1024*16 - ja .fail - - stdcall kernel_alloc, [file_size] - mov [file], eax - test eax, eax - jz .fail - - stdcall read_file, [file_name], eax, dword 0, [file_size] - cmp ebx, [file_size] - jne .cleanup - - mov eax, [file] - cmp dword [eax], 0x4B43504B - jne .exit - mov ebx, [eax+4] - mov [file_size], ebx - stdcall kernel_alloc, ebx - - test eax, eax - jz .cleanup - - mov [file2], eax - pushfd - cli - stdcall unpack, [file], eax - popfd - stdcall kernel_free, [file] - mov eax, [file2] - mov ebx, [file_size] -.exit: - push eax - lea edi, [eax+ebx] ;cleanup remain space - mov ecx, 4096 ;from file end - and ebx, 4095 - jz @f - sub ecx, ebx - xor eax, eax - cld - rep stosb -@@: - mov ebx, [file_size] - pop eax - pop edi - pop esi - ret -.cleanup: - stdcall kernel_free, [file] -.fail: - xor eax, eax - xor ebx, ebx - pop edi - pop esi - ret -endp - -align 4 -proc get_proc_ex stdcall, proc_name:dword, imports:dword - -.look_up: - mov edx, [imports] - test edx, edx - jz .end - mov edx, [edx] - test edx, edx - jz .end -.next: - mov eax, [edx] - test eax, eax - jz .next_table - - push edx - stdcall strncmp, eax, [proc_name], 256 - pop edx - test eax, eax - jz .ok - - add edx,8 - jmp .next -.next_table: - add [imports], 4 - jmp .look_up -.ok: - mov eax, [edx+4] - ret -.end: - xor eax, eax - ret -endp - -align 4 -proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\ - sym_count:dword, strings:dword, imports:dword - locals - retval dd ? - endl - - mov edi, [symbols] - mov [retval], 1 -.fix: - movzx ebx, [edi+CSYM.SectionNumber] - test ebx, ebx - jnz .internal - mov eax, dword [edi+CSYM.Name] - test eax, eax - jnz @F - - mov edi, [edi+4] - add edi, [strings] -@@: - push edi - stdcall get_proc_ex, edi,[imports] - pop edi - - xor ebx, ebx - test eax, eax - jnz @F - - mov esi, msg_unresolved - call sys_msg_board_str - mov esi, edi - call sys_msg_board_str - mov esi, msg_CR - call sys_msg_board_str - - mov [retval],0 -@@: - mov edi, [symbols] - mov [edi+CSYM.Value], eax - jmp .next -.internal: - cmp bx, -1 - je .next - cmp bx, -2 - je .next - - dec ebx - shl ebx, 3 - lea ebx, [ebx+ebx*4] - add ebx, [sec] - - mov eax, [ebx+CFS.VirtualAddress] - add [edi+CSYM.Value], eax -.next: - add edi, CSYM_SIZE - mov [symbols], edi - dec [sym_count] - jnz .fix - mov eax, [retval] - ret -endp - -align 4 -proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \ - delta:dword - locals - n_sec dd ? - endl - - mov eax, [coff] - movzx ebx, [eax+CFH.nSections] - mov [n_sec], ebx - lea esi, [eax+20] -.fix_sec: - mov edi, [esi+CFS.PtrReloc] - add edi, [coff] - - movzx ecx, [esi+CFS.NumReloc] - test ecx, ecx - jz .next -.reloc_loop: - mov ebx, [edi+CRELOC.SymIndex] - add ebx,ebx - lea ebx,[ebx+ebx*8] - add ebx, [sym] - - mov edx, [ebx+CSYM.Value] - - cmp [edi+CRELOC.Type], 6 - je .dir_32 - - cmp [edi+CRELOC.Type], 20 - jne .next_reloc -.rel_32: - mov eax, [edi+CRELOC.VirtualAddress] - add eax, [esi+CFS.VirtualAddress] - sub edx, eax - sub edx, 4 - jmp .fix -.dir_32: - mov eax, [edi+CRELOC.VirtualAddress] - add eax, [esi+CFS.VirtualAddress] -.fix: - add eax, [delta] - add [eax], edx -.next_reloc: - add edi, 10 - dec ecx - jnz .reloc_loop -.next: - add esi, COFF_SECTION_SIZE - dec [n_sec] - jnz .fix_sec -.exit: - ret -endp - -align 4 -proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \ - delta:dword - locals - n_sec dd ? - endl - - mov eax, [coff] - movzx ebx, [eax+CFH.nSections] - mov [n_sec], ebx - lea esi, [eax+20] - mov edx, [delta] -.fix_sec: - mov edi, [esi+CFS.PtrReloc] - add edi, [coff] - - movzx ecx, [esi+CFS.NumReloc] - test ecx, ecx - jz .next -.reloc_loop: - cmp [edi+CRELOC.Type], 6 - jne .next_reloc -.dir_32: - mov eax, [edi+CRELOC.VirtualAddress] - add eax, [esi+CFS.VirtualAddress] - add [eax+edx], edx -.next_reloc: - add edi, 10 - dec ecx - jnz .reloc_loop -.next: - add esi, COFF_SECTION_SIZE - dec [n_sec] - jnz .fix_sec -.exit: - ret -endp - -align 4 -proc load_driver stdcall, driver_name:dword - locals - coff dd ? - sym dd ? - strings dd ? - img_size dd ? - img_base dd ? - start dd ? - - exports dd ? ;fake exports table - dd ? - file_name rb 13+16+4+1 ; '/sys/drivers/.obj' - endl - - lea edx, [file_name] - mov dword [edx], '/sys' - mov dword [edx+4], '/dri' - mov dword [edx+8], 'vers' - mov byte [edx+12], '/' - mov esi, [driver_name] -.redo: - lea edx, [file_name] - lea edi, [edx+13] - mov ecx, 16 -@@: - lodsb - test al, al - jz @f - stosb - loop @b -@@: - mov dword [edi], '.obj' - mov byte [edi+4], 0 - stdcall load_file, edx - - test eax, eax - jz .exit - - mov [coff], eax - - movzx ecx, [eax+CFH.nSections] - xor ebx, ebx - - lea edx, [eax+20] -@@: - add ebx, [edx+CFS.SizeOfRawData] - add ebx, 15 - and ebx, not 15 - add edx, COFF_SECTION_SIZE - dec ecx - jnz @B - mov [img_size], ebx - - stdcall kernel_alloc, ebx - test eax, eax - jz .fail - mov [img_base], eax - - mov edi, eax - xor eax, eax - mov ecx, [img_size] - add ecx, 4095 - and ecx, not 4095 - shr ecx, 2 - cld - rep stosd - - mov edx, [coff] - movzx ebx, [edx+CFH.nSections] - mov edi, [img_base] - lea eax, [edx+20] -@@: - mov [eax+CFS.VirtualAddress], edi - mov esi, [eax+CFS.PtrRawData] - test esi, esi - jnz .copy - add edi, [eax+CFS.SizeOfRawData] - jmp .next -.copy: - add esi, edx - mov ecx, [eax+CFS.SizeOfRawData] - cld - rep movsb -.next: - add edi, 15 - and edi, not 15 - add eax, COFF_SECTION_SIZE - dec ebx - jnz @B - - mov ebx, [edx+CFH.pSymTable] - add ebx, edx - mov [sym], ebx - mov ecx, [edx+CFH.nSymbols] - add ecx,ecx - lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE - add ecx, [sym] - mov [strings], ecx - - lea ebx, [exports] - mov dword [ebx], kernel_export - mov dword [ebx+4], 0 - lea eax, [edx+20] - - stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\ - [strings], ebx - test eax, eax - jz .link_fail - - mov ebx, [coff] - stdcall fix_coff_relocs, ebx, [sym], 0 - - stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szVersion - test eax, eax - jz .link_fail - - mov eax, [eax] - shr eax, 16 - cmp eax, DRV_COMPAT - jb .ver_fail - - cmp eax, DRV_CURRENT - ja .ver_fail - - mov ebx, [coff] - stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szSTART - mov [start], eax - - stdcall kernel_free, [coff] - - mov ebx, [start] - stdcall ebx, DRV_ENTRY - test eax, eax - jnz .ok - - stdcall kernel_free, [img_base] - cmp dword [file_name+13], 'SOUN' - jnz @f - cmp dword [file_name+17], 'D.ob' - jnz @f - cmp word [file_name+21], 'j' - jnz @f - mov esi, aSis - jmp .redo -@@: - xor eax, eax - ret -.ok: - mov ebx, [img_base] - mov [eax+SRV.base], ebx - mov ecx, [start] - mov [eax+SRV.entry], ecx - ret - -.ver_fail: - mov esi, msg_CR - call sys_msg_board_str - mov esi, [driver_name] - call sys_msg_board_str - mov esi, msg_CR - call sys_msg_board_str - mov esi, msg_version - call sys_msg_board_str - mov esi, msg_www - call sys_msg_board_str - jmp .cleanup - -.link_fail: - mov esi, msg_module - call sys_msg_board_str - mov esi, [driver_name] - call sys_msg_board_str - mov esi, msg_CR - call sys_msg_board_str -.cleanup: - stdcall kernel_free,[img_base] -.fail: - stdcall kernel_free, [coff] -.exit: - xor eax, eax - ret -endp - -; in: edx -> COFF_SECTION struct -; out: eax = alignment as mask for bits to drop -coff_get_align: -; Rules: -; - if alignment is not given, use default = 4K; -; - if alignment is given and is no more than 4K, use it; -; - if alignment is more than 4K, revert to 4K. - push ecx - mov cl, byte [edx+CFS.Characteristics+2] - mov eax, 1 - shr cl, 4 - dec cl - js .default - cmp cl, 12 - jbe @f -.default: - mov cl, 12 -@@: - shl eax, cl - pop ecx - dec eax - ret - -align 4 -proc load_library stdcall, file_name:dword - locals - fullname rb 260 - fileinfo rb 40 - coff dd ? - img_base dd ? - endl - - cli - -; resolve file name - mov ebx, [file_name] - lea edi, [fullname+1] - mov byte [edi-1], '/' - stdcall get_full_file_name, edi, 259 - test al, al - jz .fail - -; scan for required DLL in list of already loaded for this process, -; ignore timestamp - mov esi, [CURRENT_TASK] - shl esi, 8 - lea edi, [fullname] - mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr] - test ebx, ebx - jz .not_in_process - mov esi, [ebx+HDLL.fd] -.scan_in_process: - cmp esi, ebx - jz .not_in_process - mov eax, [esi+HDLL.parent] - add eax, DLLDESCR.name - stdcall strncmp, eax, edi, -1 - test eax, eax - jnz .next_in_process -; simple variant: load DLL which is already loaded in this process -; just increment reference counters and return address of exports table - inc [esi+HDLL.refcount] - mov ecx, [esi+HDLL.parent] - inc [ecx+DLLDESCR.refcount] - mov eax, [ecx+DLLDESCR.exports] - sub eax, [ecx+DLLDESCR.defaultbase] - add eax, [esi+HDLL.base] - ret -.next_in_process: - mov esi, [esi+HDLL.fd] - jmp .scan_in_process -.not_in_process: - -; scan in full list, compare timestamp - lea eax, [fileinfo] - stdcall get_fileinfo, edi, eax - test eax, eax - jnz .fail - mov esi, [dll_list.fd] -.scan_for_dlls: - cmp esi, dll_list - jz .load_new - lea eax, [esi+DLLDESCR.name] - stdcall strncmp, eax, edi, -1 - test eax, eax - jnz .continue_scan -.test_prev_dll: - mov eax, dword [fileinfo+24] ; last modified time - mov edx, dword [fileinfo+28] ; last modified date - cmp dword [esi+DLLDESCR.timestamp], eax - jnz .continue_scan - cmp dword [esi+DLLDESCR.timestamp+4], edx - jz .dll_already_loaded -.continue_scan: - mov esi, [esi+DLLDESCR.fd] - jmp .scan_for_dlls - -; new DLL -.load_new: -; load file - stdcall load_file, edi - test eax, eax - jz .fail - mov [coff], eax - mov dword [fileinfo+32], ebx - -; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name - mov esi, edi - mov ecx, -1 - xor eax, eax - repnz scasb - not ecx - lea eax, [ecx+DLLDESCR.sizeof] - push ecx - call malloc - pop ecx - test eax, eax - jz .fail_and_free_coff -; save timestamp - lea edi, [eax+DLLDESCR.name] - rep movsb - mov esi, eax - mov eax, dword [fileinfo+24] - mov dword [esi+DLLDESCR.timestamp], eax - mov eax, dword [fileinfo+28] - mov dword [esi+DLLDESCR.timestamp+4], eax -; initialize DLLDESCR struct - and dword [esi+DLLDESCR.refcount], 0 ; no HDLLs yet; later it will be incremented - mov [esi+DLLDESCR.fd], dll_list - mov eax, [dll_list.bk] - mov [dll_list.bk], esi - mov [esi+DLLDESCR.bk], eax - mov [eax+DLLDESCR.fd], esi - -; calculate size of loaded DLL - mov edx, [coff] - movzx ecx, [edx+CFH.nSections] - xor ebx, ebx - - add edx, 20 -@@: - call coff_get_align - add ebx, eax - not eax - and ebx, eax - add ebx, [edx+CFS.SizeOfRawData] - add edx, COFF_SECTION_SIZE - dec ecx - jnz @B -; it must be nonzero and not too big - mov [esi+DLLDESCR.size], ebx - test ebx, ebx - jz .fail_and_free_dll - cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR - ja .fail_and_free_dll -; allocate memory for kernel-side image - stdcall kernel_alloc, ebx - test eax, eax - jz .fail_and_free_dll - mov [esi+DLLDESCR.data], eax -; calculate preferred base address - add ebx, 0x1FFF - and ebx, not 0xFFF - mov ecx, [dll_cur_addr] - lea edx, [ecx+ebx] - cmp edx, MAX_DEFAULT_DLL_ADDR - jb @f - mov ecx, MIN_DEFAULT_DLL_ADDR - lea edx, [ecx+ebx] -@@: - mov [esi+DLLDESCR.defaultbase], ecx - mov [dll_cur_addr], edx - -; copy sections and set correct values for VirtualAddress'es in headers - push esi - mov edx, [coff] - movzx ebx, [edx+CFH.nSections] - mov edi, eax - add edx, 20 - cld -@@: - call coff_get_align - add ecx, eax - add edi, eax - not eax - and ecx, eax - and edi, eax - mov [edx+CFS.VirtualAddress], ecx - add ecx, [edx+CFS.SizeOfRawData] - mov esi, [edx+CFS.PtrRawData] - push ecx - mov ecx, [edx+CFS.SizeOfRawData] - test esi, esi - jnz .copy - xor eax, eax - rep stosb - jmp .next -.copy: - add esi, [coff] - rep movsb -.next: - pop ecx - add edx, COFF_SECTION_SIZE - dec ebx - jnz @B - pop esi - -; save some additional data from COFF file -; later we will use COFF header, headers for sections and symbol table -; and also relocations table for all sections - mov edx, [coff] - mov ebx, [edx+CFH.pSymTable] - mov edi, dword [fileinfo+32] - sub edi, ebx - jc .fail_and_free_data - mov [esi+DLLDESCR.symbols_lim], edi - add ebx, edx - movzx ecx, [edx+CFH.nSections] - lea ecx, [ecx*5] - lea edi, [edi+ecx*8+20] - add edx, 20 -@@: - movzx eax, [edx+CFS.NumReloc] - lea eax, [eax*5] - lea edi, [edi+eax*2] - add edx, COFF_SECTION_SIZE - sub ecx, 5 - jnz @b - stdcall kernel_alloc, edi - test eax, eax - jz .fail_and_free_data - mov edx, [coff] - movzx ecx, [edx+CFH.nSections] - lea ecx, [ecx*5] - lea ecx, [ecx*2+5] - mov [esi+DLLDESCR.coff_hdr], eax - push esi - mov esi, edx - mov edi, eax - rep movsd - pop esi - mov [esi+DLLDESCR.symbols_ptr], edi - push esi - mov ecx, [edx+CFH.nSymbols] - mov [esi+DLLDESCR.symbols_num], ecx - mov ecx, [esi+DLLDESCR.symbols_lim] - mov esi, ebx - rep movsb - pop esi - mov ebx, [esi+DLLDESCR.coff_hdr] - push esi - movzx eax, [edx+CFH.nSections] - lea edx, [ebx+20] -@@: - movzx ecx, [edx+CFS.NumReloc] - lea ecx, [ecx*5] - mov esi, [edx+CFS.PtrReloc] - mov [edx+CFS.PtrReloc], edi - sub [edx+CFS.PtrReloc], ebx - add esi, [coff] - shr ecx, 1 - rep movsd - adc ecx, ecx - rep movsw - add edx, COFF_SECTION_SIZE - dec eax - jnz @b - pop esi - -; fixup symbols - mov edx, ebx - mov eax, [ebx+CFH.nSymbols] - add edx, 20 - mov ecx, [esi+DLLDESCR.symbols_num] - lea ecx, [ecx*9] - add ecx, ecx - add ecx, [esi+DLLDESCR.symbols_ptr] - - stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax,\ - ecx, 0 -; test eax, eax -; jnz @F -; -;@@: - - stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],szEXPORTS - test eax, eax - jnz @F - - stdcall get_coff_sym,[esi+DLLDESCR.symbols_ptr],[ebx+CFH.nSymbols],sz_EXPORTS -@@: - mov [esi+DLLDESCR.exports], eax - -; fix relocs in the hidden copy in kernel memory to default address -; it is first fix; usually this will be enough, but second fix -; can be necessary if real load address will not equal assumption - mov eax, [esi+DLLDESCR.data] - sub eax, [esi+DLLDESCR.defaultbase] - stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax - - stdcall kernel_free, [coff] - -.dll_already_loaded: - inc [esi+DLLDESCR.refcount] - push esi - call init_heap - pop esi - - mov edi, [esi+DLLDESCR.size] - stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi - test eax, eax - jnz @f - stdcall user_alloc, edi - test eax, eax - jz .fail_and_dereference -@@: - mov [img_base], eax - mov eax, HDLL.sizeof - call malloc - test eax, eax - jz .fail_and_free_user - mov ebx, [CURRENT_TASK] - shl ebx, 5 - mov edx, [CURRENT_TASK+ebx+TASKDATA.pid] - mov [eax+HDLL.pid], edx - push eax - call init_dlls_in_thread - pop ebx - test eax, eax - jz .fail_and_free_user - mov edx, [eax+HDLL.fd] - mov [ebx+HDLL.fd], edx - mov [ebx+HDLL.bk], eax - mov [eax+HDLL.fd], ebx - mov [edx+HDLL.bk], ebx - mov eax, ebx - mov ebx, [img_base] - mov [eax+HDLL.base], ebx - mov [eax+HDLL.size], edi - mov [eax+HDLL.refcount], 1 - mov [eax+HDLL.parent], esi - mov edx, ebx - shr edx, 12 - or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK -; copy entries of page table from kernel-side image to usermode -; use copy-on-write for user-mode image, so map as readonly - xor edi, edi - mov ecx, [esi+DLLDESCR.data] - shr ecx, 12 -.map_pages_loop: - mov eax, [page_tabs+ecx*4] - and eax, not 0xFFF - or al, PG_USER - xchg eax, [page_tabs+edx*4] - test al, 1 - jz @f - call free_page -@@: - invlpg [ebx+edi] - inc ecx - inc edx - add edi, 0x1000 - cmp edi, [esi+DLLDESCR.size] - jb .map_pages_loop - -; if real user-mode base is not equal to preferred base, relocate image - sub ebx, [esi+DLLDESCR.defaultbase] - jz @f - stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx -@@: - - mov eax, [esi+DLLDESCR.exports] - sub eax, [esi+DLLDESCR.defaultbase] - add eax, [img_base] - ret -.fail_and_free_data: - stdcall kernel_free, [esi+DLLDESCR.data] -.fail_and_free_dll: - mov eax, esi - call free -.fail_and_free_coff: - stdcall kernel_free, [coff] -.fail: - xor eax, eax - ret -.fail_and_free_user: - stdcall user_free, [img_base] -.fail_and_dereference: - mov eax, 1 ; delete 1 reference - call dereference_dll - xor eax, eax - ret -endp - -; initialize [APPDATA.dlls_list_ptr] for given thread -; DLL is per-process object, so APPDATA.dlls_list_ptr must be -; kept in sync for all threads of one process. -; out: eax = APPDATA.dlls_list_ptr if all is OK, -; NULL if memory allocation failed -init_dlls_in_thread: - mov ebx, [current_slot] - mov eax, [ebx+APPDATA.dlls_list_ptr] - test eax, eax - jnz .ret - push [ebx+APPDATA.dir_table] - mov eax, 8 - call malloc - pop edx - test eax, eax - jz .ret - mov [eax], eax - mov [eax+4], eax - mov ecx, [TASK_COUNT] - mov ebx, SLOT_BASE+256 -.set: - cmp [ebx+APPDATA.dir_table], edx - jnz @f - mov [ebx+APPDATA.dlls_list_ptr], eax -@@: - add ebx, 256 - dec ecx - jnz .set -.ret: - ret - -; in: eax = number of references to delete, esi -> DLLDESCR struc -dereference_dll: - sub [esi+DLLDESCR.refcount], eax - jnz .ret - mov eax, [esi+DLLDESCR.fd] - mov edx, [esi+DLLDESCR.bk] - mov [eax+DLLDESCR.bk], edx - mov [edx+DLLDESCR.fd], eax - stdcall kernel_free, [esi+DLLDESCR.coff_hdr] - stdcall kernel_free, [esi+DLLDESCR.data] - mov eax, esi - call free -.ret: - ret - -destroy_hdll: - push ebx ecx esi edi - push eax - mov ebx, [eax+HDLL.base] - mov esi, [eax+HDLL.parent] - mov edx, [esi+DLLDESCR.size] -; The following actions require the context of application where HDLL is mapped. -; However, destroy_hdll can be called in the context of OS thread when -; cleaning up objects created by the application which is destroyed. -; So remember current cr3 and set it to page table of target. - mov eax, [ecx+APPDATA.dir_table] -; Because we cheat with cr3, disable interrupts: task switch would restore -; page table from APPDATA of current thread. -; Also set [current_slot] because it is used by user_free. - pushf - cli - push [current_slot] - mov [current_slot], ecx - mov ecx, cr3 - push ecx - mov cr3, eax - push ebx ; argument for user_free - mov eax, ebx - shr ebx, 12 - push ebx - mov esi, [esi+DLLDESCR.data] - shr esi, 12 -.unmap_loop: - push eax - mov eax, 2 - xchg eax, [page_tabs+ebx*4] - mov ecx, [page_tabs+esi*4] - and eax, not 0xFFF - and ecx, not 0xFFF - cmp eax, ecx - jz @f - call free_page -@@: - pop eax - invlpg [eax] - add eax, 0x1000 - inc ebx - inc esi - sub edx, 0x1000 - ja .unmap_loop - pop ebx - and dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK - call user_free -; Restore context. - pop eax - mov cr3, eax - pop [current_slot] - popf -; Ok, cheating is done. - pop eax - push eax - mov esi, [eax+HDLL.parent] - mov eax, [eax+HDLL.refcount] - call dereference_dll - pop eax - mov edx, [eax+HDLL.bk] - mov ebx, [eax+HDLL.fd] - mov [ebx+HDLL.bk], edx - mov [edx+HDLL.fd], ebx - call free - pop edi esi ecx ebx - ret - -; ecx -> APPDATA for slot, esi = dlls_list_ptr -destroy_all_hdlls: - test esi, esi - jz .ret -.loop: - mov eax, [esi+HDLL.fd] - cmp eax, esi - jz free - call destroy_hdll - jmp .loop -.ret: - ret - -align 4 -stop_all_services: - push ebp - mov edx, [srv.fd] -.next: - cmp edx, srv.fd-SRV_FD_OFFSET - je .done - cmp [edx+SRV.magic], ' SRV' - jne .next - cmp [edx+SRV.size], SRV.sizeof - jne .next - - mov ebx, [edx+SRV.entry] - mov edx, [edx+SRV.fd] - test ebx, ebx - jz .next - - push edx - mov ebp, esp - push 0 - push -1 - call ebx - mov esp, ebp - pop edx - jmp .next -.done: - pop ebp - ret - -; param -; eax= size -; ebx= pid - -align 4 -create_kernel_object: - - push ebx - call malloc - pop ebx - test eax, eax - jz .fail - - mov ecx,[current_slot] - add ecx, APP_OBJ_OFFSET - - pushfd - cli - mov edx, [ecx+APPOBJ.fd] - mov [eax+APPOBJ.fd], edx - mov [eax+APPOBJ.bk], ecx - mov [eax+APPOBJ.pid], ebx - - mov [ecx+APPOBJ.fd], eax - mov [edx+APPOBJ.bk], eax - popfd -.fail: - ret - -; param -; eax= object - -align 4 -destroy_kernel_object: - - pushfd - cli - mov ebx, [eax+APPOBJ.fd] - mov ecx, [eax+APPOBJ.bk] - mov [ebx+APPOBJ.bk], ecx - mov [ecx+APPOBJ.fd], ebx - popfd - - xor edx, edx ;clear common header - mov [eax], edx - mov [eax+4], edx - mov [eax+8], edx - mov [eax+12], edx - mov [eax+16], edx - - call free ;release object memory - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +DRV_COMPAT equ 5 ;minimal required drivers version +DRV_CURRENT equ 6 ;current drivers model version + +DRV_VERSION equ (DRV_COMPAT shl 16) or DRV_CURRENT +PID_KERNEL equ 1 ;os_idle thread + + + +align 4 +proc get_notify stdcall, p_ev:dword + +.wait: + mov ebx, [current_slot] + test dword [ebx+APPDATA.event_mask], EVENT_NOTIFY + jz @f + and dword [ebx+APPDATA.event_mask], not EVENT_NOTIFY + mov edi, [p_ev] + mov dword [edi], EV_INTR + mov eax, [ebx+APPDATA.event] + mov dword [edi+4], eax + ret +@@: + call change_task + jmp .wait +endp + +align 4 +proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword + push ebx + xor eax, eax + xor ebx, ebx + mov ah, byte [bus] + mov al, 6 + mov bh, byte [devfn] + mov bl, byte [reg] + call pci_read_reg + pop ebx + ret +endp + +align 4 +proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword + push ebx + xor eax, eax + xor ebx, ebx + mov ah, byte [bus] + mov al, 5 + mov bh, byte [devfn] + mov bl, byte [reg] + call pci_read_reg + pop ebx + ret +endp + +align 4 +proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword + push ebx + xor eax, eax + xor ebx, ebx + mov ah, byte [bus] + mov al, 4 + mov bh, byte [devfn] + mov bl, byte [reg] + call pci_read_reg + pop ebx + ret +endp + +align 4 +proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword + push ebx + xor eax, eax + xor ebx, ebx + mov ah, byte [bus] + mov al, 8 + mov bh, byte [devfn] + mov bl, byte [reg] + mov ecx, [val] + call pci_write_reg + pop ebx + ret +endp + +align 4 +proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword + push ebx + xor eax, eax + xor ebx, ebx + mov ah, byte [bus] + mov al, 9 + mov bh, byte [devfn] + mov bl, byte [reg] + mov ecx, [val] + call pci_write_reg + pop ebx + ret +endp + +align 4 +proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword + push ebx + xor eax, eax + xor ebx, ebx + mov ah, byte [bus] + mov al, 10 + mov bh, byte [devfn] + mov bl, byte [reg] + mov ecx, [val] + call pci_write_reg + pop ebx + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + + +align 4 +proc srv_handler stdcall, ioctl:dword + mov esi, [ioctl] + test esi, esi + jz .err + + mov edi, [esi+handle] + cmp [edi+SRV.magic], ' SRV' + jne .fail + + cmp [edi+SRV.size], SRV.sizeof + jne .fail + + stdcall [edi+SRV.srv_proc], esi + ret +.fail: + xor eax, eax + not eax + mov [esi+output], eax + mov [esi+out_size], 4 + ret +.err: + xor eax, eax + not eax + ret +endp + +; param +; ecx= io_control +; +; retval +; eax= error code + +align 4 +srv_handlerEx: + cmp ecx, OS_BASE + jae .fail + + mov eax, [ecx+handle] + cmp [eax+SRV.magic], ' SRV' + jne .fail + + cmp [eax+SRV.size], SRV.sizeof + jne .fail + + stdcall [eax+SRV.srv_proc], ecx + ret +.fail: + or eax, -1 + ret + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +align 4 +proc get_service stdcall, sz_name:dword + mov eax, [sz_name] + test eax, eax + jnz @F + ret +@@: + mov edx, [srv.fd] +@@: + cmp edx, srv.fd-SRV_FD_OFFSET + je .not_load + + stdcall strncmp, edx, [sz_name], 16 + test eax, eax + je .ok + + mov edx, [edx+SRV.fd] + jmp @B +.not_load: + pop ebp + jmp load_driver +.ok: + mov eax, edx + ret +endp + +align 4 +proc reg_service stdcall, name:dword, handler:dword + + push ebx + + xor eax, eax + + cmp [name], eax + je .fail + + cmp [handler], eax + je .fail + + mov eax, SRV.sizeof + call malloc + test eax, eax + jz .fail + + push esi + push edi + mov edi, eax + mov esi, [name] + movsd + movsd + movsd + movsd + pop edi + pop esi + + mov [eax+SRV.magic], ' SRV' + mov [eax+SRV.size], SRV.sizeof + + mov ebx, srv.fd-SRV_FD_OFFSET + mov edx, [ebx+SRV.fd] + mov [eax+SRV.fd], edx + mov [eax+SRV.bk], ebx + mov [ebx+SRV.fd], eax + mov [edx+SRV.bk], eax + + mov ecx, [handler] + mov [eax+SRV.srv_proc], ecx + pop ebx + ret +.fail: + xor eax, eax + pop ebx + ret +endp + +align 4 +proc get_proc stdcall, exp:dword, sz_name:dword + + mov edx, [exp] +.next: + mov eax, [edx] + test eax, eax + jz .end + + push edx + stdcall strncmp, eax, [sz_name], 16 + pop edx + test eax, eax + jz .ok + + add edx, 8 + jmp .next +.ok: + mov eax, [edx+4] +.end: + ret +endp + +align 4 +proc get_coff_sym stdcall, pSym:dword,count:dword, sz_sym:dword + +@@: + stdcall strncmp, [pSym], [sz_sym], 8 + test eax, eax + jz .ok + add [pSym], 18 + dec [count] + jnz @b + xor eax, eax + ret +.ok: + mov eax, [pSym] + mov eax, [eax+8] + ret +endp + +align 4 +proc get_curr_task + mov eax, [CURRENT_TASK] + shl eax, 8 + ret +endp + +align 4 +proc get_fileinfo stdcall, file_name:dword, info:dword + locals + cmd dd ? + offset dd ? + dd ? + count dd ? + buff dd ? + db ? + name dd ? + endl + + xor eax, eax + mov ebx, [file_name] + mov ecx, [info] + + mov [cmd], 5 + mov [offset], eax + mov [offset+4], eax + mov [count], eax + mov [buff], ecx + mov byte [buff+4], al + mov [name], ebx + + mov eax, 70 + lea ebx, [cmd] + int 0x40 + ret +endp + +align 4 +proc read_file stdcall,file_name:dword, buffer:dword, off:dword,\ + bytes:dword + locals + cmd dd ? + offset dd ? + dd ? + count dd ? + buff dd ? + db ? + name dd ? + endl + + xor eax, eax + mov ebx, [file_name] + mov ecx, [off] + mov edx, [bytes] + mov esi, [buffer] + + mov [cmd], eax + mov [offset], ecx + mov [offset+4], eax + mov [count], edx + mov [buff], esi + mov byte [buff+4], al + mov [name], ebx + + pushad + lea ebx, [cmd] + call file_system_lfn + popad + ret +endp + +; description +; allocate kernel memory and loads the specified file +; +; param +; file_name= full path to file +; +; retval +; eax= file image in kernel memory +; ebx= size of file +; +; warging +; You mast call kernel_free() to delete each file +; loaded by the load_file() function + +align 4 +proc load_file stdcall, file_name:dword + locals + attr dd ? + flags dd ? + cr_time dd ? + cr_date dd ? + acc_time dd ? + acc_date dd ? + mod_time dd ? + mod_date dd ? + file_size dd ? + + file dd ? + file2 dd ? + endl + + push esi + push edi + + lea eax, [attr] + stdcall get_fileinfo, [file_name], eax + test eax, eax + jnz .fail + + mov eax, [file_size] + cmp eax, 1024*1024*16 + ja .fail + + stdcall kernel_alloc, [file_size] + mov [file], eax + test eax, eax + jz .fail + + stdcall read_file, [file_name], eax, dword 0, [file_size] + cmp ebx, [file_size] + jne .cleanup + + mov eax, [file] + cmp dword [eax], 0x4B43504B + jne .exit + mov ebx, [eax+4] + mov [file_size], ebx + stdcall kernel_alloc, ebx + + test eax, eax + jz .cleanup + + mov [file2], eax + pushfd + cli + stdcall unpack, [file], eax + popfd + stdcall kernel_free, [file] + mov eax, [file2] + mov ebx, [file_size] +.exit: + push eax + lea edi, [eax+ebx] ;cleanup remain space + mov ecx, 4096 ;from file end + and ebx, 4095 + jz @f + sub ecx, ebx + xor eax, eax + cld + rep stosb +@@: + mov ebx, [file_size] + pop eax + pop edi + pop esi + ret +.cleanup: + stdcall kernel_free, [file] +.fail: + xor eax, eax + xor ebx, ebx + pop edi + pop esi + ret +endp + +align 4 +proc get_proc_ex stdcall, proc_name:dword, imports:dword + +.look_up: + mov edx, [imports] + test edx, edx + jz .end + mov edx, [edx] + test edx, edx + jz .end +.next: + mov eax, [edx] + test eax, eax + jz .next_table + + push edx + stdcall strncmp, eax, [proc_name], 256 + pop edx + test eax, eax + jz .ok + + add edx, 8 + jmp .next +.next_table: + add [imports], 4 + jmp .look_up +.ok: + mov eax, [edx+4] + ret +.end: + xor eax, eax + ret +endp + +align 4 +proc fix_coff_symbols stdcall uses ebx esi, sec:dword, symbols:dword,\ + sym_count:dword, strings:dword, imports:dword + locals + retval dd ? + endl + + mov edi, [symbols] + mov [retval], 1 +.fix: + movzx ebx, [edi+CSYM.SectionNumber] + test ebx, ebx + jnz .internal + mov eax, dword [edi+CSYM.Name] + test eax, eax + jnz @F + + mov edi, [edi+4] + add edi, [strings] +@@: + push edi + stdcall get_proc_ex, edi, [imports] + pop edi + + xor ebx, ebx + test eax, eax + jnz @F + + mov esi, msg_unresolved + call sys_msg_board_str + mov esi, edi + call sys_msg_board_str + mov esi, msg_CR + call sys_msg_board_str + + mov [retval], 0 +@@: + mov edi, [symbols] + mov [edi+CSYM.Value], eax + jmp .next +.internal: + cmp bx, -1 + je .next + cmp bx, -2 + je .next + + dec ebx + shl ebx, 3 + lea ebx, [ebx+ebx*4] + add ebx, [sec] + + mov eax, [ebx+CFS.VirtualAddress] + add [edi+CSYM.Value], eax +.next: + add edi, CSYM_SIZE + mov [symbols], edi + dec [sym_count] + jnz .fix + mov eax, [retval] + ret +endp + +align 4 +proc fix_coff_relocs stdcall uses ebx esi, coff:dword, sym:dword, \ + delta:dword + locals + n_sec dd ? + endl + + mov eax, [coff] + movzx ebx, [eax+CFH.nSections] + mov [n_sec], ebx + lea esi, [eax+20] +.fix_sec: + mov edi, [esi+CFS.PtrReloc] + add edi, [coff] + + movzx ecx, [esi+CFS.NumReloc] + test ecx, ecx + jz .next +.reloc_loop: + mov ebx, [edi+CRELOC.SymIndex] + add ebx, ebx + lea ebx, [ebx+ebx*8] + add ebx, [sym] + + mov edx, [ebx+CSYM.Value] + + cmp [edi+CRELOC.Type], 6 + je .dir_32 + + cmp [edi+CRELOC.Type], 20 + jne .next_reloc +.rel_32: + mov eax, [edi+CRELOC.VirtualAddress] + add eax, [esi+CFS.VirtualAddress] + sub edx, eax + sub edx, 4 + jmp .fix +.dir_32: + mov eax, [edi+CRELOC.VirtualAddress] + add eax, [esi+CFS.VirtualAddress] +.fix: + add eax, [delta] + add [eax], edx +.next_reloc: + add edi, 10 + dec ecx + jnz .reloc_loop +.next: + add esi, COFF_SECTION_SIZE + dec [n_sec] + jnz .fix_sec +.exit: + ret +endp + +align 4 +proc rebase_coff stdcall uses ebx esi, coff:dword, sym:dword, \ + delta:dword + locals + n_sec dd ? + endl + + mov eax, [coff] + movzx ebx, [eax+CFH.nSections] + mov [n_sec], ebx + lea esi, [eax+20] + mov edx, [delta] +.fix_sec: + mov edi, [esi+CFS.PtrReloc] + add edi, [coff] + + movzx ecx, [esi+CFS.NumReloc] + test ecx, ecx + jz .next +.reloc_loop: + cmp [edi+CRELOC.Type], 6 + jne .next_reloc +.dir_32: + mov eax, [edi+CRELOC.VirtualAddress] + add eax, [esi+CFS.VirtualAddress] + add [eax+edx], edx +.next_reloc: + add edi, 10 + dec ecx + jnz .reloc_loop +.next: + add esi, COFF_SECTION_SIZE + dec [n_sec] + jnz .fix_sec +.exit: + ret +endp + +align 4 +proc load_driver stdcall, driver_name:dword + locals + coff dd ? + sym dd ? + strings dd ? + img_size dd ? + img_base dd ? + start dd ? + + exports dd ? ;fake exports table + dd ? + file_name rb 13+16+4+1 ; '/sys/drivers/.obj' + endl + + lea edx, [file_name] + mov dword [edx], '/sys' + mov dword [edx+4], '/dri' + mov dword [edx+8], 'vers' + mov byte [edx+12], '/' + mov esi, [driver_name] +.redo: + lea edx, [file_name] + lea edi, [edx+13] + mov ecx, 16 +@@: + lodsb + test al, al + jz @f + stosb + loop @b +@@: + mov dword [edi], '.obj' + mov byte [edi+4], 0 + stdcall load_file, edx + + test eax, eax + jz .exit + + mov [coff], eax + + movzx ecx, [eax+CFH.nSections] + xor ebx, ebx + + lea edx, [eax+20] +@@: + add ebx, [edx+CFS.SizeOfRawData] + add ebx, 15 + and ebx, not 15 + add edx, COFF_SECTION_SIZE + dec ecx + jnz @B + mov [img_size], ebx + + stdcall kernel_alloc, ebx + test eax, eax + jz .fail + mov [img_base], eax + + mov edi, eax + xor eax, eax + mov ecx, [img_size] + add ecx, 4095 + and ecx, not 4095 + shr ecx, 2 + cld + rep stosd + + mov edx, [coff] + movzx ebx, [edx+CFH.nSections] + mov edi, [img_base] + lea eax, [edx+20] +@@: + mov [eax+CFS.VirtualAddress], edi + mov esi, [eax+CFS.PtrRawData] + test esi, esi + jnz .copy + add edi, [eax+CFS.SizeOfRawData] + jmp .next +.copy: + add esi, edx + mov ecx, [eax+CFS.SizeOfRawData] + cld + rep movsb +.next: + add edi, 15 + and edi, not 15 + add eax, COFF_SECTION_SIZE + dec ebx + jnz @B + + mov ebx, [edx+CFH.pSymTable] + add ebx, edx + mov [sym], ebx + mov ecx, [edx+CFH.nSymbols] + add ecx, ecx + lea ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE + add ecx, [sym] + mov [strings], ecx + + lea ebx, [exports] + mov dword [ebx], kernel_export + mov dword [ebx+4], 0 + lea eax, [edx+20] + + stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols], \ + [strings], ebx + test eax, eax + jz .link_fail + + mov ebx, [coff] + stdcall fix_coff_relocs, ebx, [sym], 0 + + stdcall get_coff_sym, [sym], [ebx+CFH.nSymbols], szVersion + test eax, eax + jz .link_fail + + mov eax, [eax] + shr eax, 16 + cmp eax, DRV_COMPAT + jb .ver_fail + + cmp eax, DRV_CURRENT + ja .ver_fail + + mov ebx, [coff] + stdcall get_coff_sym, [sym], [ebx+CFH.nSymbols], szSTART + mov [start], eax + + stdcall kernel_free, [coff] + + mov ebx, [start] + stdcall ebx, DRV_ENTRY + test eax, eax + jnz .ok + + stdcall kernel_free, [img_base] + cmp dword [file_name+13], 'SOUN' + jnz @f + cmp dword [file_name+17], 'D.ob' + jnz @f + cmp word [file_name+21], 'j' + jnz @f + mov esi, aSis + jmp .redo +@@: + xor eax, eax + ret +.ok: + mov ebx, [img_base] + mov [eax+SRV.base], ebx + mov ecx, [start] + mov [eax+SRV.entry], ecx + ret + +.ver_fail: + mov esi, msg_CR + call sys_msg_board_str + mov esi, [driver_name] + call sys_msg_board_str + mov esi, msg_CR + call sys_msg_board_str + mov esi, msg_version + call sys_msg_board_str + mov esi, msg_www + call sys_msg_board_str + jmp .cleanup + +.link_fail: + mov esi, msg_module + call sys_msg_board_str + mov esi, [driver_name] + call sys_msg_board_str + mov esi, msg_CR + call sys_msg_board_str +.cleanup: + stdcall kernel_free, [img_base] +.fail: + stdcall kernel_free, [coff] +.exit: + xor eax, eax + ret +endp + +; in: edx -> COFF_SECTION struct +; out: eax = alignment as mask for bits to drop +coff_get_align: +; Rules: +; - if alignment is not given, use default = 4K; +; - if alignment is given and is no more than 4K, use it; +; - if alignment is more than 4K, revert to 4K. + push ecx + mov cl, byte [edx+CFS.Characteristics+2] + mov eax, 1 + shr cl, 4 + dec cl + js .default + cmp cl, 12 + jbe @f +.default: + mov cl, 12 +@@: + shl eax, cl + pop ecx + dec eax + ret + +align 4 +proc load_library stdcall, file_name:dword + locals + fullname rb 260 + fileinfo rb 40 + coff dd ? + img_base dd ? + endl + + cli + +; resolve file name + mov ebx, [file_name] + lea edi, [fullname+1] + mov byte [edi-1], '/' + stdcall get_full_file_name, edi, 259 + test al, al + jz .fail + +; scan for required DLL in list of already loaded for this process, +; ignore timestamp + mov esi, [CURRENT_TASK] + shl esi, 8 + lea edi, [fullname] + mov ebx, [esi+SLOT_BASE+APPDATA.dlls_list_ptr] + test ebx, ebx + jz .not_in_process + mov esi, [ebx+HDLL.fd] +.scan_in_process: + cmp esi, ebx + jz .not_in_process + mov eax, [esi+HDLL.parent] + add eax, DLLDESCR.name + stdcall strncmp, eax, edi, -1 + test eax, eax + jnz .next_in_process +; simple variant: load DLL which is already loaded in this process +; just increment reference counters and return address of exports table + inc [esi+HDLL.refcount] + mov ecx, [esi+HDLL.parent] + inc [ecx+DLLDESCR.refcount] + mov eax, [ecx+DLLDESCR.exports] + sub eax, [ecx+DLLDESCR.defaultbase] + add eax, [esi+HDLL.base] + ret +.next_in_process: + mov esi, [esi+HDLL.fd] + jmp .scan_in_process +.not_in_process: + +; scan in full list, compare timestamp + lea eax, [fileinfo] + stdcall get_fileinfo, edi, eax + test eax, eax + jnz .fail + mov esi, [dll_list.fd] +.scan_for_dlls: + cmp esi, dll_list + jz .load_new + lea eax, [esi+DLLDESCR.name] + stdcall strncmp, eax, edi, -1 + test eax, eax + jnz .continue_scan +.test_prev_dll: + mov eax, dword [fileinfo+24]; last modified time + mov edx, dword [fileinfo+28]; last modified date + cmp dword [esi+DLLDESCR.timestamp], eax + jnz .continue_scan + cmp dword [esi+DLLDESCR.timestamp+4], edx + jz .dll_already_loaded +.continue_scan: + mov esi, [esi+DLLDESCR.fd] + jmp .scan_for_dlls + +; new DLL +.load_new: +; load file + stdcall load_file, edi + test eax, eax + jz .fail + mov [coff], eax + mov dword [fileinfo+32], ebx + +; allocate DLLDESCR struct; size is DLLDESCR.sizeof plus size of DLL name + mov esi, edi + mov ecx, -1 + xor eax, eax + repnz scasb + not ecx + lea eax, [ecx+DLLDESCR.sizeof] + push ecx + call malloc + pop ecx + test eax, eax + jz .fail_and_free_coff +; save timestamp + lea edi, [eax+DLLDESCR.name] + rep movsb + mov esi, eax + mov eax, dword [fileinfo+24] + mov dword [esi+DLLDESCR.timestamp], eax + mov eax, dword [fileinfo+28] + mov dword [esi+DLLDESCR.timestamp+4], eax +; initialize DLLDESCR struct + and dword [esi+DLLDESCR.refcount], 0; no HDLLs yet; later it will be incremented + mov [esi+DLLDESCR.fd], dll_list + mov eax, [dll_list.bk] + mov [dll_list.bk], esi + mov [esi+DLLDESCR.bk], eax + mov [eax+DLLDESCR.fd], esi + +; calculate size of loaded DLL + mov edx, [coff] + movzx ecx, [edx+CFH.nSections] + xor ebx, ebx + + add edx, 20 +@@: + call coff_get_align + add ebx, eax + not eax + and ebx, eax + add ebx, [edx+CFS.SizeOfRawData] + add edx, COFF_SECTION_SIZE + dec ecx + jnz @B +; it must be nonzero and not too big + mov [esi+DLLDESCR.size], ebx + test ebx, ebx + jz .fail_and_free_dll + cmp ebx, MAX_DEFAULT_DLL_ADDR-MIN_DEFAULT_DLL_ADDR + ja .fail_and_free_dll +; allocate memory for kernel-side image + stdcall kernel_alloc, ebx + test eax, eax + jz .fail_and_free_dll + mov [esi+DLLDESCR.data], eax +; calculate preferred base address + add ebx, 0x1FFF + and ebx, not 0xFFF + mov ecx, [dll_cur_addr] + lea edx, [ecx+ebx] + cmp edx, MAX_DEFAULT_DLL_ADDR + jb @f + mov ecx, MIN_DEFAULT_DLL_ADDR + lea edx, [ecx+ebx] +@@: + mov [esi+DLLDESCR.defaultbase], ecx + mov [dll_cur_addr], edx + +; copy sections and set correct values for VirtualAddress'es in headers + push esi + mov edx, [coff] + movzx ebx, [edx+CFH.nSections] + mov edi, eax + add edx, 20 + cld +@@: + call coff_get_align + add ecx, eax + add edi, eax + not eax + and ecx, eax + and edi, eax + mov [edx+CFS.VirtualAddress], ecx + add ecx, [edx+CFS.SizeOfRawData] + mov esi, [edx+CFS.PtrRawData] + push ecx + mov ecx, [edx+CFS.SizeOfRawData] + test esi, esi + jnz .copy + xor eax, eax + rep stosb + jmp .next +.copy: + add esi, [coff] + rep movsb +.next: + pop ecx + add edx, COFF_SECTION_SIZE + dec ebx + jnz @B + pop esi + +; save some additional data from COFF file +; later we will use COFF header, headers for sections and symbol table +; and also relocations table for all sections + mov edx, [coff] + mov ebx, [edx+CFH.pSymTable] + mov edi, dword [fileinfo+32] + sub edi, ebx + jc .fail_and_free_data + mov [esi+DLLDESCR.symbols_lim], edi + add ebx, edx + movzx ecx, [edx+CFH.nSections] + lea ecx, [ecx*5] + lea edi, [edi+ecx*8+20] + add edx, 20 +@@: + movzx eax, [edx+CFS.NumReloc] + lea eax, [eax*5] + lea edi, [edi+eax*2] + add edx, COFF_SECTION_SIZE + sub ecx, 5 + jnz @b + stdcall kernel_alloc, edi + test eax, eax + jz .fail_and_free_data + mov edx, [coff] + movzx ecx, [edx+CFH.nSections] + lea ecx, [ecx*5] + lea ecx, [ecx*2+5] + mov [esi+DLLDESCR.coff_hdr], eax + push esi + mov esi, edx + mov edi, eax + rep movsd + pop esi + mov [esi+DLLDESCR.symbols_ptr], edi + push esi + mov ecx, [edx+CFH.nSymbols] + mov [esi+DLLDESCR.symbols_num], ecx + mov ecx, [esi+DLLDESCR.symbols_lim] + mov esi, ebx + rep movsb + pop esi + mov ebx, [esi+DLLDESCR.coff_hdr] + push esi + movzx eax, [edx+CFH.nSections] + lea edx, [ebx+20] +@@: + movzx ecx, [edx+CFS.NumReloc] + lea ecx, [ecx*5] + mov esi, [edx+CFS.PtrReloc] + mov [edx+CFS.PtrReloc], edi + sub [edx+CFS.PtrReloc], ebx + add esi, [coff] + shr ecx, 1 + rep movsd + adc ecx, ecx + rep movsw + add edx, COFF_SECTION_SIZE + dec eax + jnz @b + pop esi + +; fixup symbols + mov edx, ebx + mov eax, [ebx+CFH.nSymbols] + add edx, 20 + mov ecx, [esi+DLLDESCR.symbols_num] + lea ecx, [ecx*9] + add ecx, ecx + add ecx, [esi+DLLDESCR.symbols_ptr] + + stdcall fix_coff_symbols, edx, [esi+DLLDESCR.symbols_ptr], eax, \ + ecx, 0 +; test eax, eax +; jnz @F +; +;@@: + + stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+CFH.nSymbols], szEXPORTS + test eax, eax + jnz @F + + stdcall get_coff_sym, [esi+DLLDESCR.symbols_ptr], [ebx+CFH.nSymbols], sz_EXPORTS +@@: + mov [esi+DLLDESCR.exports], eax + +; fix relocs in the hidden copy in kernel memory to default address +; it is first fix; usually this will be enough, but second fix +; can be necessary if real load address will not equal assumption + mov eax, [esi+DLLDESCR.data] + sub eax, [esi+DLLDESCR.defaultbase] + stdcall fix_coff_relocs, ebx, [esi+DLLDESCR.symbols_ptr], eax + + stdcall kernel_free, [coff] + +.dll_already_loaded: + inc [esi+DLLDESCR.refcount] + push esi + call init_heap + pop esi + + mov edi, [esi+DLLDESCR.size] + stdcall user_alloc_at, [esi+DLLDESCR.defaultbase], edi + test eax, eax + jnz @f + stdcall user_alloc, edi + test eax, eax + jz .fail_and_dereference +@@: + mov [img_base], eax + mov eax, HDLL.sizeof + call malloc + test eax, eax + jz .fail_and_free_user + mov ebx, [CURRENT_TASK] + shl ebx, 5 + mov edx, [CURRENT_TASK+ebx+TASKDATA.pid] + mov [eax+HDLL.pid], edx + push eax + call init_dlls_in_thread + pop ebx + test eax, eax + jz .fail_and_free_user + mov edx, [eax+HDLL.fd] + mov [ebx+HDLL.fd], edx + mov [ebx+HDLL.bk], eax + mov [eax+HDLL.fd], ebx + mov [edx+HDLL.bk], ebx + mov eax, ebx + mov ebx, [img_base] + mov [eax+HDLL.base], ebx + mov [eax+HDLL.size], edi + mov [eax+HDLL.refcount], 1 + mov [eax+HDLL.parent], esi + mov edx, ebx + shr edx, 12 + or dword [page_tabs+(edx-1)*4], DONT_FREE_BLOCK +; copy entries of page table from kernel-side image to usermode +; use copy-on-write for user-mode image, so map as readonly + xor edi, edi + mov ecx, [esi+DLLDESCR.data] + shr ecx, 12 +.map_pages_loop: + mov eax, [page_tabs+ecx*4] + and eax, not 0xFFF + or al, PG_USER + xchg eax, [page_tabs+edx*4] + test al, 1 + jz @f + call free_page +@@: + invlpg [ebx+edi] + inc ecx + inc edx + add edi, 0x1000 + cmp edi, [esi+DLLDESCR.size] + jb .map_pages_loop + +; if real user-mode base is not equal to preferred base, relocate image + sub ebx, [esi+DLLDESCR.defaultbase] + jz @f + stdcall rebase_coff, [esi+DLLDESCR.coff_hdr], [esi+DLLDESCR.symbols_ptr], ebx +@@: + + mov eax, [esi+DLLDESCR.exports] + sub eax, [esi+DLLDESCR.defaultbase] + add eax, [img_base] + ret +.fail_and_free_data: + stdcall kernel_free, [esi+DLLDESCR.data] +.fail_and_free_dll: + mov eax, esi + call free +.fail_and_free_coff: + stdcall kernel_free, [coff] +.fail: + xor eax, eax + ret +.fail_and_free_user: + stdcall user_free, [img_base] +.fail_and_dereference: + mov eax, 1 ; delete 1 reference + call dereference_dll + xor eax, eax + ret +endp + +; initialize [APPDATA.dlls_list_ptr] for given thread +; DLL is per-process object, so APPDATA.dlls_list_ptr must be +; kept in sync for all threads of one process. +; out: eax = APPDATA.dlls_list_ptr if all is OK, +; NULL if memory allocation failed +init_dlls_in_thread: + mov ebx, [current_slot] + mov eax, [ebx+APPDATA.dlls_list_ptr] + test eax, eax + jnz .ret + push [ebx+APPDATA.dir_table] + mov eax, 8 + call malloc + pop edx + test eax, eax + jz .ret + mov [eax], eax + mov [eax+4], eax + mov ecx, [TASK_COUNT] + mov ebx, SLOT_BASE+256 +.set: + cmp [ebx+APPDATA.dir_table], edx + jnz @f + mov [ebx+APPDATA.dlls_list_ptr], eax +@@: + add ebx, 256 + dec ecx + jnz .set +.ret: + ret + +; in: eax = number of references to delete, esi -> DLLDESCR struc +dereference_dll: + sub [esi+DLLDESCR.refcount], eax + jnz .ret + mov eax, [esi+DLLDESCR.fd] + mov edx, [esi+DLLDESCR.bk] + mov [eax+DLLDESCR.bk], edx + mov [edx+DLLDESCR.fd], eax + stdcall kernel_free, [esi+DLLDESCR.coff_hdr] + stdcall kernel_free, [esi+DLLDESCR.data] + mov eax, esi + call free +.ret: + ret + +destroy_hdll: + push ebx ecx esi edi + push eax + mov ebx, [eax+HDLL.base] + mov esi, [eax+HDLL.parent] + mov edx, [esi+DLLDESCR.size] +; The following actions require the context of application where HDLL is mapped. +; However, destroy_hdll can be called in the context of OS thread when +; cleaning up objects created by the application which is destroyed. +; So remember current cr3 and set it to page table of target. + mov eax, [ecx+APPDATA.dir_table] +; Because we cheat with cr3, disable interrupts: task switch would restore +; page table from APPDATA of current thread. +; Also set [current_slot] because it is used by user_free. + pushf + cli + push [current_slot] + mov [current_slot], ecx + mov ecx, cr3 + push ecx + mov cr3, eax + push ebx ; argument for user_free + mov eax, ebx + shr ebx, 12 + push ebx + mov esi, [esi+DLLDESCR.data] + shr esi, 12 +.unmap_loop: + push eax + mov eax, 2 + xchg eax, [page_tabs+ebx*4] + mov ecx, [page_tabs+esi*4] + and eax, not 0xFFF + and ecx, not 0xFFF + cmp eax, ecx + jz @f + call free_page +@@: + pop eax + invlpg [eax] + add eax, 0x1000 + inc ebx + inc esi + sub edx, 0x1000 + ja .unmap_loop + pop ebx + and dword [page_tabs+(ebx-1)*4], not DONT_FREE_BLOCK + call user_free +; Restore context. + pop eax + mov cr3, eax + pop [current_slot] + popf +; Ok, cheating is done. + pop eax + push eax + mov esi, [eax+HDLL.parent] + mov eax, [eax+HDLL.refcount] + call dereference_dll + pop eax + mov edx, [eax+HDLL.bk] + mov ebx, [eax+HDLL.fd] + mov [ebx+HDLL.bk], edx + mov [edx+HDLL.fd], ebx + call free + pop edi esi ecx ebx + ret + +; ecx -> APPDATA for slot, esi = dlls_list_ptr +destroy_all_hdlls: + test esi, esi + jz .ret +.loop: + mov eax, [esi+HDLL.fd] + cmp eax, esi + jz free + call destroy_hdll + jmp .loop +.ret: + ret + +align 4 +stop_all_services: + push ebp + mov edx, [srv.fd] +.next: + cmp edx, srv.fd-SRV_FD_OFFSET + je .done + cmp [edx+SRV.magic], ' SRV' + jne .next + cmp [edx+SRV.size], SRV.sizeof + jne .next + + mov ebx, [edx+SRV.entry] + mov edx, [edx+SRV.fd] + test ebx, ebx + jz .next + + push edx + mov ebp, esp + push 0 + push -1 + call ebx + mov esp, ebp + pop edx + jmp .next +.done: + pop ebp + ret + +; param +; eax= size +; ebx= pid + +align 4 +create_kernel_object: + + push ebx + call malloc + pop ebx + test eax, eax + jz .fail + + mov ecx, [current_slot] + add ecx, APP_OBJ_OFFSET + + pushfd + cli + mov edx, [ecx+APPOBJ.fd] + mov [eax+APPOBJ.fd], edx + mov [eax+APPOBJ.bk], ecx + mov [eax+APPOBJ.pid], ebx + + mov [ecx+APPOBJ.fd], eax + mov [edx+APPOBJ.bk], eax + popfd +.fail: + ret + +; param +; eax= object + +align 4 +destroy_kernel_object: + + pushfd + cli + mov ebx, [eax+APPOBJ.fd] + mov ecx, [eax+APPOBJ.bk] + mov [ebx+APPOBJ.bk], ecx + mov [ecx+APPOBJ.fd], ebx + popfd + + xor edx, edx ;clear common header + mov [eax], edx + mov [eax+4], edx + mov [eax+8], edx + mov [eax+12], edx + mov [eax+16], edx + + call free ;release object memory + ret diff --git a/kernel/trunk/core/export.inc b/kernel/trunk/core/export.inc index edb5c373b..73e347089 100644 --- a/kernel/trunk/core/export.inc +++ b/kernel/trunk/core/export.inc @@ -1,39 +1,40 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; Macroinstruction for making export section - - -macro export dllname,[label,string] - { common - local module,addresses,names,ordinal,count - count = 0 - forward - count = count+1 - common - dd 0,0,0, (module-OS_BASE) , 1 - dd count,count,(addresses-OS_BASE),(names-OS_BASE),(ordinal-OS_BASE) - addresses: - forward - dd (label-OS_BASE) - common - names: - forward - local name - dd (name-OS_BASE) - common - ordinal: count = 0 - forward - dw count - count = count+1 - common - module db dllname,0 - forward - name db string,0 - } +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; Macroinstruction for making export section + + +macro export dllname,[label,string] + { common + local module,addresses,names,ordinal,count + count = 0 + forward + count = count+1 + common + dd 0,0,0, (module-OS_BASE) , 1 + dd count,count,(addresses-OS_BASE),(names-OS_BASE),(ordinal-OS_BASE) + addresses: + forward + dd (label-OS_BASE) + common + names: + forward + local name + dd (name-OS_BASE) + common + ordinal: + count = 0 + forward + dw count + count = count+1 + common + module db dllname,0 + forward + name db string,0 + } diff --git a/kernel/trunk/core/exports.inc b/kernel/trunk/core/exports.inc index baddeeb27..9870707b8 100644 --- a/kernel/trunk/core/exports.inc +++ b/kernel/trunk/core/exports.inc @@ -1,181 +1,181 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -iglobal - szKernel db 'KERNEL', 0 - szVersion db 'version',0 - - szRegService db 'RegService',0 - szGetService db 'GetService',0 - szServiceHandler db 'ServiceHandler',0 - szAttachIntHandler db 'AttachIntHandler',0 -; szGetIntHandler db 'GetIntHandler', 0 - szFpuSave db 'FpuSave',0 - szFpuRestore db 'FpuRestore',0 - szReservePortArea db 'ReservePortArea',0 - szBoot_Log db 'Boot_Log',0 - - szMutexInit db 'MutexInit',0 - szMutexLock db 'MutexLock',0 - szMutexUnlock db 'MutexUnlock',0 - - szPciApi db 'PciApi', 0 - szPciRead32 db 'PciRead32', 0 - szPciRead16 db 'PciRead16', 0 - szPciRead8 db 'PciRead8', 0 - szPciWrite8 db 'PciWrite8',0 - szPciWrite16 db 'PciWrite16',0 - szPciWrite32 db 'PciWrite32',0 - - szAllocPage db 'AllocPage',0 - szAllocPages db 'AllocPages',0 - szFreePage db 'FreePage',0 - szGetPgAddr db 'GetPgAddr',0 - szMapPage db 'MapPage',0 - szMapSpace db 'MapSpace',0 - szMapIoMem db 'MapIoMem',0 - szCommitPages db 'CommitPages',0 - szReleasePages db 'ReleasePages',0 - - szAllocKernelSpace db 'AllocKernelSpace',0 - szFreeKernelSpace db 'FreeKernelSpace',0 - szKernelAlloc db 'KernelAlloc',0 - szKernelFree db 'KernelFree',0 - szUserAlloc db 'UserAlloc',0 - szUserFree db 'UserFree',0 - szKmalloc db 'Kmalloc',0 - szKfree db 'Kfree',0 - szCreateRingBuffer db 'CreateRingBuffer',0 - - szGetPid db 'GetPid',0 - szCreateObject db 'CreateObject',0 - szDestroyObject db 'DestroyObject',0 - szCreateEvent db 'CreateEvent',0 - szRaiseEvent db 'RaiseEvent',0 - szWaitEvent db 'WaitEvent',0 - szDestroyEvent db 'DestroyEvent',0 - szClearEvent db 'ClearEvent',0 - - szLoadCursor db 'LoadCursor',0 - - szSysMsgBoardStr db 'SysMsgBoardStr', 0 - szSysMsgBoardChar db 'SysMsgBoardChar', 0 - szGetCurrentTask db 'GetCurrentTask',0 - szLFBAddress db 'LFBAddress',0 - szLoadFile db 'LoadFile',0 - szSendEvent db 'SendEvent',0 - szSetMouseData db 'SetMouseData',0 - szSleep db 'Sleep',0 - szGetTimerTicks db 'GetTimerTicks',0 - - szGetDisplay db 'GetDisplay',0 - szSetScreen db 'SetScreen',0 - - szStrncat db 'strncat',0 - szStrncpy db 'strncpy',0 - szstrncmp db 'strncmp',0 - szStrnlen db 'strnlen',0 - szStrchr db 'strchr',0 - szStrrchr db 'strrchr',0 - - szDiskAdd db 'DiskAdd',0 - szDiskDel db 'DiskDel',0 - szDiskMediaChanged db 'DiskMediaChanged',0 - - szTimerHS db 'TimerHS',0 - szCancelTimerHS db 'CancelTimerHS',0 - - -align 16 -kernel_export: - dd szRegService , reg_service - dd szGetService , get_service - dd szServiceHandler , srv_handler - dd szAttachIntHandler, attach_int_handler -; dd szGetIntHandler , get_int_handler - dd szFpuSave , fpu_save - dd szFpuRestore , fpu_restore - dd szReservePortArea , r_f_port_area - dd szBoot_Log , boot_log - - dd szMutexInit , mutex_init ;gcc fastcall - dd szMutexLock , mutex_lock ;gcc fastcall - dd szMutexUnlock , mutex_unlock ;gcc fastcall - - dd szPciApi , pci_api_drv - dd szPciRead32 , pci_read32 - dd szPciRead16 , pci_read16 - dd szPciRead8 , pci_read8 - dd szPciWrite8 , pci_write8 - dd szPciWrite16 , pci_write16 - dd szPciWrite32 , pci_write32 - - dd szAllocPage , alloc_page ;stdcall - dd szAllocPages , alloc_pages ;stdcall - dd szFreePage , free_page - dd szMapPage , map_page ;stdcall - dd szMapSpace , map_space - dd szMapIoMem , map_io_mem ;stdcall - dd szGetPgAddr , get_pg_addr - dd szCommitPages , commit_pages ;not implemented - dd szReleasePages , release_pages - - dd szAllocKernelSpace, alloc_kernel_space ;stdcall - dd szFreeKernelSpace , free_kernel_space ;stdcall - dd szKernelAlloc , kernel_alloc ;stdcall - dd szKernelFree , kernel_free ;stdcall - dd szUserAlloc , user_alloc ;stdcall - dd szUserFree , user_free ;stdcall - dd szKmalloc , malloc - dd szKfree , free - dd szCreateRingBuffer, create_ring_buffer ;stdcall - - dd szGetPid , get_pid - dd szCreateObject , create_kernel_object - dd szDestroyObject , destroy_kernel_object - dd szCreateEvent , create_event ;see EVENT.inc for specification - dd szRaiseEvent , raise_event ;see EVENT.inc for specification - dd szWaitEvent , wait_event ;see EVENT.inc for specification - dd szDestroyEvent , destroy_event ;see EVENT.inc for specification - dd szClearEvent , clear_event ;see EVENT.inc for specification - - dd szLoadCursor , load_cursor ;stdcall - - dd szSysMsgBoardStr , sys_msg_board_str - dd szSysMsgBoardChar , sys_msg_board - dd szGetCurrentTask , get_curr_task - dd szLoadFile , load_file ;retval eax, ebx - dd szSendEvent , send_event ;see EVENT.inc for specification - dd szSetMouseData , set_mouse_data ;stdcall - dd szSleep , delay_ms - dd szGetTimerTicks , get_timer_ticks - - dd szGetDisplay , get_display - dd szSetScreen , set_screen - - dd szStrncat , strncat - dd szStrncpy , strncpy - dd szstrncmp , strncmp - dd szStrnlen , strnlen - dd szStrchr , strchr - dd szStrrchr , strrchr - - dd szDiskAdd , disk_add - dd szDiskDel , disk_del - dd szDiskMediaChanged, disk_media_changed - - dd szTimerHS , timer_hs - dd szCancelTimerHS , cancel_timer_hs - -exp_lfb: - dd szLFBAddress , 0 - dd 0 ;terminator, must be zero - -endg +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +iglobal + szKernel db 'KERNEL', 0 + szVersion db 'version',0 + + szRegService db 'RegService',0 + szGetService db 'GetService',0 + szServiceHandler db 'ServiceHandler',0 + szAttachIntHandler db 'AttachIntHandler',0 +; szGetIntHandler db 'GetIntHandler', 0 + szFpuSave db 'FpuSave',0 + szFpuRestore db 'FpuRestore',0 + szReservePortArea db 'ReservePortArea',0 + szBoot_Log db 'Boot_Log',0 + + szMutexInit db 'MutexInit',0 + szMutexLock db 'MutexLock',0 + szMutexUnlock db 'MutexUnlock',0 + + szPciApi db 'PciApi', 0 + szPciRead32 db 'PciRead32', 0 + szPciRead16 db 'PciRead16', 0 + szPciRead8 db 'PciRead8', 0 + szPciWrite8 db 'PciWrite8',0 + szPciWrite16 db 'PciWrite16',0 + szPciWrite32 db 'PciWrite32',0 + + szAllocPage db 'AllocPage',0 + szAllocPages db 'AllocPages',0 + szFreePage db 'FreePage',0 + szGetPgAddr db 'GetPgAddr',0 + szMapPage db 'MapPage',0 + szMapSpace db 'MapSpace',0 + szMapIoMem db 'MapIoMem',0 + szCommitPages db 'CommitPages',0 + szReleasePages db 'ReleasePages',0 + + szAllocKernelSpace db 'AllocKernelSpace',0 + szFreeKernelSpace db 'FreeKernelSpace',0 + szKernelAlloc db 'KernelAlloc',0 + szKernelFree db 'KernelFree',0 + szUserAlloc db 'UserAlloc',0 + szUserFree db 'UserFree',0 + szKmalloc db 'Kmalloc',0 + szKfree db 'Kfree',0 + szCreateRingBuffer db 'CreateRingBuffer',0 + + szGetPid db 'GetPid',0 + szCreateObject db 'CreateObject',0 + szDestroyObject db 'DestroyObject',0 + szCreateEvent db 'CreateEvent',0 + szRaiseEvent db 'RaiseEvent',0 + szWaitEvent db 'WaitEvent',0 + szDestroyEvent db 'DestroyEvent',0 + szClearEvent db 'ClearEvent',0 + + szLoadCursor db 'LoadCursor',0 + + szSysMsgBoardStr db 'SysMsgBoardStr', 0 + szSysMsgBoardChar db 'SysMsgBoardChar', 0 + szGetCurrentTask db 'GetCurrentTask',0 + szLFBAddress db 'LFBAddress',0 + szLoadFile db 'LoadFile',0 + szSendEvent db 'SendEvent',0 + szSetMouseData db 'SetMouseData',0 + szSleep db 'Sleep',0 + szGetTimerTicks db 'GetTimerTicks',0 + + szGetDisplay db 'GetDisplay',0 + szSetScreen db 'SetScreen',0 + + szStrncat db 'strncat',0 + szStrncpy db 'strncpy',0 + szstrncmp db 'strncmp',0 + szStrnlen db 'strnlen',0 + szStrchr db 'strchr',0 + szStrrchr db 'strrchr',0 + + szDiskAdd db 'DiskAdd',0 + szDiskDel db 'DiskDel',0 + szDiskMediaChanged db 'DiskMediaChanged',0 + + szTimerHS db 'TimerHS',0 + szCancelTimerHS db 'CancelTimerHS',0 + + +align 16 +kernel_export: + dd szRegService , reg_service + dd szGetService , get_service + dd szServiceHandler , srv_handler + dd szAttachIntHandler, attach_int_handler +; dd szGetIntHandler , get_int_handler + dd szFpuSave , fpu_save + dd szFpuRestore , fpu_restore + dd szReservePortArea , r_f_port_area + dd szBoot_Log , boot_log + + dd szMutexInit , mutex_init ;gcc fastcall + dd szMutexLock , mutex_lock ;gcc fastcall + dd szMutexUnlock , mutex_unlock ;gcc fastcall + + dd szPciApi , pci_api_drv + dd szPciRead32 , pci_read32 + dd szPciRead16 , pci_read16 + dd szPciRead8 , pci_read8 + dd szPciWrite8 , pci_write8 + dd szPciWrite16 , pci_write16 + dd szPciWrite32 , pci_write32 + + dd szAllocPage , alloc_page ;stdcall + dd szAllocPages , alloc_pages ;stdcall + dd szFreePage , free_page + dd szMapPage , map_page ;stdcall + dd szMapSpace , map_space + dd szMapIoMem , map_io_mem ;stdcall + dd szGetPgAddr , get_pg_addr + dd szCommitPages , commit_pages ;not implemented + dd szReleasePages , release_pages + + dd szAllocKernelSpace, alloc_kernel_space ;stdcall + dd szFreeKernelSpace , free_kernel_space ;stdcall + dd szKernelAlloc , kernel_alloc ;stdcall + dd szKernelFree , kernel_free ;stdcall + dd szUserAlloc , user_alloc ;stdcall + dd szUserFree , user_free ;stdcall + dd szKmalloc , malloc + dd szKfree , free + dd szCreateRingBuffer, create_ring_buffer ;stdcall + + dd szGetPid , get_pid + dd szCreateObject , create_kernel_object + dd szDestroyObject , destroy_kernel_object + dd szCreateEvent , create_event ;see EVENT.inc for specification + dd szRaiseEvent , raise_event ;see EVENT.inc for specification + dd szWaitEvent , wait_event ;see EVENT.inc for specification + dd szDestroyEvent , destroy_event ;see EVENT.inc for specification + dd szClearEvent , clear_event ;see EVENT.inc for specification + + dd szLoadCursor , load_cursor ;stdcall + + dd szSysMsgBoardStr , sys_msg_board_str + dd szSysMsgBoardChar , sys_msg_board + dd szGetCurrentTask , get_curr_task + dd szLoadFile , load_file ;retval eax, ebx + dd szSendEvent , send_event ;see EVENT.inc for specification + dd szSetMouseData , set_mouse_data ;stdcall + dd szSleep , delay_ms + dd szGetTimerTicks , get_timer_ticks + + dd szGetDisplay , get_display + dd szSetScreen , set_screen + + dd szStrncat , strncat + dd szStrncpy , strncpy + dd szstrncmp , strncmp + dd szStrnlen , strnlen + dd szStrchr , strchr + dd szStrrchr , strrchr + + dd szDiskAdd , disk_add + dd szDiskDel , disk_del + dd szDiskMediaChanged, disk_media_changed + + dd szTimerHS , timer_hs + dd szCancelTimerHS , cancel_timer_hs + +exp_lfb: + dd szLFBAddress , 0 + dd 0 ;terminator, must be zero + +endg diff --git a/kernel/trunk/core/ext_lib.inc b/kernel/trunk/core/ext_lib.inc index db53e6326..58d57aa53 100644 --- a/kernel/trunk/core/ext_lib.inc +++ b/kernel/trunk/core/ext_lib.inc @@ -1,320 +1,333 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;============================================================================ -; -; External kernel dependencies (libraries) loading -; -;============================================================================ - -$Revision$ - -if 0 -; The code currently does not work. Kill "if 0/end if" only after correcting -; to current kernel (dll.inc). -macro library [name,fname] -{ - forward - dd __#name#_library_table__,__#name#_library_name__ - common - dd 0 - forward - __#name#_library_name__ db fname,0 -} - -macro import lname,[name,sname] -{ - common - align 4 - __#lname#_library_table__: - forward - name dd __#name#_import_name__ - common - dd 0 - forward - __#name#_import_name__ db sname,0 -} - -macro export [name,sname] -{ -align 4 - forward - dd __#name#_export_name__,name - common - dd 0 - forward - __#name#_export_name__ db sname,0 -} - - - -align 4 ; loading library (use kernel functions) -proc load_k_library stdcall, file_name:dword - locals - coff dd ? - sym dd ? - strings dd ? - img_size dd ? - img_base dd ? - exports dd ? - endl - - cli - - stdcall load_file, [file_name] - test eax, eax - jz .fail - - mov [coff], eax - movzx ecx, [eax+CFH.nSections] - xor ebx, ebx - - lea edx, [eax+20] -@@: - add ebx, [edx+CFS.SizeOfRawData] - add ebx, 15 - and ebx, not 15 - add edx, COFF_SECTION_SIZE - dec ecx - jnz @B - mov [img_size], ebx - - stdcall kernel_alloc, [img_size] - - test eax, eax - jz .fail - mov [img_base], eax - - mov edx, [coff] - movzx ebx, [edx+CFH.nSections] - mov edi, [img_base] - lea eax, [edx+20] -@@: - mov [eax+CFS.VirtualAddress], edi - mov esi, [eax+CFS.PtrRawData] - test esi, esi - jnz .copy - add edi, [eax+CFS.SizeOfRawData] - jmp .next -.copy: - add esi, edx - mov ecx, [eax+CFS.SizeOfRawData] - cld - rep movsb -.next: - add edi, 15 - and edi, not 15 - add eax, COFF_SECTION_SIZE - dec ebx - jnz @B - - mov ebx, [edx+CFH.pSymTable] - add ebx, edx - mov [sym], ebx - mov ecx, [edx+CFH.nSymbols] - add ecx,ecx - lea ecx,[ecx+ecx*8] ;ecx*=18 = nSymbols*CSYM_SIZE - add ecx, [sym] - mov [strings], ecx - - lea eax, [edx+20] - - stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols],\ - [strings], dword 0 - test eax, eax - jnz @F - -@@: - mov edx, [coff] - movzx ebx, [edx+CFH.nSections] - mov edi, 0 - lea eax, [edx+20] -@@: - add [eax+CFS.VirtualAddress], edi ;patch user space offset - add eax, COFF_SECTION_SIZE - dec ebx - jnz @B - - add edx, 20 - stdcall fix_coff_relocs, [coff], edx, [sym] - - mov ebx, [coff] - stdcall get_coff_sym,[sym],[ebx+CFH.nSymbols],szEXPORTS - mov [exports], eax - - stdcall kernel_free, [coff] - - mov eax, [exports] - ret -.fail: - xor eax, eax - ret -endp - - -proc dll.Load, import_table:dword - mov esi,[import_table] - .next_lib: mov edx,[esi] - or edx,edx - jz .exit - push esi - - mov edi,s_libname - - mov al, '/' - stosb - mov esi,sysdir_path - @@: lodsb - stosb - or al,al - jnz @b - dec edi - mov [edi], dword '/lib' - mov [edi+4],byte '/' - add edi,5 - pop esi - push esi - mov esi,[esi+4] - @@: lodsb - stosb - or al,al - jnz @b - - pushad - stdcall load_k_library,s_libname - mov [esp+28],eax - popad - or eax,eax - jz .fail - stdcall dll.Link,eax,edx - stdcall dll.Init,[eax+4] - pop esi - add esi,8 - jmp .next_lib - .exit: xor eax,eax - ret - .fail: add esp,4 - xor eax,eax - inc eax - ret -endp - -proc dll.Link, exp:dword,imp:dword - push eax - mov esi,[imp] - test esi,esi - jz .done - .next: lodsd - test eax,eax - jz .done - stdcall dll.GetProcAddress,[exp],eax - or eax,eax - jz @f - mov [esi-4],eax - jmp .next - @@: mov dword[esp],0 - .done: pop eax - ret -endp - -proc dll.Init, dllentry:dword - pushad - mov eax,mem.Alloc - mov ebx,mem.Free - mov ecx,mem.ReAlloc - mov edx,dll.Load - stdcall [dllentry] - popad - ret -endp - -proc dll.GetProcAddress, exp:dword,sz_name:dword - mov edx,[exp] - .next: test edx,edx - jz .end - stdcall strncmp,[edx],[sz_name], dword -1 - test eax,eax - jz .ok - add edx,8 - jmp .next - .ok: mov eax,[edx+4] - .end: ret -endp - -;----------------------------------------------------------------------------- -proc mem.Alloc size ;///////////////////////////////////////////////////////// -;----------------------------------------------------------------------------- - push ebx ecx -; mov eax,[size] -; lea ecx,[eax+4+4095] -; and ecx,not 4095 -; stdcall kernel_alloc, ecx -; add ecx,-4 -; mov [eax],ecx -; add eax,4 - - stdcall kernel_alloc, [size] - - pop ecx ebx - ret -endp - -;----------------------------------------------------------------------------- -proc mem.ReAlloc mptr,size;/////////////////////////////////////////////////// -;----------------------------------------------------------------------------- - push ebx ecx esi edi eax - mov eax,[mptr] - mov ebx,[size] - or eax,eax - jz @f - lea ecx,[ebx+4+4095] - and ecx,not 4095 - add ecx,-4 - cmp ecx,[eax-4] - je .exit - @@: mov eax,ebx - call mem.Alloc - xchg eax,[esp] - or eax,eax - jz .exit - mov esi,eax - xchg eax,[esp] - mov edi,eax - mov ecx,[esi-4] - cmp ecx,[edi-4] - jbe @f - mov ecx,[edi-4] - @@: add ecx,3 - shr ecx,2 - cld - rep movsd - xchg eax,[esp] - call mem.Free - .exit: - pop eax edi esi ecx ebx - ret -endp - -;----------------------------------------------------------------------------- -proc mem.Free mptr ;////////////////////////////////////////////////////////// -;----------------------------------------------------------------------------- -; mov eax,[mptr] -; or eax,eax -; jz @f -; push ebx ecx -; lea ecx,[eax-4] -; stdcall kernel_free, ecx -; pop ecx ebx -; @@: ret - stdcall kernel_free, [mptr] - ret -endp - -uglobal -s_libname db 64 dup (0) -endg -end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;============================================================================ +; +; External kernel dependencies (libraries) loading +; +;============================================================================ + +$Revision$ + +if 0 +; The code currently does not work. Kill "if 0/end if" only after correcting +; to current kernel (dll.inc). +macro library [name,fname] +{ + forward + dd __#name#_library_table__,__#name#_library_name__ + common + dd 0 + forward + __#name#_library_name__ db fname,0 +} + +macro import lname,[name,sname] +{ + common + align 4 + __#lname#_library_table__: + forward + name dd __#name#_import_name__ + common + dd 0 + forward + __#name#_import_name__ db sname,0 +} + +macro export [name,sname] +{ +align 4 + forward + dd __#name#_export_name__,name + common + dd 0 + forward + __#name#_export_name__ db sname,0 +} + + + +align 4 ; loading library (use kernel functions) +proc load_k_library stdcall, file_name:dword + locals + coff dd ? + sym dd ? + strings dd ? + img_size dd ? + img_base dd ? + exports dd ? + endl + + cli + + stdcall load_file, [file_name] + test eax, eax + jz .fail + + mov [coff], eax + movzx ecx, [eax+CFH.nSections] + xor ebx, ebx + + lea edx, [eax+20] +@@: + add ebx, [edx+CFS.SizeOfRawData] + add ebx, 15 + and ebx, not 15 + add edx, COFF_SECTION_SIZE + dec ecx + jnz @B + mov [img_size], ebx + + stdcall kernel_alloc, [img_size] + + test eax, eax + jz .fail + mov [img_base], eax + + mov edx, [coff] + movzx ebx, [edx+CFH.nSections] + mov edi, [img_base] + lea eax, [edx+20] +@@: + mov [eax+CFS.VirtualAddress], edi + mov esi, [eax+CFS.PtrRawData] + test esi, esi + jnz .copy + add edi, [eax+CFS.SizeOfRawData] + jmp .next +.copy: + add esi, edx + mov ecx, [eax+CFS.SizeOfRawData] + cld + rep movsb +.next: + add edi, 15 + and edi, not 15 + add eax, COFF_SECTION_SIZE + dec ebx + jnz @B + + mov ebx, [edx+CFH.pSymTable] + add ebx, edx + mov [sym], ebx + mov ecx, [edx+CFH.nSymbols] + add ecx, ecx + lea ecx, [ecx+ecx*8];ecx*=18 = nSymbols*CSYM_SIZE + add ecx, [sym] + mov [strings], ecx + + lea eax, [edx+20] + + stdcall fix_coff_symbols, eax, [sym], [edx+CFH.nSymbols], \ + [strings], dword 0 + test eax, eax + jnz @F + +@@: + mov edx, [coff] + movzx ebx, [edx+CFH.nSections] + mov edi, 0 + lea eax, [edx+20] +@@: + add [eax+CFS.VirtualAddress], edi ;patch user space offset + add eax, COFF_SECTION_SIZE + dec ebx + jnz @B + + add edx, 20 + stdcall fix_coff_relocs, [coff], edx, [sym] + + mov ebx, [coff] + stdcall get_coff_sym, [sym], [ebx+CFH.nSymbols], szEXPORTS + mov [exports], eax + + stdcall kernel_free, [coff] + + mov eax, [exports] + ret +.fail: + xor eax, eax + ret +endp + + +proc dll.Load, import_table:dword + mov esi, [import_table] + .next_lib: + mov edx, [esi] + or edx, edx + jz .exit + push esi + + mov edi, s_libname + + mov al, '/' + stosb + mov esi, sysdir_path + @@: + lodsb + stosb + or al, al + jnz @b + dec edi + mov [edi], dword '/lib' + mov [edi+4], byte '/' + add edi, 5 + pop esi + push esi + mov esi, [esi+4] + @@: + lodsb + stosb + or al, al + jnz @b + + pushad + stdcall load_k_library, s_libname + mov [esp+28], eax + popad + or eax, eax + jz .fail + stdcall dll.Link, eax, edx + stdcall dll.Init, [eax+4] + pop esi + add esi, 8 + jmp .next_lib + .exit: + xor eax, eax + ret + .fail: + add esp, 4 + xor eax, eax + inc eax + ret +endp + +proc dll.Link, exp:dword,imp:dword + push eax + mov esi, [imp] + test esi, esi + jz .done + .next: + lodsd + test eax, eax + jz .done + stdcall dll.GetProcAddress, [exp], eax + or eax, eax + jz @f + mov [esi-4], eax + jmp .next + @@: + mov dword[esp], 0 + .done: + pop eax + ret +endp + +proc dll.Init, dllentry:dword + pushad + mov eax, mem.Alloc + mov ebx, mem.Free + mov ecx, mem.ReAlloc + mov edx, dll.Load + stdcall [dllentry] + popad + ret +endp + +proc dll.GetProcAddress, exp:dword,sz_name:dword + mov edx, [exp] + .next: + test edx, edx + jz .end + stdcall strncmp, [edx], [sz_name], dword -1 + test eax, eax + jz .ok + add edx, 8 + jmp .next + .ok: + mov eax, [edx+4] + .end: + ret +endp + +;----------------------------------------------------------------------------- +proc mem.Alloc size ;///////////////////////////////////////////////////////// +;----------------------------------------------------------------------------- + push ebx ecx +; mov eax,[size] +; lea ecx,[eax+4+4095] +; and ecx,not 4095 +; stdcall kernel_alloc, ecx +; add ecx,-4 +; mov [eax],ecx +; add eax,4 + + stdcall kernel_alloc, [size] + + pop ecx ebx + ret +endp + +;----------------------------------------------------------------------------- +proc mem.ReAlloc mptr,size;/////////////////////////////////////////////////// +;----------------------------------------------------------------------------- + push ebx ecx esi edi eax + mov eax, [mptr] + mov ebx, [size] + or eax, eax + jz @f + lea ecx, [ebx+4+4095] + and ecx, not 4095 + add ecx, -4 + cmp ecx, [eax-4] + je .exit + @@: + mov eax, ebx + call mem.Alloc + xchg eax, [esp] + or eax, eax + jz .exit + mov esi, eax + xchg eax, [esp] + mov edi, eax + mov ecx, [esi-4] + cmp ecx, [edi-4] + jbe @f + mov ecx, [edi-4] + @@: + add ecx, 3 + shr ecx, 2 + cld + rep movsd + xchg eax, [esp] + call mem.Free + .exit: + pop eax edi esi ecx ebx + ret +endp + +;----------------------------------------------------------------------------- +proc mem.Free mptr ;////////////////////////////////////////////////////////// +;----------------------------------------------------------------------------- +; mov eax,[mptr] +; or eax,eax +; jz @f +; push ebx ecx +; lea ecx,[eax-4] +; stdcall kernel_free, ecx +; pop ecx ebx +; @@: ret + stdcall kernel_free, [mptr] + ret +endp + +uglobal +s_libname db 64 dup (0) +endg +end if diff --git a/kernel/trunk/core/fpu.inc b/kernel/trunk/core/fpu.inc index 5b11e0aa8..ef4072655 100644 --- a/kernel/trunk/core/fpu.inc +++ b/kernel/trunk/core/fpu.inc @@ -1,183 +1,183 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -init_fpu: - clts - fninit - - bt [cpu_caps], CAPS_SSE - jnc .no_SSE - - mov ebx, cr4 - mov ecx, cr0 - or ebx, CR4_OSFXSR+CR4_OSXMMEXPT - mov cr4, ebx - - and ecx, not (CR0_MP+CR0_EM) - or ecx, CR0_NE - mov cr0, ecx - - mov dword [esp-4], SSE_INIT - ldmxcsr [esp-4] - - xorps xmm0, xmm0 - xorps xmm1, xmm1 - xorps xmm2, xmm2 - xorps xmm3, xmm3 - xorps xmm4, xmm4 - xorps xmm5, xmm5 - xorps xmm6, xmm6 - xorps xmm7, xmm7 - fxsave [fpu_data] ;[eax] - ret -.no_SSE: - mov ecx, cr0 - and ecx, not CR0_EM - or ecx, CR0_MP+CR0_NE - mov cr0, ecx - fnsave [fpu_data] - ret - -; param -; eax= 512 bytes memory area - -align 4 -fpu_save: - push ecx - push esi - push edi - - pushfd - cli - - clts - mov edi, eax - - mov ecx, [fpu_owner] - mov esi, [CURRENT_TASK] - cmp ecx, esi - jne .save - - call save_context - jmp .exit -.save: - mov [fpu_owner], esi - - shl ecx, 8 - mov eax, [ecx+SLOT_BASE+APPDATA.fpu_state] - - call save_context - - shl esi, 8 - mov esi, [esi+SLOT_BASE+APPDATA.fpu_state] - mov ecx, 512/4 - cld - rep movsd - fninit -.exit: - popfd - pop edi - pop esi - pop ecx - ret - -align 4 -save_context: - bt [cpu_caps], CAPS_SSE - jnc .no_SSE - - fxsave [eax] - ret -.no_SSE: - fnsave [eax] - ret - -align 4 -fpu_restore: - push ecx - push esi - - mov esi, eax - - pushfd - cli - - mov ecx, [fpu_owner] - mov eax, [CURRENT_TASK] - cmp ecx, eax - jne .copy - - clts - bt [cpu_caps], CAPS_SSE - jnc .no_SSE - - fxrstor [esi] - popfd - pop esi - pop ecx - ret -.no_SSE: - fnclex ;fix possible problems - frstor [esi] - popfd - pop esi - pop ecx - ret -.copy: - shl eax, 8 - mov edi, [eax+SLOT_BASE+APPDATA.fpu_state] - mov ecx, 512/4 - cld - rep movsd - popfd - pop esi - pop ecx - ret - -align 4 -except_7: ;#NM exception handler - save_ring3_context - clts - mov ax, app_data ; - mov ds, ax - mov es, ax - - mov ebx, [fpu_owner] - cmp ebx, [CURRENT_TASK] - je .exit - - shl ebx, 8 - mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] - bt [cpu_caps], CAPS_SSE - jnc .no_SSE - - fxsave [eax] - mov ebx, [CURRENT_TASK] - mov [fpu_owner], ebx - shl ebx, 8 - mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] - fxrstor [eax] -.exit: - restore_ring3_context - iret - -.no_SSE: - fnsave [eax] - mov ebx, [CURRENT_TASK] - mov [fpu_owner], ebx - shl ebx, 8 - mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] - frstor [eax] - restore_ring3_context - iret - -iglobal - fpu_owner dd 0 -endg +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +init_fpu: + clts + fninit + + bt [cpu_caps], CAPS_SSE + jnc .no_SSE + + mov ebx, cr4 + mov ecx, cr0 + or ebx, CR4_OSFXSR+CR4_OSXMMEXPT + mov cr4, ebx + + and ecx, not (CR0_MP+CR0_EM) + or ecx, CR0_NE + mov cr0, ecx + + mov dword [esp-4], SSE_INIT + ldmxcsr [esp-4] + + xorps xmm0, xmm0 + xorps xmm1, xmm1 + xorps xmm2, xmm2 + xorps xmm3, xmm3 + xorps xmm4, xmm4 + xorps xmm5, xmm5 + xorps xmm6, xmm6 + xorps xmm7, xmm7 + fxsave [fpu_data] ;[eax] + ret +.no_SSE: + mov ecx, cr0 + and ecx, not CR0_EM + or ecx, CR0_MP+CR0_NE + mov cr0, ecx + fnsave [fpu_data] + ret + +; param +; eax= 512 bytes memory area + +align 4 +fpu_save: + push ecx + push esi + push edi + + pushfd + cli + + clts + mov edi, eax + + mov ecx, [fpu_owner] + mov esi, [CURRENT_TASK] + cmp ecx, esi + jne .save + + call save_context + jmp .exit +.save: + mov [fpu_owner], esi + + shl ecx, 8 + mov eax, [ecx+SLOT_BASE+APPDATA.fpu_state] + + call save_context + + shl esi, 8 + mov esi, [esi+SLOT_BASE+APPDATA.fpu_state] + mov ecx, 512/4 + cld + rep movsd + fninit +.exit: + popfd + pop edi + pop esi + pop ecx + ret + +align 4 +save_context: + bt [cpu_caps], CAPS_SSE + jnc .no_SSE + + fxsave [eax] + ret +.no_SSE: + fnsave [eax] + ret + +align 4 +fpu_restore: + push ecx + push esi + + mov esi, eax + + pushfd + cli + + mov ecx, [fpu_owner] + mov eax, [CURRENT_TASK] + cmp ecx, eax + jne .copy + + clts + bt [cpu_caps], CAPS_SSE + jnc .no_SSE + + fxrstor [esi] + popfd + pop esi + pop ecx + ret +.no_SSE: + fnclex ;fix possible problems + frstor [esi] + popfd + pop esi + pop ecx + ret +.copy: + shl eax, 8 + mov edi, [eax+SLOT_BASE+APPDATA.fpu_state] + mov ecx, 512/4 + cld + rep movsd + popfd + pop esi + pop ecx + ret + +align 4 +except_7: ;#NM exception handler + save_ring3_context + clts + mov ax, app_data; + mov ds, ax + mov es, ax + + mov ebx, [fpu_owner] + cmp ebx, [CURRENT_TASK] + je .exit + + shl ebx, 8 + mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] + bt [cpu_caps], CAPS_SSE + jnc .no_SSE + + fxsave [eax] + mov ebx, [CURRENT_TASK] + mov [fpu_owner], ebx + shl ebx, 8 + mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] + fxrstor [eax] +.exit: + restore_ring3_context + iret + +.no_SSE: + fnsave [eax] + mov ebx, [CURRENT_TASK] + mov [fpu_owner], ebx + shl ebx, 8 + mov eax, [ebx+SLOT_BASE+APPDATA.fpu_state] + frstor [eax] + restore_ring3_context + iret + +iglobal + fpu_owner dd 0 +endg diff --git a/kernel/trunk/core/heap.inc b/kernel/trunk/core/heap.inc index 5b2880369..c9a2af85a 100644 --- a/kernel/trunk/core/heap.inc +++ b/kernel/trunk/core/heap.inc @@ -1,1474 +1,1474 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -struc MEM_BLOCK -{ - .list LHEAD - .next_block dd ? ;+8 - .prev_block dd ? ;+4 - .base dd ? ;+16 - .size dd ? ;+20 - .flags dd ? ;+24 - .handle dd ? ;+28 - .sizeof: -} - -FREE_BLOCK equ 4 -USED_BLOCK equ 8 -DONT_FREE_BLOCK equ 10h - -virtual at 0 - MEM_BLOCK MEM_BLOCK -end virtual - - -block_next equ MEM_BLOCK.next_block -block_prev equ MEM_BLOCK.prev_block -list_fd equ MEM_BLOCK.list.next -list_bk equ MEM_BLOCK.list.prev -block_base equ MEM_BLOCK.base -block_size equ MEM_BLOCK.size -block_flags equ MEM_BLOCK.flags - -macro calc_index op -{ shr op, 12 - dec op - cmp op, 63 - jna @f - mov op, 63 -@@: -} - -align 4 -md: -.add_to_used: - mov eax, [esi+block_base] - mov ebx, [esi+block_base] - shr ebx, 6 - add eax, ebx - shr ebx, 6 - add eax, ebx - shr eax, 12 - and eax, 63 - inc [mem_hash_cnt+eax*4] - - lea ecx, [mem_used_list+eax*8] - list_add esi, ecx - mov [esi+block_flags], USED_BLOCK - mov eax, [esi+block_size] - sub [heap_free], eax - ret -align 4 -.find_used: - mov ecx, eax - mov ebx, eax - shr ebx, 6 - add ecx, ebx - shr ebx, 6 - add ecx, ebx - shr ecx, 12 - and ecx, 63 - - lea ebx, [mem_used_list+ecx*8] - mov esi, ebx -.next: - mov esi, [esi+list_fd] - cmp esi, ebx - je .fail - - cmp eax, [esi+block_base] - jne .next - - ret -.fail: - xor esi, esi - ret - -align 4 -.del_from_used: - call .find_used - test esi, esi - jz .done - - cmp [esi+block_flags], USED_BLOCK - jne .fatal - - dec [mem_hash_cnt+ecx*4] - list_del esi -.done: - ret -.fatal: ;FIXME panic here - xor esi, esi - ret - -;Initial heap state -; -;+heap_size terminator USED_BLOCK -;+4096*MEM_BLOCK.sizeof free space FREE_BLOCK -;HEAP_BASE heap_descriptors USED_BLOCK -; - -align 4 -proc init_kernel_heap - - mov ecx, 64 - mov edi, mem_block_list -@@: - mov eax, edi - stosd - stosd - loop @B - - mov ecx, 64 - mov edi, mem_used_list -@@: - mov eax, edi - stosd - stosd - loop @B - - stdcall alloc_pages, dword 32 - mov ecx, 32 - mov edx, eax - mov edi, HEAP_BASE -.l1: - stdcall map_page,edi,edx,PG_SW - add edi, 0x1000 - add edx, 0x1000 - dec ecx - jnz .l1 - - mov edi, HEAP_BASE ;descriptors - mov ebx, HEAP_BASE+MEM_BLOCK.sizeof ;free space - mov ecx, HEAP_BASE+MEM_BLOCK.sizeof*2 ;terminator - - xor eax, eax - mov [edi+block_next], ebx - mov [edi+block_prev], eax - mov [edi+list_fd], eax - mov [edi+list_bk], eax - mov [edi+block_base], HEAP_BASE - mov [edi+block_size], 4096*MEM_BLOCK.sizeof - mov [edi+block_flags], USED_BLOCK - - mov [ecx+block_next], eax - mov [ecx+block_prev], ebx - mov [edi+list_fd], eax - mov [edi+list_bk], eax - mov [edi+block_base], eax - mov [edi+block_size], eax - mov [edi+block_flags], USED_BLOCK - - mov [ebx+block_next], ecx - mov [ebx+block_prev], edi - mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK.sizeof - - mov ecx, [pg_data.kernel_pages] - shl ecx, 12 - sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK.sizeof - mov [heap_size], ecx - mov [heap_free], ecx - mov [ebx+block_size], ecx - mov [ebx+block_flags], FREE_BLOCK - - mov [mem_block_mask], eax - mov [mem_block_mask+4],0x80000000 - - mov ecx, mem_block_list+63*8 - list_add ebx, ecx - - mov ecx, 4096-3-1 - mov eax, HEAP_BASE+MEM_BLOCK.sizeof*4 - - mov [next_memblock], HEAP_BASE+MEM_BLOCK.sizeof*3 -@@: - mov [eax-MEM_BLOCK.sizeof], eax - add eax, MEM_BLOCK.sizeof - loop @B - - mov [eax-MEM_BLOCK.sizeof], dword 0 - - mov ecx, heap_mutex - call mutex_init - mov [heap_blocks], 4094 - mov [free_blocks], 4093 - ret -endp - -; param -; eax= required size -; -; retval -; edi= memory block descriptor -; ebx= descriptor index - -align 4 -get_small_block: - mov ecx, eax - shr ecx, 12 - dec ecx - cmp ecx, 63 - jle .get_index - mov ecx, 63 -.get_index: - lea esi, [mem_block_mask] - xor ebx, ebx - or edx, -1 - - cmp ecx, 32 - jb .bit_test - - sub ecx, 32 - add ebx, 32 - add esi, 4 -.bit_test: - shl edx, cl - and edx, [esi] -.find: - bsf edi, edx - jz .high_mask - add ebx, edi - lea ecx, [mem_block_list+ebx*8] - mov edi, ecx -.next: - mov edi, [edi+list_fd] - cmp edi, ecx - je .err - cmp eax, [edi+block_size] - ja .next - ret -.err: - xor edi, edi - ret - -.high_mask: - add esi, 4 - cmp esi, mem_block_mask+8 - jae .err - add ebx, 32 - mov edx, [esi] - jmp .find - - -align 4 -free_mem_block: - mov ebx, [next_memblock] - mov [eax], ebx - mov [next_memblock], eax - xor ebx, ebx - - mov dword [eax+4], ebx - mov dword [eax+8], ebx - mov dword [eax+12], ebx - mov dword [eax+16], ebx -; mov dword [eax+20], 0 ;don't clear block size - mov dword [eax+24], ebx - mov dword [eax+28], ebx - inc [free_blocks] - ret - -align 4 -proc alloc_kernel_space stdcall, size:dword - local block_ind:DWORD - - push ebx - push esi - push edi - - mov eax, [size] - add eax, 4095 - and eax, not 4095 - mov [size], eax - - cmp eax, [heap_free] - ja .error - - mov ecx, heap_mutex - call mutex_lock - - mov eax, [size] - - call get_small_block ; eax - test edi, edi - jz .error_unlock - - cmp [edi+block_flags], FREE_BLOCK - jne .error_unlock - - mov [block_ind], ebx ;index of allocated block - - mov eax, [edi+block_size] - cmp eax, [size] - je .m_eq_size - - mov esi, [next_memblock] ;new memory block - test esi, esi - jz .error_unlock - - dec [free_blocks] - mov eax, [esi] - mov [next_memblock], eax - - mov [esi+block_next], edi - mov eax, [edi+block_prev] - mov [esi+block_prev], eax - mov [edi+block_prev], esi - mov [esi+list_fd], 0 - mov [esi+list_bk], 0 - mov [eax+block_next], esi - - mov ebx, [edi+block_base] - mov [esi+block_base], ebx - mov edx, [size] - mov [esi+block_size], edx - add [edi+block_base], edx - sub [edi+block_size], edx - - mov eax, [edi+block_size] - calc_index eax - cmp eax, [block_ind] - je .add_used - - list_del edi - - mov ecx, [block_ind] - lea edx, [mem_block_list+ecx*8] - cmp edx, [edx] - jnz @f - btr [mem_block_mask], ecx -@@: - bts [mem_block_mask], eax - lea edx, [mem_block_list+eax*8] ;edx= list head - list_add edi, edx -.add_used: - - call md.add_to_used - - mov ecx, heap_mutex - call mutex_unlock - mov eax, [esi+block_base] - pop edi - pop esi - pop ebx - ret - -.m_eq_size: - list_del edi - lea edx, [mem_block_list+ebx*8] - cmp edx, [edx] - jnz @f - btr [mem_block_mask], ebx -@@: - mov esi, edi - jmp .add_used - -.error_unlock: - mov ecx, heap_mutex - call mutex_unlock -.error: - xor eax, eax - pop edi - pop esi - pop ebx - ret -endp - -align 4 -proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword - - mov ecx, heap_mutex - call mutex_lock - - mov eax, [base] - - call md.del_from_used - test esi, esi - jz .fail - - mov eax, [esi+block_size] - add [heap_free], eax - - mov edi, [esi+block_next] - cmp [edi+block_flags], FREE_BLOCK - jne .prev - - list_del edi - - mov edx, [edi+block_next] - mov [esi+block_next], edx - mov [edx+block_prev], esi - mov ecx, [edi+block_size] - add [esi+block_size], ecx - - calc_index ecx - - lea edx, [mem_block_list+ecx*8] - cmp edx, [edx] - jne @F - btr [mem_block_mask], ecx -@@: - mov eax, edi - call free_mem_block -.prev: - mov edi, [esi+block_prev] - cmp [edi+block_flags], FREE_BLOCK - jne .insert - - mov edx, [esi+block_next] - mov [edi+block_next], edx - mov [edx+block_prev], edi - - mov eax, esi - call free_mem_block - - mov ecx, [edi+block_size] - mov eax, [esi+block_size] - add eax, ecx - mov [edi+block_size], eax - - calc_index eax ;new index - calc_index ecx ;old index - cmp eax, ecx - je .m_eq - - push ecx - list_del edi - pop ecx - - lea edx, [mem_block_list+ecx*8] - cmp edx, [edx] - jne .add_block - btr [mem_block_mask], ecx -.add_block: - bts [mem_block_mask], eax - lea edx, [mem_block_list+eax*8] - list_add edi, edx -.m_eq: - mov ecx, heap_mutex - call mutex_unlock - xor eax, eax - not eax - ret -.insert: - mov [esi+block_flags], FREE_BLOCK - mov eax, [esi+block_size] - calc_index eax - mov edi, esi - jmp .add_block - -.fail: - mov ecx, heap_mutex - call mutex_unlock - xor eax, eax - ret -endp - -align 4 -proc kernel_alloc stdcall, size:dword - locals - lin_addr dd ? - pages_count dd ? - endl - - push ebx - push edi - - mov eax, [size] - add eax, 4095 - and eax, not 4095; - mov [size], eax - and eax, eax - jz .err - mov ebx, eax - shr ebx, 12 - mov [pages_count], ebx - - stdcall alloc_kernel_space, eax - test eax, eax - jz .err - mov [lin_addr], eax - - mov ecx, [pages_count] - mov edx, eax - mov ebx, ecx - - shr ecx, 3 - jz .next - - and ebx, not 7 - push ebx - stdcall alloc_pages, ebx - pop ecx ; yes ecx!!! - and eax, eax - jz .err - - mov edi, eax - mov edx, [lin_addr] -@@: - stdcall map_page,edx,edi,dword PG_SW - add edx, 0x1000 - add edi, 0x1000 - dec ecx - jnz @B -.next: - mov ecx, [pages_count] - and ecx, 7 - jz .end -@@: - push ecx - call alloc_page - pop ecx - test eax, eax - jz .err - - stdcall map_page,edx,eax,dword PG_SW - add edx, 0x1000 - dec ecx - jnz @B -.end: - mov eax, [lin_addr] - pop edi - pop ebx - ret -.err: - xor eax, eax - pop edi - pop ebx - ret -endp - -align 4 -proc kernel_free stdcall, base:dword - - push ebx esi - - mov ecx, heap_mutex - call mutex_lock - - mov eax, [base] - call md.find_used - - mov ecx, heap_mutex - cmp [esi+block_flags], USED_BLOCK - jne .fail - - call mutex_unlock - - mov eax, [esi+block_base] - mov ecx, [esi+block_size] - shr ecx, 12 - call release_pages ;eax, ecx - stdcall free_kernel_space, [base] - pop esi ebx - ret -.fail: - call mutex_unlock - xor eax, eax - pop esi ebx - ret -endp - -restore block_next -restore block_prev -restore block_list -restore block_base -restore block_size -restore block_flags - -;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;; - -HEAP_TOP equ 0x5FC00000 - -align 4 -proc init_heap - - mov ebx,[current_slot] - mov eax, [ebx+APPDATA.heap_top] - test eax, eax - jz @F - sub eax,[ebx+APPDATA.heap_base] - sub eax, 4096 - ret -@@: - mov esi, [ebx+APPDATA.mem_size] - add esi, 4095 - and esi, not 4095 - mov [ebx+APPDATA.mem_size], esi - mov eax, HEAP_TOP - mov [ebx+APPDATA.heap_base], esi - mov [ebx+APPDATA.heap_top], eax - - sub eax, esi - shr esi, 10 - mov ecx, eax - sub eax, 4096 - or ecx, FREE_BLOCK - mov [page_tabs+esi], ecx - ret -endp - -align 4 -proc user_alloc stdcall, alloc_size:dword - - push ebx - push esi - push edi - - mov ecx, [alloc_size] - add ecx, (4095+4096) - and ecx, not 4095 - - mov ebx, [current_slot] - mov esi, dword [ebx+APPDATA.heap_base] ; heap_base - mov edi, dword [ebx+APPDATA.heap_top] ; heap_top -l_0: - cmp esi, edi - jae m_exit - - mov ebx, esi - shr ebx, 12 - mov eax, [page_tabs+ebx*4] - test al, FREE_BLOCK - jz test_used - and eax, 0xFFFFF000 - cmp eax, ecx ;alloc_size - jb m_next - jz @f - - lea edx, [esi+ecx] - sub eax, ecx - or al, FREE_BLOCK - shr edx, 12 - mov [page_tabs+edx*4], eax -@@: - or ecx, USED_BLOCK - mov [page_tabs+ebx*4], ecx - shr ecx, 12 - inc ebx - dec ecx - jz .no -@@: - mov dword [page_tabs+ebx*4], 2 - inc ebx - dec ecx - jnz @B -.no: - - mov edx, [current_slot] - mov ebx, [alloc_size] - add ebx, 0xFFF - and ebx, not 0xFFF - add ebx, [edx+APPDATA.mem_size] - call update_mem_size - - lea eax, [esi+4096] - - pop edi - pop esi - pop ebx - ret -test_used: - test al, USED_BLOCK - jz m_exit - - and eax, 0xFFFFF000 -m_next: - add esi, eax - jmp l_0 -m_exit: - xor eax, eax - pop edi - pop esi - pop ebx - ret -endp - -align 4 -proc user_alloc_at stdcall, address:dword, alloc_size:dword - - push ebx - push esi - push edi - - mov ebx, [current_slot] - mov edx, [address] - and edx, not 0xFFF - mov [address], edx - sub edx, 0x1000 - jb .error - mov esi, [ebx+APPDATA.heap_base] - mov edi, [ebx+APPDATA.heap_top] - cmp edx, esi - jb .error -.scan: - cmp esi, edi - jae .error - mov ebx, esi - shr ebx, 12 - mov eax, [page_tabs+ebx*4] - mov ecx, eax - and ecx, 0xFFFFF000 - add ecx, esi - cmp edx, ecx - jb .found - mov esi, ecx - jmp .scan -.error: - xor eax, eax - pop edi - pop esi - pop ebx - ret -.found: - test al, FREE_BLOCK - jz .error - mov eax, ecx - sub eax, edx - sub eax, 0x1000 - cmp eax, [alloc_size] - jb .error - -; Here we have 1 big free block which includes requested area. -; In general, 3 other blocks must be created instead: -; free at [esi, edx); -; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000)); -; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx) -; First or third block (or both) may be absent. - mov eax, edx - sub eax, esi - jz .nofirst - or al, FREE_BLOCK - mov [page_tabs+ebx*4], eax -.nofirst: - mov eax, [alloc_size] - add eax, 0x1FFF - and eax, not 0xFFF - mov ebx, edx - add edx, eax - shr ebx, 12 - or al, USED_BLOCK - mov [page_tabs+ebx*4], eax - shr eax, 12 - dec eax - jz .second_nofill - inc ebx -.fill: - mov dword [page_tabs+ebx*4], 2 - inc ebx - dec eax - jnz .fill -.second_nofill: - sub ecx, edx - jz .nothird - or cl, FREE_BLOCK - mov [page_tabs+ebx*4], ecx -.nothird: - - mov edx, [current_slot] - mov ebx, [alloc_size] - add ebx, 0xFFF - and ebx, not 0xFFF - add ebx, [edx+APPDATA.mem_size] - call update_mem_size - - mov eax, [address] - - pop edi - pop esi - pop ebx - ret -endp - -align 4 -proc user_free stdcall, base:dword - - push esi - - mov esi, [base] - test esi, esi - jz .exit - - push ebx - - xor ebx, ebx - shr esi, 12 - mov eax, [page_tabs+(esi-1)*4] - test al, USED_BLOCK - jz .cantfree - test al, DONT_FREE_BLOCK - jnz .cantfree - - and eax, not 4095 - mov ecx, eax - or al, FREE_BLOCK - mov [page_tabs+(esi-1)*4], eax - sub ecx, 4096 - mov ebx, ecx - shr ecx, 12 - jz .released -.release: - xor eax, eax - xchg eax, [page_tabs+esi*4] - test al, 1 - jz @F - test eax, PG_SHARED - jnz @F - call free_page - mov eax, esi - shl eax, 12 - invlpg [eax] -@@: - inc esi - dec ecx - jnz .release -.released: - push edi - - mov edx, [current_slot] - mov esi, dword [edx+APPDATA.heap_base] - mov edi, dword [edx+APPDATA.heap_top] - sub ebx, [edx+APPDATA.mem_size] - neg ebx - call update_mem_size - call user_normalize - pop edi - pop ebx - pop esi - ret -.exit: - xor eax, eax - inc eax - pop esi - ret -.cantfree: - xor eax, eax - pop ebx - pop esi - ret -endp - -user_normalize: -; in: esi=heap_base, edi=heap_top -; out: eax=0 <=> OK -; destroys: ebx,edx,esi,edi - shr esi, 12 - shr edi, 12 -@@: - mov eax, [page_tabs+esi*4] - test al, USED_BLOCK - jz .test_free - shr eax, 12 - add esi, eax - jmp @B -.test_free: - test al, FREE_BLOCK - jz .err - mov edx, eax - shr edx, 12 - add edx, esi - cmp edx, edi - jae .exit - - mov ebx, [page_tabs+edx*4] - test bl, USED_BLOCK - jz .next_free - - shr ebx, 12 - add edx, ebx - mov esi, edx - jmp @B -.next_free: - test bl, FREE_BLOCK - jz .err - and dword [page_tabs+edx*4], 0 - add eax, ebx - and eax, not 4095 - or eax, FREE_BLOCK - mov [page_tabs+esi*4], eax - jmp @B -.exit: - xor eax, eax - inc eax - ret -.err: - xor eax, eax - ret - -user_realloc: -; in: eax = pointer, ebx = new size -; out: eax = new pointer or NULL - test eax, eax - jnz @f -; realloc(NULL,sz) - same as malloc(sz) - push ebx - call user_alloc - ret -@@: - push ecx edx - lea ecx, [eax - 0x1000] - shr ecx, 12 - mov edx, [page_tabs+ecx*4] - test dl, USED_BLOCK - jnz @f -; attempt to realloc invalid pointer -.ret0: - pop edx ecx - xor eax, eax - ret -@@: - test dl, DONT_FREE_BLOCK - jnz .ret0 - add ebx, 0x1FFF - shr edx, 12 - shr ebx, 12 -; edx = allocated size, ebx = new size - add edx, ecx - add ebx, ecx - cmp edx, ebx - jb .realloc_add -; release part of allocated memory -.loop: - cmp edx, ebx - jz .release_done - dec edx - xor eax, eax - xchg eax, [page_tabs+edx*4] - test al, 1 - jz .loop - call free_page - mov eax, edx - shl eax, 12 - invlpg [eax] - jmp .loop -.release_done: - sub ebx, ecx - cmp ebx, 1 - jnz .nofreeall - mov eax, [page_tabs+ecx*4] - and eax, not 0xFFF - mov edx, [current_slot] - mov ebx, [APPDATA.mem_size+edx] - sub ebx, eax - add ebx, 0x1000 - or al, FREE_BLOCK - mov [page_tabs+ecx*4], eax - push esi edi - mov esi, [APPDATA.heap_base+edx] - mov edi, [APPDATA.heap_top+edx] - call update_mem_size - call user_normalize - pop edi esi - jmp .ret0 ; all freed -.nofreeall: - sub edx, ecx - shl ebx, 12 - or ebx, USED_BLOCK - xchg [page_tabs+ecx*4], ebx - shr ebx, 12 - sub ebx, edx - push ebx ecx edx - mov edx, [current_slot] - shl ebx, 12 - sub ebx, [APPDATA.mem_size+edx] - neg ebx - call update_mem_size - pop edx ecx ebx - lea eax, [ecx+1] - shl eax, 12 - push eax - add ecx, edx - lea edx, [ecx+ebx] - shl ebx, 12 - jz .ret - push esi - mov esi, [current_slot] - mov esi, [APPDATA.heap_top+esi] - shr esi, 12 -@@: - cmp edx, esi - jae .merge_done - mov eax, [page_tabs+edx*4] - test al, USED_BLOCK - jnz .merge_done - and dword [page_tabs+edx*4], 0 - shr eax, 12 - add edx, eax - shl eax, 12 - add ebx, eax - jmp @b -.merge_done: - pop esi - or ebx, FREE_BLOCK - mov [page_tabs+ecx*4], ebx -.ret: - pop eax edx ecx - ret -.realloc_add: -; get some additional memory - mov eax, [current_slot] - mov eax, [APPDATA.heap_top+eax] - shr eax, 12 - cmp edx, eax - jae .cant_inplace - mov eax, [page_tabs+edx*4] - test al, FREE_BLOCK - jz .cant_inplace - shr eax, 12 - add eax, edx - sub eax, ebx - jb .cant_inplace - jz @f - shl eax, 12 - or al, FREE_BLOCK - mov [page_tabs+ebx*4], eax -@@: - mov eax, ebx - sub eax, ecx - shl eax, 12 - or al, USED_BLOCK - mov [page_tabs+ecx*4], eax - lea eax, [ecx+1] - shl eax, 12 - push eax - push edi - lea edi, [page_tabs+edx*4] - mov eax, 2 - sub ebx, edx - mov ecx, ebx - cld - rep stosd - pop edi - mov edx, [current_slot] - shl ebx, 12 - add ebx, [APPDATA.mem_size+edx] - call update_mem_size - pop eax edx ecx - ret -.cant_inplace: - push esi edi - mov eax, [current_slot] - mov esi, [APPDATA.heap_base+eax] - mov edi, [APPDATA.heap_top+eax] - shr esi, 12 - shr edi, 12 - sub ebx, ecx -.find_place: - cmp esi, edi - jae .place_not_found - mov eax, [page_tabs+esi*4] - test al, FREE_BLOCK - jz .next_place - shr eax, 12 - cmp eax, ebx - jae .place_found - add esi, eax - jmp .find_place -.next_place: - shr eax, 12 - add esi, eax - jmp .find_place -.place_not_found: - pop edi esi - jmp .ret0 -.place_found: - sub eax, ebx - jz @f - push esi - add esi, ebx - shl eax, 12 - or al, FREE_BLOCK - mov [page_tabs+esi*4], eax - pop esi -@@: - mov eax, ebx - shl eax, 12 - or al, USED_BLOCK - mov [page_tabs+esi*4], eax - inc esi - mov eax, esi - shl eax, 12 - push eax - mov eax, [page_tabs+ecx*4] - and eax, not 0xFFF - or al, FREE_BLOCK - sub edx, ecx - mov [page_tabs+ecx*4], eax - inc ecx - dec ebx - dec edx - jz .no -@@: - xor eax, eax - xchg eax, [page_tabs+ecx*4] - mov [page_tabs+esi*4], eax - mov eax, ecx - shl eax, 12 - invlpg [eax] - inc esi - inc ecx - dec ebx - dec edx - jnz @b -.no: - push ebx - mov edx, [current_slot] - shl ebx, 12 - add ebx, [APPDATA.mem_size+edx] - call update_mem_size - pop ebx -@@: - mov dword [page_tabs+esi*4], 2 - inc esi - dec ebx - jnz @b - pop eax edi esi edx ecx - ret - -if 0 -align 4 -proc alloc_dll - pushf - cli - bsf eax, [dll_map] - jnz .find - popf - xor eax, eax - ret -.find: - btr [dll_map], eax - popf - shl eax, 5 - add eax, dll_tab - ret -endp - -align 4 -proc alloc_service - pushf - cli - bsf eax, [srv_map] - jnz .find - popf - xor eax, eax - ret -.find: - btr [srv_map], eax - popf - shl eax,0x02 - lea eax,[srv_tab+eax+eax*8] ;srv_tab+eax*36 - ret -endp - -end if - - -;;;;;;;;;;;;;; SHARED ;;;;;;;;;;;;;;;;; - - -; param -; eax= shm_map object - -align 4 -destroy_smap: - - pushfd - cli - - push esi - push edi - - mov edi, eax - mov esi, [eax+SMAP.parent] - test esi, esi - jz .done - - lock dec [esi+SMEM.refcount] - jnz .done - - mov ecx, [esi+SMEM.bk] - mov edx, [esi+SMEM.fd] - - mov [ecx+SMEM.fd], edx - mov [edx+SMEM.bk], ecx - - stdcall kernel_free, [esi+SMEM.base] - mov eax, esi - call free -.done: - mov eax, edi - call destroy_kernel_object - - pop edi - pop esi - popfd - - ret - -E_NOTFOUND equ 5 -E_ACCESS equ 10 -E_NOMEM equ 30 -E_PARAM equ 33 - -SHM_READ equ 0 -SHM_WRITE equ 1 - -SHM_ACCESS_MASK equ 3 - -SHM_OPEN equ (0 shl 2) -SHM_OPEN_ALWAYS equ (1 shl 2) -SHM_CREATE equ (2 shl 2) - -SHM_OPEN_MASK equ (3 shl 2) - -align 4 -proc shmem_open stdcall name:dword, size:dword, access:dword - locals - action dd ? - owner_access dd ? - mapped dd ? - endl - - push ebx - push esi - push edi - - mov [mapped], 0 - mov [owner_access], 0 - - pushfd ;mutex required - cli - - mov eax, [access] - and eax, SHM_OPEN_MASK - mov [action], eax - - mov ebx, [name] - test ebx, ebx - mov edx, E_PARAM - jz .fail - - mov esi, [shmem_list.fd] -align 4 -@@: - cmp esi, shmem_list - je .not_found - - lea edx, [esi+SMEM.name] ; link , base, size - stdcall strncmp, edx, ebx, 32 - test eax, eax - je .found - - mov esi, [esi+SMEM.fd] - jmp @B - -.not_found: - mov eax, [action] - - cmp eax, SHM_OPEN - mov edx, E_NOTFOUND - je .fail - - cmp eax, SHM_CREATE - mov edx, E_PARAM - je .create_shm - - cmp eax, SHM_OPEN_ALWAYS - jne .fail - -.create_shm: - - mov ecx, [size] - test ecx, ecx - jz .fail - - add ecx, 4095 - and ecx, -4096 - mov [size], ecx - - mov eax, SMEM.sizeof - call malloc - test eax, eax - mov esi, eax - mov edx, E_NOMEM - jz .fail - - stdcall kernel_alloc, [size] - test eax, eax - mov [mapped], eax - mov edx, E_NOMEM - jz .cleanup - - mov ecx, [size] - mov edx, [access] - and edx, SHM_ACCESS_MASK - - mov [esi+SMEM.base], eax - mov [esi+SMEM.size], ecx - mov [esi+SMEM.access], edx - mov [esi+SMEM.refcount], 0 - mov [esi+SMEM.name+28], 0 - - lea eax, [esi+SMEM.name] - stdcall strncpy, eax, [name], 31 - - mov eax, [shmem_list.fd] - mov [esi+SMEM.bk], shmem_list - mov [esi+SMEM.fd], eax - - mov [eax+SMEM.bk], esi - mov [shmem_list.fd], esi - - mov [action], SHM_OPEN - mov [owner_access], SHM_WRITE - -.found: - mov eax, [action] - - cmp eax, SHM_CREATE - mov edx, E_ACCESS - je .exit - - cmp eax, SHM_OPEN - mov edx, E_PARAM - je .create_map - - cmp eax, SHM_OPEN_ALWAYS - jne .fail - -.create_map: - - mov eax, [access] - and eax, SHM_ACCESS_MASK - cmp eax, [esi+SMEM.access] - mov [access], eax - mov edx, E_ACCESS - ja .fail - - mov ebx, [CURRENT_TASK] - shl ebx, 5 - mov ebx, [CURRENT_TASK+ebx+4] - mov eax, SMAP.sizeof - - call create_kernel_object - test eax, eax - mov edi, eax - mov edx, E_NOMEM - jz .fail - - inc [esi+SMEM.refcount] - - mov [edi+SMAP.magic], 'SMAP' - mov [edi+SMAP.destroy], destroy_smap - mov [edi+SMAP.parent], esi - mov [edi+SMAP.base], 0 - - stdcall user_alloc, [esi+SMEM.size] - test eax, eax - mov [mapped], eax - mov edx, E_NOMEM - jz .cleanup2 - - mov [edi+SMAP.base], eax - - mov ecx, [esi+SMEM.size] - mov [size], ecx - - shr ecx, 12 - shr eax, 10 - - mov esi, [esi+SMEM.base] - shr esi, 10 - lea edi, [page_tabs+eax] - add esi, page_tabs - - mov edx, [access] - or edx, [owner_access] - shl edx, 1 - or edx, PG_USER+PG_SHARED -@@: - lodsd - and eax, 0xFFFFF000 - or eax, edx - stosd - loop @B - - xor edx, edx - - cmp [owner_access], 0 - jne .fail -.exit: - mov edx, [size] -.fail: - mov eax, [mapped] - - popfd - pop edi - pop esi - pop ebx - ret -.cleanup: - mov [size], edx - mov eax, esi - call free - jmp .exit - -.cleanup2: - mov [size], edx - mov eax, edi - call destroy_smap - jmp .exit -endp - -align 4 -proc shmem_close stdcall, name:dword - - mov eax, [name] - test eax, eax - jz .fail - - push esi - push edi - pushfd - cli - - mov esi, [current_slot] - add esi, APP_OBJ_OFFSET -.next: - mov eax, [esi+APPOBJ.fd] - test eax, eax - jz @F - - cmp eax, esi - mov esi, eax - je @F - - cmp [eax+SMAP.magic], 'SMAP' - jne .next - - mov edi, [eax+SMAP.parent] - test edi, edi - jz .next - - lea edi, [edi+SMEM.name] - stdcall strncmp, [name], edi, 32 - test eax, eax - jne .next - - stdcall user_free, [esi+SMAP.base] - - mov eax,esi - call [esi+APPOBJ.destroy] -@@: - popfd - pop edi - pop esi -.fail: - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +struc MEM_BLOCK +{ + .list LHEAD + .next_block dd ? ;+8 + .prev_block dd ? ;+4 + .base dd ? ;+16 + .size dd ? ;+20 + .flags dd ? ;+24 + .handle dd ? ;+28 + .sizeof: +} + +FREE_BLOCK equ 4 +USED_BLOCK equ 8 +DONT_FREE_BLOCK equ 10h + +virtual at 0 + MEM_BLOCK MEM_BLOCK +end virtual + + +block_next equ MEM_BLOCK.next_block +block_prev equ MEM_BLOCK.prev_block +list_fd equ MEM_BLOCK.list.next +list_bk equ MEM_BLOCK.list.prev +block_base equ MEM_BLOCK.base +block_size equ MEM_BLOCK.size +block_flags equ MEM_BLOCK.flags + +macro calc_index op +{ shr op, 12 + dec op + cmp op, 63 + jna @f + mov op, 63 +@@: +} + +align 4 +md: +.add_to_used: + mov eax, [esi+block_base] + mov ebx, [esi+block_base] + shr ebx, 6 + add eax, ebx + shr ebx, 6 + add eax, ebx + shr eax, 12 + and eax, 63 + inc [mem_hash_cnt+eax*4] + + lea ecx, [mem_used_list+eax*8] + list_add esi, ecx + mov [esi+block_flags], USED_BLOCK + mov eax, [esi+block_size] + sub [heap_free], eax + ret +align 4 +.find_used: + mov ecx, eax + mov ebx, eax + shr ebx, 6 + add ecx, ebx + shr ebx, 6 + add ecx, ebx + shr ecx, 12 + and ecx, 63 + + lea ebx, [mem_used_list+ecx*8] + mov esi, ebx +.next: + mov esi, [esi+list_fd] + cmp esi, ebx + je .fail + + cmp eax, [esi+block_base] + jne .next + + ret +.fail: + xor esi, esi + ret + +align 4 +.del_from_used: + call .find_used + test esi, esi + jz .done + + cmp [esi+block_flags], USED_BLOCK + jne .fatal + + dec [mem_hash_cnt+ecx*4] + list_del esi +.done: + ret +.fatal: ;FIXME panic here + xor esi, esi + ret + +;Initial heap state +; +;+heap_size terminator USED_BLOCK +;+4096*MEM_BLOCK.sizeof free space FREE_BLOCK +;HEAP_BASE heap_descriptors USED_BLOCK +; + +align 4 +proc init_kernel_heap + + mov ecx, 64 + mov edi, mem_block_list +@@: + mov eax, edi + stosd + stosd + loop @B + + mov ecx, 64 + mov edi, mem_used_list +@@: + mov eax, edi + stosd + stosd + loop @B + + stdcall alloc_pages, dword 32 + mov ecx, 32 + mov edx, eax + mov edi, HEAP_BASE +.l1: + stdcall map_page, edi, edx, PG_SW + add edi, 0x1000 + add edx, 0x1000 + dec ecx + jnz .l1 + + mov edi, HEAP_BASE ;descriptors + mov ebx, HEAP_BASE+MEM_BLOCK.sizeof ;free space + mov ecx, HEAP_BASE+MEM_BLOCK.sizeof*2 ;terminator + + xor eax, eax + mov [edi+block_next], ebx + mov [edi+block_prev], eax + mov [edi+list_fd], eax + mov [edi+list_bk], eax + mov [edi+block_base], HEAP_BASE + mov [edi+block_size], 4096*MEM_BLOCK.sizeof + mov [edi+block_flags], USED_BLOCK + + mov [ecx+block_next], eax + mov [ecx+block_prev], ebx + mov [edi+list_fd], eax + mov [edi+list_bk], eax + mov [edi+block_base], eax + mov [edi+block_size], eax + mov [edi+block_flags], USED_BLOCK + + mov [ebx+block_next], ecx + mov [ebx+block_prev], edi + mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK.sizeof + + mov ecx, [pg_data.kernel_pages] + shl ecx, 12 + sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK.sizeof + mov [heap_size], ecx + mov [heap_free], ecx + mov [ebx+block_size], ecx + mov [ebx+block_flags], FREE_BLOCK + + mov [mem_block_mask], eax + mov [mem_block_mask+4], 0x80000000 + + mov ecx, mem_block_list+63*8 + list_add ebx, ecx + + mov ecx, 4096-3-1 + mov eax, HEAP_BASE+MEM_BLOCK.sizeof*4 + + mov [next_memblock], HEAP_BASE+MEM_BLOCK.sizeof*3 +@@: + mov [eax-MEM_BLOCK.sizeof], eax + add eax, MEM_BLOCK.sizeof + loop @B + + mov [eax-MEM_BLOCK.sizeof], dword 0 + + mov ecx, heap_mutex + call mutex_init + mov [heap_blocks], 4094 + mov [free_blocks], 4093 + ret +endp + +; param +; eax= required size +; +; retval +; edi= memory block descriptor +; ebx= descriptor index + +align 4 +get_small_block: + mov ecx, eax + shr ecx, 12 + dec ecx + cmp ecx, 63 + jle .get_index + mov ecx, 63 +.get_index: + lea esi, [mem_block_mask] + xor ebx, ebx + or edx, -1 + + cmp ecx, 32 + jb .bit_test + + sub ecx, 32 + add ebx, 32 + add esi, 4 +.bit_test: + shl edx, cl + and edx, [esi] +.find: + bsf edi, edx + jz .high_mask + add ebx, edi + lea ecx, [mem_block_list+ebx*8] + mov edi, ecx +.next: + mov edi, [edi+list_fd] + cmp edi, ecx + je .err + cmp eax, [edi+block_size] + ja .next + ret +.err: + xor edi, edi + ret + +.high_mask: + add esi, 4 + cmp esi, mem_block_mask+8 + jae .err + add ebx, 32 + mov edx, [esi] + jmp .find + + +align 4 +free_mem_block: + mov ebx, [next_memblock] + mov [eax], ebx + mov [next_memblock], eax + xor ebx, ebx + + mov dword [eax+4], ebx + mov dword [eax+8], ebx + mov dword [eax+12], ebx + mov dword [eax+16], ebx +; mov dword [eax+20], 0 ;don't clear block size + mov dword [eax+24], ebx + mov dword [eax+28], ebx + inc [free_blocks] + ret + +align 4 +proc alloc_kernel_space stdcall, size:dword + local block_ind:DWORD + + push ebx + push esi + push edi + + mov eax, [size] + add eax, 4095 + and eax, not 4095 + mov [size], eax + + cmp eax, [heap_free] + ja .error + + mov ecx, heap_mutex + call mutex_lock + + mov eax, [size] + + call get_small_block ; eax + test edi, edi + jz .error_unlock + + cmp [edi+block_flags], FREE_BLOCK + jne .error_unlock + + mov [block_ind], ebx ;index of allocated block + + mov eax, [edi+block_size] + cmp eax, [size] + je .m_eq_size + + mov esi, [next_memblock] ;new memory block + test esi, esi + jz .error_unlock + + dec [free_blocks] + mov eax, [esi] + mov [next_memblock], eax + + mov [esi+block_next], edi + mov eax, [edi+block_prev] + mov [esi+block_prev], eax + mov [edi+block_prev], esi + mov [esi+list_fd], 0 + mov [esi+list_bk], 0 + mov [eax+block_next], esi + + mov ebx, [edi+block_base] + mov [esi+block_base], ebx + mov edx, [size] + mov [esi+block_size], edx + add [edi+block_base], edx + sub [edi+block_size], edx + + mov eax, [edi+block_size] + calc_index eax + cmp eax, [block_ind] + je .add_used + + list_del edi + + mov ecx, [block_ind] + lea edx, [mem_block_list+ecx*8] + cmp edx, [edx] + jnz @f + btr [mem_block_mask], ecx +@@: + bts [mem_block_mask], eax + lea edx, [mem_block_list+eax*8] ;edx= list head + list_add edi, edx +.add_used: + + call md.add_to_used + + mov ecx, heap_mutex + call mutex_unlock + mov eax, [esi+block_base] + pop edi + pop esi + pop ebx + ret + +.m_eq_size: + list_del edi + lea edx, [mem_block_list+ebx*8] + cmp edx, [edx] + jnz @f + btr [mem_block_mask], ebx +@@: + mov esi, edi + jmp .add_used + +.error_unlock: + mov ecx, heap_mutex + call mutex_unlock +.error: + xor eax, eax + pop edi + pop esi + pop ebx + ret +endp + +align 4 +proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword + + mov ecx, heap_mutex + call mutex_lock + + mov eax, [base] + + call md.del_from_used + test esi, esi + jz .fail + + mov eax, [esi+block_size] + add [heap_free], eax + + mov edi, [esi+block_next] + cmp [edi+block_flags], FREE_BLOCK + jne .prev + + list_del edi + + mov edx, [edi+block_next] + mov [esi+block_next], edx + mov [edx+block_prev], esi + mov ecx, [edi+block_size] + add [esi+block_size], ecx + + calc_index ecx + + lea edx, [mem_block_list+ecx*8] + cmp edx, [edx] + jne @F + btr [mem_block_mask], ecx +@@: + mov eax, edi + call free_mem_block +.prev: + mov edi, [esi+block_prev] + cmp [edi+block_flags], FREE_BLOCK + jne .insert + + mov edx, [esi+block_next] + mov [edi+block_next], edx + mov [edx+block_prev], edi + + mov eax, esi + call free_mem_block + + mov ecx, [edi+block_size] + mov eax, [esi+block_size] + add eax, ecx + mov [edi+block_size], eax + + calc_index eax ;new index + calc_index ecx ;old index + cmp eax, ecx + je .m_eq + + push ecx + list_del edi + pop ecx + + lea edx, [mem_block_list+ecx*8] + cmp edx, [edx] + jne .add_block + btr [mem_block_mask], ecx +.add_block: + bts [mem_block_mask], eax + lea edx, [mem_block_list+eax*8] + list_add edi, edx +.m_eq: + mov ecx, heap_mutex + call mutex_unlock + xor eax, eax + not eax + ret +.insert: + mov [esi+block_flags], FREE_BLOCK + mov eax, [esi+block_size] + calc_index eax + mov edi, esi + jmp .add_block + +.fail: + mov ecx, heap_mutex + call mutex_unlock + xor eax, eax + ret +endp + +align 4 +proc kernel_alloc stdcall, size:dword + locals + lin_addr dd ? + pages_count dd ? + endl + + push ebx + push edi + + mov eax, [size] + add eax, 4095 + and eax, not 4095; + mov [size], eax + and eax, eax + jz .err + mov ebx, eax + shr ebx, 12 + mov [pages_count], ebx + + stdcall alloc_kernel_space, eax + test eax, eax + jz .err + mov [lin_addr], eax + + mov ecx, [pages_count] + mov edx, eax + mov ebx, ecx + + shr ecx, 3 + jz .next + + and ebx, not 7 + push ebx + stdcall alloc_pages, ebx + pop ecx ; yes ecx!!! + and eax, eax + jz .err + + mov edi, eax + mov edx, [lin_addr] +@@: + stdcall map_page, edx, edi, dword PG_SW + add edx, 0x1000 + add edi, 0x1000 + dec ecx + jnz @B +.next: + mov ecx, [pages_count] + and ecx, 7 + jz .end +@@: + push ecx + call alloc_page + pop ecx + test eax, eax + jz .err + + stdcall map_page, edx, eax, dword PG_SW + add edx, 0x1000 + dec ecx + jnz @B +.end: + mov eax, [lin_addr] + pop edi + pop ebx + ret +.err: + xor eax, eax + pop edi + pop ebx + ret +endp + +align 4 +proc kernel_free stdcall, base:dword + + push ebx esi + + mov ecx, heap_mutex + call mutex_lock + + mov eax, [base] + call md.find_used + + mov ecx, heap_mutex + cmp [esi+block_flags], USED_BLOCK + jne .fail + + call mutex_unlock + + mov eax, [esi+block_base] + mov ecx, [esi+block_size] + shr ecx, 12 + call release_pages ;eax, ecx + stdcall free_kernel_space, [base] + pop esi ebx + ret +.fail: + call mutex_unlock + xor eax, eax + pop esi ebx + ret +endp + +restore block_next +restore block_prev +restore block_list +restore block_base +restore block_size +restore block_flags + +;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;; + +HEAP_TOP equ 0x5FC00000 + +align 4 +proc init_heap + + mov ebx, [current_slot] + mov eax, [ebx+APPDATA.heap_top] + test eax, eax + jz @F + sub eax, [ebx+APPDATA.heap_base] + sub eax, 4096 + ret +@@: + mov esi, [ebx+APPDATA.mem_size] + add esi, 4095 + and esi, not 4095 + mov [ebx+APPDATA.mem_size], esi + mov eax, HEAP_TOP + mov [ebx+APPDATA.heap_base], esi + mov [ebx+APPDATA.heap_top], eax + + sub eax, esi + shr esi, 10 + mov ecx, eax + sub eax, 4096 + or ecx, FREE_BLOCK + mov [page_tabs+esi], ecx + ret +endp + +align 4 +proc user_alloc stdcall, alloc_size:dword + + push ebx + push esi + push edi + + mov ecx, [alloc_size] + add ecx, (4095+4096) + and ecx, not 4095 + + mov ebx, [current_slot] + mov esi, dword [ebx+APPDATA.heap_base] ; heap_base + mov edi, dword [ebx+APPDATA.heap_top] ; heap_top +l_0: + cmp esi, edi + jae m_exit + + mov ebx, esi + shr ebx, 12 + mov eax, [page_tabs+ebx*4] + test al, FREE_BLOCK + jz test_used + and eax, 0xFFFFF000 + cmp eax, ecx ;alloc_size + jb m_next + jz @f + + lea edx, [esi+ecx] + sub eax, ecx + or al, FREE_BLOCK + shr edx, 12 + mov [page_tabs+edx*4], eax +@@: + or ecx, USED_BLOCK + mov [page_tabs+ebx*4], ecx + shr ecx, 12 + inc ebx + dec ecx + jz .no +@@: + mov dword [page_tabs+ebx*4], 2 + inc ebx + dec ecx + jnz @B +.no: + + mov edx, [current_slot] + mov ebx, [alloc_size] + add ebx, 0xFFF + and ebx, not 0xFFF + add ebx, [edx+APPDATA.mem_size] + call update_mem_size + + lea eax, [esi+4096] + + pop edi + pop esi + pop ebx + ret +test_used: + test al, USED_BLOCK + jz m_exit + + and eax, 0xFFFFF000 +m_next: + add esi, eax + jmp l_0 +m_exit: + xor eax, eax + pop edi + pop esi + pop ebx + ret +endp + +align 4 +proc user_alloc_at stdcall, address:dword, alloc_size:dword + + push ebx + push esi + push edi + + mov ebx, [current_slot] + mov edx, [address] + and edx, not 0xFFF + mov [address], edx + sub edx, 0x1000 + jb .error + mov esi, [ebx+APPDATA.heap_base] + mov edi, [ebx+APPDATA.heap_top] + cmp edx, esi + jb .error +.scan: + cmp esi, edi + jae .error + mov ebx, esi + shr ebx, 12 + mov eax, [page_tabs+ebx*4] + mov ecx, eax + and ecx, 0xFFFFF000 + add ecx, esi + cmp edx, ecx + jb .found + mov esi, ecx + jmp .scan +.error: + xor eax, eax + pop edi + pop esi + pop ebx + ret +.found: + test al, FREE_BLOCK + jz .error + mov eax, ecx + sub eax, edx + sub eax, 0x1000 + cmp eax, [alloc_size] + jb .error + +; Here we have 1 big free block which includes requested area. +; In general, 3 other blocks must be created instead: +; free at [esi, edx); +; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000)); +; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx) +; First or third block (or both) may be absent. + mov eax, edx + sub eax, esi + jz .nofirst + or al, FREE_BLOCK + mov [page_tabs+ebx*4], eax +.nofirst: + mov eax, [alloc_size] + add eax, 0x1FFF + and eax, not 0xFFF + mov ebx, edx + add edx, eax + shr ebx, 12 + or al, USED_BLOCK + mov [page_tabs+ebx*4], eax + shr eax, 12 + dec eax + jz .second_nofill + inc ebx +.fill: + mov dword [page_tabs+ebx*4], 2 + inc ebx + dec eax + jnz .fill +.second_nofill: + sub ecx, edx + jz .nothird + or cl, FREE_BLOCK + mov [page_tabs+ebx*4], ecx +.nothird: + + mov edx, [current_slot] + mov ebx, [alloc_size] + add ebx, 0xFFF + and ebx, not 0xFFF + add ebx, [edx+APPDATA.mem_size] + call update_mem_size + + mov eax, [address] + + pop edi + pop esi + pop ebx + ret +endp + +align 4 +proc user_free stdcall, base:dword + + push esi + + mov esi, [base] + test esi, esi + jz .exit + + push ebx + + xor ebx, ebx + shr esi, 12 + mov eax, [page_tabs+(esi-1)*4] + test al, USED_BLOCK + jz .cantfree + test al, DONT_FREE_BLOCK + jnz .cantfree + + and eax, not 4095 + mov ecx, eax + or al, FREE_BLOCK + mov [page_tabs+(esi-1)*4], eax + sub ecx, 4096 + mov ebx, ecx + shr ecx, 12 + jz .released +.release: + xor eax, eax + xchg eax, [page_tabs+esi*4] + test al, 1 + jz @F + test eax, PG_SHARED + jnz @F + call free_page + mov eax, esi + shl eax, 12 + invlpg [eax] +@@: + inc esi + dec ecx + jnz .release +.released: + push edi + + mov edx, [current_slot] + mov esi, dword [edx+APPDATA.heap_base] + mov edi, dword [edx+APPDATA.heap_top] + sub ebx, [edx+APPDATA.mem_size] + neg ebx + call update_mem_size + call user_normalize + pop edi + pop ebx + pop esi + ret +.exit: + xor eax, eax + inc eax + pop esi + ret +.cantfree: + xor eax, eax + pop ebx + pop esi + ret +endp + +user_normalize: +; in: esi=heap_base, edi=heap_top +; out: eax=0 <=> OK +; destroys: ebx,edx,esi,edi + shr esi, 12 + shr edi, 12 +@@: + mov eax, [page_tabs+esi*4] + test al, USED_BLOCK + jz .test_free + shr eax, 12 + add esi, eax + jmp @B +.test_free: + test al, FREE_BLOCK + jz .err + mov edx, eax + shr edx, 12 + add edx, esi + cmp edx, edi + jae .exit + + mov ebx, [page_tabs+edx*4] + test bl, USED_BLOCK + jz .next_free + + shr ebx, 12 + add edx, ebx + mov esi, edx + jmp @B +.next_free: + test bl, FREE_BLOCK + jz .err + and dword [page_tabs+edx*4], 0 + add eax, ebx + and eax, not 4095 + or eax, FREE_BLOCK + mov [page_tabs+esi*4], eax + jmp @B +.exit: + xor eax, eax + inc eax + ret +.err: + xor eax, eax + ret + +user_realloc: +; in: eax = pointer, ebx = new size +; out: eax = new pointer or NULL + test eax, eax + jnz @f +; realloc(NULL,sz) - same as malloc(sz) + push ebx + call user_alloc + ret +@@: + push ecx edx + lea ecx, [eax - 0x1000] + shr ecx, 12 + mov edx, [page_tabs+ecx*4] + test dl, USED_BLOCK + jnz @f +; attempt to realloc invalid pointer +.ret0: + pop edx ecx + xor eax, eax + ret +@@: + test dl, DONT_FREE_BLOCK + jnz .ret0 + add ebx, 0x1FFF + shr edx, 12 + shr ebx, 12 +; edx = allocated size, ebx = new size + add edx, ecx + add ebx, ecx + cmp edx, ebx + jb .realloc_add +; release part of allocated memory +.loop: + cmp edx, ebx + jz .release_done + dec edx + xor eax, eax + xchg eax, [page_tabs+edx*4] + test al, 1 + jz .loop + call free_page + mov eax, edx + shl eax, 12 + invlpg [eax] + jmp .loop +.release_done: + sub ebx, ecx + cmp ebx, 1 + jnz .nofreeall + mov eax, [page_tabs+ecx*4] + and eax, not 0xFFF + mov edx, [current_slot] + mov ebx, [APPDATA.mem_size+edx] + sub ebx, eax + add ebx, 0x1000 + or al, FREE_BLOCK + mov [page_tabs+ecx*4], eax + push esi edi + mov esi, [APPDATA.heap_base+edx] + mov edi, [APPDATA.heap_top+edx] + call update_mem_size + call user_normalize + pop edi esi + jmp .ret0 ; all freed +.nofreeall: + sub edx, ecx + shl ebx, 12 + or ebx, USED_BLOCK + xchg [page_tabs+ecx*4], ebx + shr ebx, 12 + sub ebx, edx + push ebx ecx edx + mov edx, [current_slot] + shl ebx, 12 + sub ebx, [APPDATA.mem_size+edx] + neg ebx + call update_mem_size + pop edx ecx ebx + lea eax, [ecx+1] + shl eax, 12 + push eax + add ecx, edx + lea edx, [ecx+ebx] + shl ebx, 12 + jz .ret + push esi + mov esi, [current_slot] + mov esi, [APPDATA.heap_top+esi] + shr esi, 12 +@@: + cmp edx, esi + jae .merge_done + mov eax, [page_tabs+edx*4] + test al, USED_BLOCK + jnz .merge_done + and dword [page_tabs+edx*4], 0 + shr eax, 12 + add edx, eax + shl eax, 12 + add ebx, eax + jmp @b +.merge_done: + pop esi + or ebx, FREE_BLOCK + mov [page_tabs+ecx*4], ebx +.ret: + pop eax edx ecx + ret +.realloc_add: +; get some additional memory + mov eax, [current_slot] + mov eax, [APPDATA.heap_top+eax] + shr eax, 12 + cmp edx, eax + jae .cant_inplace + mov eax, [page_tabs+edx*4] + test al, FREE_BLOCK + jz .cant_inplace + shr eax, 12 + add eax, edx + sub eax, ebx + jb .cant_inplace + jz @f + shl eax, 12 + or al, FREE_BLOCK + mov [page_tabs+ebx*4], eax +@@: + mov eax, ebx + sub eax, ecx + shl eax, 12 + or al, USED_BLOCK + mov [page_tabs+ecx*4], eax + lea eax, [ecx+1] + shl eax, 12 + push eax + push edi + lea edi, [page_tabs+edx*4] + mov eax, 2 + sub ebx, edx + mov ecx, ebx + cld + rep stosd + pop edi + mov edx, [current_slot] + shl ebx, 12 + add ebx, [APPDATA.mem_size+edx] + call update_mem_size + pop eax edx ecx + ret +.cant_inplace: + push esi edi + mov eax, [current_slot] + mov esi, [APPDATA.heap_base+eax] + mov edi, [APPDATA.heap_top+eax] + shr esi, 12 + shr edi, 12 + sub ebx, ecx +.find_place: + cmp esi, edi + jae .place_not_found + mov eax, [page_tabs+esi*4] + test al, FREE_BLOCK + jz .next_place + shr eax, 12 + cmp eax, ebx + jae .place_found + add esi, eax + jmp .find_place +.next_place: + shr eax, 12 + add esi, eax + jmp .find_place +.place_not_found: + pop edi esi + jmp .ret0 +.place_found: + sub eax, ebx + jz @f + push esi + add esi, ebx + shl eax, 12 + or al, FREE_BLOCK + mov [page_tabs+esi*4], eax + pop esi +@@: + mov eax, ebx + shl eax, 12 + or al, USED_BLOCK + mov [page_tabs+esi*4], eax + inc esi + mov eax, esi + shl eax, 12 + push eax + mov eax, [page_tabs+ecx*4] + and eax, not 0xFFF + or al, FREE_BLOCK + sub edx, ecx + mov [page_tabs+ecx*4], eax + inc ecx + dec ebx + dec edx + jz .no +@@: + xor eax, eax + xchg eax, [page_tabs+ecx*4] + mov [page_tabs+esi*4], eax + mov eax, ecx + shl eax, 12 + invlpg [eax] + inc esi + inc ecx + dec ebx + dec edx + jnz @b +.no: + push ebx + mov edx, [current_slot] + shl ebx, 12 + add ebx, [APPDATA.mem_size+edx] + call update_mem_size + pop ebx +@@: + mov dword [page_tabs+esi*4], 2 + inc esi + dec ebx + jnz @b + pop eax edi esi edx ecx + ret + +if 0 +align 4 +proc alloc_dll + pushf + cli + bsf eax, [dll_map] + jnz .find + popf + xor eax, eax + ret +.find: + btr [dll_map], eax + popf + shl eax, 5 + add eax, dll_tab + ret +endp + +align 4 +proc alloc_service + pushf + cli + bsf eax, [srv_map] + jnz .find + popf + xor eax, eax + ret +.find: + btr [srv_map], eax + popf + shl eax, 0x02 + lea eax, [srv_tab+eax+eax*8] ;srv_tab+eax*36 + ret +endp + +end if + + +;;;;;;;;;;;;;; SHARED ;;;;;;;;;;;;;;;;; + + +; param +; eax= shm_map object + +align 4 +destroy_smap: + + pushfd + cli + + push esi + push edi + + mov edi, eax + mov esi, [eax+SMAP.parent] + test esi, esi + jz .done + + lock dec [esi+SMEM.refcount] + jnz .done + + mov ecx, [esi+SMEM.bk] + mov edx, [esi+SMEM.fd] + + mov [ecx+SMEM.fd], edx + mov [edx+SMEM.bk], ecx + + stdcall kernel_free, [esi+SMEM.base] + mov eax, esi + call free +.done: + mov eax, edi + call destroy_kernel_object + + pop edi + pop esi + popfd + + ret + +E_NOTFOUND equ 5 +E_ACCESS equ 10 +E_NOMEM equ 30 +E_PARAM equ 33 + +SHM_READ equ 0 +SHM_WRITE equ 1 + +SHM_ACCESS_MASK equ 3 + +SHM_OPEN equ (0 shl 2) +SHM_OPEN_ALWAYS equ (1 shl 2) +SHM_CREATE equ (2 shl 2) + +SHM_OPEN_MASK equ (3 shl 2) + +align 4 +proc shmem_open stdcall name:dword, size:dword, access:dword + locals + action dd ? + owner_access dd ? + mapped dd ? + endl + + push ebx + push esi + push edi + + mov [mapped], 0 + mov [owner_access], 0 + + pushfd ;mutex required + cli + + mov eax, [access] + and eax, SHM_OPEN_MASK + mov [action], eax + + mov ebx, [name] + test ebx, ebx + mov edx, E_PARAM + jz .fail + + mov esi, [shmem_list.fd] +align 4 +@@: + cmp esi, shmem_list + je .not_found + + lea edx, [esi+SMEM.name]; link , base, size + stdcall strncmp, edx, ebx, 32 + test eax, eax + je .found + + mov esi, [esi+SMEM.fd] + jmp @B + +.not_found: + mov eax, [action] + + cmp eax, SHM_OPEN + mov edx, E_NOTFOUND + je .fail + + cmp eax, SHM_CREATE + mov edx, E_PARAM + je .create_shm + + cmp eax, SHM_OPEN_ALWAYS + jne .fail + +.create_shm: + + mov ecx, [size] + test ecx, ecx + jz .fail + + add ecx, 4095 + and ecx, -4096 + mov [size], ecx + + mov eax, SMEM.sizeof + call malloc + test eax, eax + mov esi, eax + mov edx, E_NOMEM + jz .fail + + stdcall kernel_alloc, [size] + test eax, eax + mov [mapped], eax + mov edx, E_NOMEM + jz .cleanup + + mov ecx, [size] + mov edx, [access] + and edx, SHM_ACCESS_MASK + + mov [esi+SMEM.base], eax + mov [esi+SMEM.size], ecx + mov [esi+SMEM.access], edx + mov [esi+SMEM.refcount], 0 + mov [esi+SMEM.name+28], 0 + + lea eax, [esi+SMEM.name] + stdcall strncpy, eax, [name], 31 + + mov eax, [shmem_list.fd] + mov [esi+SMEM.bk], shmem_list + mov [esi+SMEM.fd], eax + + mov [eax+SMEM.bk], esi + mov [shmem_list.fd], esi + + mov [action], SHM_OPEN + mov [owner_access], SHM_WRITE + +.found: + mov eax, [action] + + cmp eax, SHM_CREATE + mov edx, E_ACCESS + je .exit + + cmp eax, SHM_OPEN + mov edx, E_PARAM + je .create_map + + cmp eax, SHM_OPEN_ALWAYS + jne .fail + +.create_map: + + mov eax, [access] + and eax, SHM_ACCESS_MASK + cmp eax, [esi+SMEM.access] + mov [access], eax + mov edx, E_ACCESS + ja .fail + + mov ebx, [CURRENT_TASK] + shl ebx, 5 + mov ebx, [CURRENT_TASK+ebx+4] + mov eax, SMAP.sizeof + + call create_kernel_object + test eax, eax + mov edi, eax + mov edx, E_NOMEM + jz .fail + + inc [esi+SMEM.refcount] + + mov [edi+SMAP.magic], 'SMAP' + mov [edi+SMAP.destroy], destroy_smap + mov [edi+SMAP.parent], esi + mov [edi+SMAP.base], 0 + + stdcall user_alloc, [esi+SMEM.size] + test eax, eax + mov [mapped], eax + mov edx, E_NOMEM + jz .cleanup2 + + mov [edi+SMAP.base], eax + + mov ecx, [esi+SMEM.size] + mov [size], ecx + + shr ecx, 12 + shr eax, 10 + + mov esi, [esi+SMEM.base] + shr esi, 10 + lea edi, [page_tabs+eax] + add esi, page_tabs + + mov edx, [access] + or edx, [owner_access] + shl edx, 1 + or edx, PG_USER+PG_SHARED +@@: + lodsd + and eax, 0xFFFFF000 + or eax, edx + stosd + loop @B + + xor edx, edx + + cmp [owner_access], 0 + jne .fail +.exit: + mov edx, [size] +.fail: + mov eax, [mapped] + + popfd + pop edi + pop esi + pop ebx + ret +.cleanup: + mov [size], edx + mov eax, esi + call free + jmp .exit + +.cleanup2: + mov [size], edx + mov eax, edi + call destroy_smap + jmp .exit +endp + +align 4 +proc shmem_close stdcall, name:dword + + mov eax, [name] + test eax, eax + jz .fail + + push esi + push edi + pushfd + cli + + mov esi, [current_slot] + add esi, APP_OBJ_OFFSET +.next: + mov eax, [esi+APPOBJ.fd] + test eax, eax + jz @F + + cmp eax, esi + mov esi, eax + je @F + + cmp [eax+SMAP.magic], 'SMAP' + jne .next + + mov edi, [eax+SMAP.parent] + test edi, edi + jz .next + + lea edi, [edi+SMEM.name] + stdcall strncmp, [name], edi, 32 + test eax, eax + jne .next + + stdcall user_free, [esi+SMAP.base] + + mov eax, esi + call [esi+APPOBJ.destroy] +@@: + popfd + pop edi + pop esi +.fail: + ret +endp diff --git a/kernel/trunk/core/irq.inc b/kernel/trunk/core/irq.inc index 076ff66cd..2b592b751 100644 --- a/kernel/trunk/core/irq.inc +++ b/kernel/trunk/core/irq.inc @@ -1,229 +1,229 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -IRQ_RESERVED equ 24 - -IRQ_POOL_SIZE equ 48 - -uglobal - -align 16 -irqh_tab rd LHEAD.sizeof * IRQ_RESERVED / 4 - -irqh_pool rd IRQH.sizeof * IRQ_POOL_SIZE /4 -next_irqh rd 1 - -irq_active_set rd 1 -irq_failed rd IRQ_RESERVED - -endg - -align 4 -init_irqs: - - mov ecx, IRQ_RESERVED - mov edi, irqh_tab -@@: - mov eax, edi - stosd - stosd - loop @B - - mov ecx, IRQ_POOL_SIZE-1 - mov eax, irqh_pool+IRQH.sizeof - mov [next_irqh], irqh_pool -@@: - mov [eax-IRQH.sizeof], eax - add eax, IRQH.sizeof - loop @B - - mov [eax-IRQH.sizeof], dword 0 - ret - - -align 4 -proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword - locals - .irqh dd ? - endl - - and [.irqh], 0 - - push ebx - - mov ebx, [irq] ;irq num - test ebx, ebx - jz .err - - cmp ebx, IRQ_RESERVED - jae .err - - mov edx, [handler] - test edx, edx - jz .err - - pushfd - cli - -;allocate handler - - mov ecx, [next_irqh] - test ecx, ecx - jz .fail - - mov eax, [ecx] - mov [next_irqh], eax - mov [.irqh], ecx - - mov [irq_failed+ebx*4], 0 ;clear counter - - mov eax, [user_data] - mov [ecx+IRQH.handler], edx - mov [ecx+IRQH.data], eax - - lea edx, [irqh_tab+ebx*8] - list_add_tail ecx, edx ;clobber eax - stdcall enable_irq, ebx - -.fail: - popfd -.err: - pop ebx - mov eax, [.irqh] - ret - -endp - -if 0 -align 4 -proc get_int_handler stdcall, irq:dword - - mov eax, [irq] - cmp eax, 15 - ja .fail - mov eax, [irq_tab + 4 * eax] - ret -.fail: - xor eax, eax - ret -endp -end if - - -align 4 -proc detach_int_handler - - ret -endp - - -macro irq_serv_h [num] { - forward -align 4 - .irq_#num : - push num - jmp .main -} - -align 16 -irq_serv: - -; .irq_1: -; push 1 -; jmp .main -; etc... - -irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 -irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23 - -purge irq_serv_h - -align 16 -.main: - save_ring3_context - - mov ebp, [esp + 32] - mov bx, app_data ;os_data - mov ds, bx - mov es, bx - - cmp [v86_irqhooks+ebp*8], 0 - jnz v86_irq - - cmp bp, 6 - jnz @f - push ebp - call [fdc_irq_func] - pop ebp -@@: - - cmp bp, 14 - jnz @f - push ebp - call [irq14_func] - pop ebp -@@: - cmp bp, 15 - jnz @f - push ebp - call [irq15_func] - pop ebp -@@: - bts [irq_active_set], ebp - - lea esi, [irqh_tab+ebp*8] ; esi= list head - mov ebx, esi -.next: - mov ebx, [ebx+IRQH.list.next] ; ebx= irqh pointer - cmp ebx, esi - je .done - - push ebx ; FIX THIS - push edi - push esi - - push [ebx+IRQH.data] - call [ebx+IRQH.handler] - add esp, 4 - - pop esi - pop edi - pop ebx - - test eax, eax - jz .next - - btr [irq_active_set], ebp - jmp .next - -.done: - btr [irq_active_set], ebp - jnc .exit - - inc [irq_failed+ebp*4] -.exit: - mov [check_idle_semaphore],5 - - mov ecx, ebp - call irq_eoi - - restore_ring3_context - add esp, 4 - iret - -align 4 -irqD: - push eax - push ecx - xor eax,eax - out 0xf0,al - mov cl, 13 - call irq_eoi - pop ecx - pop eax - iret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +IRQ_RESERVED equ 24 + +IRQ_POOL_SIZE equ 48 + +uglobal + +align 16 +irqh_tab rd LHEAD.sizeof * IRQ_RESERVED / 4 + +irqh_pool rd IRQH.sizeof * IRQ_POOL_SIZE /4 +next_irqh rd 1 + +irq_active_set rd 1 +irq_failed rd IRQ_RESERVED + +endg + +align 4 +init_irqs: + + mov ecx, IRQ_RESERVED + mov edi, irqh_tab +@@: + mov eax, edi + stosd + stosd + loop @B + + mov ecx, IRQ_POOL_SIZE-1 + mov eax, irqh_pool+IRQH.sizeof + mov [next_irqh], irqh_pool +@@: + mov [eax-IRQH.sizeof], eax + add eax, IRQH.sizeof + loop @B + + mov [eax-IRQH.sizeof], dword 0 + ret + + +align 4 +proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword + locals + .irqh dd ? + endl + + and [.irqh], 0 + + push ebx + + mov ebx, [irq] ;irq num + test ebx, ebx + jz .err + + cmp ebx, IRQ_RESERVED + jae .err + + mov edx, [handler] + test edx, edx + jz .err + + pushfd + cli + +;allocate handler + + mov ecx, [next_irqh] + test ecx, ecx + jz .fail + + mov eax, [ecx] + mov [next_irqh], eax + mov [.irqh], ecx + + mov [irq_failed+ebx*4], 0;clear counter + + mov eax, [user_data] + mov [ecx+IRQH.handler], edx + mov [ecx+IRQH.data], eax + + lea edx, [irqh_tab+ebx*8] + list_add_tail ecx, edx ;clobber eax + stdcall enable_irq, ebx + +.fail: + popfd +.err: + pop ebx + mov eax, [.irqh] + ret + +endp + +if 0 +align 4 +proc get_int_handler stdcall, irq:dword + + mov eax, [irq] + cmp eax, 15 + ja .fail + mov eax, [irq_tab + 4 * eax] + ret +.fail: + xor eax, eax + ret +endp +end if + + +align 4 +proc detach_int_handler + + ret +endp + + +macro irq_serv_h [num] { + forward +align 4 + .irq_#num : + push num + jmp .main +} + +align 16 +irq_serv: + +; .irq_1: +; push 1 +; jmp .main +; etc... + +irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 +irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23 + +purge irq_serv_h + +align 16 +.main: + save_ring3_context + + mov ebp, [esp + 32] + mov bx, app_data;os_data + mov ds, bx + mov es, bx + + cmp [v86_irqhooks+ebp*8], 0 + jnz v86_irq + + cmp bp, 6 + jnz @f + push ebp + call [fdc_irq_func] + pop ebp +@@: + + cmp bp, 14 + jnz @f + push ebp + call [irq14_func] + pop ebp +@@: + cmp bp, 15 + jnz @f + push ebp + call [irq15_func] + pop ebp +@@: + bts [irq_active_set], ebp + + lea esi, [irqh_tab+ebp*8] ; esi= list head + mov ebx, esi +.next: + mov ebx, [ebx+IRQH.list.next]; ebx= irqh pointer + cmp ebx, esi + je .done + + push ebx ; FIX THIS + push edi + push esi + + push [ebx+IRQH.data] + call [ebx+IRQH.handler] + add esp, 4 + + pop esi + pop edi + pop ebx + + test eax, eax + jz .next + + btr [irq_active_set], ebp + jmp .next + +.done: + btr [irq_active_set], ebp + jnc .exit + + inc [irq_failed+ebp*4] +.exit: + mov [check_idle_semaphore], 5 + + mov ecx, ebp + call irq_eoi + + restore_ring3_context + add esp, 4 + iret + +align 4 +irqD: + push eax + push ecx + xor eax, eax + out 0xf0, al + mov cl, 13 + call irq_eoi + pop ecx + pop eax + iret + diff --git a/kernel/trunk/core/malloc.inc b/kernel/trunk/core/malloc.inc index fedcdde28..3e93e6435 100644 --- a/kernel/trunk/core/malloc.inc +++ b/kernel/trunk/core/malloc.inc @@ -1,1042 +1,1042 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; Small heap based on malloc/free/realloc written by Doug Lea -; Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) -; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c -; License http://creativecommons.org/licenses/publicdomain. - - -; eax= size - -; temp -; esi= nb -; ebx= idx -; -align 4 -malloc: - push esi - -; nb = ((size+7)&~7)+8; - - mov esi, eax ;size - add esi, 7 - and esi, -8 - add esi, 8 - - mov ecx, mst.mutex - call mutex_lock - - cmp esi, 256 - jae .large - - mov ecx, esi - shr ecx, 3 - or eax, -1 - shl eax, cl - and eax, [mst.smallmap] - jz .small - - push ebp - push edi - - bsf eax, eax - mov ebx, eax - -; psize= idx<<3; -; B = &ms.smallbins[idx]; -; p = B->fd; -; F = p->fd; -; rsize= psize-nb; - - lea ebp, [eax*8] ;ebp= psize - shl eax, 4 - lea edi, [mst.smallbins+eax] ;edi= B - mov edx, [edi+8] ;edx= p - mov eax, [edx+8] ;eax= F - mov ecx, ebp - sub ecx, esi ;ecx= rsize - -; if (B == F) - cmp edi, eax - jne @F - - btr [mst.smallmap], ebx -@@: - -; B->fd = F; -; F->bk = B; -; if(rsize<16) - - cmp ecx, 16 - mov [edi+8], eax - mov [eax+12], edi - jae .split - -; p->head = psize|PINUSE_BIT|CINUSE_BIT; -; (p + psize)->head |= PINUSE_BIT; - - lea eax, [edx+8] - or dword [edx+ebp+4], 1 - - or ebp, 3 - mov [edx+4], ebp - - pop edi - pop ebp -.done: - mov esi, eax - mov ecx, mst.mutex - call mutex_unlock - mov eax, esi - pop esi - ret - -.split: - lea ebx, [edx+8] ;ebx=mem - -; r = chunk_plus_offset(p, nb); -; p->head = nb|PINUSE_BIT|CINUSE_BIT; -; r->head = rsize|PINUSE_BIT; - - lea eax, [edx+esi] ;eax= r - or esi, 3 - mov [edx+4], esi - - mov edx, ecx - or edx, 1 - mov [eax+4], edx - -; (r + rsize)->prev_foot = rsize; - - mov [eax+ecx], ecx - -; I = rsize>>3; - - shr ecx, 3 - -; ms.smallmap |= 1<< I; - bts [mst.smallmap], ecx - -; B = &ms.smallbins[I]; - - shl ecx, 4 - pop edi - pop ebp - add ecx, mst.smallbins ;ecx= B - - mov edx, [ecx+8] ; F = B->fd; - mov [ecx+8], eax ; B->fd = r; - mov [edx+12], eax ; F->bk = r; - mov [eax+8], edx ; r->fd = F; - mov [eax+12], ecx ; r->bk = B; - - mov eax, ebx - jmp .done - -.small: - -; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0) -;;;;;;;;;;; start a change - mov eax,[mst.treemap] - test eax,eax -;;;;;;;;;;; end the change -; cmp [mst.treemap], 0 - jz .from_top - mov eax, esi - call malloc_small - test eax, eax - jz .from_top - jmp .done - -.large: - -; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0) - - cmp [mst.treemap], 0 - je .from_top - - call malloc_large ;esi= nb - test eax, eax - jne .done -.from_top: - -; if (nb < ms.topsize) - - mov eax, [mst.topsize] - cmp esi, eax - jae .fail - -; rsize = ms.topsize -= nb; -; p = ms.top; - - mov ecx, [mst.top] - sub eax, esi - mov [mst.topsize], eax - -; r = ms.top = chunk_plus_offset(p, nb); -; r->head = rsize | PINUSE_BIT; -; p->head = nb |PINUSE_BIT|CINUSE_BIT; - - lea edx, [ecx+esi] - or eax, 1 - mov [mst.top], edx - or esi, 3 - mov [edx+4], eax - mov [ecx+4], esi - lea eax, [ecx+8] - jmp .done - -.fail: - xor eax, eax - jmp .done - -; param -; eax= mem -align 4 -free: - test eax, eax - jz .exit - - push edi - mov edi, eax - add edi, -8 - -; if(p->head & CINUSE_BIT) - - test byte [edi+4], 2 - je .fail - - mov ecx, mst.mutex - call mutex_lock - -; psize = p->head & (~3); - - mov eax, [edi+4] - push esi - mov esi, eax - and esi, -4 - -; next = chunk_plus_offset(p, psize); -; if(!(p->head & PINUSE_BIT)) - - test al, 1 - lea ebx, [esi+edi] - jne .next - -; prevsize = p->prev_foot; -; prev=p - prevsize; -; psize += prevsize; -; p = prev; - - mov ecx, [edi] ;ecx= prevsize - add esi, ecx ;esi= psize - sub edi, ecx ;edi= p - -; if (prevsize < 256) - - cmp ecx, 256 - jae .unlink_large - - mov eax, [edi+8] ;F = p->fd; - mov edx, [edi+12] ;B = p->bk; - -; if (F == B) -; ms.smallmap &= ~(1<< I); - shr ecx, 3 - cmp eax, edx - jne @F - btr [mst.smallmap], ecx -@@: - mov [eax+12], edx ;F->bk = B; - mov [edx+8], eax ;B->fd = F - jmp .next -.unlink_large: - mov edx, edi - call unlink_large_chunk -.next: - -; if(next->head & PINUSE_BIT) - - mov eax, [ebx+4] - test al, 1 - jz .fail2 - -; if (! (next->head & CINUSE_BIT)) - - test al, 2 - jnz .fix_next - -; if (next == ms.top) - - cmp ebx, [mst.top] - jne @F - -; tsize = ms.topsize += psize; - - mov eax, [mst.topsize] - add eax, esi - mov [mst.topsize], eax - -; ms.top = p; -; p->head = tsize | PINUSE_BIT; - - or eax, 1 - mov [mst.top], edi - mov [edi+4], eax -.fail2: - mov esi, eax - mov ecx, mst.mutex - call mutex_unlock - mov eax, esi - pop esi -.fail: - pop edi -.exit: - ret - -@@: - -; nsize = next->head & ~INUSE_BITS; - - and eax, -4 - add esi, eax ;psize += nsize; - -; if (nsize < 256) - - cmp eax, 256 - jae .unl_large - - mov edx, [ebx+8] ;F = next->fd - mov ebx, [ebx+12] ;B = next->bk - -; if (F == B) - - cmp edx, ebx - jne @F - mov ecx, eax - shr ecx, 3 - btr [mst.smallmap], ecx -@@: - mov [edx+12], ebx ;F->bk = B - -; p->head = psize|PINUSE_BIT; - - mov ecx, esi - mov [ebx+8], edx - or ecx, 1 - mov [edi+4], ecx - -; (p+psize)->prev_foot = psize; - - mov [esi+edi], esi - -; insert_chunk(p,psize); - - mov eax, esi - pop esi - mov ecx, edi - pop edi - jmp insert_chunk -.unl_large: - -; unlink_large_chunk((tchunkptr)next); - - mov edx, ebx - call unlink_large_chunk -; p->head = psize|PINUSE_BIT; - - mov ecx, esi - or ecx, 1 - mov [edi+4], ecx - -; (p+psize)->prev_foot = psize; - - mov [esi+edi], esi - -; insert_chunk(p,psize); - - mov eax, esi - pop esi - mov ecx, edi - pop edi - jmp insert_chunk -.fix_next: - -; (p+psize)->prev_foot = psize; -; next->head &= ~PINUSE_BIT; -; p->head = psize|PINUSE_BIT; - - and eax, -2 - mov edx, esi - mov [ebx+4], eax - or edx, 1 - mov [edi+4], edx - -; (p+psize)->prev_foot = psize; - - mov [esi+edi], esi -; insert_chunk(p,psize); - - mov eax, esi - pop esi - mov ecx, edi - pop edi - jmp insert_chunk - -; param -; ecx = chunk -; eax = size - -insert_chunk: - - cmp eax, 256 - push esi - mov esi, ecx - jae .large - -; I = S>>3; -; ms.smallmap |= 1<< I; - - shr eax, 3 - bts [mst.smallmap], eax - -; B = &ms.smallbins[I]; - - shl eax, 4 - add eax, mst.smallbins - mov edx, [eax+8] ;F = B->fd - mov [eax+8], esi ;B->fd = P - mov [edx+12], esi ;F->bk = P - mov [esi+8], edx ;P->fd = F - mov [esi+12], eax ;P->bk = B - pop esi - mov ecx, mst.mutex - call mutex_unlock - ret -.large: - mov ebx, eax - call insert_large_chunk - pop esi - mov ecx, mst.mutex - call mutex_unlock - ret - - -; param -; esi= chunk -; ebx= size - -insert_large_chunk: - -; I = compute_tree_index(S); - - mov edx, ebx - shr edx, 8 - bsr eax, edx - lea ecx, [eax+7] - mov edx, ebx - shr edx, cl - and edx, 1 - lea ecx, [edx+eax*2] - -; X->index = I; - mov dword [esi+28], ecx - -; X->child[0] = X->child[1] = 0; - and dword [esi+20], 0 - and dword [esi+16], 0 - -; H = &ms.treebins[I]; - - mov eax, ecx - lea edx, [mst.treebins+eax*4] - -; if (!(ms.treemap & 1<child[(K >> 31) & 1]); - mov ecx, eax - shr ecx, 31 - lea ecx, [edx+ecx*4+16] - -; K <<= 1; -; if (*C != 0) - mov edi, [ecx] - add eax, eax - test edi, edi - jz .insert_child - -; T = *C; - mov edx, edi -.loop: - -; for (;;) -; if ((T->head & ~INUSE_BITS) != S) - - mov ecx, [edx+4] - and ecx, not 3 - cmp ecx, ebx - jne .not_eq_size - -; F = T->fd; - mov eax, [edx+8] - -; T->fd = F->bk = X; - mov [eax+12], esi - mov [edx+8], esi - -; X->fd = F; -; X->bk = T; -; X->parent = 0; - - and dword [esi+24], 0 - mov [esi+8], eax - mov [esi+12], edx - ret -.insert_child: - -; *C = X; - mov [ecx], esi -.done: - -; X->parent = T; - mov [esi+24], edx - -; X->fd = X->bk = X; - mov [esi+12], esi - mov [esi+8], esi - ret - - -; param -; edx= chunk - -unlink_large_chunk: - - mov eax, [edx+12] - cmp eax, edx - push edi - mov edi, [edx+24] - je @F - - mov ecx, [edx+8] ;F = X->fd - mov [ecx+12], eax ;F->bk = R; - mov [eax+8], ecx ;R->fd = F - jmp .parent -@@: - mov eax, [edx+20] - test eax, eax - push esi - lea esi, [edx+20] - jne .loop - - mov eax, [edx+16] - test eax, eax - lea esi, [edx+16] - je .l2 -.loop: - cmp dword [eax+20], 0 - lea ecx, [eax+20] - jne @F - - cmp dword [eax+16], 0 - lea ecx, [eax+16] - je .l1 -@@: - mov eax, [ecx] - mov esi, ecx - jmp .loop -.l1: - mov dword [esi], 0 -.l2: - pop esi -.parent: - test edi, edi - je .done - - mov ecx, [edx+28] - cmp edx, [mst.treebins+ecx*4] - lea ecx, [mst.treebins+ecx*4] - jne .l3 - - test eax, eax - mov [ecx], eax - jne .l5 - - mov ecx, [edx+28] - btr [mst.treemap], ecx - pop edi - ret - -.l3: - cmp [edi+16], edx - jne @F - - mov [edi+16], eax - jmp .l4 - -@@: - mov [edi+20], eax - -.l4: - test eax, eax - je .done - -.l5: - mov [eax+24], edi - mov ecx, [edx+16] - test ecx, ecx - je .l6 - - mov [eax+16], ecx - mov [ecx+24], eax - -.l6: - mov edx, [edx+20] - test edx, edx - je .done - - mov [eax+20], edx - mov [edx+24], eax - -.done: - pop edi - ret - -; param -; esi= nb - -malloc_small: - push ebp - mov ebp, esi - - push edi - - bsf eax,[mst.treemap] - mov ecx, [mst.treebins+eax*4] - -; rsize = (t->head & ~INUSE_BITS) - nb; - - mov edi, [ecx+4] - and edi, -4 - sub edi, esi - -.loop: - mov ebx, ecx - -.loop_1: - -; while ((t = leftmost_child(t)) != 0) - - mov eax, [ecx+16] - test eax, eax - jz @F - mov ecx, eax - jmp .l1 - -@@: - mov ecx, [ecx+20] - -.l1: - test ecx, ecx - jz .unlink - -; trem = (t->head & ~INUSE_BITS) - nb; - - mov eax, [ecx+4] - and eax, -4 - sub eax, ebp - -; if (trem < rsize) - - cmp eax, edi - jae .loop_1 - -; rsize = trem; - - mov edi, eax - jmp .loop -.unlink: - - -; r = chunk_plus_offset((mchunkptr)v, nb); -; unlink_large_chunk(v); - - mov edx, ebx - lea esi, [ebx+ebp] - call unlink_large_chunk - -; if (rsize < 16) - - cmp edi, 16 - jae .split - -; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; - - lea ecx, [edi+ebp] - -; (v+rsize + nb)->head |= PINUSE_BIT; - - add edi, ebx - lea eax, [edi+ebp+4] - pop edi - or ecx, 3 - mov [ebx+4], ecx - or dword [eax], 1 - pop ebp - - lea eax, [ebx+8] - ret - -.split: - -; v->head = nb|PINUSE_BIT|CINUSE_BIT; -; r->head = rsize|PINUSE_BIT; -; (r+rsize)->prev_foot = rsize; - - or ebp, 3 - mov edx, edi - or edx, 1 - - cmp edi, 256 - mov [ebx+4], ebp - mov [esi+4], edx - mov [esi+edi], edi - jae .large - - shr edi, 3 - bts [mst.smallmap], edi - - mov eax, edi - shl eax, 4 - add eax, mst.smallbins - - mov edx, [eax+8] - mov [eax+8], esi - mov [edx+12], esi - pop edi - mov [esi+12], eax - mov [esi+8], edx - pop ebp - lea eax, [ebx+8] - ret - -.large: - lea eax, [ebx+8] - push eax - mov ebx, edi - call insert_large_chunk - pop eax - pop edi - pop ebp - ret - - -; param -; esi= nb - -malloc_large: -.idx equ esp+4 -.rst equ esp - - push ebp - push esi - push edi - sub esp, 8 -; v = 0; -; rsize = -nb; - - mov edi, esi - mov ebx, esi - xor ebp, ebp - neg edi - -; idx = compute_tree_index(nb); - - mov edx, esi - shr edx, 8 - bsr eax, edx - lea ecx, [eax+7] - shr esi, cl - and esi, 1 - lea ecx, [esi+eax*2] - mov [.idx], ecx - -; if ((t = ms.treebins[idx]) != 0) - - mov eax, [mst.treebins+ecx*4] - test eax, eax - jz .l3 - -; sizebits = nb << leftshift_for_tree_index(idx); - - cmp ecx, 31 - jne @F - xor ecx, ecx - jmp .l1 - -@@: - mov edx, ecx - shr edx, 1 - mov ecx, 37 - sub ecx, edx - -.l1: - mov edx, ebx - shl edx, cl - -; rst = 0; - mov [.rst], ebp - -.loop: - -; trem = (t->head & ~INUSE_BITS) - nb; - - mov ecx, [eax+4] - and ecx, -4 - sub ecx, ebx - -; if (trem < rsize) - - cmp ecx, edi - jae @F -; v = t; -; if ((rsize = trem) == 0) - - test ecx, ecx - mov ebp, eax - mov edi, ecx - je .l2 - -@@: - -; rt = t->child[1]; - - mov ecx, [eax+20] - -; t = t->child[(sizebits >> 31) & 1]; - - mov esi, edx - shr esi, 31 - -; if (rt != 0 && rt != t) - - test ecx, ecx - mov eax, [eax+esi*4+16] - jz @F - cmp ecx, eax - jz @F - -; rst = rt; - mov [.rst], ecx - -@@: -; if (t == 0) - - test eax, eax - jz @F - -; sizebits <<= 1; - - add edx, edx - jmp .loop - -@@: -; t = rst; - mov eax, [.rst] - -.l2: -; if (t == 0 && v == 0) - - test eax, eax - jne .l4 - test ebp, ebp - jne .l7 - mov ecx, [.idx] - -.l3: - -; leftbits = (-1<head & ~INUSE_BITS) - nb; - - mov ecx, [eax+4] - and ecx, -4 - sub ecx, ebx - -; if (trem < rsize) - - cmp ecx, edi - jae @F -; rsize = trem; - - mov edi, ecx -; v = t; - mov ebp, eax - -@@: - -; t = leftmost_child(t); - - mov ecx, [eax+16] - test ecx, ecx - je @F - mov eax, ecx - jmp .l6 - -@@: - mov eax, [eax+20] - -.l6: - -; while (t != 0) - - test eax, eax - jne .l4 - -.l5: - -; if (v != 0) - - test ebp, ebp - jz .done - -.l7: - -; r = chunk_plus_offset((mchunkptr)v, nb); -; unlink_large_chunk(v); - - mov edx, ebp - lea esi, [ebx+ebp] - call unlink_large_chunk - -; if (rsize < 16) - - cmp edi, 16 - jae .large - -; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; - - lea ecx, [edi+ebx] - -; (v+rsize + nb)->head |= PINUSE_BIT; - - add edi, ebp - lea eax, [edi+ebx+4] - or ecx, 3 - mov [ebp+4], ecx - or dword [eax], 1 - lea eax, [ebp+8] - add esp, 8 - pop edi - pop esi - pop ebp - ret - -.large: - -; v->head = nb|PINUSE_BIT|CINUSE_BIT; -; r->head = rsize|PINUSE_BIT; - - mov edx, edi - or ebx, 3 - mov [ebp+4], ebx - or edx, 1 - mov [esi+4], edx - -; (r+rsize)->prev_foot = rsize; -; insert_large_chunk((tchunkptr)r, rsize); - - mov [esi+edi], edi - mov eax, edi - mov ecx, esi - call insert_chunk - - lea eax, [ebp+8] - add esp, 8 - pop edi - pop esi - pop ebp - ret - -.done: - add esp, 8 - pop edi - pop esi - pop ebp - xor eax, eax - ret - -init_malloc: - - stdcall kernel_alloc, 0x40000 - - mov [mst.top], eax - mov [mst.topsize], 128*1024 - mov dword [eax+4], (128*1024) or 1 - mov eax, mst.smallbins - -@@: - mov [eax+8], eax - mov [eax+12], eax - add eax, 16 - cmp eax, mst.smallbins+512 - jb @B - - mov ecx, mst.mutex - call mutex_init - - ret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; Small heap based on malloc/free/realloc written by Doug Lea +; Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) +; Source ftp://gee.cs.oswego.edu/pub/misc/malloc.c +; License http://creativecommons.org/licenses/publicdomain. + + +; eax= size + +; temp +; esi= nb +; ebx= idx +; +align 4 +malloc: + push esi + +; nb = ((size+7)&~7)+8; + + mov esi, eax ;size + add esi, 7 + and esi, -8 + add esi, 8 + + mov ecx, mst.mutex + call mutex_lock + + cmp esi, 256 + jae .large + + mov ecx, esi + shr ecx, 3 + or eax, -1 + shl eax, cl + and eax, [mst.smallmap] + jz .small + + push ebp + push edi + + bsf eax, eax + mov ebx, eax + +; psize= idx<<3; +; B = &ms.smallbins[idx]; +; p = B->fd; +; F = p->fd; +; rsize= psize-nb; + + lea ebp, [eax*8] ;ebp= psize + shl eax, 4 + lea edi, [mst.smallbins+eax] ;edi= B + mov edx, [edi+8] ;edx= p + mov eax, [edx+8] ;eax= F + mov ecx, ebp + sub ecx, esi ;ecx= rsize + +; if (B == F) + cmp edi, eax + jne @F + + btr [mst.smallmap], ebx +@@: + +; B->fd = F; +; F->bk = B; +; if(rsize<16) + + cmp ecx, 16 + mov [edi+8], eax + mov [eax+12], edi + jae .split + +; p->head = psize|PINUSE_BIT|CINUSE_BIT; +; (p + psize)->head |= PINUSE_BIT; + + lea eax, [edx+8] + or dword [edx+ebp+4], 1 + + or ebp, 3 + mov [edx+4], ebp + + pop edi + pop ebp +.done: + mov esi, eax + mov ecx, mst.mutex + call mutex_unlock + mov eax, esi + pop esi + ret + +.split: + lea ebx, [edx+8] ;ebx=mem + +; r = chunk_plus_offset(p, nb); +; p->head = nb|PINUSE_BIT|CINUSE_BIT; +; r->head = rsize|PINUSE_BIT; + + lea eax, [edx+esi] ;eax= r + or esi, 3 + mov [edx+4], esi + + mov edx, ecx + or edx, 1 + mov [eax+4], edx + +; (r + rsize)->prev_foot = rsize; + + mov [eax+ecx], ecx + +; I = rsize>>3; + + shr ecx, 3 + +; ms.smallmap |= 1<< I; + bts [mst.smallmap], ecx + +; B = &ms.smallbins[I]; + + shl ecx, 4 + pop edi + pop ebp + add ecx, mst.smallbins ;ecx= B + + mov edx, [ecx+8] ; F = B->fd; + mov [ecx+8], eax ; B->fd = r; + mov [edx+12], eax ; F->bk = r; + mov [eax+8], edx ; r->fd = F; + mov [eax+12], ecx ; r->bk = B; + + mov eax, ebx + jmp .done + +.small: + +; if (ms.treemap != 0 && (mem = malloc_small(nb)) != 0) +;;;;;;;;;;; start a change + mov eax, [mst.treemap] + test eax, eax +;;;;;;;;;;; end the change +; cmp [mst.treemap], 0 + jz .from_top + mov eax, esi + call malloc_small + test eax, eax + jz .from_top + jmp .done + +.large: + +; if (ms.treemap != 0 && (mem = malloc_large(nb)) != 0) + + cmp [mst.treemap], 0 + je .from_top + + call malloc_large ;esi= nb + test eax, eax + jne .done +.from_top: + +; if (nb < ms.topsize) + + mov eax, [mst.topsize] + cmp esi, eax + jae .fail + +; rsize = ms.topsize -= nb; +; p = ms.top; + + mov ecx, [mst.top] + sub eax, esi + mov [mst.topsize], eax + +; r = ms.top = chunk_plus_offset(p, nb); +; r->head = rsize | PINUSE_BIT; +; p->head = nb |PINUSE_BIT|CINUSE_BIT; + + lea edx, [ecx+esi] + or eax, 1 + mov [mst.top], edx + or esi, 3 + mov [edx+4], eax + mov [ecx+4], esi + lea eax, [ecx+8] + jmp .done + +.fail: + xor eax, eax + jmp .done + +; param +; eax= mem +align 4 +free: + test eax, eax + jz .exit + + push edi + mov edi, eax + add edi, -8 + +; if(p->head & CINUSE_BIT) + + test byte [edi+4], 2 + je .fail + + mov ecx, mst.mutex + call mutex_lock + +; psize = p->head & (~3); + + mov eax, [edi+4] + push esi + mov esi, eax + and esi, -4 + +; next = chunk_plus_offset(p, psize); +; if(!(p->head & PINUSE_BIT)) + + test al, 1 + lea ebx, [esi+edi] + jne .next + +; prevsize = p->prev_foot; +; prev=p - prevsize; +; psize += prevsize; +; p = prev; + + mov ecx, [edi] ;ecx= prevsize + add esi, ecx ;esi= psize + sub edi, ecx ;edi= p + +; if (prevsize < 256) + + cmp ecx, 256 + jae .unlink_large + + mov eax, [edi+8] ;F = p->fd; + mov edx, [edi+12] ;B = p->bk; + +; if (F == B) +; ms.smallmap &= ~(1<< I); + shr ecx, 3 + cmp eax, edx + jne @F + btr [mst.smallmap], ecx +@@: + mov [eax+12], edx ;F->bk = B; + mov [edx+8], eax ;B->fd = F + jmp .next +.unlink_large: + mov edx, edi + call unlink_large_chunk +.next: + +; if(next->head & PINUSE_BIT) + + mov eax, [ebx+4] + test al, 1 + jz .fail2 + +; if (! (next->head & CINUSE_BIT)) + + test al, 2 + jnz .fix_next + +; if (next == ms.top) + + cmp ebx, [mst.top] + jne @F + +; tsize = ms.topsize += psize; + + mov eax, [mst.topsize] + add eax, esi + mov [mst.topsize], eax + +; ms.top = p; +; p->head = tsize | PINUSE_BIT; + + or eax, 1 + mov [mst.top], edi + mov [edi+4], eax +.fail2: + mov esi, eax + mov ecx, mst.mutex + call mutex_unlock + mov eax, esi + pop esi +.fail: + pop edi +.exit: + ret + +@@: + +; nsize = next->head & ~INUSE_BITS; + + and eax, -4 + add esi, eax ;psize += nsize; + +; if (nsize < 256) + + cmp eax, 256 + jae .unl_large + + mov edx, [ebx+8] ;F = next->fd + mov ebx, [ebx+12] ;B = next->bk + +; if (F == B) + + cmp edx, ebx + jne @F + mov ecx, eax + shr ecx, 3 + btr [mst.smallmap], ecx +@@: + mov [edx+12], ebx ;F->bk = B + +; p->head = psize|PINUSE_BIT; + + mov ecx, esi + mov [ebx+8], edx + or ecx, 1 + mov [edi+4], ecx + +; (p+psize)->prev_foot = psize; + + mov [esi+edi], esi + +; insert_chunk(p,psize); + + mov eax, esi + pop esi + mov ecx, edi + pop edi + jmp insert_chunk +.unl_large: + +; unlink_large_chunk((tchunkptr)next); + + mov edx, ebx + call unlink_large_chunk +; p->head = psize|PINUSE_BIT; + + mov ecx, esi + or ecx, 1 + mov [edi+4], ecx + +; (p+psize)->prev_foot = psize; + + mov [esi+edi], esi + +; insert_chunk(p,psize); + + mov eax, esi + pop esi + mov ecx, edi + pop edi + jmp insert_chunk +.fix_next: + +; (p+psize)->prev_foot = psize; +; next->head &= ~PINUSE_BIT; +; p->head = psize|PINUSE_BIT; + + and eax, -2 + mov edx, esi + mov [ebx+4], eax + or edx, 1 + mov [edi+4], edx + +; (p+psize)->prev_foot = psize; + + mov [esi+edi], esi +; insert_chunk(p,psize); + + mov eax, esi + pop esi + mov ecx, edi + pop edi + jmp insert_chunk + +; param +; ecx = chunk +; eax = size + +insert_chunk: + + cmp eax, 256 + push esi + mov esi, ecx + jae .large + +; I = S>>3; +; ms.smallmap |= 1<< I; + + shr eax, 3 + bts [mst.smallmap], eax + +; B = &ms.smallbins[I]; + + shl eax, 4 + add eax, mst.smallbins + mov edx, [eax+8] ;F = B->fd + mov [eax+8], esi ;B->fd = P + mov [edx+12], esi ;F->bk = P + mov [esi+8], edx ;P->fd = F + mov [esi+12], eax ;P->bk = B + pop esi + mov ecx, mst.mutex + call mutex_unlock + ret +.large: + mov ebx, eax + call insert_large_chunk + pop esi + mov ecx, mst.mutex + call mutex_unlock + ret + + +; param +; esi= chunk +; ebx= size + +insert_large_chunk: + +; I = compute_tree_index(S); + + mov edx, ebx + shr edx, 8 + bsr eax, edx + lea ecx, [eax+7] + mov edx, ebx + shr edx, cl + and edx, 1 + lea ecx, [edx+eax*2] + +; X->index = I; + mov dword [esi+28], ecx + +; X->child[0] = X->child[1] = 0; + and dword [esi+20], 0 + and dword [esi+16], 0 + +; H = &ms.treebins[I]; + + mov eax, ecx + lea edx, [mst.treebins+eax*4] + +; if (!(ms.treemap & 1<child[(K >> 31) & 1]); + mov ecx, eax + shr ecx, 31 + lea ecx, [edx+ecx*4+16] + +; K <<= 1; +; if (*C != 0) + mov edi, [ecx] + add eax, eax + test edi, edi + jz .insert_child + +; T = *C; + mov edx, edi +.loop: + +; for (;;) +; if ((T->head & ~INUSE_BITS) != S) + + mov ecx, [edx+4] + and ecx, not 3 + cmp ecx, ebx + jne .not_eq_size + +; F = T->fd; + mov eax, [edx+8] + +; T->fd = F->bk = X; + mov [eax+12], esi + mov [edx+8], esi + +; X->fd = F; +; X->bk = T; +; X->parent = 0; + + and dword [esi+24], 0 + mov [esi+8], eax + mov [esi+12], edx + ret +.insert_child: + +; *C = X; + mov [ecx], esi +.done: + +; X->parent = T; + mov [esi+24], edx + +; X->fd = X->bk = X; + mov [esi+12], esi + mov [esi+8], esi + ret + + +; param +; edx= chunk + +unlink_large_chunk: + + mov eax, [edx+12] + cmp eax, edx + push edi + mov edi, [edx+24] + je @F + + mov ecx, [edx+8] ;F = X->fd + mov [ecx+12], eax ;F->bk = R; + mov [eax+8], ecx ;R->fd = F + jmp .parent +@@: + mov eax, [edx+20] + test eax, eax + push esi + lea esi, [edx+20] + jne .loop + + mov eax, [edx+16] + test eax, eax + lea esi, [edx+16] + je .l2 +.loop: + cmp dword [eax+20], 0 + lea ecx, [eax+20] + jne @F + + cmp dword [eax+16], 0 + lea ecx, [eax+16] + je .l1 +@@: + mov eax, [ecx] + mov esi, ecx + jmp .loop +.l1: + mov dword [esi], 0 +.l2: + pop esi +.parent: + test edi, edi + je .done + + mov ecx, [edx+28] + cmp edx, [mst.treebins+ecx*4] + lea ecx, [mst.treebins+ecx*4] + jne .l3 + + test eax, eax + mov [ecx], eax + jne .l5 + + mov ecx, [edx+28] + btr [mst.treemap], ecx + pop edi + ret + +.l3: + cmp [edi+16], edx + jne @F + + mov [edi+16], eax + jmp .l4 + +@@: + mov [edi+20], eax + +.l4: + test eax, eax + je .done + +.l5: + mov [eax+24], edi + mov ecx, [edx+16] + test ecx, ecx + je .l6 + + mov [eax+16], ecx + mov [ecx+24], eax + +.l6: + mov edx, [edx+20] + test edx, edx + je .done + + mov [eax+20], edx + mov [edx+24], eax + +.done: + pop edi + ret + +; param +; esi= nb + +malloc_small: + push ebp + mov ebp, esi + + push edi + + bsf eax, [mst.treemap] + mov ecx, [mst.treebins+eax*4] + +; rsize = (t->head & ~INUSE_BITS) - nb; + + mov edi, [ecx+4] + and edi, -4 + sub edi, esi + +.loop: + mov ebx, ecx + +.loop_1: + +; while ((t = leftmost_child(t)) != 0) + + mov eax, [ecx+16] + test eax, eax + jz @F + mov ecx, eax + jmp .l1 + +@@: + mov ecx, [ecx+20] + +.l1: + test ecx, ecx + jz .unlink + +; trem = (t->head & ~INUSE_BITS) - nb; + + mov eax, [ecx+4] + and eax, -4 + sub eax, ebp + +; if (trem < rsize) + + cmp eax, edi + jae .loop_1 + +; rsize = trem; + + mov edi, eax + jmp .loop +.unlink: + + +; r = chunk_plus_offset((mchunkptr)v, nb); +; unlink_large_chunk(v); + + mov edx, ebx + lea esi, [ebx+ebp] + call unlink_large_chunk + +; if (rsize < 16) + + cmp edi, 16 + jae .split + +; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; + + lea ecx, [edi+ebp] + +; (v+rsize + nb)->head |= PINUSE_BIT; + + add edi, ebx + lea eax, [edi+ebp+4] + pop edi + or ecx, 3 + mov [ebx+4], ecx + or dword [eax], 1 + pop ebp + + lea eax, [ebx+8] + ret + +.split: + +; v->head = nb|PINUSE_BIT|CINUSE_BIT; +; r->head = rsize|PINUSE_BIT; +; (r+rsize)->prev_foot = rsize; + + or ebp, 3 + mov edx, edi + or edx, 1 + + cmp edi, 256 + mov [ebx+4], ebp + mov [esi+4], edx + mov [esi+edi], edi + jae .large + + shr edi, 3 + bts [mst.smallmap], edi + + mov eax, edi + shl eax, 4 + add eax, mst.smallbins + + mov edx, [eax+8] + mov [eax+8], esi + mov [edx+12], esi + pop edi + mov [esi+12], eax + mov [esi+8], edx + pop ebp + lea eax, [ebx+8] + ret + +.large: + lea eax, [ebx+8] + push eax + mov ebx, edi + call insert_large_chunk + pop eax + pop edi + pop ebp + ret + + +; param +; esi= nb + +malloc_large: +.idx equ esp+4 +.rst equ esp + + push ebp + push esi + push edi + sub esp, 8 +; v = 0; +; rsize = -nb; + + mov edi, esi + mov ebx, esi + xor ebp, ebp + neg edi + +; idx = compute_tree_index(nb); + + mov edx, esi + shr edx, 8 + bsr eax, edx + lea ecx, [eax+7] + shr esi, cl + and esi, 1 + lea ecx, [esi+eax*2] + mov [.idx], ecx + +; if ((t = ms.treebins[idx]) != 0) + + mov eax, [mst.treebins+ecx*4] + test eax, eax + jz .l3 + +; sizebits = nb << leftshift_for_tree_index(idx); + + cmp ecx, 31 + jne @F + xor ecx, ecx + jmp .l1 + +@@: + mov edx, ecx + shr edx, 1 + mov ecx, 37 + sub ecx, edx + +.l1: + mov edx, ebx + shl edx, cl + +; rst = 0; + mov [.rst], ebp + +.loop: + +; trem = (t->head & ~INUSE_BITS) - nb; + + mov ecx, [eax+4] + and ecx, -4 + sub ecx, ebx + +; if (trem < rsize) + + cmp ecx, edi + jae @F +; v = t; +; if ((rsize = trem) == 0) + + test ecx, ecx + mov ebp, eax + mov edi, ecx + je .l2 + +@@: + +; rt = t->child[1]; + + mov ecx, [eax+20] + +; t = t->child[(sizebits >> 31) & 1]; + + mov esi, edx + shr esi, 31 + +; if (rt != 0 && rt != t) + + test ecx, ecx + mov eax, [eax+esi*4+16] + jz @F + cmp ecx, eax + jz @F + +; rst = rt; + mov [.rst], ecx + +@@: +; if (t == 0) + + test eax, eax + jz @F + +; sizebits <<= 1; + + add edx, edx + jmp .loop + +@@: +; t = rst; + mov eax, [.rst] + +.l2: +; if (t == 0 && v == 0) + + test eax, eax + jne .l4 + test ebp, ebp + jne .l7 + mov ecx, [.idx] + +.l3: + +; leftbits = (-1<head & ~INUSE_BITS) - nb; + + mov ecx, [eax+4] + and ecx, -4 + sub ecx, ebx + +; if (trem < rsize) + + cmp ecx, edi + jae @F +; rsize = trem; + + mov edi, ecx +; v = t; + mov ebp, eax + +@@: + +; t = leftmost_child(t); + + mov ecx, [eax+16] + test ecx, ecx + je @F + mov eax, ecx + jmp .l6 + +@@: + mov eax, [eax+20] + +.l6: + +; while (t != 0) + + test eax, eax + jne .l4 + +.l5: + +; if (v != 0) + + test ebp, ebp + jz .done + +.l7: + +; r = chunk_plus_offset((mchunkptr)v, nb); +; unlink_large_chunk(v); + + mov edx, ebp + lea esi, [ebx+ebp] + call unlink_large_chunk + +; if (rsize < 16) + + cmp edi, 16 + jae .large + +; v->head = (rsize + nb)|PINUSE_BIT|CINUSE_BIT; + + lea ecx, [edi+ebx] + +; (v+rsize + nb)->head |= PINUSE_BIT; + + add edi, ebp + lea eax, [edi+ebx+4] + or ecx, 3 + mov [ebp+4], ecx + or dword [eax], 1 + lea eax, [ebp+8] + add esp, 8 + pop edi + pop esi + pop ebp + ret + +.large: + +; v->head = nb|PINUSE_BIT|CINUSE_BIT; +; r->head = rsize|PINUSE_BIT; + + mov edx, edi + or ebx, 3 + mov [ebp+4], ebx + or edx, 1 + mov [esi+4], edx + +; (r+rsize)->prev_foot = rsize; +; insert_large_chunk((tchunkptr)r, rsize); + + mov [esi+edi], edi + mov eax, edi + mov ecx, esi + call insert_chunk + + lea eax, [ebp+8] + add esp, 8 + pop edi + pop esi + pop ebp + ret + +.done: + add esp, 8 + pop edi + pop esi + pop ebp + xor eax, eax + ret + +init_malloc: + + stdcall kernel_alloc, 0x40000 + + mov [mst.top], eax + mov [mst.topsize], 128*1024 + mov dword [eax+4], (128*1024) or 1 + mov eax, mst.smallbins + +@@: + mov [eax+8], eax + mov [eax+12], eax + add eax, 16 + cmp eax, mst.smallbins+512 + jb @B + + mov ecx, mst.mutex + call mutex_init + + ret + diff --git a/kernel/trunk/core/memory.inc b/kernel/trunk/core/memory.inc index 9cd24427e..aaaced57f 100644 --- a/kernel/trunk/core/memory.inc +++ b/kernel/trunk/core/memory.inc @@ -1,1541 +1,1545 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -align 4 -proc alloc_page - - pushfd - cli - push ebx -;//- - cmp [pg_data.pages_free], 1 - jle .out_of_memory -;//- - - mov ebx, [page_start] - mov ecx, [page_end] -.l1: - bsf eax,[ebx]; - jnz .found - add ebx,4 - cmp ebx, ecx - jb .l1 - pop ebx - popfd - xor eax,eax - ret -.found: -;//- - dec [pg_data.pages_free] - jz .out_of_memory -;//- - btr [ebx], eax - mov [page_start],ebx - sub ebx, sys_pgmap - lea eax, [eax+ebx*8] - shl eax, 12 -;//- dec [pg_data.pages_free] - pop ebx - popfd - ret -;//- -.out_of_memory: - mov [pg_data.pages_free], 1 - xor eax, eax - pop ebx - popfd - ret -;//- -endp - -align 4 -proc alloc_pages stdcall, count:dword - pushfd - push ebx - push edi - cli - mov eax, [count] - add eax, 7 - shr eax, 3 - mov [count], eax -;//- - mov ebx, [pg_data.pages_free] - sub ebx, 9 - js .out_of_memory - shr ebx, 3 - cmp eax, ebx - jg .out_of_memory -;//- - mov ecx, [page_start] - mov ebx, [page_end] -.find: - mov edx, [count] - mov edi, ecx -.match: - cmp byte [ecx], 0xFF - jne .next - dec edx - jz .ok - inc ecx - cmp ecx,ebx - jb .match -.out_of_memory: -.fail: - xor eax, eax - pop edi - pop ebx - popfd - ret -.next: - inc ecx - cmp ecx, ebx - jb .find - pop edi - pop ebx - popfd - xor eax, eax - ret -.ok: - sub ecx, edi - inc ecx - push esi - mov esi, edi - xor eax, eax - rep stosb - sub esi, sys_pgmap - shl esi, 3+12 - mov eax, esi - mov ebx, [count] - shl ebx, 3 - sub [pg_data.pages_free], ebx - pop esi - pop edi - pop ebx - popfd - ret -endp - -align 4 -proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword - push ebx - mov eax, [phis_addr] - and eax, not 0xFFF - or eax, [flags] - mov ebx, [lin_addr] - shr ebx, 12 - mov [page_tabs+ebx*4], eax - mov eax, [lin_addr] - invlpg [eax] - pop ebx - ret -endp - -align 4 -map_space: ;not implemented - - - ret - - -align 4 -proc free_page -;arg: eax page address - pushfd - cli - shr eax, 12 ;page index - bts dword [sys_pgmap], eax ;that's all! - cmc - adc [pg_data.pages_free], 0 - shr eax, 3 - and eax, not 3 ;dword offset from page_map - add eax, sys_pgmap - cmp [page_start], eax - ja @f - popfd - ret -@@: - mov [page_start], eax - popfd - ret -endp - -proc map_io_mem stdcall, base:dword, size:dword, flags:dword - - push ebx - push edi - mov eax, [size] - add eax, [base] - add eax, 4095 - and eax, -4096 - mov ecx, [base] - and ecx, -4096 - sub eax, ecx - mov [size], eax - - stdcall alloc_kernel_space, eax - test eax, eax - jz .fail - push eax - - mov edi, 0x1000 - mov ebx, eax - mov ecx,[size] - mov edx, [base] - shr eax, 12 - shr ecx, 12 - and edx, -4096 - or edx, [flags] -@@: - mov [page_tabs+eax*4], edx - invlpg [ebx] - inc eax - add ebx, edi - add edx, edi - loop @B - - pop eax - mov edx, [base] - and edx, 4095 - add eax, edx -.fail: - pop edi - pop ebx - ret -endp - -; param -; eax= page base + page flags -; ebx= linear address -; ecx= count - -align 4 -commit_pages: - test ecx, ecx - jz .fail - - push edi - push eax - push ecx - mov ecx, pg_data.mutex - call mutex_lock - pop ecx - pop eax - - mov edi, ebx - shr edi, 12 - lea edi, [page_tabs+edi*4] -@@: - stosd - invlpg [ebx] - add eax, 0x1000 - add ebx, 0x1000 - loop @B - - pop edi - - mov ecx, pg_data.mutex - call mutex_unlock -.fail: - ret - - -; param -; eax= base -; ecx= count - -align 4 -release_pages: - - push ebp - push esi - push edi - push ebx - - mov esi, eax - mov edi, eax - - shr esi, 12 - lea esi, [page_tabs+esi*4] - - push ecx - mov ecx, pg_data.mutex - call mutex_lock - pop ecx - - mov ebp, [pg_data.pages_free] - mov ebx, [page_start] - mov edx, sys_pgmap -@@: - xor eax, eax - xchg eax, [esi] - invlpg [edi] - - test eax, 1 - jz .next - - shr eax, 12 - bts [edx], eax - cmc - adc ebp, 0 - shr eax, 3 - and eax, -4 - add eax, edx - cmp eax, ebx - jae .next - - mov ebx, eax -.next: - add edi, 0x1000 - add esi, 4 - loop @B - - mov [pg_data.pages_free], ebp - mov ecx, pg_data.mutex - call mutex_unlock - - pop ebx - pop edi - pop esi - pop ebp - ret - -; param -; eax= base -; ecx= count - -align 4 -unmap_pages: - - push edi - - mov edi, eax - mov edx, eax - - shr edi, 10 - add edi, page_tabs - - xor eax, eax -@@: - stosd - invlpg [edx] - add edx, 0x1000 - loop @b - - pop edi - ret - - -align 4 -proc map_page_table stdcall, lin_addr:dword, phis_addr:dword - push ebx - mov ebx, [lin_addr] - shr ebx, 22 - mov eax, [phis_addr] - and eax, not 0xFFF - or eax, PG_UW ;+PG_NOCACHE - mov dword [master_tab+ebx*4], eax - mov eax, [lin_addr] - shr eax, 10 - add eax, page_tabs - invlpg [eax] - pop ebx - ret -endp - -align 4 -proc init_LFB - locals - pg_count dd ? - endl - - cmp dword [LFBAddress], -1 - jne @f - mov [BOOT_VAR+0x901c],byte 2 - stdcall alloc_pages, (0x280000 / 4096) - - push eax - call alloc_page - stdcall map_page_table, LFB_BASE, eax - pop eax - or eax, PG_UW - mov ebx, LFB_BASE - mov ecx, 0x280000 / 4096 - call commit_pages - mov [LFBAddress], dword LFB_BASE - ret -@@: - test [SCR_MODE],word 0100000000000000b - jnz @f - mov [BOOT_VAR+0x901c],byte 2 - ret -@@: - call init_mtrr - - mov edx, LFB_BASE - mov esi, [LFBAddress] - mov edi, 0x00C00000 - mov dword [exp_lfb+4], edx - - shr edi, 12 - mov [pg_count], edi - shr edi, 10 - - bt [cpu_caps], CAPS_PSE - jnc .map_page_tables - or esi, PG_LARGE+PG_UW - mov edx, sys_pgdir+(LFB_BASE shr 20) -@@: - mov [edx], esi - add edx, 4 - add esi, 0x00400000 - dec edi - jnz @B - - bt [cpu_caps], CAPS_PGE - jnc @F - or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL -@@: - mov dword [LFBAddress], LFB_BASE - mov eax, cr3 ;flush TLB - mov cr3, eax - ret - -.map_page_tables: - -@@: - call alloc_page - stdcall map_page_table, edx, eax - add edx, 0x00400000 - dec edi - jnz @B - - mov eax, [LFBAddress] - mov edi, page_tabs + (LFB_BASE shr 10) - or eax, PG_UW - mov ecx, [pg_count] - cld -@@: - stosd - add eax, 0x1000 - dec ecx - jnz @B - - mov dword [LFBAddress], LFB_BASE - mov eax, cr3 ;flush TLB - mov cr3, eax - - ret -endp - -align 4 -proc new_mem_resize stdcall, new_size:dword - - mov ecx, pg_data.mutex - call mutex_lock - - mov edi, [new_size] - add edi,4095 - and edi,not 4095 - mov [new_size], edi - - mov edx,[current_slot] - cmp [edx+APPDATA.heap_base],0 - jne .exit - - mov esi, [edx+APPDATA.mem_size] - add esi, 4095 - and esi, not 4095 - - cmp edi, esi - jae .expand - - shr edi, 12 - shr esi, 12 -@@: - mov eax, [app_page_tabs+edi*4] - test eax, 1 - jz .next - mov dword [app_page_tabs+edi*4], 2 - mov ebx, edi - shl ebx, 12 - push eax - invlpg [ebx] - pop eax - call free_page - -.next: add edi, 1 - cmp edi, esi - jb @B - -.update_size: - mov ebx, [new_size] - call update_mem_size - - mov ecx, pg_data.mutex - call mutex_unlock - - xor eax, eax - ret -.expand: - - push esi - push edi - - add edi, 0x3FFFFF - and edi, not(0x3FFFFF) - add esi, 0x3FFFFF - and esi, not(0x3FFFFF) - - cmp esi, edi - jae .grow - - xchg esi, edi - -@@: - call alloc_page - test eax, eax - jz .exit_pop - - stdcall map_page_table, edi, eax - - push edi - shr edi, 10 - add edi, page_tabs - mov ecx, 1024 - xor eax, eax - cld - rep stosd - pop edi - - add edi, 0x00400000 - cmp edi, esi - jb @B -.grow: -;//- - pop edi - push edi - mov esi, [pg_data.pages_free] - sub esi, 1 - shr edi, 12 - cmp esi, edi - jle .out_of_memory -;//- - pop edi - pop esi -@@: - call alloc_page - test eax, eax - jz .exit - stdcall map_page,esi,eax,dword PG_UW - - push edi - mov edi, esi - xor eax, eax - mov ecx, 1024 - cld - rep stosd - pop edi - - add esi, 0x1000 - cmp esi, edi - jb @B - - jmp .update_size -;//- -.exit_pop: -.out_of_memory: -;//- - pop edi - pop esi -.exit: - mov ecx, pg_data.mutex - call mutex_unlock - - xor eax, eax - inc eax - ret -endp - -update_mem_size: -; in: edx = slot base -; ebx = new memory size -; destroys eax,ecx,edx - - mov [APPDATA.mem_size+edx],ebx -;search threads and update -;application memory size infomation - mov ecx,[APPDATA.dir_table+edx] - mov eax,2 - -.search_threads: -;eax = current slot -;ebx = new memory size -;ecx = page directory - cmp eax,[TASK_COUNT] - jg .search_threads_end - mov edx,eax - shl edx,5 - cmp word [CURRENT_TASK+edx+TASKDATA.state],9 ;if slot empty? - jz .search_threads_next - shl edx,3 - cmp [SLOT_BASE+edx+APPDATA.dir_table],ecx ;if it is our thread? - jnz .search_threads_next - mov [SLOT_BASE+edx+APPDATA.mem_size],ebx ;update memory size -.search_threads_next: - inc eax - jmp .search_threads -.search_threads_end: - ret - -; param -; eax= linear address -; -; retval -; eax= phisical page address - -align 4 -get_pg_addr: - shr eax, 12 - mov eax, [page_tabs+eax*4] - and eax, 0xFFFFF000 - ret - - -align 4 -; Now it is called from core/sys32::exc_c (see stack frame there) -proc page_fault_handler - - .err_addr equ ebp-4 - - push ebx ;save exception number (#PF) - mov ebp, esp - mov ebx, cr2 - push ebx ;that is locals: .err_addr = cr2 - inc [pg_data.pages_faults] - - mov eax, [pf_err_code] - - cmp ebx, OS_BASE ;ebx == .err_addr - jb .user_space ;страница в памяти приложения ; - - cmp ebx, page_tabs - jb .kernel_space ;страница в памяти ядра - - cmp ebx, kernel_tabs - jb .alloc;.app_tabs ;таблицы страниц приложения ; - ;просто создадим одну -if 0 ;пока это просто лишнее - cmp ebx, LFB_BASE - jb .core_tabs ;таблицы страниц ядра - ;Ошибка - .lfb: - ;область LFB - ;Ошибка - jmp .fail -end if -.core_tabs: -.fail: ;simply return to caller - mov esp, ebp - pop ebx ;restore exception number (#PF) - ret - -; xchg bx, bx -; add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller -; restore_ring3_context -; iretd - -.user_space: - test eax, PG_MAP - jnz .err_access ;Страница присутствует - ;Ошибка доступа ? - - shr ebx, 12 - mov ecx, ebx - shr ecx, 10 - mov edx, [master_tab+ecx*4] - test edx, PG_MAP - jz .fail ;таблица страниц не создана - ;неверный адрес в программе - - mov eax, [page_tabs+ebx*4] - test eax, 2 - jz .fail ;адрес не зарезервирован для ; - ;использования. Ошибка -.alloc: - call alloc_page - test eax, eax - jz .fail - - stdcall map_page,[.err_addr],eax,PG_UW - - mov edi, [.err_addr] - and edi, 0xFFFFF000 - mov ecx, 1024 - xor eax, eax - ;cld ;caller is duty for this - rep stosd -.exit: ;iret with repeat fault instruction - add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller - restore_ring3_context - iretd - -.err_access: -; access denied? this may be a result of copy-on-write protection for DLL -; check list of HDLLs - and ebx, not 0xFFF - mov eax, [CURRENT_TASK] - shl eax, 8 - mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] - test eax, eax - jz .fail - mov esi, [eax+HDLL.fd] -.scan_hdll: - cmp esi, eax - jz .fail - mov edx, ebx - sub edx, [esi+HDLL.base] - cmp edx, [esi+HDLL.size] - jb .fault_in_hdll -.scan_hdll.next: - mov esi, [esi+HDLL.fd] - jmp .scan_hdll -.fault_in_hdll: -; allocate new page, map it as rw and copy data - call alloc_page - test eax, eax - jz .fail - stdcall map_page,ebx,eax,PG_UW - mov edi, ebx - mov ecx, 1024 - sub ebx, [esi+HDLL.base] - mov esi, [esi+HDLL.parent] - mov esi, [esi+DLLDESCR.data] - add esi, ebx - rep movsd - jmp .exit - -.kernel_space: - test eax, PG_MAP - jz .fail ;страница не присутствует - - test eax,12 ;U/S (+below) - jnz .fail ;приложение обратилось к памяти - ;ядра - ;test eax, 8 - ;jnz .fail ;установлен зарезервированный бит - ;в таблицах страниц. добавлено в P4/Xeon - -;попытка записи в защищённую страницу ядра - - cmp ebx, tss._io_map_0 - jb .fail - - cmp ebx, tss._io_map_0+8192 - jae .fail - -; io permission map -; copy-on-write protection - - call alloc_page - test eax, eax - jz .fail - - push eax - stdcall map_page,[.err_addr],eax,dword PG_SW - pop eax - mov edi, [.err_addr] - and edi, -4096 - lea esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0 - - mov ebx, esi - shr ebx, 12 - mov edx, [current_slot] - or eax, PG_SW - mov [edx+APPDATA.io_map+ebx*4], eax - - add esi, [default_io_map] - mov ecx, 4096/4 - ;cld ;caller is duty for this - rep movsd - jmp .exit -endp - -; returns number of mapped bytes -proc map_mem stdcall, lin_addr:dword,slot:dword,\ - ofs:dword,buf_size:dword,req_access:dword - push 0 ; initialize number of mapped bytes - - cmp [buf_size], 0 - jz .exit - - mov eax, [slot] - shl eax, 8 - mov eax, [SLOT_BASE+eax+APPDATA.dir_table] - and eax, 0xFFFFF000 - - stdcall map_page,[ipc_pdir],eax,PG_UW - mov ebx, [ofs] - shr ebx, 22 - mov esi, [ipc_pdir] - mov edi, [ipc_ptab] - mov eax, [esi+ebx*4] - and eax, 0xFFFFF000 - jz .exit - stdcall map_page,edi,eax,PG_UW -; inc ebx -; add edi, 0x1000 -; mov eax, [esi+ebx*4] -; test eax, eax -; jz @f -; and eax, 0xFFFFF000 -; stdcall map_page, edi, eax - -@@: mov edi, [lin_addr] - and edi, 0xFFFFF000 - mov ecx, [buf_size] - add ecx, 4095 - shr ecx, 12 - inc ecx - - mov edx, [ofs] - shr edx, 12 - and edx, 0x3FF - mov esi, [ipc_ptab] - -.map: - stdcall safe_map_page,[slot],[req_access],[ofs] - jnc .exit - add dword [ebp-4], 4096 - add [ofs], 4096 - dec ecx - jz .exit - add edi, 0x1000 - inc edx - cmp edx, 0x400 - jnz .map - inc ebx - mov eax, [ipc_pdir] - mov eax, [eax+ebx*4] - and eax, 0xFFFFF000 - jz .exit - stdcall map_page,esi,eax,PG_UW - xor edx, edx - jmp .map - -.exit: - pop eax - ret -endp - -proc map_memEx stdcall, lin_addr:dword,slot:dword,\ - ofs:dword,buf_size:dword,req_access:dword - push 0 ; initialize number of mapped bytes - - cmp [buf_size], 0 - jz .exit - - mov eax, [slot] - shl eax, 8 - mov eax, [SLOT_BASE+eax+APPDATA.dir_table] - and eax, 0xFFFFF000 - - stdcall map_page,[proc_mem_pdir],eax,PG_UW - mov ebx, [ofs] - shr ebx, 22 - mov esi, [proc_mem_pdir] - mov edi, [proc_mem_tab] - mov eax, [esi+ebx*4] - and eax, 0xFFFFF000 - test eax, eax - jz .exit - stdcall map_page,edi,eax,PG_UW - -@@: mov edi, [lin_addr] - and edi, 0xFFFFF000 - mov ecx, [buf_size] - add ecx, 4095 - shr ecx, 12 - inc ecx - - mov edx, [ofs] - shr edx, 12 - and edx, 0x3FF - mov esi, [proc_mem_tab] - -.map: - stdcall safe_map_page,[slot],[req_access],[ofs] - jnc .exit - add dword [ebp-4], 0x1000 - add edi, 0x1000 - add [ofs], 0x1000 - inc edx - dec ecx - jnz .map -.exit: - pop eax - ret -endp - -; in: esi+edx*4 = pointer to page table entry -; in: [slot], [req_access], [ofs] on the stack -; in: edi = linear address to map -; out: CF cleared <=> failed -; destroys: only eax -proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword - mov eax, [esi+edx*4] - test al, PG_MAP - jz .not_present - test al, PG_WRITE - jz .resolve_readonly -; normal case: writable page, just map with requested access -.map: - stdcall map_page, edi, eax, [req_access] - stc -.fail: - ret -.not_present: -; check for alloc-on-demand page - test al, 2 - jz .fail -; allocate new page, save it to source page table - push ecx - call alloc_page - pop ecx - test eax, eax - jz .fail - or al, PG_UW - mov [esi+edx*4], eax - jmp .map -.resolve_readonly: -; readonly page, probably copy-on-write -; check: readonly request of readonly page is ok - test [req_access], PG_WRITE - jz .map -; find control structure for this page - pushf - cli - cld - push ebx ecx - mov eax, [slot] - shl eax, 8 - mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] - test eax, eax - jz .no_hdll - mov ecx, [eax+HDLL.fd] -.scan_hdll: - cmp ecx, eax - jz .no_hdll - mov ebx, [ofs] - and ebx, not 0xFFF - sub ebx, [ecx+HDLL.base] - cmp ebx, [ecx+HDLL.size] - jb .hdll_found - mov ecx, [ecx+HDLL.fd] - jmp .scan_hdll -.no_hdll: - pop ecx ebx - popf - clc - ret -.hdll_found: -; allocate page, save it in page table, map it, copy contents from base - mov eax, [ecx+HDLL.parent] - add ebx, [eax+DLLDESCR.data] - call alloc_page - test eax, eax - jz .no_hdll - or al, PG_UW - mov [esi+edx*4], eax - stdcall map_page, edi, eax, [req_access] - push esi edi - mov esi, ebx - mov ecx, 4096/4 - rep movsd - pop edi esi - pop ecx ebx - popf - stc - ret -endp - -sys_IPC: -;input: -; ebx=1 - set ipc buffer area -; ecx=address of buffer -; edx=size of buffer -; eax=2 - send message -; ebx=PID -; ecx=address of message -; edx=size of message - - dec ebx - jnz @f - - mov eax,[current_slot] - pushf - cli - mov [eax+APPDATA.ipc_start],ecx ;set fields in extended information area - mov [eax+APPDATA.ipc_size],edx - - add edx, ecx - add edx, 4095 - and edx, not 4095 - -.touch: mov eax, [ecx] - add ecx, 0x1000 - cmp ecx, edx - jb .touch - - popf - mov [esp+32], ebx ;ebx=0 - ret - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;2 -@@: - dec ebx - jnz @f - - stdcall sys_ipc_send, ecx, edx, esi - mov [esp+32], eax - ret -@@: - or eax,-1 - mov [esp+32], eax - ret - -;align 4 -;proc set_ipc_buff - -; mov eax,[current_slot] -; pushf -; cli -; mov [eax+APPDATA.ipc_start],ebx ;set fields in extended information area -; mov [eax+APPDATA.ipc_size],ecx -; -; add ecx, ebx -; add ecx, 4095 -; and ecx, not 4095 -; -;.touch: mov eax, [ebx] -; add ebx, 0x1000 -; cmp ebx, ecx -; jb .touch -; -; popf -; xor eax, eax -; ret -;endp - -proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword - locals - dst_slot dd ? - dst_offset dd ? - buf_size dd ? - used_buf dd ? - endl - - pushf - cli - - mov eax, [PID] - call pid_to_slot - test eax,eax - jz .no_pid - - mov [dst_slot], eax - shl eax,8 - mov edi,[eax+SLOT_BASE+0xa0] ;is ipc area defined? - test edi,edi - jz .no_ipc_area - - mov ebx, edi - and ebx, 0xFFF - mov [dst_offset], ebx - - mov esi, [eax+SLOT_BASE+0xa4] - mov [buf_size], esi - - mov ecx, [ipc_tmp] - cmp esi, 0x40000-0x1000 ; size of [ipc_tmp] minus one page - jbe @f - push esi edi - add esi,0x1000 - stdcall alloc_kernel_space,esi - mov ecx, eax - pop edi esi -@@: - mov [used_buf], ecx - stdcall map_mem, ecx, [dst_slot],\ - edi, esi, PG_SW - - mov edi, [dst_offset] - add edi, [used_buf] - cmp dword [edi], 0 - jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now - - mov edx, dword [edi+4] - lea ebx, [edx+8] - add ebx, [msg_size] - cmp ebx, [buf_size] - ja .buffer_overflow ;esi<0 - not enough memory in buffer - - mov dword [edi+4], ebx - mov eax,[TASK_BASE] - mov eax, [eax+0x04] ;eax - our PID - add edi, edx - mov [edi], eax - mov ecx, [msg_size] - - mov [edi+4], ecx - add edi, 8 - mov esi, [msg_addr] - ; add esi, new_app_base - cld - rep movsb - - mov ebx, [ipc_tmp] - mov edx, ebx - shr ebx, 12 - xor eax, eax - mov [page_tabs+ebx*4], eax - invlpg [edx] - - mov ebx, [ipc_pdir] - mov edx, ebx - shr ebx, 12 - xor eax, eax - mov [page_tabs+ebx*4], eax - invlpg [edx] - - mov ebx, [ipc_ptab] - mov edx, ebx - shr ebx, 12 - xor eax, eax - mov [page_tabs+ebx*4], eax - invlpg [edx] - - mov eax, [dst_slot] - shl eax, 8 - or [eax+SLOT_BASE+0xA8],dword 0x40 - cmp dword [check_idle_semaphore],20 - jge .ipc_no_cis - - mov dword [check_idle_semaphore],5 -.ipc_no_cis: - push 0 - jmp .ret -.no_pid: - popf - mov eax, 4 - ret -.no_ipc_area: - popf - xor eax, eax - inc eax - ret -.ipc_blocked: - push 2 - jmp .ret -.buffer_overflow: - push 3 -.ret: - mov eax, [used_buf] - cmp eax, [ipc_tmp] - jz @f - stdcall free_kernel_space,eax -@@: - pop eax - popf - ret -endp - -align 4 -sysfn_meminfo: - - ; add ecx, new_app_base - cmp ecx, OS_BASE - jae .fail - - mov eax, [pg_data.pages_count] - mov [ecx], eax - shl eax, 12 - mov [esp+32], eax - mov eax, [pg_data.pages_free] - mov [ecx+4], eax - mov eax, [pg_data.pages_faults] - mov [ecx+8], eax - mov eax, [heap_size] - mov [ecx+12], eax - mov eax, [heap_free] - mov [ecx+16], eax - mov eax, [heap_blocks] - mov [ecx+20], eax - mov eax, [free_blocks] - mov [ecx+24], eax - ret -.fail: - or dword [esp+32], -1 - ret - -align 4 -f68: - cmp ebx,4 - jbe sys_sheduler - - cmp ebx, 11 - jb .fail - - cmp ebx, 25 - ja .fail - - jmp dword [f68call+ebx*4-11*4] -.11: - call init_heap - mov [esp+32], eax - ret -.12: - stdcall user_alloc, ecx - mov [esp+32], eax - ret -.13: - stdcall user_free, ecx - mov [esp+32], eax - ret -.14: - cmp ecx, OS_BASE - jae .fail - mov edi,ecx - call get_event_ex - mov [esp+32], eax - ret -.16: - test ecx, ecx - jz .fail - cmp ecx, OS_BASE - jae .fail - stdcall get_service, ecx - mov [esp+32], eax - ret -.17: - call srv_handlerEx ;ecx - mov [esp+32], eax - ret -.19: - cmp ecx, OS_BASE - jae .fail - stdcall load_library, ecx - mov [esp+32], eax - ret -.20: - mov eax, edx - mov ebx, ecx - call user_realloc ;in: eax = pointer, ebx = new size - mov [esp+32], eax - ret -.21: - cmp ecx, OS_BASE - jae .fail - - cmp ebx, OS_BASE - jae .fail - - mov edi, edx - stdcall load_PE, ecx - mov esi, eax - test eax, eax - jz @F - - push edi - push DRV_ENTRY - call eax - add esp, 8 - test eax, eax - jz @F - - mov [eax+SRV.entry], esi - -@@: - mov [esp+32], eax - ret -.22: - cmp ecx, OS_BASE - jae .fail - - stdcall shmem_open, ecx, edx, esi - mov [esp+24], edx - mov [esp+32], eax - ret - -.23: - cmp ecx, OS_BASE - jae .fail - - stdcall shmem_close, ecx - mov [esp+32], eax - ret -.24: - mov eax, [current_slot] - xchg ecx, [eax+APPDATA.exc_handler] - xchg edx, [eax+APPDATA.except_mask] - mov [esp+32], ecx ; reg_eax+8 - mov [esp+20], edx ; reg_ebx+8 - ret -.25: - cmp ecx,32 - jae .fail - mov eax, [current_slot] - btr [eax+APPDATA.except_mask],ecx - setc byte[esp+32] - jecxz @f - bts [eax+APPDATA.except_mask],ecx -@@: - ret - -.fail: - xor eax, eax - mov [esp+32], eax - ret - - -align 4 -f68call: ; keep this table closer to main code - - dd f68.11 ; init_heap - dd f68.12 ; user_alloc - dd f68.13 ; user_free - dd f68.14 ; get_event_ex - dd f68.fail ; moved to f68.24 - dd f68.16 ; get_service - dd f68.17 ; call_service - dd f68.fail ; moved to f68.25 - dd f68.19 ; load_dll - dd f68.20 ; user_realloc - dd f68.21 ; load_driver - dd f68.22 ; shmem_open - dd f68.23 ; shmem_close - dd f68.24 - dd f68.25 - - -align 4 -proc load_pe_driver stdcall, file:dword - - stdcall load_PE, [file] - test eax, eax - jz .fail - - mov esi, eax - stdcall eax, DRV_ENTRY - test eax, eax - jz .fail - - mov [eax+SRV.entry], esi - ret - -.fail: - xor eax, eax - ret -endp - - -align 4 -proc init_mtrr - - cmp [BOOT_VAR+0x901c],byte 2 - je .exit - - bt [cpu_caps], CAPS_MTRR - jnc .exit - - mov eax, cr0 - or eax, 0x60000000 ;disable caching - mov cr0, eax - wbinvd ;invalidate cache - - mov ecx, 0x2FF - rdmsr ; -; has BIOS already initialized MTRRs? - test ah, 8 - jnz .skip_init -; rarely needed, so mainly placeholder -; main memory - cached - push eax - - mov eax, [MEM_AMOUNT] -; round eax up to next power of 2 - dec eax - bsr ecx, eax - mov ebx, 2 - shl ebx, cl - dec ebx -; base of memory range = 0, type of memory range = MEM_WB - xor edx, edx - mov eax, MEM_WB - mov ecx, 0x200 - wrmsr -; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1 - mov eax, 0xFFFFFFFF - mov edx, 0x0000000F - sub eax, ebx - sbb edx, 0 - or eax, 0x800 - inc ecx - wrmsr -; clear unused MTRRs - xor eax, eax - xor edx, edx -@@: - wrmsr - inc ecx - cmp ecx, 0x210 - jb @b -; enable MTRRs - pop eax - or ah, 8 - and al, 0xF0 ; default memtype = UC - mov ecx, 0x2FF - wrmsr -.skip_init: - stdcall set_mtrr, [LFBAddress],[LFBSize],MEM_WC - - wbinvd ;again invalidate - - mov eax, cr0 - and eax, not 0x60000000 - mov cr0, eax ; enable caching -.exit: - ret -endp - -align 4 -proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword -; find unused register - mov ecx, 0x201 -@@: - rdmsr - dec ecx - test ah, 8 - jz .found - rdmsr - mov al, 0 ; clear memory type field - cmp eax, [base] - jz .ret - add ecx, 3 - cmp ecx, 0x210 - jb @b -; no free registers, ignore the call -.ret: - ret -.found: -; found, write values - xor edx, edx - mov eax, [base] - or eax, [mem_type] - wrmsr - - mov ebx, [size] - dec ebx - mov eax, 0xFFFFFFFF - mov edx, 0x00000000 - sub eax, ebx - sbb edx, 0 - or eax, 0x800 - inc ecx - wrmsr - ret -endp - -align 4 -proc stall stdcall, delay:dword - push ecx - push edx - push ebx - push eax - - mov eax, [delay] - mul [stall_mcs] - mov ebx, eax ;low - mov ecx, edx ;high - rdtsc - add ebx, eax - adc ecx,edx -@@: - rdtsc - sub eax, ebx - sbb edx, ecx - jb @B - - pop eax - pop ebx - pop edx - pop ecx - ret -endp - -align 4 -proc create_ring_buffer stdcall, size:dword, flags:dword - locals - buf_ptr dd ? - endl - - mov eax, [size] - test eax, eax - jz .fail - - add eax, eax - stdcall alloc_kernel_space, eax - test eax, eax - jz .fail - - push ebx - - mov [buf_ptr], eax - - mov ebx, [size] - shr ebx, 12 - push ebx - - stdcall alloc_pages, ebx - pop ecx - - test eax, eax - jz .mm_fail - - push edi - - or eax, [flags] - mov edi, [buf_ptr] - mov ebx, [buf_ptr] - mov edx, ecx - shl edx, 2 - shr edi, 10 -@@: - mov [page_tabs+edi], eax - mov [page_tabs+edi+edx], eax - invlpg [ebx] - invlpg [ebx+0x10000] - add eax, 0x1000 - add ebx, 0x1000 - add edi, 4 - dec ecx - jnz @B - - mov eax, [buf_ptr] - pop edi - pop ebx - ret -.mm_fail: - stdcall free_kernel_space, [buf_ptr] - xor eax, eax - pop ebx -.fail: - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +align 4 +proc alloc_page + + pushfd + cli + push ebx +;//- + cmp [pg_data.pages_free], 1 + jle .out_of_memory +;//- + + mov ebx, [page_start] + mov ecx, [page_end] +.l1: + bsf eax, [ebx]; + jnz .found + add ebx, 4 + cmp ebx, ecx + jb .l1 + pop ebx + popfd + xor eax, eax + ret +.found: +;//- + dec [pg_data.pages_free] + jz .out_of_memory +;//- + btr [ebx], eax + mov [page_start], ebx + sub ebx, sys_pgmap + lea eax, [eax+ebx*8] + shl eax, 12 +;//- dec [pg_data.pages_free] + pop ebx + popfd + ret +;//- +.out_of_memory: + mov [pg_data.pages_free], 1 + xor eax, eax + pop ebx + popfd + ret +;//- +endp + +align 4 +proc alloc_pages stdcall, count:dword + pushfd + push ebx + push edi + cli + mov eax, [count] + add eax, 7 + shr eax, 3 + mov [count], eax +;//- + mov ebx, [pg_data.pages_free] + sub ebx, 9 + js .out_of_memory + shr ebx, 3 + cmp eax, ebx + jg .out_of_memory +;//- + mov ecx, [page_start] + mov ebx, [page_end] +.find: + mov edx, [count] + mov edi, ecx +.match: + cmp byte [ecx], 0xFF + jne .next + dec edx + jz .ok + inc ecx + cmp ecx, ebx + jb .match +.out_of_memory: +.fail: + xor eax, eax + pop edi + pop ebx + popfd + ret +.next: + inc ecx + cmp ecx, ebx + jb .find + pop edi + pop ebx + popfd + xor eax, eax + ret +.ok: + sub ecx, edi + inc ecx + push esi + mov esi, edi + xor eax, eax + rep stosb + sub esi, sys_pgmap + shl esi, 3+12 + mov eax, esi + mov ebx, [count] + shl ebx, 3 + sub [pg_data.pages_free], ebx + pop esi + pop edi + pop ebx + popfd + ret +endp + +align 4 +proc map_page stdcall,lin_addr:dword,phis_addr:dword,flags:dword + push ebx + mov eax, [phis_addr] + and eax, not 0xFFF + or eax, [flags] + mov ebx, [lin_addr] + shr ebx, 12 + mov [page_tabs+ebx*4], eax + mov eax, [lin_addr] + invlpg [eax] + pop ebx + ret +endp + +align 4 +map_space: ;not implemented + + + ret + + +align 4 +proc free_page +;arg: eax page address + pushfd + cli + shr eax, 12 ;page index + bts dword [sys_pgmap], eax ;that's all! + cmc + adc [pg_data.pages_free], 0 + shr eax, 3 + and eax, not 3 ;dword offset from page_map + add eax, sys_pgmap + cmp [page_start], eax + ja @f + popfd + ret +@@: + mov [page_start], eax + popfd + ret +endp + +proc map_io_mem stdcall, base:dword, size:dword, flags:dword + + push ebx + push edi + mov eax, [size] + add eax, [base] + add eax, 4095 + and eax, -4096 + mov ecx, [base] + and ecx, -4096 + sub eax, ecx + mov [size], eax + + stdcall alloc_kernel_space, eax + test eax, eax + jz .fail + push eax + + mov edi, 0x1000 + mov ebx, eax + mov ecx, [size] + mov edx, [base] + shr eax, 12 + shr ecx, 12 + and edx, -4096 + or edx, [flags] +@@: + mov [page_tabs+eax*4], edx + invlpg [ebx] + inc eax + add ebx, edi + add edx, edi + loop @B + + pop eax + mov edx, [base] + and edx, 4095 + add eax, edx +.fail: + pop edi + pop ebx + ret +endp + +; param +; eax= page base + page flags +; ebx= linear address +; ecx= count + +align 4 +commit_pages: + test ecx, ecx + jz .fail + + push edi + push eax + push ecx + mov ecx, pg_data.mutex + call mutex_lock + pop ecx + pop eax + + mov edi, ebx + shr edi, 12 + lea edi, [page_tabs+edi*4] +@@: + stosd + invlpg [ebx] + add eax, 0x1000 + add ebx, 0x1000 + loop @B + + pop edi + + mov ecx, pg_data.mutex + call mutex_unlock +.fail: + ret + + +; param +; eax= base +; ecx= count + +align 4 +release_pages: + + push ebp + push esi + push edi + push ebx + + mov esi, eax + mov edi, eax + + shr esi, 12 + lea esi, [page_tabs+esi*4] + + push ecx + mov ecx, pg_data.mutex + call mutex_lock + pop ecx + + mov ebp, [pg_data.pages_free] + mov ebx, [page_start] + mov edx, sys_pgmap +@@: + xor eax, eax + xchg eax, [esi] + invlpg [edi] + + test eax, 1 + jz .next + + shr eax, 12 + bts [edx], eax + cmc + adc ebp, 0 + shr eax, 3 + and eax, -4 + add eax, edx + cmp eax, ebx + jae .next + + mov ebx, eax +.next: + add edi, 0x1000 + add esi, 4 + loop @B + + mov [pg_data.pages_free], ebp + mov ecx, pg_data.mutex + call mutex_unlock + + pop ebx + pop edi + pop esi + pop ebp + ret + +; param +; eax= base +; ecx= count + +align 4 +unmap_pages: + + push edi + + mov edi, eax + mov edx, eax + + shr edi, 10 + add edi, page_tabs + + xor eax, eax +@@: + stosd + invlpg [edx] + add edx, 0x1000 + loop @b + + pop edi + ret + + +align 4 +proc map_page_table stdcall, lin_addr:dword, phis_addr:dword + push ebx + mov ebx, [lin_addr] + shr ebx, 22 + mov eax, [phis_addr] + and eax, not 0xFFF + or eax, PG_UW ;+PG_NOCACHE + mov dword [master_tab+ebx*4], eax + mov eax, [lin_addr] + shr eax, 10 + add eax, page_tabs + invlpg [eax] + pop ebx + ret +endp + +align 4 +proc init_LFB + locals + pg_count dd ? + endl + + cmp dword [LFBAddress], -1 + jne @f + mov [BOOT_VAR+0x901c], byte 2 + stdcall alloc_pages, (0x280000 / 4096) + + push eax + call alloc_page + stdcall map_page_table, LFB_BASE, eax + pop eax + or eax, PG_UW + mov ebx, LFB_BASE + mov ecx, 0x280000 / 4096 + call commit_pages + mov [LFBAddress], dword LFB_BASE + ret +@@: + test [SCR_MODE], word 0100000000000000b + jnz @f + mov [BOOT_VAR+0x901c], byte 2 + ret +@@: + call init_mtrr + + mov edx, LFB_BASE + mov esi, [LFBAddress] + mov edi, 0x00C00000 + mov dword [exp_lfb+4], edx + + shr edi, 12 + mov [pg_count], edi + shr edi, 10 + + bt [cpu_caps], CAPS_PSE + jnc .map_page_tables + or esi, PG_LARGE+PG_UW + mov edx, sys_pgdir+(LFB_BASE shr 20) +@@: + mov [edx], esi + add edx, 4 + add esi, 0x00400000 + dec edi + jnz @B + + bt [cpu_caps], CAPS_PGE + jnc @F + or dword [sys_pgdir+(LFB_BASE shr 20)], PG_GLOBAL +@@: + mov dword [LFBAddress], LFB_BASE + mov eax, cr3 ;flush TLB + mov cr3, eax + ret + +.map_page_tables: + +@@: + call alloc_page + stdcall map_page_table, edx, eax + add edx, 0x00400000 + dec edi + jnz @B + + mov eax, [LFBAddress] + mov edi, page_tabs + (LFB_BASE shr 10) + or eax, PG_UW + mov ecx, [pg_count] + cld +@@: + stosd + add eax, 0x1000 + dec ecx + jnz @B + + mov dword [LFBAddress], LFB_BASE + mov eax, cr3 ;flush TLB + mov cr3, eax + + ret +endp + +align 4 +proc new_mem_resize stdcall, new_size:dword + + mov ecx, pg_data.mutex + call mutex_lock + + mov edi, [new_size] + add edi, 4095 + and edi, not 4095 + mov [new_size], edi + + mov edx, [current_slot] + cmp [edx+APPDATA.heap_base], 0 + jne .exit + + mov esi, [edx+APPDATA.mem_size] + add esi, 4095 + and esi, not 4095 + + cmp edi, esi + jae .expand + + shr edi, 12 + shr esi, 12 +@@: + mov eax, [app_page_tabs+edi*4] + test eax, 1 + jz .next + mov dword [app_page_tabs+edi*4], 2 + mov ebx, edi + shl ebx, 12 + push eax + invlpg [ebx] + pop eax + call free_page + +.next: + add edi, 1 + cmp edi, esi + jb @B + +.update_size: + mov ebx, [new_size] + call update_mem_size + + mov ecx, pg_data.mutex + call mutex_unlock + + xor eax, eax + ret +.expand: + + push esi + push edi + + add edi, 0x3FFFFF + and edi, not(0x3FFFFF) + add esi, 0x3FFFFF + and esi, not(0x3FFFFF) + + cmp esi, edi + jae .grow + + xchg esi, edi + +@@: + call alloc_page + test eax, eax + jz .exit_pop + + stdcall map_page_table, edi, eax + + push edi + shr edi, 10 + add edi, page_tabs + mov ecx, 1024 + xor eax, eax + cld + rep stosd + pop edi + + add edi, 0x00400000 + cmp edi, esi + jb @B +.grow: +;//- + pop edi + push edi + mov esi, [pg_data.pages_free] + sub esi, 1 + shr edi, 12 + cmp esi, edi + jle .out_of_memory +;//- + pop edi + pop esi +@@: + call alloc_page + test eax, eax + jz .exit + stdcall map_page, esi, eax, dword PG_UW + + push edi + mov edi, esi + xor eax, eax + mov ecx, 1024 + cld + rep stosd + pop edi + + add esi, 0x1000 + cmp esi, edi + jb @B + + jmp .update_size +;//- +.exit_pop: +.out_of_memory: +;//- + pop edi + pop esi +.exit: + mov ecx, pg_data.mutex + call mutex_unlock + + xor eax, eax + inc eax + ret +endp + +update_mem_size: +; in: edx = slot base +; ebx = new memory size +; destroys eax,ecx,edx + + mov [APPDATA.mem_size+edx], ebx +;search threads and update +;application memory size infomation + mov ecx, [APPDATA.dir_table+edx] + mov eax, 2 + +.search_threads: +;eax = current slot +;ebx = new memory size +;ecx = page directory + cmp eax, [TASK_COUNT] + jg .search_threads_end + mov edx, eax + shl edx, 5 + cmp word [CURRENT_TASK+edx+TASKDATA.state], 9 ;if slot empty? + jz .search_threads_next + shl edx, 3 + cmp [SLOT_BASE+edx+APPDATA.dir_table], ecx ;if it is our thread? + jnz .search_threads_next + mov [SLOT_BASE+edx+APPDATA.mem_size], ebx ;update memory size +.search_threads_next: + inc eax + jmp .search_threads +.search_threads_end: + ret + +; param +; eax= linear address +; +; retval +; eax= phisical page address + +align 4 +get_pg_addr: + shr eax, 12 + mov eax, [page_tabs+eax*4] + and eax, 0xFFFFF000 + ret + + +align 4 +; Now it is called from core/sys32::exc_c (see stack frame there) +proc page_fault_handler + + .err_addr equ ebp-4 + + push ebx ;save exception number (#PF) + mov ebp, esp + mov ebx, cr2 + push ebx ;that is locals: .err_addr = cr2 + inc [pg_data.pages_faults] + + mov eax, [pf_err_code] + + cmp ebx, OS_BASE ;ebx == .err_addr + jb .user_space ;страница в памяти приложения ; + + cmp ebx, page_tabs + jb .kernel_space ;страница в памяти ядра + + cmp ebx, kernel_tabs + jb .alloc;.app_tabs ;таблицы страниц приложения ; + ;просто создадим одну +if 0 ;пока это просто лишнее + cmp ebx, LFB_BASE + jb .core_tabs ;таблицы страниц ядра + ;Ошибка + .lfb: + ;область LFB + ;Ошибка + jmp .fail +end if +.core_tabs: +.fail: ;simply return to caller + mov esp, ebp + pop ebx ;restore exception number (#PF) + ret + +; xchg bx, bx +; add esp,12 ;clear in stack: locals(.err_addr) + #PF + ret_to_caller +; restore_ring3_context +; iretd + +.user_space: + test eax, PG_MAP + jnz .err_access ;Страница присутствует + ;Ошибка доступа ? + + shr ebx, 12 + mov ecx, ebx + shr ecx, 10 + mov edx, [master_tab+ecx*4] + test edx, PG_MAP + jz .fail ;таблица страниц не создана + ;неверный адрес в программе + + mov eax, [page_tabs+ebx*4] + test eax, 2 + jz .fail ;адрес не зарезервирован для ; + ;использования. Ошибка +.alloc: + call alloc_page + test eax, eax + jz .fail + + stdcall map_page, [.err_addr], eax, PG_UW + + mov edi, [.err_addr] + and edi, 0xFFFFF000 + mov ecx, 1024 + xor eax, eax + ;cld ;caller is duty for this + rep stosd +.exit: ;iret with repeat fault instruction + add esp, 12;clear in stack: locals(.err_addr) + #PF + ret_to_caller + restore_ring3_context + iretd + +.err_access: +; access denied? this may be a result of copy-on-write protection for DLL +; check list of HDLLs + and ebx, not 0xFFF + mov eax, [CURRENT_TASK] + shl eax, 8 + mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] + test eax, eax + jz .fail + mov esi, [eax+HDLL.fd] +.scan_hdll: + cmp esi, eax + jz .fail + mov edx, ebx + sub edx, [esi+HDLL.base] + cmp edx, [esi+HDLL.size] + jb .fault_in_hdll +.scan_hdll.next: + mov esi, [esi+HDLL.fd] + jmp .scan_hdll +.fault_in_hdll: +; allocate new page, map it as rw and copy data + call alloc_page + test eax, eax + jz .fail + stdcall map_page, ebx, eax, PG_UW + mov edi, ebx + mov ecx, 1024 + sub ebx, [esi+HDLL.base] + mov esi, [esi+HDLL.parent] + mov esi, [esi+DLLDESCR.data] + add esi, ebx + rep movsd + jmp .exit + +.kernel_space: + test eax, PG_MAP + jz .fail ;страница не присутствует + + test eax, 12 ;U/S (+below) + jnz .fail ;приложение обратилось к памяти + ;ядра + ;test eax, 8 + ;jnz .fail ;установлен зарезервированный бит + ;в таблицах страниц. добавлено в P4/Xeon + +;попытка записи в защищённую страницу ядра + + cmp ebx, tss._io_map_0 + jb .fail + + cmp ebx, tss._io_map_0+8192 + jae .fail + +; io permission map +; copy-on-write protection + + call alloc_page + test eax, eax + jz .fail + + push eax + stdcall map_page, [.err_addr], eax, dword PG_SW + pop eax + mov edi, [.err_addr] + and edi, -4096 + lea esi, [edi+(not tss._io_map_0)+1]; -tss._io_map_0 + + mov ebx, esi + shr ebx, 12 + mov edx, [current_slot] + or eax, PG_SW + mov [edx+APPDATA.io_map+ebx*4], eax + + add esi, [default_io_map] + mov ecx, 4096/4 + ;cld ;caller is duty for this + rep movsd + jmp .exit +endp + +; returns number of mapped bytes +proc map_mem stdcall, lin_addr:dword,slot:dword,\ + ofs:dword,buf_size:dword,req_access:dword + push 0 ; initialize number of mapped bytes + + cmp [buf_size], 0 + jz .exit + + mov eax, [slot] + shl eax, 8 + mov eax, [SLOT_BASE+eax+APPDATA.dir_table] + and eax, 0xFFFFF000 + + stdcall map_page, [ipc_pdir], eax, PG_UW + mov ebx, [ofs] + shr ebx, 22 + mov esi, [ipc_pdir] + mov edi, [ipc_ptab] + mov eax, [esi+ebx*4] + and eax, 0xFFFFF000 + jz .exit + stdcall map_page, edi, eax, PG_UW +; inc ebx +; add edi, 0x1000 +; mov eax, [esi+ebx*4] +; test eax, eax +; jz @f +; and eax, 0xFFFFF000 +; stdcall map_page, edi, eax + +@@: + mov edi, [lin_addr] + and edi, 0xFFFFF000 + mov ecx, [buf_size] + add ecx, 4095 + shr ecx, 12 + inc ecx + + mov edx, [ofs] + shr edx, 12 + and edx, 0x3FF + mov esi, [ipc_ptab] + +.map: + stdcall safe_map_page, [slot], [req_access], [ofs] + jnc .exit + add dword [ebp-4], 4096 + add [ofs], 4096 + dec ecx + jz .exit + add edi, 0x1000 + inc edx + cmp edx, 0x400 + jnz .map + inc ebx + mov eax, [ipc_pdir] + mov eax, [eax+ebx*4] + and eax, 0xFFFFF000 + jz .exit + stdcall map_page, esi, eax, PG_UW + xor edx, edx + jmp .map + +.exit: + pop eax + ret +endp + +proc map_memEx stdcall, lin_addr:dword,slot:dword,\ + ofs:dword,buf_size:dword,req_access:dword + push 0 ; initialize number of mapped bytes + + cmp [buf_size], 0 + jz .exit + + mov eax, [slot] + shl eax, 8 + mov eax, [SLOT_BASE+eax+APPDATA.dir_table] + and eax, 0xFFFFF000 + + stdcall map_page, [proc_mem_pdir], eax, PG_UW + mov ebx, [ofs] + shr ebx, 22 + mov esi, [proc_mem_pdir] + mov edi, [proc_mem_tab] + mov eax, [esi+ebx*4] + and eax, 0xFFFFF000 + test eax, eax + jz .exit + stdcall map_page, edi, eax, PG_UW + +@@: + mov edi, [lin_addr] + and edi, 0xFFFFF000 + mov ecx, [buf_size] + add ecx, 4095 + shr ecx, 12 + inc ecx + + mov edx, [ofs] + shr edx, 12 + and edx, 0x3FF + mov esi, [proc_mem_tab] + +.map: + stdcall safe_map_page, [slot], [req_access], [ofs] + jnc .exit + add dword [ebp-4], 0x1000 + add edi, 0x1000 + add [ofs], 0x1000 + inc edx + dec ecx + jnz .map +.exit: + pop eax + ret +endp + +; in: esi+edx*4 = pointer to page table entry +; in: [slot], [req_access], [ofs] on the stack +; in: edi = linear address to map +; out: CF cleared <=> failed +; destroys: only eax +proc safe_map_page stdcall, slot:dword, req_access:dword, ofs:dword + mov eax, [esi+edx*4] + test al, PG_MAP + jz .not_present + test al, PG_WRITE + jz .resolve_readonly +; normal case: writable page, just map with requested access +.map: + stdcall map_page, edi, eax, [req_access] + stc +.fail: + ret +.not_present: +; check for alloc-on-demand page + test al, 2 + jz .fail +; allocate new page, save it to source page table + push ecx + call alloc_page + pop ecx + test eax, eax + jz .fail + or al, PG_UW + mov [esi+edx*4], eax + jmp .map +.resolve_readonly: +; readonly page, probably copy-on-write +; check: readonly request of readonly page is ok + test [req_access], PG_WRITE + jz .map +; find control structure for this page + pushf + cli + cld + push ebx ecx + mov eax, [slot] + shl eax, 8 + mov eax, [SLOT_BASE+eax+APPDATA.dlls_list_ptr] + test eax, eax + jz .no_hdll + mov ecx, [eax+HDLL.fd] +.scan_hdll: + cmp ecx, eax + jz .no_hdll + mov ebx, [ofs] + and ebx, not 0xFFF + sub ebx, [ecx+HDLL.base] + cmp ebx, [ecx+HDLL.size] + jb .hdll_found + mov ecx, [ecx+HDLL.fd] + jmp .scan_hdll +.no_hdll: + pop ecx ebx + popf + clc + ret +.hdll_found: +; allocate page, save it in page table, map it, copy contents from base + mov eax, [ecx+HDLL.parent] + add ebx, [eax+DLLDESCR.data] + call alloc_page + test eax, eax + jz .no_hdll + or al, PG_UW + mov [esi+edx*4], eax + stdcall map_page, edi, eax, [req_access] + push esi edi + mov esi, ebx + mov ecx, 4096/4 + rep movsd + pop edi esi + pop ecx ebx + popf + stc + ret +endp + +sys_IPC: +;input: +; ebx=1 - set ipc buffer area +; ecx=address of buffer +; edx=size of buffer +; eax=2 - send message +; ebx=PID +; ecx=address of message +; edx=size of message + + dec ebx + jnz @f + + mov eax, [current_slot] + pushf + cli + mov [eax+APPDATA.ipc_start], ecx ;set fields in extended information area + mov [eax+APPDATA.ipc_size], edx + + add edx, ecx + add edx, 4095 + and edx, not 4095 + +.touch: + mov eax, [ecx] + add ecx, 0x1000 + cmp ecx, edx + jb .touch + + popf + mov [esp+32], ebx ;ebx=0 + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;2 +@@: + dec ebx + jnz @f + + stdcall sys_ipc_send, ecx, edx, esi + mov [esp+32], eax + ret +@@: + or eax, -1 + mov [esp+32], eax + ret + +;align 4 +;proc set_ipc_buff + +; mov eax,[current_slot] +; pushf +; cli +; mov [eax+APPDATA.ipc_start],ebx ;set fields in extended information area +; mov [eax+APPDATA.ipc_size],ecx +; +; add ecx, ebx +; add ecx, 4095 +; and ecx, not 4095 +; +;.touch: mov eax, [ebx] +; add ebx, 0x1000 +; cmp ebx, ecx +; jb .touch +; +; popf +; xor eax, eax +; ret +;endp + +proc sys_ipc_send stdcall, PID:dword, msg_addr:dword, msg_size:dword + locals + dst_slot dd ? + dst_offset dd ? + buf_size dd ? + used_buf dd ? + endl + + pushf + cli + + mov eax, [PID] + call pid_to_slot + test eax, eax + jz .no_pid + + mov [dst_slot], eax + shl eax, 8 + mov edi, [eax+SLOT_BASE+0xa0] ;is ipc area defined? + test edi, edi + jz .no_ipc_area + + mov ebx, edi + and ebx, 0xFFF + mov [dst_offset], ebx + + mov esi, [eax+SLOT_BASE+0xa4] + mov [buf_size], esi + + mov ecx, [ipc_tmp] + cmp esi, 0x40000-0x1000; size of [ipc_tmp] minus one page + jbe @f + push esi edi + add esi, 0x1000 + stdcall alloc_kernel_space, esi + mov ecx, eax + pop edi esi +@@: + mov [used_buf], ecx + stdcall map_mem, ecx, [dst_slot], \ + edi, esi, PG_SW + + mov edi, [dst_offset] + add edi, [used_buf] + cmp dword [edi], 0 + jnz .ipc_blocked ;if dword [buffer]<>0 - ipc blocked now + + mov edx, dword [edi+4] + lea ebx, [edx+8] + add ebx, [msg_size] + cmp ebx, [buf_size] + ja .buffer_overflow ;esi<0 - not enough memory in buffer + + mov dword [edi+4], ebx + mov eax, [TASK_BASE] + mov eax, [eax+0x04] ;eax - our PID + add edi, edx + mov [edi], eax + mov ecx, [msg_size] + + mov [edi+4], ecx + add edi, 8 + mov esi, [msg_addr] + ; add esi, new_app_base + cld + rep movsb + + mov ebx, [ipc_tmp] + mov edx, ebx + shr ebx, 12 + xor eax, eax + mov [page_tabs+ebx*4], eax + invlpg [edx] + + mov ebx, [ipc_pdir] + mov edx, ebx + shr ebx, 12 + xor eax, eax + mov [page_tabs+ebx*4], eax + invlpg [edx] + + mov ebx, [ipc_ptab] + mov edx, ebx + shr ebx, 12 + xor eax, eax + mov [page_tabs+ebx*4], eax + invlpg [edx] + + mov eax, [dst_slot] + shl eax, 8 + or [eax+SLOT_BASE+0xA8], dword 0x40 + cmp dword [check_idle_semaphore], 20 + jge .ipc_no_cis + + mov dword [check_idle_semaphore], 5 +.ipc_no_cis: + push 0 + jmp .ret +.no_pid: + popf + mov eax, 4 + ret +.no_ipc_area: + popf + xor eax, eax + inc eax + ret +.ipc_blocked: + push 2 + jmp .ret +.buffer_overflow: + push 3 +.ret: + mov eax, [used_buf] + cmp eax, [ipc_tmp] + jz @f + stdcall free_kernel_space, eax +@@: + pop eax + popf + ret +endp + +align 4 +sysfn_meminfo: + + ; add ecx, new_app_base + cmp ecx, OS_BASE + jae .fail + + mov eax, [pg_data.pages_count] + mov [ecx], eax + shl eax, 12 + mov [esp+32], eax + mov eax, [pg_data.pages_free] + mov [ecx+4], eax + mov eax, [pg_data.pages_faults] + mov [ecx+8], eax + mov eax, [heap_size] + mov [ecx+12], eax + mov eax, [heap_free] + mov [ecx+16], eax + mov eax, [heap_blocks] + mov [ecx+20], eax + mov eax, [free_blocks] + mov [ecx+24], eax + ret +.fail: + or dword [esp+32], -1 + ret + +align 4 +f68: + cmp ebx, 4 + jbe sys_sheduler + + cmp ebx, 11 + jb .fail + + cmp ebx, 25 + ja .fail + + jmp dword [f68call+ebx*4-11*4] +.11: + call init_heap + mov [esp+32], eax + ret +.12: + stdcall user_alloc, ecx + mov [esp+32], eax + ret +.13: + stdcall user_free, ecx + mov [esp+32], eax + ret +.14: + cmp ecx, OS_BASE + jae .fail + mov edi, ecx + call get_event_ex + mov [esp+32], eax + ret +.16: + test ecx, ecx + jz .fail + cmp ecx, OS_BASE + jae .fail + stdcall get_service, ecx + mov [esp+32], eax + ret +.17: + call srv_handlerEx ;ecx + mov [esp+32], eax + ret +.19: + cmp ecx, OS_BASE + jae .fail + stdcall load_library, ecx + mov [esp+32], eax + ret +.20: + mov eax, edx + mov ebx, ecx + call user_realloc ;in: eax = pointer, ebx = new size + mov [esp+32], eax + ret +.21: + cmp ecx, OS_BASE + jae .fail + + cmp ebx, OS_BASE + jae .fail + + mov edi, edx + stdcall load_PE, ecx + mov esi, eax + test eax, eax + jz @F + + push edi + push DRV_ENTRY + call eax + add esp, 8 + test eax, eax + jz @F + + mov [eax+SRV.entry], esi + +@@: + mov [esp+32], eax + ret +.22: + cmp ecx, OS_BASE + jae .fail + + stdcall shmem_open, ecx, edx, esi + mov [esp+24], edx + mov [esp+32], eax + ret + +.23: + cmp ecx, OS_BASE + jae .fail + + stdcall shmem_close, ecx + mov [esp+32], eax + ret +.24: + mov eax, [current_slot] + xchg ecx, [eax+APPDATA.exc_handler] + xchg edx, [eax+APPDATA.except_mask] + mov [esp+32], ecx ; reg_eax+8 + mov [esp+20], edx ; reg_ebx+8 + ret +.25: + cmp ecx, 32 + jae .fail + mov eax, [current_slot] + btr [eax+APPDATA.except_mask], ecx + setc byte[esp+32] + jecxz @f + bts [eax+APPDATA.except_mask], ecx +@@: + ret + +.fail: + xor eax, eax + mov [esp+32], eax + ret + + +align 4 +f68call: ; keep this table closer to main code + + dd f68.11 ; init_heap + dd f68.12 ; user_alloc + dd f68.13 ; user_free + dd f68.14 ; get_event_ex + dd f68.fail ; moved to f68.24 + dd f68.16 ; get_service + dd f68.17 ; call_service + dd f68.fail ; moved to f68.25 + dd f68.19 ; load_dll + dd f68.20 ; user_realloc + dd f68.21 ; load_driver + dd f68.22 ; shmem_open + dd f68.23 ; shmem_close + dd f68.24 + dd f68.25 + + +align 4 +proc load_pe_driver stdcall, file:dword + + stdcall load_PE, [file] + test eax, eax + jz .fail + + mov esi, eax + stdcall eax, DRV_ENTRY + test eax, eax + jz .fail + + mov [eax+SRV.entry], esi + ret + +.fail: + xor eax, eax + ret +endp + + +align 4 +proc init_mtrr + + cmp [BOOT_VAR+0x901c], byte 2 + je .exit + + bt [cpu_caps], CAPS_MTRR + jnc .exit + + mov eax, cr0 + or eax, 0x60000000 ;disable caching + mov cr0, eax + wbinvd ;invalidate cache + + mov ecx, 0x2FF + rdmsr ; +; has BIOS already initialized MTRRs? + test ah, 8 + jnz .skip_init +; rarely needed, so mainly placeholder +; main memory - cached + push eax + + mov eax, [MEM_AMOUNT] +; round eax up to next power of 2 + dec eax + bsr ecx, eax + mov ebx, 2 + shl ebx, cl + dec ebx +; base of memory range = 0, type of memory range = MEM_WB + xor edx, edx + mov eax, MEM_WB + mov ecx, 0x200 + wrmsr +; mask of memory range = 0xFFFFFFFFF - (size - 1), ebx = size - 1 + mov eax, 0xFFFFFFFF + mov edx, 0x0000000F + sub eax, ebx + sbb edx, 0 + or eax, 0x800 + inc ecx + wrmsr +; clear unused MTRRs + xor eax, eax + xor edx, edx +@@: + wrmsr + inc ecx + cmp ecx, 0x210 + jb @b +; enable MTRRs + pop eax + or ah, 8 + and al, 0xF0; default memtype = UC + mov ecx, 0x2FF + wrmsr +.skip_init: + stdcall set_mtrr, [LFBAddress], [LFBSize], MEM_WC + + wbinvd ;again invalidate + + mov eax, cr0 + and eax, not 0x60000000 + mov cr0, eax ; enable caching +.exit: + ret +endp + +align 4 +proc set_mtrr stdcall, base:dword,size:dword,mem_type:dword +; find unused register + mov ecx, 0x201 +@@: + rdmsr + dec ecx + test ah, 8 + jz .found + rdmsr + mov al, 0; clear memory type field + cmp eax, [base] + jz .ret + add ecx, 3 + cmp ecx, 0x210 + jb @b +; no free registers, ignore the call +.ret: + ret +.found: +; found, write values + xor edx, edx + mov eax, [base] + or eax, [mem_type] + wrmsr + + mov ebx, [size] + dec ebx + mov eax, 0xFFFFFFFF + mov edx, 0x00000000 + sub eax, ebx + sbb edx, 0 + or eax, 0x800 + inc ecx + wrmsr + ret +endp + +align 4 +proc stall stdcall, delay:dword + push ecx + push edx + push ebx + push eax + + mov eax, [delay] + mul [stall_mcs] + mov ebx, eax ;low + mov ecx, edx ;high + rdtsc + add ebx, eax + adc ecx, edx +@@: + rdtsc + sub eax, ebx + sbb edx, ecx + jb @B + + pop eax + pop ebx + pop edx + pop ecx + ret +endp + +align 4 +proc create_ring_buffer stdcall, size:dword, flags:dword + locals + buf_ptr dd ? + endl + + mov eax, [size] + test eax, eax + jz .fail + + add eax, eax + stdcall alloc_kernel_space, eax + test eax, eax + jz .fail + + push ebx + + mov [buf_ptr], eax + + mov ebx, [size] + shr ebx, 12 + push ebx + + stdcall alloc_pages, ebx + pop ecx + + test eax, eax + jz .mm_fail + + push edi + + or eax, [flags] + mov edi, [buf_ptr] + mov ebx, [buf_ptr] + mov edx, ecx + shl edx, 2 + shr edi, 10 +@@: + mov [page_tabs+edi], eax + mov [page_tabs+edi+edx], eax + invlpg [ebx] + invlpg [ebx+0x10000] + add eax, 0x1000 + add ebx, 0x1000 + add edi, 4 + dec ecx + jnz @B + + mov eax, [buf_ptr] + pop edi + pop ebx + ret +.mm_fail: + stdcall free_kernel_space, [buf_ptr] + xor eax, eax + pop ebx +.fail: + ret +endp diff --git a/kernel/trunk/core/peload.inc b/kernel/trunk/core/peload.inc index 9856b070a..882854c39 100644 --- a/kernel/trunk/core/peload.inc +++ b/kernel/trunk/core/peload.inc @@ -1,332 +1,332 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -include 'export.inc' - -align 4 - -proc load_PE stdcall, file_name:dword - locals - image dd ? - entry dd ? - base dd ? - endl - - stdcall load_file, [file_name] - test eax, eax - jz .fail - - mov [image], eax - - mov edx, [eax+60] - - stdcall kernel_alloc, [eax+80+edx] - test eax, eax - jz .cleanup - - mov [base], eax - - stdcall map_PE, eax, [image] - - mov [entry], eax - test eax, eax - jnz .cleanup - - stdcall kernel_free, [base] -.cleanup: - stdcall kernel_free, [image] - mov eax, [entry] - ret -.fail: - xor eax, eax - ret -endp - -DWORD equ dword -PTR equ - -align 4 -map_PE: ;stdcall base:dword, image:dword - cld - push ebp - push edi - push esi - push ebx - sub esp, 60 - mov ebx, DWORD PTR [esp+84] - mov ebp, DWORD PTR [esp+80] - mov edx, ebx - mov esi, ebx - add edx, DWORD PTR [ebx+60] - mov edi, ebp - mov DWORD PTR [esp+32], edx - mov ecx, DWORD PTR [edx+84] - - shr ecx, 2 - rep movsd - - movzx eax, WORD PTR [edx+6] - mov DWORD PTR [esp+36], 0 - mov DWORD PTR [esp+16], eax - jmp L2 -L3: - mov eax, DWORD PTR [edx+264] - test eax, eax - je L4 - mov esi, ebx - mov edi, ebp - add esi, DWORD PTR [edx+268] - mov ecx, eax - add edi, DWORD PTR [edx+260] - - shr ecx, 2 - rep movsd - -L4: - mov ecx, DWORD PTR [edx+256] - add ecx, 4095 - and ecx, -4096 - cmp ecx, eax - jbe L6 - sub ecx, eax - add eax, DWORD PTR [edx+260] - lea edi, [eax+ebp] - - xor eax, eax - rep stosb - -L6: - inc DWORD PTR [esp+36] - add edx, 40 -L2: - mov esi, DWORD PTR [esp+16] - cmp DWORD PTR [esp+36], esi - jne L3 - mov edi, DWORD PTR [esp+32] - cmp DWORD PTR [edi+164], 0 - je L9 - mov esi, ebp - mov ecx, ebp - sub esi, DWORD PTR [edi+52] - add ecx, DWORD PTR [edi+160] - mov eax, esi - shr eax, 16 - mov DWORD PTR [esp+12], eax - jmp L11 -L12: - lea ebx, [eax-8] - xor edi, edi - shr ebx,1 - jmp L13 -L14: - movzx eax, WORD PTR [ecx+8+edi*2] - mov edx, eax - shr eax, 12 - and edx, 4095 - add edx, DWORD PTR [ecx] - cmp ax, 2 - je L17 - cmp ax, 3 - je L18 - dec ax - jne L15 - mov eax, DWORD PTR [esp+12] - add WORD PTR [edx+ebp], ax -L17: - add WORD PTR [edx+ebp], si -L18: - add DWORD PTR [edx+ebp], esi -L15: - inc edi -L13: - cmp edi, ebx - jne L14 - add ecx, DWORD PTR [ecx+4] -L11: - mov eax, DWORD PTR [ecx+4] - test eax, eax - jne L12 -L9: - mov edx, DWORD PTR [esp+32] - cmp DWORD PTR [edx+132], 0 - je L20 - mov eax, ebp - add eax, DWORD PTR [edx+128] - mov DWORD PTR [esp+40], 0 - add eax, 20 - mov DWORD PTR [esp+56], eax -L22: - mov ecx, DWORD PTR [esp+56] - cmp DWORD PTR [ecx-16], 0 - jne L23 - cmp DWORD PTR [ecx-8], 0 - je L25 -L23: - mov edi, DWORD PTR [__exports+32] - mov esi, DWORD PTR [__exports+28] - mov eax, DWORD PTR [esp+56] - mov DWORD PTR [esp+20], edi - add edi, OS_BASE - add esi, OS_BASE - mov DWORD PTR [esp+44], esi - mov ecx, DWORD PTR [eax-4] - mov DWORD PTR [esp+48], edi - mov edx, DWORD PTR [eax-20] - mov DWORD PTR [esp+52], 0 - add ecx, ebp - add edx, ebp - mov DWORD PTR [esp+24], edx - mov DWORD PTR [esp+28], ecx -L26: - mov esi, DWORD PTR [esp+52] - mov edi, DWORD PTR [esp+24] - mov eax, DWORD PTR [edi+esi*4] - test eax, eax - je L27 - test eax, eax - js L27 - lea edi, [ebp+eax] - mov eax, DWORD PTR [esp+28] - mov DWORD PTR [eax+esi*4], 0 - lea esi, [edi+2] - push eax - push 32 - movzx eax, WORD PTR [edi] - mov edx, DWORD PTR [esp+56] - mov eax, DWORD PTR [edx+eax*4] - add eax, OS_BASE - push eax - push esi - call strncmp - pop ebx - xor ebx, ebx - test eax, eax - jne L32 - jmp L30 -L33: - push ecx - push 32 - mov ecx, DWORD PTR [esp+28] - mov eax, DWORD PTR [ecx+OS_BASE+ebx*4] - add eax, OS_BASE - push eax - push esi - call strncmp - pop edx - test eax, eax - jne L34 - mov esi, DWORD PTR [esp+44] - mov edx, DWORD PTR [esp+52] - mov ecx, DWORD PTR [esp+28] - mov eax, DWORD PTR [esi+ebx*4] - add eax, OS_BASE - mov DWORD PTR [ecx+edx*4], eax - jmp L36 -L34: - inc ebx -L32: - cmp ebx, DWORD PTR [__exports+24] - jb L33 -L36: - cmp ebx, DWORD PTR [__exports+24] - jne L37 - - mov esi, msg_unresolved - call sys_msg_board_str - lea esi, [edi+2] - call sys_msg_board_str - mov esi, msg_CR - call sys_msg_board_str - - mov DWORD PTR [esp+40], 1 - jmp L37 -L30: - movzx eax, WORD PTR [edi] - mov esi, DWORD PTR [esp+44] - mov edi, DWORD PTR [esp+52] - mov edx, DWORD PTR [esp+28] - mov eax, DWORD PTR [esi+eax*4] - add eax, OS_BASE - mov DWORD PTR [edx+edi*4], eax -L37: - inc DWORD PTR [esp+52] - jmp L26 -L27: - add DWORD PTR [esp+56], 20 - jmp L22 -L25: - xor eax, eax - cmp DWORD PTR [esp+40], 0 - jne L40 -L20: - mov ecx, DWORD PTR [esp+32] - mov eax, ebp - add eax, DWORD PTR [ecx+40] -L40: - add esp, 60 - pop ebx - pop esi - pop edi - pop ebp - ret 8 - - align 16 -__exports: - export 'KERNEL', \ - alloc_kernel_space, 'AllocKernelSpace', \ ; stdcall - alloc_page, 'AllocPage', \ ; gcc ABI - alloc_pages, 'AllocPages', \ ; stdcall - commit_pages, 'CommitPages', \ ; eax, ebx, ecx -\ - create_event, 'CreateEvent', \ ; ecx, esi - raise_event, 'RaiseEvent', \ ; eax, ebx, edx, esi - wait_event, 'WaitEvent', \ ; eax, ebx - get_event_ex, 'GetEvent', \ ; edi -\ - create_kernel_object, 'CreateObject', \ - create_ring_buffer, 'CreateRingBuffer', \ ; stdcall - destroy_kernel_object, 'DestroyObject', \ - free_kernel_space, 'FreeKernelSpace', \ ; stdcall - kernel_alloc, 'KernelAlloc', \ ; stdcall - kernel_free, 'KernelFree', \ ; stdcall - malloc, 'Kmalloc', \ - free, 'Kfree', \ - map_io_mem, 'MapIoMem', \ ; stdcall - get_pg_addr, 'GetPgAddr', \ ; eax -\ - mutex_init, 'MutexInit', \ ; gcc fastcall - mutex_lock, 'MutexLock', \ ; gcc fastcall - mutex_unlock, 'MutexUnlock', \ ; gcc fastcall -\ - get_display, 'GetDisplay', \ - set_screen, 'SetScreen', \ - pci_api_drv, 'PciApi', \ - pci_read8, 'PciRead8', \ ; stdcall - pci_read16, 'PciRead16', \ ; stdcall - pci_read32, 'PciRead32', \ ; stdcall - pci_write8, 'PciWrite8', \ ; stdcall - pci_write16, 'PciWrite16', \ ; stdcall - pci_write32, 'PciWrite32', \ ; stdcall -\ - get_pid, 'GetPid', \ - get_service, 'GetService', \ ; - reg_service, 'RegService', \ ; stdcall - attach_int_handler, 'AttachIntHandler', \ ; stdcall - user_alloc, 'UserAlloc', \ ; stdcall - user_free, 'UserFree', \ ; stdcall - unmap_pages, 'UnmapPages', \ ; eax, ecx - sys_msg_board_str, 'SysMsgBoardStr', \ - get_timer_ticks, 'GetTimerTicks', \ - get_stack_base, 'GetStackBase', \ - delay_hs, 'Delay', \ ; ebx - set_mouse_data, 'SetMouseData', \ ; - set_keyboard_data, 'SetKeyboardData' ; gcc fastcall - - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +include 'export.inc' + +align 4 + +proc load_PE stdcall, file_name:dword + locals + image dd ? + entry dd ? + base dd ? + endl + + stdcall load_file, [file_name] + test eax, eax + jz .fail + + mov [image], eax + + mov edx, [eax+60] + + stdcall kernel_alloc, [eax+80+edx] + test eax, eax + jz .cleanup + + mov [base], eax + + stdcall map_PE, eax, [image] + + mov [entry], eax + test eax, eax + jnz .cleanup + + stdcall kernel_free, [base] +.cleanup: + stdcall kernel_free, [image] + mov eax, [entry] + ret +.fail: + xor eax, eax + ret +endp + +DWORD equ dword +PTR equ + +align 4 +map_PE: ;stdcall base:dword, image:dword + cld + push ebp + push edi + push esi + push ebx + sub esp, 60 + mov ebx, DWORD PTR [esp+84] + mov ebp, DWORD PTR [esp+80] + mov edx, ebx + mov esi, ebx + add edx, DWORD PTR [ebx+60] + mov edi, ebp + mov DWORD PTR [esp+32], edx + mov ecx, DWORD PTR [edx+84] + + shr ecx, 2 + rep movsd + + movzx eax, WORD PTR [edx+6] + mov DWORD PTR [esp+36], 0 + mov DWORD PTR [esp+16], eax + jmp L2 +L3: + mov eax, DWORD PTR [edx+264] + test eax, eax + je L4 + mov esi, ebx + mov edi, ebp + add esi, DWORD PTR [edx+268] + mov ecx, eax + add edi, DWORD PTR [edx+260] + + shr ecx, 2 + rep movsd + +L4: + mov ecx, DWORD PTR [edx+256] + add ecx, 4095 + and ecx, -4096 + cmp ecx, eax + jbe L6 + sub ecx, eax + add eax, DWORD PTR [edx+260] + lea edi, [eax+ebp] + + xor eax, eax + rep stosb + +L6: + inc DWORD PTR [esp+36] + add edx, 40 +L2: + mov esi, DWORD PTR [esp+16] + cmp DWORD PTR [esp+36], esi + jne L3 + mov edi, DWORD PTR [esp+32] + cmp DWORD PTR [edi+164], 0 + je L9 + mov esi, ebp + mov ecx, ebp + sub esi, DWORD PTR [edi+52] + add ecx, DWORD PTR [edi+160] + mov eax, esi + shr eax, 16 + mov DWORD PTR [esp+12], eax + jmp L11 +L12: + lea ebx, [eax-8] + xor edi, edi + shr ebx, 1 + jmp L13 +L14: + movzx eax, WORD PTR [ecx+8+edi*2] + mov edx, eax + shr eax, 12 + and edx, 4095 + add edx, DWORD PTR [ecx] + cmp ax, 2 + je L17 + cmp ax, 3 + je L18 + dec ax + jne L15 + mov eax, DWORD PTR [esp+12] + add WORD PTR [edx+ebp], ax +L17: + add WORD PTR [edx+ebp], si +L18: + add DWORD PTR [edx+ebp], esi +L15: + inc edi +L13: + cmp edi, ebx + jne L14 + add ecx, DWORD PTR [ecx+4] +L11: + mov eax, DWORD PTR [ecx+4] + test eax, eax + jne L12 +L9: + mov edx, DWORD PTR [esp+32] + cmp DWORD PTR [edx+132], 0 + je L20 + mov eax, ebp + add eax, DWORD PTR [edx+128] + mov DWORD PTR [esp+40], 0 + add eax, 20 + mov DWORD PTR [esp+56], eax +L22: + mov ecx, DWORD PTR [esp+56] + cmp DWORD PTR [ecx-16], 0 + jne L23 + cmp DWORD PTR [ecx-8], 0 + je L25 +L23: + mov edi, DWORD PTR [__exports+32] + mov esi, DWORD PTR [__exports+28] + mov eax, DWORD PTR [esp+56] + mov DWORD PTR [esp+20], edi + add edi, OS_BASE + add esi, OS_BASE + mov DWORD PTR [esp+44], esi + mov ecx, DWORD PTR [eax-4] + mov DWORD PTR [esp+48], edi + mov edx, DWORD PTR [eax-20] + mov DWORD PTR [esp+52], 0 + add ecx, ebp + add edx, ebp + mov DWORD PTR [esp+24], edx + mov DWORD PTR [esp+28], ecx +L26: + mov esi, DWORD PTR [esp+52] + mov edi, DWORD PTR [esp+24] + mov eax, DWORD PTR [edi+esi*4] + test eax, eax + je L27 + test eax, eax + js L27 + lea edi, [ebp+eax] + mov eax, DWORD PTR [esp+28] + mov DWORD PTR [eax+esi*4], 0 + lea esi, [edi+2] + push eax + push 32 + movzx eax, WORD PTR [edi] + mov edx, DWORD PTR [esp+56] + mov eax, DWORD PTR [edx+eax*4] + add eax, OS_BASE + push eax + push esi + call strncmp + pop ebx + xor ebx, ebx + test eax, eax + jne L32 + jmp L30 +L33: + push ecx + push 32 + mov ecx, DWORD PTR [esp+28] + mov eax, DWORD PTR [ecx+OS_BASE+ebx*4] + add eax, OS_BASE + push eax + push esi + call strncmp + pop edx + test eax, eax + jne L34 + mov esi, DWORD PTR [esp+44] + mov edx, DWORD PTR [esp+52] + mov ecx, DWORD PTR [esp+28] + mov eax, DWORD PTR [esi+ebx*4] + add eax, OS_BASE + mov DWORD PTR [ecx+edx*4], eax + jmp L36 +L34: + inc ebx +L32: + cmp ebx, DWORD PTR [__exports+24] + jb L33 +L36: + cmp ebx, DWORD PTR [__exports+24] + jne L37 + + mov esi, msg_unresolved + call sys_msg_board_str + lea esi, [edi+2] + call sys_msg_board_str + mov esi, msg_CR + call sys_msg_board_str + + mov DWORD PTR [esp+40], 1 + jmp L37 +L30: + movzx eax, WORD PTR [edi] + mov esi, DWORD PTR [esp+44] + mov edi, DWORD PTR [esp+52] + mov edx, DWORD PTR [esp+28] + mov eax, DWORD PTR [esi+eax*4] + add eax, OS_BASE + mov DWORD PTR [edx+edi*4], eax +L37: + inc DWORD PTR [esp+52] + jmp L26 +L27: + add DWORD PTR [esp+56], 20 + jmp L22 +L25: + xor eax, eax + cmp DWORD PTR [esp+40], 0 + jne L40 +L20: + mov ecx, DWORD PTR [esp+32] + mov eax, ebp + add eax, DWORD PTR [ecx+40] +L40: + add esp, 60 + pop ebx + pop esi + pop edi + pop ebp + ret 8 + + align 16 +__exports: + export 'KERNEL', \ + alloc_kernel_space, 'AllocKernelSpace', \ ; stdcall + alloc_page, 'AllocPage', \ ; gcc ABI + alloc_pages, 'AllocPages', \ ; stdcall + commit_pages, 'CommitPages', \ ; eax, ebx, ecx +\ + create_event, 'CreateEvent', \ ; ecx, esi + raise_event, 'RaiseEvent', \ ; eax, ebx, edx, esi + wait_event, 'WaitEvent', \ ; eax, ebx + get_event_ex, 'GetEvent', \ ; edi +\ + create_kernel_object, 'CreateObject', \ + create_ring_buffer, 'CreateRingBuffer', \ ; stdcall + destroy_kernel_object, 'DestroyObject', \ + free_kernel_space, 'FreeKernelSpace', \ ; stdcall + kernel_alloc, 'KernelAlloc', \ ; stdcall + kernel_free, 'KernelFree', \ ; stdcall + malloc, 'Kmalloc', \ + free, 'Kfree', \ + map_io_mem, 'MapIoMem', \ ; stdcall + get_pg_addr, 'GetPgAddr', \ ; eax +\ + mutex_init, 'MutexInit', \ ; gcc fastcall + mutex_lock, 'MutexLock', \ ; gcc fastcall + mutex_unlock, 'MutexUnlock', \ ; gcc fastcall +\ + get_display, 'GetDisplay', \ + set_screen, 'SetScreen', \ + pci_api_drv, 'PciApi', \ + pci_read8, 'PciRead8', \ ; stdcall + pci_read16, 'PciRead16', \ ; stdcall + pci_read32, 'PciRead32', \ ; stdcall + pci_write8, 'PciWrite8', \ ; stdcall + pci_write16, 'PciWrite16', \ ; stdcall + pci_write32, 'PciWrite32', \ ; stdcall +\ + get_pid, 'GetPid', \ + get_service, 'GetService', \ ; + reg_service, 'RegService', \ ; stdcall + attach_int_handler, 'AttachIntHandler', \ ; stdcall + user_alloc, 'UserAlloc', \ ; stdcall + user_free, 'UserFree', \ ; stdcall + unmap_pages, 'UnmapPages', \ ; eax, ecx + sys_msg_board_str, 'SysMsgBoardStr', \ + get_timer_ticks, 'GetTimerTicks', \ + get_stack_base, 'GetStackBase', \ + delay_hs, 'Delay', \ ; ebx + set_mouse_data, 'SetMouseData', \ ; + set_keyboard_data, 'SetKeyboardData' ; gcc fastcall + + + diff --git a/kernel/trunk/core/sched.inc b/kernel/trunk/core/sched.inc index 7612a0df9..2357115a4 100644 --- a/kernel/trunk/core/sched.inc +++ b/kernel/trunk/core/sched.inc @@ -1,402 +1,406 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; IRQ0 HANDLER (TIMER INTERRUPT) ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -align 32 -irq0: - pushad - Mov ds, ax, app_data - mov es, ax - inc [timer_ticks] - mov eax, [timer_ticks] - call playNote ; <<<--- Speaker driver - sub eax,[next_usage_update] - cmp eax,100 - jb .nocounter - add [next_usage_update],100 - call updatecputimes - .nocounter: - xor ecx, ecx ; send End Of Interrupt signal - call irq_eoi - btr dword[DONT_SWITCH], 0 - jc .return - call find_next_task - jz .return ; if there is only one running process - call do_change_task - .return: - popad - iretd - -align 4 -change_task: - pushfd - cli - pushad -if 0 -; \begin{Mario79} ; <- must be refractoried, if used... - cmp [dma_task_switched], 1 - jne .find_next_task - mov [dma_task_switched], 0 - mov ebx, [dma_process] - cmp [CURRENT_TASK], ebx - je .return - mov edi, [dma_slot_ptr] - mov [CURRENT_TASK], ebx - mov [TASK_BASE], edi - jmp @f -.find_next_task: -; \end{Mario79} -end if - call find_next_task - jz .return ; the same task -> skip switch - @@: mov byte[DONT_SWITCH], 1 - call do_change_task - .return: - popad - popfd - ret - -uglobal -align 4 -; far_jump: -; .offs dd ? -; .sel dw ? - context_counter dd 0 ;noname & halyavin - next_usage_update dd 0 - timer_ticks dd 0 -; prev_slot dd ? -; event_sched dd ? -endg - -align 4 -update_counters: - mov edi, [TASK_BASE] - rdtsc - sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add - add [edi+TASKDATA.counter_sum], eax ; counter sum - ret -align 4 -updatecputimes: - xor eax,eax - xchg eax,[idleuse] - mov [idleusesec],eax - mov ecx, [TASK_COUNT] - mov edi, TASK_DATA - .newupdate: - xor eax,eax - xchg eax,[edi+TASKDATA.counter_sum] - mov [edi+TASKDATA.cpu_usage],eax - add edi,0x20 - loop .newupdate - ret - -align 4 -find_next_task: -;info: -; Find next task to execute -;retval: -; ebx = address of the APPDATA for the selected task (slot-base) -; esi = previous slot-base ([current_slot] at the begin) -; edi = address of the TASKDATA for the selected task -; ZF = 1 if the task is the same -;warning: -; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result -; [current_slot] is not set to new value (ebx)!!! -;scratched: eax,ecx - call update_counters ; edi := [TASK_BASE] - Mov esi, ebx, [current_slot] - .loop: - cmp bh,[TASK_COUNT] - jb @f - xor bh, bh - mov edi,CURRENT_TASK - @@: inc bh ; ebx += APPDATA.size - add edi,0x20 ; edi += TASKDATA.size - mov al, [edi+TASKDATA.state] - test al, al - jz .found ; state == 0 - cmp al, 5 - jne .loop ; state == 1,2,3,4,9 - ; state == 5 - pushad ; more freedom for [APPDATA.wait_test] - call [ebx+APPDATA.wait_test] - mov [esp+28],eax - popad - or eax,eax - jnz @f - ; testing for timeout - mov ecx, [timer_ticks] - sub ecx, [ebx+APPDATA.wait_begin] - cmp ecx, [ebx+APPDATA.wait_timeout] - jb .loop - @@: mov [ebx+APPDATA.wait_param], eax ; retval for wait - mov [edi+TASKDATA.state], 0 - .found: - mov [CURRENT_TASK],bh - mov [TASK_BASE],edi - rdtsc ;call _rdtsc - mov [edi+TASKDATA.counter_add],eax ; for next using update_counters - cmp ebx, esi ;esi - previous slot-base - ret -;TODO: Надо бы убрать использование do_change_task из V86... -; и после этого перенести обработку TASKDATA.counter_add/sum в do_change_task - -align 4 -do_change_task: -;param: -; ebx = address of the APPDATA for incoming task (new) -;warning: -; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task) -; [current_slot] is the outcoming (old), and set here to a new value (ebx) -;scratched: eax,ecx,esi - mov esi,ebx - xchg esi,[current_slot] -; set new stack after saving old - mov [esi+APPDATA.saved_esp], esp - mov esp, [ebx+APPDATA.saved_esp] -; set new thread io-map - Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map] - Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4] -; set new thread memory-map - mov ecx, APPDATA.dir_table - mov eax, [ebx+ecx] ;offset>0x7F - cmp eax, [esi+ecx] ;offset>0x7F - je @f - mov cr3, eax -@@: -; set tss.esp0 - - Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0] - - mov edx, [ebx+APPDATA.tls_base] - cmp edx, [esi+APPDATA.tls_base] - je @f - - mov [tls_data_l+2],dx - shr edx,16 - mov [tls_data_l+4],dl - mov [tls_data_l+7],dh - - mov dx, app_tls - mov fs, dx -@@: -; set gs selector unconditionally - Mov gs,ax,graph_data - ; set CR0.TS - cmp bh, byte[fpu_owner] ;bh == incoming task (new) - clts ;clear a task switch flag - je @f - mov eax, cr0 ;and set it again if the owner - or eax, CR0_TS ;of a fpu has changed - mov cr0, eax - @@: ; set context_counter (only for user pleasure ???) - inc [context_counter] ;noname & halyavin - ; set debug-registers, if it's necessary - test byte[ebx+APPDATA.dbg_state], 1 - jz @f - xor eax, eax - mov dr6, eax - lea esi,[ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table] ;offset>0x7F - cld - macro lodsReg [reg] { - lodsd - mov reg,eax - } lodsReg dr0, dr1, dr2, dr3, dr7 - purge lodsReg - @@: ret -;end. - - - -struc MUTEX_WAITER -{ - .list LHEAD - .task rd 1 - .sizeof: -}; - -virtual at 0 - MUTEX_WAITER MUTEX_WAITER -end virtual - -;void __fastcall mutex_init(struct mutex *lock) - -align 4 -mutex_init: - mov [ecx+MUTEX.wait.next], ecx - mov [ecx+MUTEX.wait.prev], ecx - mov [ecx+MUTEX.count],1 - ret - - -;void __fastcall mutex_lock(struct mutex *lock) - -align 4 -mutex_lock: - - dec [ecx+MUTEX.count] - jns .done - - pushfd - cli - - sub esp, MUTEX_WAITER.sizeof - - list_add_tail esp, ecx ;esp= new waiter, ecx= list head - - mov edx, [TASK_BASE] - mov [esp+MUTEX_WAITER.task], edx - -.forever: - - mov eax, -1 - xchg eax, [ecx+MUTEX.count] - dec eax - jz @F - - mov [edx+TASKDATA.state], 1 - call change_task - jmp .forever -@@: - mov edx, [esp+MUTEX_WAITER.list.next] - mov eax, [esp+MUTEX_WAITER.list.prev] - - mov [eax+MUTEX_WAITER.list.next], edx - mov [edx+MUTEX_WAITER.list.prev], eax - cmp [ecx+MUTEX.wait.next], ecx - jne @F - - mov [ecx+MUTEX.count], 0 -@@: - add esp, MUTEX_WAITER.sizeof - - popfd -.done: - ret - -;void __fastcall mutex_unlock(struct mutex *lock) - -align 4 -mutex_unlock: - - pushfd - cli - - mov eax, [ecx+MUTEX.wait.next] - cmp eax, ecx - mov [ecx+MUTEX.count], 1 - je @F - - mov eax, [eax+MUTEX_WAITER.task] - mov [eax+TASKDATA.state], 0 -@@: - popfd - ret - - -purge MUTEX_WAITER - -if 0 - -struc TIMER -{ - .next dd ? - .exp_time dd ? - .func dd ? - .arg dd ? -} - - -MAX_PROIRITY 0 ; highest, used for kernel tasks -MAX_USER_PRIORITY 0 ; highest priority for user processes -USER_PRIORITY 7 ; default (should correspond to nice 0) -MIN_USER_PRIORITY 14 ; minimum priority for user processes -IDLE_PRIORITY 15 ; lowest, only IDLE process goes here -NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1 - -uglobal -rdy_head rd 16 -endg - -align 4 -pick_task: - - xor eax, eax - .pick: - mov ebx, [rdy_head+eax*4] - test ebx, ebx - jz .next - - mov [next_task], ebx - test [ebx+flags.billable] - jz @F - mov [bill_task], ebx - @@: - ret - .next: - inc eax - jmp .pick - -; param -; eax= task -; -; retval -; eax= task -; ebx= queue -; ecx= front if 1 or back if 0 -align 4 -shed: - cmp [eax+.tics_left], 0 ;signed compare - mov ebx, [eax+.priority] - setg ecx - jg @F - - mov edx, [eax+.tics_quantum] - mov [eax+.ticks_left], edx - cmp ebx, (IDLE_PRIORITY-1) - je @F - inc ebx - @@: - ret - -; param -; eax= task -align 4 -enqueue: - call shed ;eax - cmp [rdy_head+ebx*4],0 - jnz @F - - mov [rdy_head+ebx*4], eax - mov [rdy_tail+ebx*4], eax - mov [eax+.next_ready], 0 - jmp .pick - @@: - test ecx, ecx - jz .back - - mov ecx, [rdy_head+ebx*4] - mov [eax+.next_ready], ecx - mov [rdy_head+ebx*4], eax - jmp .pick - .back: - mov ecx, [rdy_tail+ebx*4] - mov [ecx+.next_ready], eax - mov [rdy_tail+ebx*4], eax - mov [eax+.next_ready], 0 - .pick: - call pick_proc ;select next task - ret - -end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; IRQ0 HANDLER (TIMER INTERRUPT) ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +align 32 +irq0: + pushad + Mov ds, ax, app_data + mov es, ax + inc [timer_ticks] + mov eax, [timer_ticks] + call playNote ; <<<--- Speaker driver + sub eax, [next_usage_update] + cmp eax, 100 + jb .nocounter + add [next_usage_update], 100 + call updatecputimes + .nocounter: + xor ecx, ecx ; send End Of Interrupt signal + call irq_eoi + btr dword[DONT_SWITCH], 0 + jc .return + call find_next_task + jz .return ; if there is only one running process + call do_change_task + .return: + popad + iretd + +align 4 +change_task: + pushfd + cli + pushad +if 0 +; \begin{Mario79} ; <- must be refractoried, if used... + cmp [dma_task_switched], 1 + jne .find_next_task + mov [dma_task_switched], 0 + mov ebx, [dma_process] + cmp [CURRENT_TASK], ebx + je .return + mov edi, [dma_slot_ptr] + mov [CURRENT_TASK], ebx + mov [TASK_BASE], edi + jmp @f +.find_next_task: +; \end{Mario79} +end if + call find_next_task + jz .return ; the same task -> skip switch + @@: + mov byte[DONT_SWITCH], 1 + call do_change_task + .return: + popad + popfd + ret + +uglobal +align 4 +; far_jump: +; .offs dd ? +; .sel dw ? + context_counter dd 0 ;noname & halyavin + next_usage_update dd 0 + timer_ticks dd 0 +; prev_slot dd ? +; event_sched dd ? +endg + +align 4 +update_counters: + mov edi, [TASK_BASE] + rdtsc + sub eax, [edi+TASKDATA.counter_add] ; time stamp counter add + add [edi+TASKDATA.counter_sum], eax ; counter sum + ret +align 4 +updatecputimes: + xor eax, eax + xchg eax, [idleuse] + mov [idleusesec], eax + mov ecx, [TASK_COUNT] + mov edi, TASK_DATA + .newupdate: + xor eax, eax + xchg eax, [edi+TASKDATA.counter_sum] + mov [edi+TASKDATA.cpu_usage], eax + add edi, 0x20 + loop .newupdate + ret + +align 4 +find_next_task: +;info: +; Find next task to execute +;retval: +; ebx = address of the APPDATA for the selected task (slot-base) +; esi = previous slot-base ([current_slot] at the begin) +; edi = address of the TASKDATA for the selected task +; ZF = 1 if the task is the same +;warning: +; [CURRENT_TASK] = bh , [TASK_BASE] = edi -- as result +; [current_slot] is not set to new value (ebx)!!! +;scratched: eax,ecx + call update_counters ; edi := [TASK_BASE] + Mov esi, ebx, [current_slot] + .loop: + cmp bh, [TASK_COUNT] + jb @f + xor bh, bh + mov edi, CURRENT_TASK + @@: + inc bh ; ebx += APPDATA.size + add edi, 0x20; edi += TASKDATA.size + mov al, [edi+TASKDATA.state] + test al, al + jz .found ; state == 0 + cmp al, 5 + jne .loop ; state == 1,2,3,4,9 + ; state == 5 + pushad ; more freedom for [APPDATA.wait_test] + call [ebx+APPDATA.wait_test] + mov [esp+28], eax + popad + or eax, eax + jnz @f + ; testing for timeout + mov ecx, [timer_ticks] + sub ecx, [ebx+APPDATA.wait_begin] + cmp ecx, [ebx+APPDATA.wait_timeout] + jb .loop + @@: + mov [ebx+APPDATA.wait_param], eax ; retval for wait + mov [edi+TASKDATA.state], 0 + .found: + mov [CURRENT_TASK], bh + mov [TASK_BASE], edi + rdtsc ;call _rdtsc + mov [edi+TASKDATA.counter_add], eax; for next using update_counters + cmp ebx, esi ;esi - previous slot-base + ret +;TODO: Надо бы убрать использование do_change_task из V86... +; и после этого перенести обработку TASKDATA.counter_add/sum в do_change_task + +align 4 +do_change_task: +;param: +; ebx = address of the APPDATA for incoming task (new) +;warning: +; [CURRENT_TASK] and [TASK_BASE] must be changed before (e.g. in find_next_task) +; [current_slot] is the outcoming (old), and set here to a new value (ebx) +;scratched: eax,ecx,esi + mov esi, ebx + xchg esi, [current_slot] +; set new stack after saving old + mov [esi+APPDATA.saved_esp], esp + mov esp, [ebx+APPDATA.saved_esp] +; set new thread io-map + Mov dword [page_tabs+((tss._io_map_0 and -4096) shr 10)],eax,[ebx+APPDATA.io_map] + Mov dword [page_tabs+((tss._io_map_1 and -4096) shr 10)],eax,[ebx+APPDATA.io_map+4] +; set new thread memory-map + mov ecx, APPDATA.dir_table + mov eax, [ebx+ecx] ;offset>0x7F + cmp eax, [esi+ecx] ;offset>0x7F + je @f + mov cr3, eax +@@: +; set tss.esp0 + + Mov [tss._esp0],eax,[ebx+APPDATA.saved_esp0] + + mov edx, [ebx+APPDATA.tls_base] + cmp edx, [esi+APPDATA.tls_base] + je @f + + mov [tls_data_l+2], dx + shr edx, 16 + mov [tls_data_l+4], dl + mov [tls_data_l+7], dh + + mov dx, app_tls + mov fs, dx +@@: +; set gs selector unconditionally + Mov gs,ax,graph_data + ; set CR0.TS + cmp bh, byte[fpu_owner] ;bh == incoming task (new) + clts ;clear a task switch flag + je @f + mov eax, cr0 ;and set it again if the owner + or eax, CR0_TS ;of a fpu has changed + mov cr0, eax + @@: ; set context_counter (only for user pleasure ???) + inc [context_counter] ;noname & halyavin + ; set debug-registers, if it's necessary + test byte[ebx+APPDATA.dbg_state], 1 + jz @f + xor eax, eax + mov dr6, eax + lea esi, [ebx+ecx+APPDATA.dbg_regs-APPDATA.dir_table];offset>0x7F + cld + macro lodsReg [reg] { + lodsd + mov reg, eax + } lodsReg dr0, dr1, dr2, dr3, dr7 + purge lodsReg + @@: + ret +;end. + + + +struc MUTEX_WAITER +{ + .list LHEAD + .task rd 1 + .sizeof: +}; + +virtual at 0 + MUTEX_WAITER MUTEX_WAITER +end virtual + +;void __fastcall mutex_init(struct mutex *lock) + +align 4 +mutex_init: + mov [ecx+MUTEX.wait.next], ecx + mov [ecx+MUTEX.wait.prev], ecx + mov [ecx+MUTEX.count], 1 + ret + + +;void __fastcall mutex_lock(struct mutex *lock) + +align 4 +mutex_lock: + + dec [ecx+MUTEX.count] + jns .done + + pushfd + cli + + sub esp, MUTEX_WAITER.sizeof + + list_add_tail esp, ecx ;esp= new waiter, ecx= list head + + mov edx, [TASK_BASE] + mov [esp+MUTEX_WAITER.task], edx + +.forever: + + mov eax, -1 + xchg eax, [ecx+MUTEX.count] + dec eax + jz @F + + mov [edx+TASKDATA.state], 1 + call change_task + jmp .forever +@@: + mov edx, [esp+MUTEX_WAITER.list.next] + mov eax, [esp+MUTEX_WAITER.list.prev] + + mov [eax+MUTEX_WAITER.list.next], edx + mov [edx+MUTEX_WAITER.list.prev], eax + cmp [ecx+MUTEX.wait.next], ecx + jne @F + + mov [ecx+MUTEX.count], 0 +@@: + add esp, MUTEX_WAITER.sizeof + + popfd +.done: + ret + +;void __fastcall mutex_unlock(struct mutex *lock) + +align 4 +mutex_unlock: + + pushfd + cli + + mov eax, [ecx+MUTEX.wait.next] + cmp eax, ecx + mov [ecx+MUTEX.count], 1 + je @F + + mov eax, [eax+MUTEX_WAITER.task] + mov [eax+TASKDATA.state], 0 +@@: + popfd + ret + + +purge MUTEX_WAITER + +if 0 + +struc TIMER +{ + .next dd ? + .exp_time dd ? + .func dd ? + .arg dd ? +} + + +MAX_PROIRITY 0 ; highest, used for kernel tasks +MAX_USER_PRIORITY 0 ; highest priority for user processes +USER_PRIORITY 7 ; default (should correspond to nice 0) +MIN_USER_PRIORITY 14 ; minimum priority for user processes +IDLE_PRIORITY 15 ; lowest, only IDLE process goes here +NR_SCHED_QUEUES 16 ; MUST equal IDLE_PRIORYTY + 1 + +uglobal +rdy_head rd 16 +endg + +align 4 +pick_task: + + xor eax, eax + .pick: + mov ebx, [rdy_head+eax*4] + test ebx, ebx + jz .next + + mov [next_task], ebx + test [ebx+flags.billable] + jz @F + mov [bill_task], ebx + @@: + ret + .next: + inc eax + jmp .pick + +; param +; eax= task +; +; retval +; eax= task +; ebx= queue +; ecx= front if 1 or back if 0 +align 4 +shed: + cmp [eax+.tics_left], 0;signed compare + mov ebx, [eax+.priority] + setg ecx + jg @F + + mov edx, [eax+.tics_quantum] + mov [eax+.ticks_left], edx + cmp ebx, (IDLE_PRIORITY-1) + je @F + inc ebx + @@: + ret + +; param +; eax= task +align 4 +enqueue: + call shed;eax + cmp [rdy_head+ebx*4], 0 + jnz @F + + mov [rdy_head+ebx*4], eax + mov [rdy_tail+ebx*4], eax + mov [eax+.next_ready], 0 + jmp .pick + @@: + test ecx, ecx + jz .back + + mov ecx, [rdy_head+ebx*4] + mov [eax+.next_ready], ecx + mov [rdy_head+ebx*4], eax + jmp .pick + .back: + mov ecx, [rdy_tail+ebx*4] + mov [ecx+.next_ready], eax + mov [rdy_tail+ebx*4], eax + mov [eax+.next_ready], 0 + .pick: + call pick_proc;select next task + ret + +end if diff --git a/kernel/trunk/core/string.inc b/kernel/trunk/core/string.inc index fc6e35473..0abcb43a8 100644 --- a/kernel/trunk/core/string.inc +++ b/kernel/trunk/core/string.inc @@ -1,188 +1,188 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; Author: Kees J. Bot 1 Jan 1994 ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; size_t strncat(char *s1, const char *s2, size_t n) -; Append string s2 to s1. - -; char *strchr(const char *s, int c) - - -; int strncmp(const char *s1, const char *s2, size_t n) -; Compare two strings. - -; char *strncpy(char *s1, const char *s2, size_t n) -; Copy string s2 to s1. - -; size_t strnlen(const char *s, size_t n) -; Return the length of a string. - -; proc strrchr stdcall, s:dword, c:dword -; Look for the last occurrence a character in a string. - -proc strncat stdcall, s1:dword, s2:dword, n:dword - push esi - push edi - mov edi, [s1] ; String s1 - mov edx, [n] ; Maximum length - - mov ecx, -1 - xor al, al ; Null byte - cld - repne scasb ; Look for the zero byte in s1 - dec edi ; Back one up (and clear 'Z' flag) - push edi ; Save end of s1 - mov edi, [s2] ; edi = string s2 - mov ecx, edx ; Maximum count - repne scasb ; Look for the end of s2 - jne @F - inc ecx ; Exclude null byte -@@: - sub edx, ecx ; Number of bytes in s2 - mov ecx, edx - mov esi, [s2] ; esi = string s2 - pop edi ; edi = end of string s1 - rep movsb ; Copy bytes - stosb ; Add a terminating null - mov eax, [s1] ; Return s1 - pop edi - pop esi - ret -endp - -align 4 -proc strncmp stdcall, s1:dword, s2:dword, n:dword - - push esi - push edi - mov ecx, [n] - test ecx, ecx ; Max length is zero? - je .done - - mov esi, [s1] ; esi = string s1 - mov edi, [s2] ; edi = string s2 - cld -.compare: - cmpsb ; Compare two bytes - jne .done - cmp byte [esi-1], 0 ; End of string? - je .done - dec ecx ; Length limit reached? - jne .compare -.done: - seta al ; al = (s1 > s2) - setb ah ; ah = (s1 < s2) - sub al, ah - movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 - pop edi - pop esi - ret -endp - -align 4 -proc strncpy stdcall, s1:dword, s2:dword, n:dword - - push esi - push edi - - mov ecx, [n] ; Maximum length - mov edi, [s2] ; edi = string s2 - xor al, al ; Look for a zero byte - mov edx, ecx ; Save maximum count - cld - repne scasb ; Look for end of s2 - sub edx, ecx ; Number of bytes in s2 including null - xchg ecx, edx - mov esi, [s2] ; esi = string s2 - mov edi, [s1] ; edi = string s1 - rep movsb ; Copy bytes - - mov ecx, edx ; Number of bytes not copied - rep stosb ; strncpy always copies n bytes by null padding - mov eax, [s1] ; Return s1 - pop edi - pop esi - ret -endp - -align 4 -proc strnlen stdcall, s:dword, n:dword - - push edi - mov edi, [s] ; edi = string - xor al, al ; Look for a zero byte - mov edx, ecx ; Save maximum count - cmp cl, 1 ; 'Z' bit must be clear if ecx = 0 - cld - repne scasb ; Look for zero - jne @F - inc ecx ; Don't count zero byte -@@: - mov eax, edx - sub eax, ecx ; Compute bytes scanned - pop edi - ret -endp - -align 4 -proc strchr stdcall, s:dword, c:dword - push edi - cld - mov edi, [s] ; edi = string - mov edx, 16 ; Look at small chunks of the string -.next: - shl edx, 1 ; Chunks become bigger each time - mov ecx, edx - xor al, al ; Look for the zero at the end - repne scasb - pushf ; Remember the flags - sub ecx, edx - neg ecx ; Some or all of the chunk - sub edi, ecx ; Step back - mov eax, [c] ; The character to look for - repne scasb - je .found - popf ; Did we find the end of string earlier? - jne .next ; No, try again - xor eax, eax ; Return NULL - pop edi - ret -.found: - pop eax ; Get rid of those flags - lea eax, [edi-1] ; Address of byte found - pop edi - ret - -endp - - -proc strrchr stdcall, s:dword, c:dword - push edi - mov edi, [s] ; edi = string - mov ecx, -1 - xor al, al - cld - repne scasb ; Look for the end of the string - not ecx ; -1 - ecx = Length of the string + null - dec edi ; Put edi back on the zero byte - mov eax, [c] ; The character to look for - std ; Downwards search - repne scasb - cld ; Direction bit back to default - jne .fail - lea eax, [edi+1] ; Found it - pop edi - ret -.fail: - xor eax, eax ; Not there - pop edi - ret -endp - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; Author: Kees J. Bot 1 Jan 1994 ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; size_t strncat(char *s1, const char *s2, size_t n) +; Append string s2 to s1. + +; char *strchr(const char *s, int c) + + +; int strncmp(const char *s1, const char *s2, size_t n) +; Compare two strings. + +; char *strncpy(char *s1, const char *s2, size_t n) +; Copy string s2 to s1. + +; size_t strnlen(const char *s, size_t n) +; Return the length of a string. + +; proc strrchr stdcall, s:dword, c:dword +; Look for the last occurrence a character in a string. + +proc strncat stdcall, s1:dword, s2:dword, n:dword + push esi + push edi + mov edi, [s1] ; String s1 + mov edx, [n] ; Maximum length + + mov ecx, -1 + xor al, al ; Null byte + cld + repne scasb ; Look for the zero byte in s1 + dec edi ; Back one up (and clear 'Z' flag) + push edi ; Save end of s1 + mov edi, [s2] ; edi = string s2 + mov ecx, edx ; Maximum count + repne scasb ; Look for the end of s2 + jne @F + inc ecx ; Exclude null byte +@@: + sub edx, ecx ; Number of bytes in s2 + mov ecx, edx + mov esi, [s2] ; esi = string s2 + pop edi ; edi = end of string s1 + rep movsb ; Copy bytes + stosb ; Add a terminating null + mov eax, [s1] ; Return s1 + pop edi + pop esi + ret +endp + +align 4 +proc strncmp stdcall, s1:dword, s2:dword, n:dword + + push esi + push edi + mov ecx, [n] + test ecx, ecx ; Max length is zero? + je .done + + mov esi, [s1] ; esi = string s1 + mov edi, [s2] ; edi = string s2 + cld +.compare: + cmpsb ; Compare two bytes + jne .done + cmp byte [esi-1], 0 ; End of string? + je .done + dec ecx ; Length limit reached? + jne .compare +.done: + seta al ; al = (s1 > s2) + setb ah ; ah = (s1 < s2) + sub al, ah + movsx eax, al ; eax = (s1 > s2) - (s1 < s2), i.e. -1, 0, 1 + pop edi + pop esi + ret +endp + +align 4 +proc strncpy stdcall, s1:dword, s2:dword, n:dword + + push esi + push edi + + mov ecx, [n] ; Maximum length + mov edi, [s2] ; edi = string s2 + xor al, al ; Look for a zero byte + mov edx, ecx ; Save maximum count + cld + repne scasb ; Look for end of s2 + sub edx, ecx ; Number of bytes in s2 including null + xchg ecx, edx + mov esi, [s2] ; esi = string s2 + mov edi, [s1] ; edi = string s1 + rep movsb ; Copy bytes + + mov ecx, edx ; Number of bytes not copied + rep stosb ; strncpy always copies n bytes by null padding + mov eax, [s1] ; Return s1 + pop edi + pop esi + ret +endp + +align 4 +proc strnlen stdcall, s:dword, n:dword + + push edi + mov edi, [s] ; edi = string + xor al, al ; Look for a zero byte + mov edx, ecx ; Save maximum count + cmp cl, 1 ; 'Z' bit must be clear if ecx = 0 + cld + repne scasb ; Look for zero + jne @F + inc ecx ; Don't count zero byte +@@: + mov eax, edx + sub eax, ecx ; Compute bytes scanned + pop edi + ret +endp + +align 4 +proc strchr stdcall, s:dword, c:dword + push edi + cld + mov edi, [s] ; edi = string + mov edx, 16 ; Look at small chunks of the string +.next: + shl edx, 1 ; Chunks become bigger each time + mov ecx, edx + xor al, al ; Look for the zero at the end + repne scasb + pushf ; Remember the flags + sub ecx, edx + neg ecx ; Some or all of the chunk + sub edi, ecx ; Step back + mov eax, [c] ; The character to look for + repne scasb + je .found + popf ; Did we find the end of string earlier? + jne .next ; No, try again + xor eax, eax ; Return NULL + pop edi + ret +.found: + pop eax ; Get rid of those flags + lea eax, [edi-1] ; Address of byte found + pop edi + ret + +endp + + +proc strrchr stdcall, s:dword, c:dword + push edi + mov edi, [s] ; edi = string + mov ecx, -1 + xor al, al + cld + repne scasb ; Look for the end of the string + not ecx ; -1 - ecx = Length of the string + null + dec edi ; Put edi back on the zero byte + mov eax, [c] ; The character to look for + std ; Downwards search + repne scasb + cld ; Direction bit back to default + jne .fail + lea eax, [edi+1] ; Found it + pop edi + ret +.fail: + xor eax, eax ; Not there + pop edi + ret +endp + + diff --git a/kernel/trunk/core/sync.inc b/kernel/trunk/core/sync.inc index 03873ade1..852840003 100644 --- a/kernel/trunk/core/sync.inc +++ b/kernel/trunk/core/sync.inc @@ -1,119 +1,119 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; Synhronization for MenuetOS. ;; -;; Author: Halyavin Andrey, halyavin@land.ru ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -if ~defined sync_inc -sync_inc_fix: -sync_inc fix sync_inc_fix - -;simplest mutex. -macro SimpleMutex name -{ -; iglobal - name dd 0 - name#.type = 1 -; endg -} -macro WaitSimpleMutex name -{ - local start_wait,ok -start_wait=$ - cli - cmp [name],dword 0 - jz ok - sti - call change_task - jmp start_wait -ok=$ - push eax - mov eax,dword [TASK_BASE+second_base_address] - mov eax,[eax+TASKDATA.pid] - mov [name],eax - pop eax - sti -} -macro ReleaseSimpleMutex name -{ - mov [name],dword 0 -} -macro TryWaitSimpleMutex name ;result in eax and in flags -{ - local ok,try_end - cmp [name],dword 0 - jz ok - xor eax,eax - jmp try_end -ok=$ - xor eax,eax - inc eax -try_end=$ -} -macro SimpleCriticalSection name -{ -; iglobal - name dd 0 - dd 0 - name#.type=2 -; endg -} -macro WaitSimpleCriticalSection name -{ - local start_wait,first_wait,inc_counter,end_wait - push eax - mov eax,[TASK_BASE+second_base_address] - mov eax,[eax+TASKDATA.pid] -start_wait=$ - cli - cmp [name],dword 0 - jz first_wait - cmp [name],eax - jz inc_counter - sti - call change_task - jmp start_wait -first_wait=$ - mov [name],eax - mov [name+4],dword 1 - jmp end_wait -inc_counter=$ - inc dword [name+4] -end_wait=$ - sti - pop eax -} -macro ReleaseSimpleCriticalSection name -{ - local release_end - dec dword [name+4] - jnz release_end - mov [name],dword 0 -release_end=$ -} -macro TryWaitSimpleCriticalSection name ;result in eax and in flags -{ - local ok,try_end - mov eax,[CURRENT_TASK+second_base_address] - mov eax,[eax+TASKDATA.pid] - cmp [name],eax - jz ok - cmp [name],0 - jz ok - xor eax,eax - jmp try_end -ok=$ - xor eax,eax - inc eax -try_end=$ -} -_cli equ call MEM_HeapLock -_sti equ call MEM_HeapUnLock -end if - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; Synhronization for MenuetOS. ;; +;; Author: Halyavin Andrey, halyavin@land.ru ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +if ~defined sync_inc +sync_inc_fix: +sync_inc fix sync_inc_fix + +;simplest mutex. +macro SimpleMutex name +{ +; iglobal + name dd 0 + name#.type = 1 +; endg +} +macro WaitSimpleMutex name +{ + local start_wait,ok +start_wait=$ + cli + cmp [name], dword 0 + jz ok + sti + call change_task + jmp start_wait +ok=$ + push eax + mov eax, dword [TASK_BASE+second_base_address] + mov eax, [eax+TASKDATA.pid] + mov [name], eax + pop eax + sti +} +macro ReleaseSimpleMutex name +{ + mov [name], dword 0 +} +macro TryWaitSimpleMutex name ;result in eax and in flags +{ + local ok,try_end + cmp [name], dword 0 + jz ok + xor eax, eax + jmp try_end +ok=$ + xor eax, eax + inc eax +try_end=$ +} +macro SimpleCriticalSection name +{ +; iglobal + name dd 0 + dd 0 + name#.type=2 +; endg +} +macro WaitSimpleCriticalSection name +{ + local start_wait,first_wait,inc_counter,end_wait + push eax + mov eax, [TASK_BASE+second_base_address] + mov eax, [eax+TASKDATA.pid] +start_wait=$ + cli + cmp [name], dword 0 + jz first_wait + cmp [name], eax + jz inc_counter + sti + call change_task + jmp start_wait +first_wait=$ + mov [name], eax + mov [name+4], dword 1 + jmp end_wait +inc_counter=$ + inc dword [name+4] +end_wait=$ + sti + pop eax +} +macro ReleaseSimpleCriticalSection name +{ + local release_end + dec dword [name+4] + jnz release_end + mov [name], dword 0 +release_end=$ +} +macro TryWaitSimpleCriticalSection name ;result in eax and in flags +{ + local ok,try_end + mov eax, [CURRENT_TASK+second_base_address] + mov eax, [eax+TASKDATA.pid] + cmp [name], eax + jz ok + cmp [name], 0 + jz ok + xor eax, eax + jmp try_end +ok=$ + xor eax, eax + inc eax +try_end=$ +} +_cli equ call MEM_HeapLock +_sti equ call MEM_HeapUnLock +end if + diff --git a/kernel/trunk/core/sys32.inc b/kernel/trunk/core/sys32.inc index 5cc16ae91..2687a9e18 100644 --- a/kernel/trunk/core/sys32.inc +++ b/kernel/trunk/core/sys32.inc @@ -1,692 +1,700 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ;; -;; MenuetOS process management, protected ring3 ;; -;; ;; -;; Distributed under GPL. See file COPYING for details. ;; -;; Copyright 2003 Ville Turjanmaa ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -align 4 ;3A08 -build_interrupt_table: - mov edi, idts - mov esi, sys_int - mov ecx, 0x40 - mov eax, (10001110b shl 24) + os_code - @@: movsw ;low word of code-entry - stosd ;interrupt gate type : os_code selector - movsw ;high word of code-entry - loop @b - movsd ;copy low dword of trap gate for int 0x40 - movsd ;copy high dword of trap gate for int 0x40 - lidt [esi] - ret - -iglobal - align 4 - sys_int: - ;exception handlers addresses (for interrupt gate construction) - dd e0,e1,e2,e3,e4,e5,e6,except_7 ; SEE: core/fpu.inc - dd e8,e9,e10,e11,e12,e13,page_fault_exc,e15 - dd e16, e17,e18, e19 - times 12 dd unknown_interrupt ;int_20..int_31 - - ;interrupt handlers addresses (for interrupt gate construction) - ; 0x20 .. 0x2F - IRQ handlers - dd irq0, irq_serv.irq_1, irq_serv.irq_2 - dd irq_serv.irq_3, irq_serv.irq_4 - dd irq_serv.irq_5, irq_serv.irq_6, irq_serv.irq_7 - dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10 - dd irq_serv.irq_11, irq_serv.irq_12, irqD, irq_serv.irq_14, irq_serv.irq_15 - dd irq_serv.irq_16 - dd irq_serv.irq_17 - dd irq_serv.irq_18 - dd irq_serv.irq_19 - dd irq_serv.irq_20 - dd irq_serv.irq_21 - dd irq_serv.irq_22 - dd irq_serv.irq_23 - - times 32 - IRQ_RESERVED dd unknown_interrupt - ;int_0x40 gate trap (for directly copied) - dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16 - - idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data) - dw 2*($-sys_int-4)-1 - dd idts ;0x8000B100 - dw 0 ;просто выравнивание - - msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b - dd msg_exc_c,msg_exc_d,msg_exc_e - - msg_exc_8 db "Double fault", 0 - msg_exc_u db "Undefined Exception", 0 - msg_exc_a db "Invalid TSS", 0 - msg_exc_b db "Segment not present", 0 - msg_exc_c db "Stack fault", 0 - msg_exc_d db "General protection fault", 0 - msg_exc_e db "Page fault", 0 - - msg_sel_ker db "kernel", 0 - msg_sel_app db "application", 0 - -endg - -macro save_ring3_context { - pushad -} -macro restore_ring3_context { - popad -} -macro exc_wo_code [num] { - e#num : - save_ring3_context - mov bl, num - jmp exc_c -} exc_wo_code 0,1,2,3,4,5,6,15,16,19 - -macro exc_w_code [num] { - e#num : - add esp, 4 - save_ring3_context - mov bl, num - jmp exc_c -} exc_w_code 8,9,10,11,12,13,17,18 - - -uglobal - pf_err_code dd ? -endg - -page_fault_exc: ; дуракоусточивость: селекторы испорчены... - pop [ss:pf_err_code]; действительно до следующего #PF - save_ring3_context - mov bl,14 - -exc_c: ; исключения (все, кроме 7-го - #NM) -; Фрэйм стека при исключении/прерывании из 3-го кольца + pushad (т.е., именно здесь) - reg_ss equ esp+0x30 - reg_esp3 equ esp+0x2C - reg_eflags equ esp+0x28 - reg_cs3 equ esp+0x24 - reg_eip equ esp+0x20 - ; это фрэйм от pushad - reg_eax equ esp+0x1C - reg_ecx equ esp+0x18 - reg_edx equ esp+0x14 - reg_ebx equ esp+0x10 - reg_esp0 equ esp+0x0C - reg_ebp equ esp+0x08 - reg_esi equ esp+0x04 - reg_edi equ esp+0x00 - - mov ax, app_data ;исключение - mov ds, ax ;загрузим правильные значения - mov es, ax ;в регистры - cld ; и приводим DF к стандарту - movzx ebx,bl -; redirect to V86 manager? (EFLAGS & 0x20000) != 0? - test byte[reg_eflags+2],2 - jnz v86_exc_c - cmp bl,14 ; #PF - jne @f - call page_fault_handler ; SEE: core/memory.inc - @@: mov esi, [current_slot] - btr [esi+APPDATA.except_mask], ebx - jnc @f - mov eax,[esi+APPDATA.exc_handler] - test eax, eax - jnz IRetToUserHook - @@: cli - mov eax, [esi+APPDATA.debugger_slot] - test eax, eax - jnz .debug - sti -; not debuggee => say error and terminate - call show_error_parameters ;; only ONE using, inline ??? - ;mov edx, [TASK_BASE] - mov [edx + TASKDATA.state], byte 4 ; terminate - jmp change_task ; stack - here it does not matter at all, SEE: core/shed.inc -.debug: -; we are debugged process, notify debugger and suspend ourself -; eax=debugger PID - mov ecx,1 ; debug_message code=other_exception - cmp bl,1 ; #DB - jne .notify ; notify debugger and suspend ourself - mov ebx, dr6 ; debug_message data=DR6_image - xor edx, edx - mov dr6, edx - mov edx, dr7 - mov cl, not 8 - .l1: shl dl,2 - jc @f - and bl, cl - @@: sar cl,1 - jc .l1 - mov cl, 3 ; debug_message code=debug_exception -.notify: - push ebx ; debug_message data - mov ebx, [TASK_BASE] - push [ebx+TASKDATA.pid] ; PID - push ecx ; debug_message code ((here: ecx==1/3)) - mov cl, 12 ; debug_message size - call debugger_notify ;; only ONE using, inline ??? SEE: core/debug.inc - add esp,12 - mov edx, [TASK_BASE] - mov byte [edx+TASKDATA.state], 1 ; suspended - call change_task ; SEE: core/shed.inc - restore_ring3_context - iretd - -IRetToUserHook: - xchg eax, [reg_eip] - sub dword[reg_esp3], 8 - mov edi, [reg_esp3] - stosd - mov [edi], ebx - restore_ring3_context -; simply return control to interrupted process -unknown_interrupt: - iretd - -;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -; bl - error vector -show_error_parameters: - cmp bl, 0x06 - jnz .no_ud - push ebx - mov ebx, ud_user_message - mov ebp, notifyapp - call fs_execute_from_sysdir_param - pop ebx -.no_ud: - mov edx,[TASK_BASE] ;not scratched below - DEBUGF 1, "K : Process - forced terminate PID: %x\n", [edx+TASKDATA.pid] - cmp bl, 0x08 - jb .l0 - cmp bl, 0x0e - jbe .l1 - .l0: mov bl, 0x09 - .l1: mov eax,[msg_fault_sel+ebx*4 - 0x08*4] - DEBUGF 1, "K : %s\n", eax - mov eax, [reg_cs3+4] - mov edi, msg_sel_app - mov ebx, [reg_esp3+4] - cmp eax, app_code - je @f - mov edi, msg_sel_ker - mov ebx, [reg_esp0+4] - @@: DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [reg_eax+4], [reg_ebx+4], [reg_ecx+4] - DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4] - DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx - DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi - ret -;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - - restore reg_ss - restore reg_esp3 - restore reg_eflags - restore reg_cs - restore reg_eip - restore reg_eax - restore reg_ecx - restore reg_edx - restore reg_ebx - restore reg_esp0 - restore reg_ebp - restore reg_esi - restore reg_edi - - -align 4 -set_application_table_status: - push eax - - mov eax,[CURRENT_TASK] - shl eax, 5 - add eax,CURRENT_TASK+TASKDATA.pid - mov eax,[eax] - - mov [application_table_status],eax - - pop eax - - ret - -align 4 -clear_application_table_status: - push eax - - mov eax,[CURRENT_TASK] - shl eax, 5 - add eax,CURRENT_TASK+TASKDATA.pid - mov eax,[eax] - - cmp eax,[application_table_status] - jne apptsl1 - xor eax,eax - mov [application_table_status],eax - apptsl1: - - pop eax - - ret - -; * eax = 64 - номер функции -; * ebx = 1 - единственная подфункция -; * ecx = новый размер памяти -;Возвращаемое значение: -; * eax = 0 - успешно -; * eax = 1 - недостаточно памяти - -align 4 -sys_resize_app_memory: - ; ebx = 1 - resize - ; ecx = new amount of memory - -; cmp eax,1 - dec ebx - jnz .no_application_mem_resize - stdcall new_mem_resize, ecx - mov [esp+32], eax -.no_application_mem_resize: - ret - -iglobal -; process_terminating db 'K : Process - terminating',13,10,0 -; process_terminated db 'K : Process - done',13,10,0 - msg_obj_destroy db 'K : destroy app object',13,10,0 -endg - -; param -; esi= slot - -align 4 -terminate: ; terminate application - - .slot equ esp ;locals - - push esi ;save .slot - - shl esi, 8 - cmp [SLOT_BASE+esi+APPDATA.dir_table], 0 - jne @F - pop esi - shl esi, 5 - mov [CURRENT_TASK+esi+TASKDATA.state], 9 - ret -@@: - ;mov esi,process_terminating - ;call sys_msg_board_str -@@: - cli - cmp [application_table_status],0 - je term9 - sti - call change_task - jmp @b -term9: - call set_application_table_status - -; if the process is in V86 mode... - mov eax, [.slot] - shl eax, 8 - mov esi, [eax+SLOT_BASE+APPDATA.pl0_stack] - add esi, RING0_STACK_SIZE - cmp [eax+SLOT_BASE+APPDATA.saved_esp0], esi - jz .nov86 -; ...it has page directory for V86 mode - mov esi, [eax+SLOT_BASE+APPDATA.saved_esp0] - mov ecx, [esi+4] - mov [eax+SLOT_BASE+APPDATA.dir_table], ecx -; ...and I/O permission map for V86 mode - mov ecx, [esi+12] - mov [eax+SLOT_BASE+APPDATA.io_map], ecx - mov ecx, [esi+8] - mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx -.nov86: - - mov esi, [.slot] - shl esi,8 - add esi, SLOT_BASE+APP_OBJ_OFFSET -@@: - mov eax, [esi+APPOBJ.fd] - test eax, eax - jz @F - - cmp eax, esi - je @F - - push esi - call [eax+APPOBJ.destroy] - DEBUGF 1,"%s",msg_obj_destroy - pop esi - jmp @B -@@: - - mov eax, [.slot] - shl eax, 8 - stdcall destroy_app_space, [SLOT_BASE+eax+APPDATA.dir_table], [SLOT_BASE+eax+APPDATA.dlls_list_ptr] - - mov esi, [.slot] - cmp [fpu_owner],esi ; if user fpu last -> fpu user = 1 - jne @F - - mov [fpu_owner],1 - mov eax, [256+SLOT_BASE+APPDATA.fpu_state] - clts - bt [cpu_caps], CAPS_SSE - jnc .no_SSE - fxrstor [eax] - jmp @F -.no_SSE: - fnclex - frstor [eax] -@@: - - mov [KEY_COUNT],byte 0 ; empty keyboard buffer - mov [BTN_COUNT],byte 0 ; empty button buffer - - -; remove defined hotkeys - mov eax, hotkey_list -.loop: - cmp [eax+8], esi - jnz .cont - mov ecx, [eax] - jecxz @f - push dword [eax+12] - pop dword [ecx+12] -@@: - mov ecx, [eax+12] - push dword [eax] - pop dword [ecx] - xor ecx, ecx - mov [eax], ecx - mov [eax+4], ecx - mov [eax+8], ecx - mov [eax+12], ecx -.cont: - add eax, 16 - cmp eax, hotkey_list+256*16 - jb .loop -; remove hotkeys in buffer - mov eax, hotkey_buffer -.loop2: - cmp [eax], esi - jnz .cont2 - and dword [eax+4], 0 - and dword [eax], 0 -.cont2: - add eax, 8 - cmp eax, hotkey_buffer+120*8 - jb .loop2 - - mov ecx,esi ; remove buttons - bnewba2: - mov edi,[BTN_ADDR] - mov eax,edi - cld - movzx ebx,word [edi] - inc bx - bnewba: - dec bx - jz bnmba - add eax,0x10 - cmp cx,[eax] - jnz bnewba - pusha - mov ecx,ebx - inc ecx - shl ecx,4 - mov ebx,eax - add eax,0x10 - call memmove - dec dword [edi] - popa - jmp bnewba2 - bnmba: - - pusha ; save window coordinates for window restoring - cld - shl esi,5 - add esi,window_data - mov eax,[esi+WDATA.box.left] - mov [draw_limits.left],eax - add eax,[esi+WDATA.box.width] - mov [draw_limits.right],eax - mov eax,[esi+WDATA.box.top] - mov [draw_limits.top],eax - add eax,[esi+WDATA.box.height] - mov [draw_limits.bottom],eax - - xor eax, eax - mov [esi+WDATA.box.left],eax - mov [esi+WDATA.box.width],eax - mov [esi+WDATA.box.top],eax - mov [esi+WDATA.box.height],eax - mov [esi+WDATA.cl_workarea],eax - mov [esi+WDATA.cl_titlebar],eax - mov [esi+WDATA.cl_frames],eax - mov dword [esi+WDATA.reserved],eax ; clear all flags: wstate, redraw, wdrawn - lea edi, [esi-window_data+draw_data] - mov ecx,32/4 - rep stosd - popa - -; debuggee test - pushad - mov edi, esi - shl edi, 5 - mov eax, [SLOT_BASE+edi*8+APPDATA.debugger_slot] - test eax, eax - jz .nodebug - push 8 - pop ecx - push dword [CURRENT_TASK+edi+TASKDATA.pid] ; PID - push 2 - call debugger_notify - pop ecx - pop ecx -.nodebug: - popad - - mov ebx, [.slot] - shl ebx, 8 - push ebx - mov ebx,[SLOT_BASE+ebx+APPDATA.pl0_stack] - - stdcall kernel_free, ebx - - pop ebx - mov ebx,[SLOT_BASE+ebx+APPDATA.cur_dir] - stdcall kernel_free, ebx - - mov edi, [.slot] - shl edi,8 - add edi,SLOT_BASE - - mov eax, [edi+APPDATA.io_map] - cmp eax, [SLOT_BASE+256+APPDATA.io_map] - je @F - call free_page -@@: - mov eax, [edi+APPDATA.io_map+4] - cmp eax, [SLOT_BASE+256+APPDATA.io_map+4] - je @F - call free_page -@@: - mov eax, 0x20202020 - stosd - stosd - stosd - mov ecx,244/4 - xor eax, eax - rep stosd - - ; activate window - movzx eax, word [WIN_STACK + esi*2] - cmp eax, [TASK_COUNT] - jne .dont_activate - pushad - .check_next_window: - dec eax - cmp eax, 1 - jbe .nothing_to_activate - lea esi, [WIN_POS+eax*2] - movzx edi, word [esi] ; edi = process - shl edi, 5 - cmp [CURRENT_TASK + edi + TASKDATA.state], byte 9 ; skip dead slots - je .check_next_window - add edi, window_data -; \begin{diamond}[19.09.2006] -; skip minimized windows - test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED - jnz .check_next_window -; \end{diamond} - call waredraw - .nothing_to_activate: - popad - .dont_activate: - - push esi ; remove hd1 & cd & flp reservation - shl esi, 5 - mov esi, [esi+CURRENT_TASK+TASKDATA.pid] - cmp [hd1_status], esi - jnz @f - call free_hd_channel - and [hd1_status], 0 -@@: - cmp [cd_status], esi - jnz @f - call free_cd_channel - and [cd_status], 0 -@@: - cmp [flp_status], esi - jnz @f - and [flp_status], 0 -@@: - pop esi - cmp [bgrlockpid], esi - jnz @f - and [bgrlockpid], 0 - and [bgrlock], 0 -@@: - - pusha ; remove all port reservations - mov edx,esi - shl edx, 5 - add edx,CURRENT_TASK - mov edx,[edx+TASKDATA.pid] - - rmpr0: - - mov esi,[RESERVED_PORTS] - - test esi,esi - jz rmpr9 - - rmpr3: - - mov edi,esi - shl edi,4 - add edi,RESERVED_PORTS - - cmp edx,[edi] - je rmpr4 - - dec esi - jnz rmpr3 - - jmp rmpr9 - - rmpr4: - - mov ecx,256 - sub ecx,esi - shl ecx,4 - - mov esi,edi - add esi,16 - cld - rep movsb - - dec dword [RESERVED_PORTS] - - jmp rmpr0 - - rmpr9: - - popa - mov edi,esi ; do not run this process slot - shl edi, 5 - mov [edi+CURRENT_TASK + TASKDATA.state],byte 9 -; debugger test - terminate all debuggees - mov eax, 2 - mov ecx, SLOT_BASE+2*0x100+APPDATA.debugger_slot -.xd0: - cmp eax, [TASK_COUNT] - ja .xd1 - cmp dword [ecx], esi - jnz @f - and dword [ecx], 0 - pushad - xchg eax, ecx - mov ebx, 2 - call sys_system - popad -@@: - inc eax - add ecx, 0x100 - jmp .xd0 -.xd1: -; call systest - sti ; .. and life goes on - - mov eax, [draw_limits.left] - mov ebx, [draw_limits.top] - mov ecx, [draw_limits.right] - mov edx, [draw_limits.bottom] - call calculatescreen - xor eax, eax - xor esi, esi - call redrawscreen - - mov [MOUSE_BACKGROUND],byte 0 ; no mouse background - mov [DONT_DRAW_MOUSE],byte 0 ; draw mouse - - and [application_table_status],0 - ;mov esi,process_terminated - ;call sys_msg_board_str - add esp, 4 - ret -restore .slot - -iglobal -if lang eq ru - boot_sched_1 db '‘®§¤ ­ЁҐ GDT TSS гЄ § вҐ«п',0 - boot_sched_2 db '‘®§¤ ­ЁҐ IDT в Ў«Ёжл',0 -else - boot_sched_1 db 'Building gdt tss pointer',0 - boot_sched_2 db 'Building IDT table',0 -end if -endg - - -build_scheduler: - - mov esi,boot_sched_1 - call boot_log - ; call build_process_gdt_tss_pointer - - ; mov esi,boot_sched_2 - ; call boot_log - - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; MenuetOS process management, protected ring3 ;; +;; ;; +;; Distributed under GPL. See file COPYING for details. ;; +;; Copyright 2003 Ville Turjanmaa ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +align 4 ;3A08 +build_interrupt_table: + mov edi, idts + mov esi, sys_int + mov ecx, 0x40 + mov eax, (10001110b shl 24) + os_code + @@: + movsw ;low word of code-entry + stosd ;interrupt gate type : os_code selector + movsw ;high word of code-entry + loop @b + movsd ;copy low dword of trap gate for int 0x40 + movsd ;copy high dword of trap gate for int 0x40 + lidt [esi] + ret + +iglobal + align 4 + sys_int: + ;exception handlers addresses (for interrupt gate construction) + dd e0,e1,e2,e3,e4,e5,e6,except_7 ; SEE: core/fpu.inc + dd e8,e9,e10,e11,e12,e13,page_fault_exc,e15 + dd e16, e17,e18, e19 + times 12 dd unknown_interrupt ;int_20..int_31 + + ;interrupt handlers addresses (for interrupt gate construction) + ; 0x20 .. 0x2F - IRQ handlers + dd irq0, irq_serv.irq_1, irq_serv.irq_2 + dd irq_serv.irq_3, irq_serv.irq_4 + dd irq_serv.irq_5, irq_serv.irq_6, irq_serv.irq_7 + dd irq_serv.irq_8, irq_serv.irq_9, irq_serv.irq_10 + dd irq_serv.irq_11, irq_serv.irq_12, irqD, irq_serv.irq_14, irq_serv.irq_15 + dd irq_serv.irq_16 + dd irq_serv.irq_17 + dd irq_serv.irq_18 + dd irq_serv.irq_19 + dd irq_serv.irq_20 + dd irq_serv.irq_21 + dd irq_serv.irq_22 + dd irq_serv.irq_23 + + times 32 - IRQ_RESERVED dd unknown_interrupt + ;int_0x40 gate trap (for directly copied) + dw i40 and 0xFFFF, os_code, 11101111b shl 8, i40 shr 16 + + idtreg: ; data for LIDT instruction (!!! must be immediately below sys_int data) + dw 2*($-sys_int-4)-1 + dd idts ;0x8000B100 + dw 0 ;просто выравнивание + + msg_fault_sel dd msg_exc_8,msg_exc_u,msg_exc_a,msg_exc_b + dd msg_exc_c,msg_exc_d,msg_exc_e + + msg_exc_8 db "Double fault", 0 + msg_exc_u db "Undefined Exception", 0 + msg_exc_a db "Invalid TSS", 0 + msg_exc_b db "Segment not present", 0 + msg_exc_c db "Stack fault", 0 + msg_exc_d db "General protection fault", 0 + msg_exc_e db "Page fault", 0 + + msg_sel_ker db "kernel", 0 + msg_sel_app db "application", 0 + +endg + +macro save_ring3_context { + pushad +} +macro restore_ring3_context { + popad +} +macro exc_wo_code [num] { + e#num : + save_ring3_context + mov bl, num + jmp exc_c +} exc_wo_code 0,1,2,3,4,5,6,15,16,19 + +macro exc_w_code [num] { + e#num : + add esp, 4 + save_ring3_context + mov bl, num + jmp exc_c +} exc_w_code 8,9,10,11,12,13,17,18 + + +uglobal + pf_err_code dd ? +endg + +page_fault_exc: ; дуракоусточивость: селекторы испорчены... + pop [ss:pf_err_code]; действительно до следующего #PF + save_ring3_context + mov bl, 14 + +exc_c: ; исключения (все, кроме 7-го - #NM) +; Фрэйм стека при исключении/прерывании из 3-го кольца + pushad (т.е., именно здесь) + reg_ss equ esp+0x30 + reg_esp3 equ esp+0x2C + reg_eflags equ esp+0x28 + reg_cs3 equ esp+0x24 + reg_eip equ esp+0x20 + ; это фрэйм от pushad + reg_eax equ esp+0x1C + reg_ecx equ esp+0x18 + reg_edx equ esp+0x14 + reg_ebx equ esp+0x10 + reg_esp0 equ esp+0x0C + reg_ebp equ esp+0x08 + reg_esi equ esp+0x04 + reg_edi equ esp+0x00 + + mov ax, app_data ;исключение + mov ds, ax ;загрузим правильные значения + mov es, ax ;в регистры + cld ; и приводим DF к стандарту + movzx ebx, bl +; redirect to V86 manager? (EFLAGS & 0x20000) != 0? + test byte[reg_eflags+2], 2 + jnz v86_exc_c + cmp bl, 14 ; #PF + jne @f + call page_fault_handler ; SEE: core/memory.inc + @@: + mov esi, [current_slot] + btr [esi+APPDATA.except_mask], ebx + jnc @f + mov eax, [esi+APPDATA.exc_handler] + test eax, eax + jnz IRetToUserHook + @@: + cli + mov eax, [esi+APPDATA.debugger_slot] + test eax, eax + jnz .debug + sti +; not debuggee => say error and terminate + call show_error_parameters ;; only ONE using, inline ??? + ;mov edx, [TASK_BASE] + mov [edx + TASKDATA.state], byte 4 ; terminate + jmp change_task ; stack - here it does not matter at all, SEE: core/shed.inc +.debug: +; we are debugged process, notify debugger and suspend ourself +; eax=debugger PID + mov ecx, 1 ; debug_message code=other_exception + cmp bl, 1 ; #DB + jne .notify ; notify debugger and suspend ourself + mov ebx, dr6 ; debug_message data=DR6_image + xor edx, edx + mov dr6, edx + mov edx, dr7 + mov cl, not 8 + .l1: + shl dl, 2 + jc @f + and bl, cl + @@: + sar cl, 1 + jc .l1 + mov cl, 3 ; debug_message code=debug_exception +.notify: + push ebx ; debug_message data + mov ebx, [TASK_BASE] + push [ebx+TASKDATA.pid] ; PID + push ecx ; debug_message code ((here: ecx==1/3)) + mov cl, 12 ; debug_message size + call debugger_notify ;; only ONE using, inline ??? SEE: core/debug.inc + add esp, 12 + mov edx, [TASK_BASE] + mov byte [edx+TASKDATA.state], 1 ; suspended + call change_task ; SEE: core/shed.inc + restore_ring3_context + iretd + +IRetToUserHook: + xchg eax, [reg_eip] + sub dword[reg_esp3], 8 + mov edi, [reg_esp3] + stosd + mov [edi], ebx + restore_ring3_context +; simply return control to interrupted process +unknown_interrupt: + iretd + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +; bl - error vector +show_error_parameters: + cmp bl, 0x06 + jnz .no_ud + push ebx + mov ebx, ud_user_message + mov ebp, notifyapp + call fs_execute_from_sysdir_param + pop ebx +.no_ud: + mov edx, [TASK_BASE];not scratched below + DEBUGF 1, "K : Process - forced terminate PID: %x\n", [edx+TASKDATA.pid] + cmp bl, 0x08 + jb .l0 + cmp bl, 0x0e + jbe .l1 + .l0: + mov bl, 0x09 + .l1: + mov eax, [msg_fault_sel+ebx*4 - 0x08*4] + DEBUGF 1, "K : %s\n", eax + mov eax, [reg_cs3+4] + mov edi, msg_sel_app + mov ebx, [reg_esp3+4] + cmp eax, app_code + je @f + mov edi, msg_sel_ker + mov ebx, [reg_esp0+4] + @@: + DEBUGF 1, "K : EAX : %x EBX : %x ECX : %x\n", [reg_eax+4], [reg_ebx+4], [reg_ecx+4] + DEBUGF 1, "K : EDX : %x ESI : %x EDI : %x\n", [reg_edx+4], [reg_esi+4], [reg_edi+4] + DEBUGF 1, "K : EBP : %x EIP : %x ESP : %x\n", [reg_ebp+4], [reg_eip+4], ebx + DEBUGF 1, "K : Flags : %x CS : %x (%s)\n", [reg_eflags+4], eax, edi + ret +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + restore reg_ss + restore reg_esp3 + restore reg_eflags + restore reg_cs + restore reg_eip + restore reg_eax + restore reg_ecx + restore reg_edx + restore reg_ebx + restore reg_esp0 + restore reg_ebp + restore reg_esi + restore reg_edi + + +align 4 +set_application_table_status: + push eax + + mov eax, [CURRENT_TASK] + shl eax, 5 + add eax, CURRENT_TASK+TASKDATA.pid + mov eax, [eax] + + mov [application_table_status], eax + + pop eax + + ret + +align 4 +clear_application_table_status: + push eax + + mov eax, [CURRENT_TASK] + shl eax, 5 + add eax, CURRENT_TASK+TASKDATA.pid + mov eax, [eax] + + cmp eax, [application_table_status] + jne apptsl1 + xor eax, eax + mov [application_table_status], eax + apptsl1: + + pop eax + + ret + +; * eax = 64 - номер функции +; * ebx = 1 - единственная подфункция +; * ecx = новый размер памяти +;Возвращаемое значение: +; * eax = 0 - успешно +; * eax = 1 - недостаточно памяти + +align 4 +sys_resize_app_memory: + ; ebx = 1 - resize + ; ecx = new amount of memory + +; cmp eax,1 + dec ebx + jnz .no_application_mem_resize + stdcall new_mem_resize, ecx + mov [esp+32], eax +.no_application_mem_resize: + ret + +iglobal +; process_terminating db 'K : Process - terminating',13,10,0 +; process_terminated db 'K : Process - done',13,10,0 + msg_obj_destroy db 'K : destroy app object',13,10,0 +endg + +; param +; esi= slot + +align 4 +terminate: ; terminate application + + .slot equ esp ;locals + + push esi ;save .slot + + shl esi, 8 + cmp [SLOT_BASE+esi+APPDATA.dir_table], 0 + jne @F + pop esi + shl esi, 5 + mov [CURRENT_TASK+esi+TASKDATA.state], 9 + ret +@@: + ;mov esi,process_terminating + ;call sys_msg_board_str +@@: + cli + cmp [application_table_status], 0 + je term9 + sti + call change_task + jmp @b +term9: + call set_application_table_status + +; if the process is in V86 mode... + mov eax, [.slot] + shl eax, 8 + mov esi, [eax+SLOT_BASE+APPDATA.pl0_stack] + add esi, RING0_STACK_SIZE + cmp [eax+SLOT_BASE+APPDATA.saved_esp0], esi + jz .nov86 +; ...it has page directory for V86 mode + mov esi, [eax+SLOT_BASE+APPDATA.saved_esp0] + mov ecx, [esi+4] + mov [eax+SLOT_BASE+APPDATA.dir_table], ecx +; ...and I/O permission map for V86 mode + mov ecx, [esi+12] + mov [eax+SLOT_BASE+APPDATA.io_map], ecx + mov ecx, [esi+8] + mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx +.nov86: + + mov esi, [.slot] + shl esi, 8 + add esi, SLOT_BASE+APP_OBJ_OFFSET +@@: + mov eax, [esi+APPOBJ.fd] + test eax, eax + jz @F + + cmp eax, esi + je @F + + push esi + call [eax+APPOBJ.destroy] + DEBUGF 1,"%s",msg_obj_destroy + pop esi + jmp @B +@@: + + mov eax, [.slot] + shl eax, 8 + stdcall destroy_app_space, [SLOT_BASE+eax+APPDATA.dir_table], [SLOT_BASE+eax+APPDATA.dlls_list_ptr] + + mov esi, [.slot] + cmp [fpu_owner], esi ; if user fpu last -> fpu user = 1 + jne @F + + mov [fpu_owner], 1 + mov eax, [256+SLOT_BASE+APPDATA.fpu_state] + clts + bt [cpu_caps], CAPS_SSE + jnc .no_SSE + fxrstor [eax] + jmp @F +.no_SSE: + fnclex + frstor [eax] +@@: + + mov [KEY_COUNT], byte 0 ; empty keyboard buffer + mov [BTN_COUNT], byte 0 ; empty button buffer + + +; remove defined hotkeys + mov eax, hotkey_list +.loop: + cmp [eax+8], esi + jnz .cont + mov ecx, [eax] + jecxz @f + push dword [eax+12] + pop dword [ecx+12] +@@: + mov ecx, [eax+12] + push dword [eax] + pop dword [ecx] + xor ecx, ecx + mov [eax], ecx + mov [eax+4], ecx + mov [eax+8], ecx + mov [eax+12], ecx +.cont: + add eax, 16 + cmp eax, hotkey_list+256*16 + jb .loop +; remove hotkeys in buffer + mov eax, hotkey_buffer +.loop2: + cmp [eax], esi + jnz .cont2 + and dword [eax+4], 0 + and dword [eax], 0 +.cont2: + add eax, 8 + cmp eax, hotkey_buffer+120*8 + jb .loop2 + + mov ecx, esi ; remove buttons + bnewba2: + mov edi, [BTN_ADDR] + mov eax, edi + cld + movzx ebx, word [edi] + inc bx + bnewba: + dec bx + jz bnmba + add eax, 0x10 + cmp cx, [eax] + jnz bnewba + pusha + mov ecx, ebx + inc ecx + shl ecx, 4 + mov ebx, eax + add eax, 0x10 + call memmove + dec dword [edi] + popa + jmp bnewba2 + bnmba: + + pusha ; save window coordinates for window restoring + cld + shl esi, 5 + add esi, window_data + mov eax, [esi+WDATA.box.left] + mov [draw_limits.left], eax + add eax, [esi+WDATA.box.width] + mov [draw_limits.right], eax + mov eax, [esi+WDATA.box.top] + mov [draw_limits.top], eax + add eax, [esi+WDATA.box.height] + mov [draw_limits.bottom], eax + + xor eax, eax + mov [esi+WDATA.box.left], eax + mov [esi+WDATA.box.width], eax + mov [esi+WDATA.box.top], eax + mov [esi+WDATA.box.height], eax + mov [esi+WDATA.cl_workarea], eax + mov [esi+WDATA.cl_titlebar], eax + mov [esi+WDATA.cl_frames], eax + mov dword [esi+WDATA.reserved], eax; clear all flags: wstate, redraw, wdrawn + lea edi, [esi-window_data+draw_data] + mov ecx, 32/4 + rep stosd + popa + +; debuggee test + pushad + mov edi, esi + shl edi, 5 + mov eax, [SLOT_BASE+edi*8+APPDATA.debugger_slot] + test eax, eax + jz .nodebug + push 8 + pop ecx + push dword [CURRENT_TASK+edi+TASKDATA.pid]; PID + push 2 + call debugger_notify + pop ecx + pop ecx +.nodebug: + popad + + mov ebx, [.slot] + shl ebx, 8 + push ebx + mov ebx, [SLOT_BASE+ebx+APPDATA.pl0_stack] + + stdcall kernel_free, ebx + + pop ebx + mov ebx, [SLOT_BASE+ebx+APPDATA.cur_dir] + stdcall kernel_free, ebx + + mov edi, [.slot] + shl edi, 8 + add edi, SLOT_BASE + + mov eax, [edi+APPDATA.io_map] + cmp eax, [SLOT_BASE+256+APPDATA.io_map] + je @F + call free_page +@@: + mov eax, [edi+APPDATA.io_map+4] + cmp eax, [SLOT_BASE+256+APPDATA.io_map+4] + je @F + call free_page +@@: + mov eax, 0x20202020 + stosd + stosd + stosd + mov ecx, 244/4 + xor eax, eax + rep stosd + + ; activate window + movzx eax, word [WIN_STACK + esi*2] + cmp eax, [TASK_COUNT] + jne .dont_activate + pushad + .check_next_window: + dec eax + cmp eax, 1 + jbe .nothing_to_activate + lea esi, [WIN_POS+eax*2] + movzx edi, word [esi] ; edi = process + shl edi, 5 + cmp [CURRENT_TASK + edi + TASKDATA.state], byte 9 ; skip dead slots + je .check_next_window + add edi, window_data +; \begin{diamond}[19.09.2006] +; skip minimized windows + test [edi + WDATA.fl_wstate], WSTATE_MINIMIZED + jnz .check_next_window +; \end{diamond} + call waredraw + .nothing_to_activate: + popad + .dont_activate: + + push esi ; remove hd1 & cd & flp reservation + shl esi, 5 + mov esi, [esi+CURRENT_TASK+TASKDATA.pid] + cmp [hd1_status], esi + jnz @f + call free_hd_channel + and [hd1_status], 0 +@@: + cmp [cd_status], esi + jnz @f + call free_cd_channel + and [cd_status], 0 +@@: + cmp [flp_status], esi + jnz @f + and [flp_status], 0 +@@: + pop esi + cmp [bgrlockpid], esi + jnz @f + and [bgrlockpid], 0 + and [bgrlock], 0 +@@: + + pusha ; remove all port reservations + mov edx, esi + shl edx, 5 + add edx, CURRENT_TASK + mov edx, [edx+TASKDATA.pid] + + rmpr0: + + mov esi, [RESERVED_PORTS] + + test esi, esi + jz rmpr9 + + rmpr3: + + mov edi, esi + shl edi, 4 + add edi, RESERVED_PORTS + + cmp edx, [edi] + je rmpr4 + + dec esi + jnz rmpr3 + + jmp rmpr9 + + rmpr4: + + mov ecx, 256 + sub ecx, esi + shl ecx, 4 + + mov esi, edi + add esi, 16 + cld + rep movsb + + dec dword [RESERVED_PORTS] + + jmp rmpr0 + + rmpr9: + + popa + mov edi, esi ; do not run this process slot + shl edi, 5 + mov [edi+CURRENT_TASK + TASKDATA.state], byte 9 +; debugger test - terminate all debuggees + mov eax, 2 + mov ecx, SLOT_BASE+2*0x100+APPDATA.debugger_slot +.xd0: + cmp eax, [TASK_COUNT] + ja .xd1 + cmp dword [ecx], esi + jnz @f + and dword [ecx], 0 + pushad + xchg eax, ecx + mov ebx, 2 + call sys_system + popad +@@: + inc eax + add ecx, 0x100 + jmp .xd0 +.xd1: +; call systest + sti ; .. and life goes on + + mov eax, [draw_limits.left] + mov ebx, [draw_limits.top] + mov ecx, [draw_limits.right] + mov edx, [draw_limits.bottom] + call calculatescreen + xor eax, eax + xor esi, esi + call redrawscreen + + mov [MOUSE_BACKGROUND], byte 0; no mouse background + mov [DONT_DRAW_MOUSE], byte 0; draw mouse + + and [application_table_status], 0 + ;mov esi,process_terminated + ;call sys_msg_board_str + add esp, 4 + ret +restore .slot + +iglobal +if lang eq ru + boot_sched_1 db '‘®§¤ ­ЁҐ GDT TSS гЄ § вҐ«п',0 + boot_sched_2 db '‘®§¤ ­ЁҐ IDT в Ў«Ёжл',0 +else + boot_sched_1 db 'Building gdt tss pointer',0 + boot_sched_2 db 'Building IDT table',0 +end if +endg + + +build_scheduler: + + mov esi, boot_sched_1 + call boot_log + ; call build_process_gdt_tss_pointer + + ; mov esi,boot_sched_2 + ; call boot_log + + ret diff --git a/kernel/trunk/core/syscall.inc b/kernel/trunk/core/syscall.inc index 22fe51ee7..1b410b674 100644 --- a/kernel/trunk/core/syscall.inc +++ b/kernel/trunk/core/syscall.inc @@ -1,200 +1,200 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; Old style system call converter -align 16 -cross_order: - ; load all registers in crossed order - mov eax, ebx - mov ebx, ecx - mov ecx, edx - mov edx, esi - mov esi, edi - movzx edi, byte[esp+28 + 4] - sub edi,53 - call dword [servetable+edi*4] - ret - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; SYSENTER ENTRY ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -align 32 -sysenter_entry: - ; Настраиваем стек - mov esp, [ss:tss._esp0] - sti - push ebp ; save app esp + 4 - mov ebp, [ebp] ; ebp - original ebp - ;------------------ - pushad - cld - - movzx eax, al - call dword [servetable2 + eax * 4] - - popad - ;------------------ - xchg ecx, [ss:esp] ; в вершин стека - app ecx, ecx - app esp + 4 - sub ecx, 4 - xchg edx, [ecx] ; edx - return point, & save original edx - push edx - mov edx, [ss:esp + 4] - mov [ecx + 4], edx ; save original ecx - pop edx - sysexit - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; SYSTEM CALL ENTRY ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -align 16 -i40: - pushad - cld - movzx eax, al - call dword [servetable2 + eax * 4] - popad - iretd - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; SYSCALL ENTRY ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -align 32 -syscall_entry: - ; cli syscall clear IF - xchg esp, [ss:tss._esp0] - push ecx - lea ecx, [esp+4] - xchg ecx, [ss:tss._esp0] - sti - push ecx - mov ecx, [ecx] - ;------------------ - pushad - cld - - movzx eax, al - call dword [servetable2 + eax * 4] - - popad - ;------------------ - mov ecx, [ss:esp+4] - pop esp - sysret - -iglobal - ;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; SYSTEM FUNCTIONS TABLE ;; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - align 4 - servetable: - dd socket ; 53-Socket interface - dd 0 - dd 0 - dd 0 - dd 0 - dd file_system ; 58-Common file system interface - dd 0 - dd 0 - dd 0 - dd 0 ; 62-PCI functions - dd sys_msg_board ; 63-System message board - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; NEW SYSTEM FUNCTIONS TABLE ;; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - align 4 - servetable2: - - dd syscall_draw_window ; 0-DrawWindow - dd syscall_setpixel ; 1-SetPixel - dd sys_getkey ; 2-GetKey - dd sys_clock ; 3-GetTime - dd syscall_writetext ; 4-WriteText - dd delay_hs ; 5-DelayHs - dd syscall_openramdiskfile ; 6-OpenRamdiskFile - dd syscall_putimage ; 7-PutImage - dd syscall_button ; 8-DefineButton - dd sys_cpuusage ; 9-GetProcessInfo - dd sys_waitforevent ; 10-WaitForEvent - dd sys_getevent ; 11-CheckForEvent - dd sys_redrawstat ; 12-BeginDraw and EndDraw - dd syscall_drawrect ; 13-DrawRect - dd syscall_getscreensize ; 14-GetScreenSize - dd sys_background ; 15-bgr - dd sys_cachetodiskette ; 16-FlushFloppyCache - dd sys_getbutton ; 17-GetButton - dd sys_system ; 18-System Services - dd paleholder ; 19-reserved - dd sys_midi ; 20-ResetMidi and OutputMidi - dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,. - dd sys_settime ; 22-setting date,time,clock and alarm-clock - dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent - dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist - dd undefined_syscall ; 25-reserved - dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. - dd undefined_syscall ; 27-reserved - dd undefined_syscall ; 28-reserved - dd sys_date ; 29-GetDate - dd sys_current_directory ; 30-Get/SetCurrentDirectory - dd undefined_syscall ; 31-reserved - dd undefined_syscall ; 32-reserved - dd undefined_syscall ; 33-reserved - dd undefined_syscall ; 34-reserved - dd syscall_getpixel ; 35-GetPixel - dd syscall_getarea ; 36-GetArea - dd readmousepos ; 37-GetMousePosition_ScreenRelative,. - dd syscall_drawline ; 38-DrawLine - dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. - dd set_app_param ; 40-WantEvents - dd undefined_syscall ; 41- deprecated GetIrqOwner - dd undefined_syscall ; 42- deprecated ReadIrqData - dd sys_outport ; 43-SendDeviceData - dd undefined_syscall ; 44- deprecated ProgramIrqs - dd undefined_syscall ; 45- deprecated ReserveIrq and FreeIrq - dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea - dd display_number ; 47-WriteNum - dd syscall_display_settings ; 48-SetRedrawType and SetButtonType - dd sys_apm ; 49-Advanced Power Management (APM) - dd syscall_set_window_shape ; 50-Window shape & scale - dd syscall_threads ; 51-Threads - dd stack_driver_stat ; 52-Stack driver status - dd cross_order ; 53-Socket interface - dd undefined_syscall ; 54-reserved - dd sound_interface ; 55-Sound interface - dd undefined_syscall ; 56-reserved - dd sys_pcibios ; 57-PCI BIOS32 - dd cross_order ; 58-Common file system interface - dd undefined_syscall ; 59-reserved - dd sys_IPC ; 60-Inter Process Communication - dd sys_gs ; 61-Direct graphics access - dd pci_api ;cross_order ; 62-PCI functions - dd cross_order ; 63-System message board - dd sys_resize_app_memory ; 64-Resize application memory usage - dd sys_putimage_palette ; 65-PutImagePalette - dd sys_process_def ; 66-Process definitions - keyboard - dd syscall_move_window ; 67-Window move or resize - dd f68 ; 68-Some internal services - dd sys_debug_services ; 69-Debug - dd file_system_lfn ; 70-Common file system interface, version 2 - dd syscall_window_settings ; 71-Window settings - dd sys_sendwindowmsg ; 72-Send window message - dd blit_32 ; 73-blitter; - times 255 - ( ($-servetable2) /4 ) dd undefined_syscall - dd sys_end ; -1-end application - -endg +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; Old style system call converter +align 16 +cross_order: + ; load all registers in crossed order + mov eax, ebx + mov ebx, ecx + mov ecx, edx + mov edx, esi + mov esi, edi + movzx edi, byte[esp+28 + 4] + sub edi, 53 + call dword [servetable+edi*4] + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SYSENTER ENTRY ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 32 +sysenter_entry: + ; Настраиваем стек + mov esp, [ss:tss._esp0] + sti + push ebp ; save app esp + 4 + mov ebp, [ebp] ; ebp - original ebp + ;------------------ + pushad + cld + + movzx eax, al + call dword [servetable2 + eax * 4] + + popad + ;------------------ + xchg ecx, [ss:esp] ; в вершин стека - app ecx, ecx - app esp + 4 + sub ecx, 4 + xchg edx, [ecx] ; edx - return point, & save original edx + push edx + mov edx, [ss:esp + 4] + mov [ecx + 4], edx ; save original ecx + pop edx + sysexit + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SYSTEM CALL ENTRY ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 16 +i40: + pushad + cld + movzx eax, al + call dword [servetable2 + eax * 4] + popad + iretd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SYSCALL ENTRY ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +align 32 +syscall_entry: + ; cli syscall clear IF + xchg esp, [ss:tss._esp0] + push ecx + lea ecx, [esp+4] + xchg ecx, [ss:tss._esp0] + sti + push ecx + mov ecx, [ecx] + ;------------------ + pushad + cld + + movzx eax, al + call dword [servetable2 + eax * 4] + + popad + ;------------------ + mov ecx, [ss:esp+4] + pop esp + sysret + +iglobal + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; SYSTEM FUNCTIONS TABLE ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + align 4 + servetable: + dd socket ; 53-Socket interface + dd 0 + dd 0 + dd 0 + dd 0 + dd file_system ; 58-Common file system interface + dd 0 + dd 0 + dd 0 + dd 0 ; 62-PCI functions + dd sys_msg_board ; 63-System message board + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; NEW SYSTEM FUNCTIONS TABLE ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + align 4 + servetable2: + + dd syscall_draw_window ; 0-DrawWindow + dd syscall_setpixel ; 1-SetPixel + dd sys_getkey ; 2-GetKey + dd sys_clock ; 3-GetTime + dd syscall_writetext ; 4-WriteText + dd delay_hs ; 5-DelayHs + dd syscall_openramdiskfile ; 6-OpenRamdiskFile + dd syscall_putimage ; 7-PutImage + dd syscall_button ; 8-DefineButton + dd sys_cpuusage ; 9-GetProcessInfo + dd sys_waitforevent ; 10-WaitForEvent + dd sys_getevent ; 11-CheckForEvent + dd sys_redrawstat ; 12-BeginDraw and EndDraw + dd syscall_drawrect ; 13-DrawRect + dd syscall_getscreensize ; 14-GetScreenSize + dd sys_background ; 15-bgr + dd sys_cachetodiskette ; 16-FlushFloppyCache + dd sys_getbutton ; 17-GetButton + dd sys_system ; 18-System Services + dd paleholder ; 19-reserved + dd sys_midi ; 20-ResetMidi and OutputMidi + dd sys_setup ; 21-SetMidiBase,SetKeymap,SetShiftKeymap,. + dd sys_settime ; 22-setting date,time,clock and alarm-clock + dd sys_wait_event_timeout ; 23-TimeOutWaitForEvent + dd syscall_cdaudio ; 24-PlayCdTrack,StopCd and GetCdPlaylist + dd undefined_syscall ; 25-reserved + dd sys_getsetup ; 26-GetMidiBase,GetKeymap,GetShiftKeymap,. + dd undefined_syscall ; 27-reserved + dd undefined_syscall ; 28-reserved + dd sys_date ; 29-GetDate + dd sys_current_directory ; 30-Get/SetCurrentDirectory + dd undefined_syscall ; 31-reserved + dd undefined_syscall ; 32-reserved + dd undefined_syscall ; 33-reserved + dd undefined_syscall ; 34-reserved + dd syscall_getpixel ; 35-GetPixel + dd syscall_getarea ; 36-GetArea + dd readmousepos ; 37-GetMousePosition_ScreenRelative,. + dd syscall_drawline ; 38-DrawLine + dd sys_getbackground ; 39-GetBackgroundSize,ReadBgrData,. + dd set_app_param ; 40-WantEvents + dd undefined_syscall ; 41- deprecated GetIrqOwner + dd undefined_syscall ; 42- deprecated ReadIrqData + dd sys_outport ; 43-SendDeviceData + dd undefined_syscall ; 44- deprecated ProgramIrqs + dd undefined_syscall ; 45- deprecated ReserveIrq and FreeIrq + dd syscall_reserveportarea ; 46-ReservePortArea and FreePortArea + dd display_number ; 47-WriteNum + dd syscall_display_settings ; 48-SetRedrawType and SetButtonType + dd sys_apm ; 49-Advanced Power Management (APM) + dd syscall_set_window_shape ; 50-Window shape & scale + dd syscall_threads ; 51-Threads + dd stack_driver_stat ; 52-Stack driver status + dd cross_order ; 53-Socket interface + dd undefined_syscall ; 54-reserved + dd sound_interface ; 55-Sound interface + dd undefined_syscall ; 56-reserved + dd sys_pcibios ; 57-PCI BIOS32 + dd cross_order ; 58-Common file system interface + dd undefined_syscall ; 59-reserved + dd sys_IPC ; 60-Inter Process Communication + dd sys_gs ; 61-Direct graphics access + dd pci_api ;cross_order ; 62-PCI functions + dd cross_order ; 63-System message board + dd sys_resize_app_memory ; 64-Resize application memory usage + dd sys_putimage_palette ; 65-PutImagePalette + dd sys_process_def ; 66-Process definitions - keyboard + dd syscall_move_window ; 67-Window move or resize + dd f68 ; 68-Some internal services + dd sys_debug_services ; 69-Debug + dd file_system_lfn ; 70-Common file system interface, version 2 + dd syscall_window_settings ; 71-Window settings + dd sys_sendwindowmsg ; 72-Send window message + dd blit_32 ; 73-blitter; + times 255 - ( ($-servetable2) /4 ) dd undefined_syscall + dd sys_end ; -1-end application + +endg diff --git a/kernel/trunk/core/taskman.inc b/kernel/trunk/core/taskman.inc index 05e52bf0a..38f42a24b 100644 --- a/kernel/trunk/core/taskman.inc +++ b/kernel/trunk/core/taskman.inc @@ -1,1161 +1,1161 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -GREEDY_KERNEL equ 0 - -struc APP_HEADER_00 -{ .banner dq ? - .version dd ? ;+8 - .start dd ? ;+12 - .i_end dd ? ;+16 - .mem_size dd ? ;+20 - .i_param dd ? ;+24 -} - -struc APP_HEADER_01 -{ .banner dq ? - .version dd ? ;+8 - .start dd ? ;+12 - .i_end dd ? ;+16 - .mem_size dd ? ;+20 - .stack_top dd ? ;+24 - .i_param dd ? ;+28 - .i_icon dd ? ;+32 -} - - -struc APP_PARAMS -{ .app_cmdline ;0x00 - .app_path ;0x04 - .app_eip ;0x08 - .app_esp ;0x0C - .app_mem ;0x10 -} - -macro _clear_ op -{ mov ecx, op/4 - xor eax, eax - cld - rep stosd -} - -fs_execute_from_sysdir: - xor ebx, ebx -fs_execute_from_sysdir_param: - xor edx, edx - mov esi, sysdir_path - -align 4 -proc fs_execute - -;fn_read:dword, file_size:dword, cluster:dword - -; ebx - cmdline -; edx - flags -; ebp - full filename -; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it - - locals - cmdline rd 64 ;256/4 - filename rd 256 ;1024/4 - flags dd ? - - save_cr3 dd ? - slot dd ? - slot_base dd ? - file_base dd ? - file_size dd ? - ;app header data - hdr_cmdline dd ? ;0x00 - hdr_path dd ? ;0x04 - hdr_eip dd ? ;0x08 - hdr_esp dd ? ;0x0C - hdr_mem dd ? ;0x10 - hdr_i_end dd ? ;0x14 - endl - - pushad - - mov [flags], edx - -; [ebp] pointer to filename - - lea edi, [filename] - lea ecx, [edi+1024] - mov al, '/' - stosb -@@: - cmp edi, ecx - jae .bigfilename - lodsb - stosb - test al, al - jnz @b - mov esi, [ebp] - test esi, esi - jz .namecopied - mov byte [edi-1], '/' -@@: - cmp edi, ecx - jae .bigfilename - lodsb - stosb - test al, al - jnz @b - jmp .namecopied -.bigfilename: - popad - mov eax, -ERROR_FILE_NOT_FOUND - ret - -.namecopied: - - mov [cmdline], ebx - test ebx, ebx - jz @F - - lea eax, [cmdline] - mov dword [eax+252], 0 - stdcall strncpy, eax, ebx, 255 -@@: - lea eax, [filename] - stdcall load_file, eax - mov esi, -ERROR_FILE_NOT_FOUND - test eax, eax - jz .err_file - - mov [file_base], eax - mov [file_size], ebx - - lea ebx, [hdr_cmdline] - call test_app_header - mov esi, -0x1F - test eax, eax - jz .err_hdr - -.wait_lock: - cmp [application_table_status],0 - je .get_lock - call change_task - jmp .wait_lock - -.get_lock: - mov eax, 1 - xchg eax, [application_table_status] - test eax, eax - jnz .wait_lock - - call set_application_table_status - - call get_new_process_place - test eax, eax - mov esi, -0x20 ; too many processes - jz .err - - mov [slot], eax - shl eax, 8 - add eax, SLOT_BASE - mov [slot_base], eax - mov edi, eax - _clear_ 256 ;clean extended information about process - -; write application name - lea eax, [filename] - stdcall strrchr, eax, '/' ; now eax points to name without path - - lea esi, [eax+1] - test eax, eax - jnz @F - lea esi, [filename] -@@: - mov ecx, 8 ; 8 chars for name - mov edi, [slot_base] -.copy_process_name_loop: - lodsb - cmp al, '.' - jz .copy_process_name_done - test al, al - jz .copy_process_name_done - stosb - loop .copy_process_name_loop -.copy_process_name_done: - - mov ebx, cr3 - mov [save_cr3], ebx - - stdcall create_app_space,[hdr_mem],[file_base],[file_size] - mov esi, -30 ; no memory - test eax, eax - jz .failed - - mov ebx,[slot_base] - mov [ebx+APPDATA.dir_table],eax - mov eax,[hdr_mem] - mov [ebx+APPDATA.mem_size],eax - - xor edx, edx - cmp word [6], '02' - jne @f - - not edx -@@: - mov [ebx+APPDATA.tls_base],edx - -if GREEDY_KERNEL -else - mov ecx, [hdr_mem] - mov edi, [file_size] - add edi, 4095 - and edi, not 4095 - sub ecx, edi - jna @F - - xor eax, eax - cld - rep stosb -@@: -end if - -; release only virtual space, not phisical memory - - stdcall free_kernel_space, [file_base] - lea eax, [hdr_cmdline] - lea ebx, [cmdline] - lea ecx, [filename] - stdcall set_app_params ,[slot],eax,ebx,ecx,[flags] - - mov eax, [save_cr3] - call set_cr3 - - xor ebx, ebx - mov [application_table_status],ebx ;unlock application_table_status mutex - mov eax,[process_number] ;set result - ret -.failed: - mov eax, [save_cr3] - call set_cr3 -.err: -.err_hdr: - stdcall kernel_free,[file_base] -.err_file: - xor eax, eax - mov [application_table_status],eax - mov eax, esi - ret -endp - -align 4 -test_app_header: - virtual at eax - APP_HEADER_00 APP_HEADER_00 - end virtual - virtual at eax - APP_HEADER_01 APP_HEADER_01 - end virtual - - cmp dword [eax], 'MENU' - jne .fail - cmp word [eax+4],'ET' - jne .fail - - cmp [eax+6], word '00' - jne .check_01_header - - mov ecx,[APP_HEADER_00.start] - mov [ebx+0x08], ecx ;app_eip - mov edx,[APP_HEADER_00.mem_size] - mov [ebx+0x10], edx ;app_mem - shr edx,1 - sub edx,0x10 - mov [ebx+0x0C], edx ;app_esp - mov ecx,[APP_HEADER_00.i_param] - mov [ebx], ecx ;app_cmdline - mov [ebx+4], dword 0 ;app_path - mov edx, [APP_HEADER_00.i_end] - mov [ebx+0x14], edx - ret - - .check_01_header: - - cmp [eax+6], word '01' - je @f - cmp [eax+6], word '02' - jne .fail -@@: - mov ecx,[APP_HEADER_01.start] - mov [ebx+0x08], ecx ;app_eip - mov edx,[APP_HEADER_01.mem_size] - -; \begin{diamond}[20.08.2006] -; sanity check (functions 19,58 load app_i_end bytes and that must -; fit in allocated memory to prevent kernel faults) - cmp edx,[APP_HEADER_01.i_end] - jb .fail -; \end{diamond}[20.08.2006] - - mov [ebx+0x10], edx ;app_mem - mov ecx,[APP_HEADER_01.stack_top] - mov [ebx+0x0C], ecx ;app_esp - mov edx,[APP_HEADER_01.i_param] - mov [ebx], edx ;app_cmdline - mov ecx,[APP_HEADER_01.i_icon] - mov [ebx+4], ecx ;app_path - mov edx, [APP_HEADER_01.i_end] - mov [ebx+0x14], edx - ret -.fail: - xor eax, eax - ret - -align 4 -proc get_new_process_place -;input: -; none -;result: -; eax=[new_process_place]<>0 - ok -; 0 - failed. -;This function find least empty slot. -;It doesn't increase [TASK_COUNT]! - mov eax,CURRENT_TASK - mov ebx,[TASK_COUNT] - inc ebx - shl ebx,5 - add ebx,eax ;ebx - address of process information for (last+1) slot -.newprocessplace: -;eax = address of process information for current slot - cmp eax,ebx - jz .endnewprocessplace ;empty slot after high boundary - add eax,0x20 - cmp word [eax+0xa],9 ;check process state, 9 means that process slot is empty - jnz .newprocessplace -.endnewprocessplace: - mov ebx,eax - sub eax,CURRENT_TASK - shr eax,5 ;calculate slot index - cmp eax,256 - jge .failed ;it should be <256 - mov word [ebx+0xa],9 ;set process state to 9 (for slot after hight boundary) - ret -.failed: - xor eax,eax - ret -endp - -align 4 -proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword - locals - app_pages dd ? - img_pages dd ? - dir_addr dd ? - app_tabs dd ? - endl - - mov ecx, pg_data.mutex - call mutex_lock - - xor eax, eax - mov [dir_addr], eax - - mov eax, [app_size] - add eax, 4095 - and eax, NOT(4095) - mov [app_size], eax - mov ebx, eax - shr eax, 12 - mov [app_pages], eax - - add ebx, 0x3FFFFF - and ebx, NOT(0x3FFFFF) - shr ebx, 22 - mov [app_tabs], ebx - - mov ecx, [img_size] - add ecx, 4095 - and ecx, NOT(4095) - - mov [img_size], ecx - shr ecx, 12 - mov [img_pages], ecx - -if GREEDY_KERNEL - lea eax, [ecx+ebx+2] ;only image size -else - lea eax, [eax+ebx+2] ;all requested memory -end if - cmp eax, [pg_data.pages_free] - ja .fail - - call alloc_page - test eax, eax - jz .fail - mov [dir_addr], eax - stdcall map_page,[tmp_task_pdir],eax,dword PG_SW - - mov edi, [tmp_task_pdir] - mov ecx, (OS_BASE shr 20)/4 - xor eax, eax - cld - rep stosd - - mov ecx, (OS_BASE shr 20)/4 - mov esi, sys_pgdir+(OS_BASE shr 20) - rep movsd - - mov eax, [dir_addr] - or eax, PG_SW - mov [edi-4096+(page_tabs shr 20)], eax - - and eax, -4096 - call set_cr3 - - mov edx, [app_tabs] - mov edi, new_app_base -@@: - call alloc_page - test eax, eax - jz .fail - - stdcall map_page_table, edi, eax - add edi, 0x00400000 - dec edx - jnz @B - - mov edi, new_app_base - shr edi, 10 - add edi, page_tabs - - mov ecx, [app_tabs] - shl ecx, 10 - xor eax, eax - rep stosd - - mov ecx, [img_pages] - mov ebx, PG_UW - mov edx, new_app_base - mov esi, [img_base] - mov edi, new_app_base - shr esi, 10 - shr edi, 10 - add esi, page_tabs - add edi, page_tabs -.remap: - lodsd - or eax, ebx ; force user level r/w access - stosd - add edx, 0x1000 - dec [app_pages] - dec ecx - jnz .remap - - mov ecx, [app_pages] - test ecx, ecx - jz .done - -if GREEDY_KERNEL - mov eax, 0x02 - rep stosd -else - -.alloc: - call alloc_page - test eax, eax - jz .fail - - stdcall map_page,edx,eax,dword PG_UW - add edx, 0x1000 - dec [app_pages] - jnz .alloc -end if - -.done: - stdcall map_page,[tmp_task_pdir],dword 0,dword PG_UNMAP - - mov ecx, pg_data.mutex - call mutex_unlock - mov eax, [dir_addr] - ret -.fail: - mov ecx, pg_data.mutex - call mutex_unlock - cmp [dir_addr], 0 - je @f - stdcall destroy_app_space, [dir_addr], 0 -@@: - xor eax, eax - ret -endp - -align 4 -set_cr3: - - mov ebx, [current_slot] - mov [ebx+APPDATA.dir_table], eax - mov cr3, eax - ret - -align 4 -proc destroy_page_table stdcall, pg_tab:dword - - push esi - - mov esi, [pg_tab] - mov ecx, 1024 -.free: - mov eax, [esi] - test eax, 1 - jz .next - test eax, 1 shl 9 - jnz .next ;skip shared pages - call free_page -.next: - add esi, 4 - dec ecx - jnz .free - pop esi - ret -endp - -align 4 -proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword - - xor edx,edx - push edx - mov eax,0x2 - mov ebx, [pg_dir] -.loop: -;eax = current slot of process - mov ecx,eax - shl ecx,5 - cmp byte [CURRENT_TASK+ecx+0xa],9 ;if process running? - jz @f ;skip empty slots - shl ecx,3 - add ecx,SLOT_BASE - cmp [ecx+APPDATA.dir_table],ebx ;compare page directory addresses - jnz @f - mov [ebp-4],ecx - inc edx ;thread found -@@: - inc eax - cmp eax,[TASK_COUNT] ;exit loop if we look through all processes - jle .loop - -;edx = number of threads -;our process is zombi so it isn't counted - pop ecx - cmp edx,1 - jg .ret -;if there isn't threads then clear memory. - mov esi, [dlls_list] - call destroy_all_hdlls ;ecx=APPDATA - - mov ecx, pg_data.mutex - call mutex_lock - - mov eax, [pg_dir] - and eax, not 0xFFF - stdcall map_page,[tmp_task_pdir],eax,PG_SW - mov esi, [tmp_task_pdir] - mov edi, (OS_BASE shr 20)/4 -.destroy: - mov eax, [esi] - test eax, 1 - jz .next - and eax, not 0xFFF - stdcall map_page,[tmp_task_ptab],eax,PG_SW - stdcall destroy_page_table, [tmp_task_ptab] - mov eax, [esi] - call free_page -.next: - add esi, 4 - dec edi - jnz .destroy - - mov eax, [pg_dir] - call free_page -.exit: - stdcall map_page,[tmp_task_ptab],0,PG_UNMAP - stdcall map_page,[tmp_task_pdir],0,PG_UNMAP - mov ecx, pg_data.mutex - call mutex_unlock -.ret: - ret -endp - -align 4 -get_pid: - mov eax, [TASK_BASE] - mov eax, [eax+TASKDATA.pid] - ret - -pid_to_slot: -;Input: -; eax - pid of process -;Output: -; eax - slot of process or 0 if process don't exists -;Search process by PID. - push ebx - push ecx - mov ebx,[TASK_COUNT] - shl ebx,5 - mov ecx,2*32 - -.loop: -;ecx=offset of current process info entry -;ebx=maximum permitted offset - cmp byte [CURRENT_TASK+ecx+0xa],9 - jz .endloop ;skip empty slots - cmp [CURRENT_TASK+ecx+0x4],eax ;check PID - jz .pid_found -.endloop: - add ecx,32 - cmp ecx,ebx - jle .loop - - pop ecx - pop ebx - xor eax,eax - ret - -.pid_found: - shr ecx,5 - mov eax,ecx ;convert offset to index of slot - pop ecx - pop ebx - ret - -check_region: -;input: -; esi - start of buffer -; edx - size of buffer -;result: -; eax = 1 region lays in app memory -; eax = 0 region don't lays in app memory - mov eax,[CURRENT_TASK] -; jmp check_process_region -;----------------------------------------------------------------------------- -;check_process_region: -;input: -; eax - slot -; esi - start of buffer -; edx - size of buffer -;result: -; eax = 1 region lays in app memory -; eax = 0 region don't lays in app memory - - test edx,edx - jle .ok - shl eax,5 - cmp word [CURRENT_TASK+eax+0xa],0 - jnz .failed - shl eax,3 - mov eax,[SLOT_BASE+eax+0xb8] - test eax,eax - jz .failed - - mov eax,1 - ret - - -; call MEM_Get_Linear_Address -; push ebx -; push ecx -; push edx -; mov edx,ebx -; and edx,not (4096-1) -; sub ebx,edx -; add ecx,ebx -; mov ebx,edx -; add ecx,(4096-1) -; and ecx,not (4096-1) -;.loop: -;;eax - linear address of page directory -;;ebx - current page -;;ecx - current size -; mov edx,ebx -; shr edx,22 -; mov edx,[eax+4*edx] -; and edx,not (4096-1) -; test edx,edx -; jz .failed1 -; push eax -; mov eax,edx -; call MEM_Get_Linear_Address -; mov edx,ebx -; shr edx,12 -; and edx,(1024-1) -; mov eax,[eax+4*edx] -; and eax,not (4096-1) -; test eax,eax -; pop eax -; jz .failed1 -; add ebx,4096 -; sub ecx,4096 -; jg .loop -; pop edx -; pop ecx -; pop ebx -.ok: - mov eax,1 - ret -; -;.failed1: -; pop edx -; pop ecx -; pop ebx -.failed: - xor eax,eax - ret - -align 4 -proc read_process_memory -;Input: -; eax - process slot -; ecx - buffer address -; edx - buffer size -; esi - start address in other process -;Output: -; eax - number of bytes read. - locals - slot dd ? - buff dd ? - r_count dd ? - offset dd ? - tmp_r_cnt dd ? - endl - - mov [slot], eax - mov [buff], ecx - and [r_count], 0 - mov [tmp_r_cnt], edx - mov [offset], esi - - pushad -.read_mem: - mov edx, [offset] - mov ebx, [tmp_r_cnt] - - mov ecx, 0x400000 - and edx, 0x3FFFFF - sub ecx, edx - cmp ecx, ebx - jbe @f - mov ecx, ebx -@@: - cmp ecx, 0x8000 - jna @F - mov ecx, 0x8000 -@@: - mov ebx, [offset] - - push ecx - stdcall map_memEx, [proc_mem_map],\ - [slot], ebx, ecx, PG_MAP - pop ecx - - mov esi, [offset] - and esi, 0xfff - sub eax, esi - jbe .ret - cmp ecx, eax - jbe @f - mov ecx, eax - mov [tmp_r_cnt], eax -@@: - add esi, [proc_mem_map] - mov edi, [buff] - mov edx, ecx - rep movsb - add [r_count], edx - - add [offset], edx - sub [tmp_r_cnt], edx - jnz .read_mem -.ret: - popad - mov eax, [r_count] - ret -endp - -align 4 -proc write_process_memory -;Input: -; eax - process slot -; ecx - buffer address -; edx - buffer size -; esi - start address in other process -;Output: -; eax - number of bytes written - - locals - slot dd ? - buff dd ? - w_count dd ? - offset dd ? - tmp_w_cnt dd ? - endl - - mov [slot], eax - mov [buff], ecx - and [w_count], 0 - mov [tmp_w_cnt], edx - mov [offset], esi - - pushad -.read_mem: - mov edx, [offset] - mov ebx, [tmp_w_cnt] - - mov ecx, 0x400000 - and edx, 0x3FFFFF - sub ecx, edx - cmp ecx, ebx - jbe @f - mov ecx, ebx -@@: - cmp ecx, 0x8000 - jna @F - mov ecx, 0x8000 -@@: - mov ebx, [offset] - ; add ebx, new_app_base - push ecx - stdcall map_memEx, [proc_mem_map],\ - [slot], ebx, ecx, PG_SW - pop ecx - - mov edi, [offset] - and edi, 0xfff - sub eax, edi - jbe .ret - cmp ecx, eax - jbe @f - mov ecx, eax - mov [tmp_w_cnt], eax -@@: - add edi, [proc_mem_map] - mov esi, [buff] - mov edx, ecx - rep movsb - - add [w_count], edx - add [offset], edx - sub [tmp_w_cnt], edx - jnz .read_mem -.ret: - popad - mov eax, [w_count] - ret -endp - -align 4 -proc new_sys_threads - locals - slot dd ? - app_cmdline dd ? ;0x00 - app_path dd ? ;0x04 - app_eip dd ? ;0x08 - app_esp dd ? ;0x0C - app_mem dd ? ;0x10 - endl - - cmp ebx,1 - jne .failed ;other subfunctions - - xor eax,eax - mov [app_eip], ecx - mov [app_cmdline], eax - mov [app_esp], edx - mov [app_path], eax - ;mov esi,new_process_loading - ;call sys_msg_board_str -.wait_lock: - cmp [application_table_status],0 - je .get_lock - call change_task - jmp .wait_lock - -.get_lock: - mov eax, 1 - xchg eax, [application_table_status] - test eax, eax - jnz .wait_lock - - call set_application_table_status - - call get_new_process_place - test eax, eax - jz .failed - - mov [slot], eax - - mov esi,[current_slot] - mov ebx,esi ;ebx=esi - pointer to extended information about current thread - - mov edi, eax - shl edi,8 - add edi,SLOT_BASE - mov edx,edi ;edx=edi - pointer to extended infomation about new thread - mov ecx,256/4 - xor eax, eax - cld - rep stosd ;clean extended information about new thread - mov esi,ebx - mov edi,edx - mov ecx,11 - rep movsb ;copy process name - - mov eax,[ebx+APPDATA.heap_base] - mov [edx+APPDATA.heap_base], eax - - mov ecx,[ebx+APPDATA.heap_top] - mov [edx+APPDATA.heap_top], ecx - - mov eax,[ebx+APPDATA.mem_size] - mov [edx+APPDATA.mem_size], eax - - mov ecx,[ebx+APPDATA.dir_table] - mov [edx+APPDATA.dir_table],ecx ;copy page directory - - mov eax,[ebx+APPDATA.dlls_list_ptr] - mov [edx+APPDATA.dlls_list_ptr],eax - - mov eax, [ebx+APPDATA.tls_base] - test eax, eax - jz @F - - push edx - stdcall user_alloc, 4096 - pop edx - test eax, eax - jz .failed1 ;eax=0 -@@: - mov [edx+APPDATA.tls_base], eax - - lea eax, [app_cmdline] - stdcall set_app_params ,[slot],eax,dword 0,\ - dword 0,dword 0 - - ;mov esi,new_process_running - ;call sys_msg_board_str ;output information about succefull startup - xor eax,eax - mov [application_table_status],eax ;unlock application_table_status mutex - mov eax,[process_number] ;set result - ret -.failed: - xor eax,eax -.failed1: - mov [application_table_status],eax - dec eax ;-1 - ret -endp - -align 4 -tls_app_entry: - - call init_heap - stdcall user_alloc, 4096 - - mov edx, [current_slot] - mov [edx+APPDATA.tls_base], eax - mov [tls_data_l+2],ax - shr eax,16 - mov [tls_data_l+4],al - mov [tls_data_l+7],ah - mov dx, app_tls - mov fs, dx - popad - iretd - - -EFL_IF equ 0x0200 -EFL_IOPL1 equ 0x1000 -EFL_IOPL2 equ 0x2000 -EFL_IOPL3 equ 0x3000 - - -align 4 -proc set_app_params stdcall,slot:dword, params:dword,\ - cmd_line:dword, app_path:dword, flags:dword - - locals - pl0_stack dd ? - endl - - stdcall kernel_alloc, RING0_STACK_SIZE+512 - mov [pl0_stack], eax - - lea edi, [eax+RING0_STACK_SIZE] - - mov eax, [slot] - mov ebx, eax - - shl eax, 8 - mov [eax+SLOT_BASE+APPDATA.fpu_state], edi - mov [eax+SLOT_BASE+APPDATA.exc_handler], 0 - mov [eax+SLOT_BASE+APPDATA.except_mask], 0 - -;set default io permission map - mov ecx, [SLOT_BASE+256+APPDATA.io_map] - mov [eax+SLOT_BASE+APPDATA.io_map], ecx - mov ecx, [SLOT_BASE+256+APPDATA.io_map+4] - mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx - - mov esi, fpu_data - mov ecx, 512/4 - rep movsd - - cmp ebx,[TASK_COUNT] - jle .noinc - inc dword [TASK_COUNT] ;update number of processes -.noinc: - shl ebx,8 - lea edx, [ebx+SLOT_BASE+APP_EV_OFFSET] - mov [SLOT_BASE+APPDATA.fd_ev+ebx],edx - mov [SLOT_BASE+APPDATA.bk_ev+ebx],edx - - add edx, APP_OBJ_OFFSET-APP_EV_OFFSET - mov [SLOT_BASE+APPDATA.fd_obj+ebx],edx - mov [SLOT_BASE+APPDATA.bk_obj+ebx],edx - - mov ecx, [def_cursor] - mov [SLOT_BASE+APPDATA.cursor+ebx],ecx - mov eax, [pl0_stack] - mov [SLOT_BASE+APPDATA.pl0_stack+ebx],eax - add eax, RING0_STACK_SIZE - mov [SLOT_BASE+APPDATA.saved_esp0+ebx], eax - - push ebx - stdcall kernel_alloc, 0x1000 - pop ebx - mov esi,[current_slot] - mov esi,[esi+APPDATA.cur_dir] - mov ecx,0x1000/4 - mov edi,eax - mov [ebx+SLOT_BASE+APPDATA.cur_dir],eax - rep movsd - - shr ebx,3 - mov eax, new_app_base - mov dword [CURRENT_TASK+ebx+0x10],eax - -.add_command_line: - mov edx,[params] - mov edx,[edx] ;app_cmdline - test edx,edx - jz @f ;application doesn't need parameters - - mov eax, edx - add eax, 256 - jc @f - - cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] - ja @f - - mov byte [edx], 0 ;force empty string if no cmdline given - mov eax, [cmd_line] - test eax, eax - jz @f - stdcall strncpy, edx, eax, 256 -@@: - mov edx,[params] - mov edx, [edx+4] ;app_path - test edx,edx - jz @F ;application don't need path of file - mov eax, edx - add eax, 1024 - jc @f - cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] - ja @f - stdcall strncpy, edx, [app_path], 1024 -@@: - mov ebx,[slot] - mov eax,ebx - shl ebx,5 - lea ecx,[draw_data+ebx] ;ecx - pointer to draw data - - mov edx, irq0.return - cmp [ebx*8+SLOT_BASE+APPDATA.tls_base], -1 - jne @F - mov edx, tls_app_entry -@@: -; set window state to 'normal' (non-minimized/maximized/rolled-up) state - mov [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL - mov [ebx+window_data+WDATA.fl_redraw], 1 - add ebx,CURRENT_TASK ;ebx - pointer to information about process - mov [ebx+TASKDATA.wnd_number],al;set window number on screen = process slot - - mov [ebx+TASKDATA.event_mask],dword 1+2+4 ;set default event flags (see 40 function) - - inc dword [process_number] - mov eax,[process_number] - mov [ebx+4],eax ;set PID - -;set draw data to full screen - xor eax,eax - mov [ecx+0],dword eax - mov [ecx+4],dword eax - mov eax,[Screen_Max_X] - mov [ecx+8],eax - mov eax,[Screen_Max_Y] - mov [ecx+12],eax - - mov ebx, [pl0_stack] - mov esi,[params] - lea ecx, [ebx+REG_EIP] - xor eax, eax - - mov [ebx+REG_RET], edx - mov [ebx+REG_EDI], eax - mov [ebx+REG_ESI], eax - mov [ebx+REG_EBP], eax - mov [ebx+REG_ESP], ecx ;ebx+REG_EIP - mov [ebx+REG_EBX], eax - mov [ebx+REG_EDX], eax - mov [ebx+REG_ECX], eax - mov [ebx+REG_EAX], eax - - mov eax, [esi+0x08] ;app_eip - mov [ebx+REG_EIP], eax ;app_entry - mov [ebx+REG_CS], dword app_code - mov [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF - - mov eax, [esi+0x0C] ;app_esp - mov [ebx+REG_APP_ESP], eax ;app_stack - mov [ebx+REG_SS], dword app_data - - lea ecx, [ebx+REG_RET] - mov ebx, [slot] - shl ebx, 5 - mov [ebx*8+SLOT_BASE+APPDATA.saved_esp], ecx - - xor ecx, ecx ; process state - running -; set if debuggee - test byte [flags], 1 - jz .no_debug - inc ecx ; process state - suspended - mov eax,[CURRENT_TASK] - mov [SLOT_BASE+ebx*8+APPDATA.debugger_slot],eax -.no_debug: - mov [CURRENT_TASK+ebx+TASKDATA.state], cl - ;mov esi,new_process_running - ;call sys_msg_board_str ;output information about succefull startup - ret -endp - - -align 4 - -get_stack_base: - mov eax,[current_slot] - mov eax,[eax+APPDATA.pl0_stack] - ret - - -include "debug.inc" +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +GREEDY_KERNEL equ 0 + +struc APP_HEADER_00 +{ .banner dq ? + .version dd ? ;+8 + .start dd ? ;+12 + .i_end dd ? ;+16 + .mem_size dd ? ;+20 + .i_param dd ? ;+24 +} + +struc APP_HEADER_01 +{ .banner dq ? + .version dd ? ;+8 + .start dd ? ;+12 + .i_end dd ? ;+16 + .mem_size dd ? ;+20 + .stack_top dd ? ;+24 + .i_param dd ? ;+28 + .i_icon dd ? ;+32 +} + + +struc APP_PARAMS +{ .app_cmdline ;0x00 + .app_path ;0x04 + .app_eip ;0x08 + .app_esp ;0x0C + .app_mem ;0x10 +} + +macro _clear_ op +{ mov ecx, op/4 + xor eax, eax + cld + rep stosd +} + +fs_execute_from_sysdir: + xor ebx, ebx +fs_execute_from_sysdir_param: + xor edx, edx + mov esi, sysdir_path + +align 4 +proc fs_execute + +;fn_read:dword, file_size:dword, cluster:dword + +; ebx - cmdline +; edx - flags +; ebp - full filename +; [esp+4] = procedure DoRead, [esp+8] = filesize & [esp+12]... - arguments for it + + locals + cmdline rd 64 ;256/4 + filename rd 256 ;1024/4 + flags dd ? + + save_cr3 dd ? + slot dd ? + slot_base dd ? + file_base dd ? + file_size dd ? + ;app header data + hdr_cmdline dd ? ;0x00 + hdr_path dd ? ;0x04 + hdr_eip dd ? ;0x08 + hdr_esp dd ? ;0x0C + hdr_mem dd ? ;0x10 + hdr_i_end dd ? ;0x14 + endl + + pushad + + mov [flags], edx + +; [ebp] pointer to filename + + lea edi, [filename] + lea ecx, [edi+1024] + mov al, '/' + stosb +@@: + cmp edi, ecx + jae .bigfilename + lodsb + stosb + test al, al + jnz @b + mov esi, [ebp] + test esi, esi + jz .namecopied + mov byte [edi-1], '/' +@@: + cmp edi, ecx + jae .bigfilename + lodsb + stosb + test al, al + jnz @b + jmp .namecopied +.bigfilename: + popad + mov eax, -ERROR_FILE_NOT_FOUND + ret + +.namecopied: + + mov [cmdline], ebx + test ebx, ebx + jz @F + + lea eax, [cmdline] + mov dword [eax+252], 0 + stdcall strncpy, eax, ebx, 255 +@@: + lea eax, [filename] + stdcall load_file, eax + mov esi, -ERROR_FILE_NOT_FOUND + test eax, eax + jz .err_file + + mov [file_base], eax + mov [file_size], ebx + + lea ebx, [hdr_cmdline] + call test_app_header + mov esi, -0x1F + test eax, eax + jz .err_hdr + +.wait_lock: + cmp [application_table_status], 0 + je .get_lock + call change_task + jmp .wait_lock + +.get_lock: + mov eax, 1 + xchg eax, [application_table_status] + test eax, eax + jnz .wait_lock + + call set_application_table_status + + call get_new_process_place + test eax, eax + mov esi, -0x20 ; too many processes + jz .err + + mov [slot], eax + shl eax, 8 + add eax, SLOT_BASE + mov [slot_base], eax + mov edi, eax + _clear_ 256 ;clean extended information about process + +; write application name + lea eax, [filename] + stdcall strrchr, eax, '/' ; now eax points to name without path + + lea esi, [eax+1] + test eax, eax + jnz @F + lea esi, [filename] +@@: + mov ecx, 8; 8 chars for name + mov edi, [slot_base] +.copy_process_name_loop: + lodsb + cmp al, '.' + jz .copy_process_name_done + test al, al + jz .copy_process_name_done + stosb + loop .copy_process_name_loop +.copy_process_name_done: + + mov ebx, cr3 + mov [save_cr3], ebx + + stdcall create_app_space, [hdr_mem], [file_base], [file_size] + mov esi, -30; no memory + test eax, eax + jz .failed + + mov ebx, [slot_base] + mov [ebx+APPDATA.dir_table], eax + mov eax, [hdr_mem] + mov [ebx+APPDATA.mem_size], eax + + xor edx, edx + cmp word [6], '02' + jne @f + + not edx +@@: + mov [ebx+APPDATA.tls_base], edx + +if GREEDY_KERNEL +else + mov ecx, [hdr_mem] + mov edi, [file_size] + add edi, 4095 + and edi, not 4095 + sub ecx, edi + jna @F + + xor eax, eax + cld + rep stosb +@@: +end if + +; release only virtual space, not phisical memory + + stdcall free_kernel_space, [file_base] + lea eax, [hdr_cmdline] + lea ebx, [cmdline] + lea ecx, [filename] + stdcall set_app_params , [slot], eax, ebx, ecx, [flags] + + mov eax, [save_cr3] + call set_cr3 + + xor ebx, ebx + mov [application_table_status], ebx;unlock application_table_status mutex + mov eax, [process_number];set result + ret +.failed: + mov eax, [save_cr3] + call set_cr3 +.err: +.err_hdr: + stdcall kernel_free, [file_base] +.err_file: + xor eax, eax + mov [application_table_status], eax + mov eax, esi + ret +endp + +align 4 +test_app_header: + virtual at eax + APP_HEADER_00 APP_HEADER_00 + end virtual + virtual at eax + APP_HEADER_01 APP_HEADER_01 + end virtual + + cmp dword [eax], 'MENU' + jne .fail + cmp word [eax+4], 'ET' + jne .fail + + cmp [eax+6], word '00' + jne .check_01_header + + mov ecx, [APP_HEADER_00.start] + mov [ebx+0x08], ecx ;app_eip + mov edx, [APP_HEADER_00.mem_size] + mov [ebx+0x10], edx ;app_mem + shr edx, 1 + sub edx, 0x10 + mov [ebx+0x0C], edx ;app_esp + mov ecx, [APP_HEADER_00.i_param] + mov [ebx], ecx ;app_cmdline + mov [ebx+4], dword 0 ;app_path + mov edx, [APP_HEADER_00.i_end] + mov [ebx+0x14], edx + ret + + .check_01_header: + + cmp [eax+6], word '01' + je @f + cmp [eax+6], word '02' + jne .fail +@@: + mov ecx, [APP_HEADER_01.start] + mov [ebx+0x08], ecx ;app_eip + mov edx, [APP_HEADER_01.mem_size] + +; \begin{diamond}[20.08.2006] +; sanity check (functions 19,58 load app_i_end bytes and that must +; fit in allocated memory to prevent kernel faults) + cmp edx, [APP_HEADER_01.i_end] + jb .fail +; \end{diamond}[20.08.2006] + + mov [ebx+0x10], edx ;app_mem + mov ecx, [APP_HEADER_01.stack_top] + mov [ebx+0x0C], ecx ;app_esp + mov edx, [APP_HEADER_01.i_param] + mov [ebx], edx ;app_cmdline + mov ecx, [APP_HEADER_01.i_icon] + mov [ebx+4], ecx ;app_path + mov edx, [APP_HEADER_01.i_end] + mov [ebx+0x14], edx + ret +.fail: + xor eax, eax + ret + +align 4 +proc get_new_process_place +;input: +; none +;result: +; eax=[new_process_place]<>0 - ok +; 0 - failed. +;This function find least empty slot. +;It doesn't increase [TASK_COUNT]! + mov eax, CURRENT_TASK + mov ebx, [TASK_COUNT] + inc ebx + shl ebx, 5 + add ebx, eax ;ebx - address of process information for (last+1) slot +.newprocessplace: +;eax = address of process information for current slot + cmp eax, ebx + jz .endnewprocessplace ;empty slot after high boundary + add eax, 0x20 + cmp word [eax+0xa], 9;check process state, 9 means that process slot is empty + jnz .newprocessplace +.endnewprocessplace: + mov ebx, eax + sub eax, CURRENT_TASK + shr eax, 5 ;calculate slot index + cmp eax, 256 + jge .failed ;it should be <256 + mov word [ebx+0xa], 9;set process state to 9 (for slot after hight boundary) + ret +.failed: + xor eax, eax + ret +endp + +align 4 +proc create_app_space stdcall, app_size:dword,img_base:dword,img_size:dword + locals + app_pages dd ? + img_pages dd ? + dir_addr dd ? + app_tabs dd ? + endl + + mov ecx, pg_data.mutex + call mutex_lock + + xor eax, eax + mov [dir_addr], eax + + mov eax, [app_size] + add eax, 4095 + and eax, NOT(4095) + mov [app_size], eax + mov ebx, eax + shr eax, 12 + mov [app_pages], eax + + add ebx, 0x3FFFFF + and ebx, NOT(0x3FFFFF) + shr ebx, 22 + mov [app_tabs], ebx + + mov ecx, [img_size] + add ecx, 4095 + and ecx, NOT(4095) + + mov [img_size], ecx + shr ecx, 12 + mov [img_pages], ecx + +if GREEDY_KERNEL + lea eax, [ecx+ebx+2];only image size +else + lea eax, [eax+ebx+2];all requested memory +end if + cmp eax, [pg_data.pages_free] + ja .fail + + call alloc_page + test eax, eax + jz .fail + mov [dir_addr], eax + stdcall map_page, [tmp_task_pdir], eax, dword PG_SW + + mov edi, [tmp_task_pdir] + mov ecx, (OS_BASE shr 20)/4 + xor eax, eax + cld + rep stosd + + mov ecx, (OS_BASE shr 20)/4 + mov esi, sys_pgdir+(OS_BASE shr 20) + rep movsd + + mov eax, [dir_addr] + or eax, PG_SW + mov [edi-4096+(page_tabs shr 20)], eax + + and eax, -4096 + call set_cr3 + + mov edx, [app_tabs] + mov edi, new_app_base +@@: + call alloc_page + test eax, eax + jz .fail + + stdcall map_page_table, edi, eax + add edi, 0x00400000 + dec edx + jnz @B + + mov edi, new_app_base + shr edi, 10 + add edi, page_tabs + + mov ecx, [app_tabs] + shl ecx, 10 + xor eax, eax + rep stosd + + mov ecx, [img_pages] + mov ebx, PG_UW + mov edx, new_app_base + mov esi, [img_base] + mov edi, new_app_base + shr esi, 10 + shr edi, 10 + add esi, page_tabs + add edi, page_tabs +.remap: + lodsd + or eax, ebx; force user level r/w access + stosd + add edx, 0x1000 + dec [app_pages] + dec ecx + jnz .remap + + mov ecx, [app_pages] + test ecx, ecx + jz .done + +if GREEDY_KERNEL + mov eax, 0x02 + rep stosd +else + +.alloc: + call alloc_page + test eax, eax + jz .fail + + stdcall map_page, edx, eax, dword PG_UW + add edx, 0x1000 + dec [app_pages] + jnz .alloc +end if + +.done: + stdcall map_page, [tmp_task_pdir], dword 0, dword PG_UNMAP + + mov ecx, pg_data.mutex + call mutex_unlock + mov eax, [dir_addr] + ret +.fail: + mov ecx, pg_data.mutex + call mutex_unlock + cmp [dir_addr], 0 + je @f + stdcall destroy_app_space, [dir_addr], 0 +@@: + xor eax, eax + ret +endp + +align 4 +set_cr3: + + mov ebx, [current_slot] + mov [ebx+APPDATA.dir_table], eax + mov cr3, eax + ret + +align 4 +proc destroy_page_table stdcall, pg_tab:dword + + push esi + + mov esi, [pg_tab] + mov ecx, 1024 +.free: + mov eax, [esi] + test eax, 1 + jz .next + test eax, 1 shl 9 + jnz .next ;skip shared pages + call free_page +.next: + add esi, 4 + dec ecx + jnz .free + pop esi + ret +endp + +align 4 +proc destroy_app_space stdcall, pg_dir:dword, dlls_list:dword + + xor edx, edx + push edx + mov eax, 0x2 + mov ebx, [pg_dir] +.loop: +;eax = current slot of process + mov ecx, eax + shl ecx, 5 + cmp byte [CURRENT_TASK+ecx+0xa], 9;if process running? + jz @f ;skip empty slots + shl ecx, 3 + add ecx, SLOT_BASE + cmp [ecx+APPDATA.dir_table], ebx;compare page directory addresses + jnz @f + mov [ebp-4], ecx + inc edx ;thread found +@@: + inc eax + cmp eax, [TASK_COUNT] ;exit loop if we look through all processes + jle .loop + +;edx = number of threads +;our process is zombi so it isn't counted + pop ecx + cmp edx, 1 + jg .ret +;if there isn't threads then clear memory. + mov esi, [dlls_list] + call destroy_all_hdlls;ecx=APPDATA + + mov ecx, pg_data.mutex + call mutex_lock + + mov eax, [pg_dir] + and eax, not 0xFFF + stdcall map_page, [tmp_task_pdir], eax, PG_SW + mov esi, [tmp_task_pdir] + mov edi, (OS_BASE shr 20)/4 +.destroy: + mov eax, [esi] + test eax, 1 + jz .next + and eax, not 0xFFF + stdcall map_page, [tmp_task_ptab], eax, PG_SW + stdcall destroy_page_table, [tmp_task_ptab] + mov eax, [esi] + call free_page +.next: + add esi, 4 + dec edi + jnz .destroy + + mov eax, [pg_dir] + call free_page +.exit: + stdcall map_page, [tmp_task_ptab], 0, PG_UNMAP + stdcall map_page, [tmp_task_pdir], 0, PG_UNMAP + mov ecx, pg_data.mutex + call mutex_unlock +.ret: + ret +endp + +align 4 +get_pid: + mov eax, [TASK_BASE] + mov eax, [eax+TASKDATA.pid] + ret + +pid_to_slot: +;Input: +; eax - pid of process +;Output: +; eax - slot of process or 0 if process don't exists +;Search process by PID. + push ebx + push ecx + mov ebx, [TASK_COUNT] + shl ebx, 5 + mov ecx, 2*32 + +.loop: +;ecx=offset of current process info entry +;ebx=maximum permitted offset + cmp byte [CURRENT_TASK+ecx+0xa], 9 + jz .endloop ;skip empty slots + cmp [CURRENT_TASK+ecx+0x4], eax;check PID + jz .pid_found +.endloop: + add ecx, 32 + cmp ecx, ebx + jle .loop + + pop ecx + pop ebx + xor eax, eax + ret + +.pid_found: + shr ecx, 5 + mov eax, ecx ;convert offset to index of slot + pop ecx + pop ebx + ret + +check_region: +;input: +; esi - start of buffer +; edx - size of buffer +;result: +; eax = 1 region lays in app memory +; eax = 0 region don't lays in app memory + mov eax, [CURRENT_TASK] +; jmp check_process_region +;----------------------------------------------------------------------------- +;check_process_region: +;input: +; eax - slot +; esi - start of buffer +; edx - size of buffer +;result: +; eax = 1 region lays in app memory +; eax = 0 region don't lays in app memory + + test edx, edx + jle .ok + shl eax, 5 + cmp word [CURRENT_TASK+eax+0xa], 0 + jnz .failed + shl eax, 3 + mov eax, [SLOT_BASE+eax+0xb8] + test eax, eax + jz .failed + + mov eax, 1 + ret + + +; call MEM_Get_Linear_Address +; push ebx +; push ecx +; push edx +; mov edx,ebx +; and edx,not (4096-1) +; sub ebx,edx +; add ecx,ebx +; mov ebx,edx +; add ecx,(4096-1) +; and ecx,not (4096-1) +;.loop: +;;eax - linear address of page directory +;;ebx - current page +;;ecx - current size +; mov edx,ebx +; shr edx,22 +; mov edx,[eax+4*edx] +; and edx,not (4096-1) +; test edx,edx +; jz .failed1 +; push eax +; mov eax,edx +; call MEM_Get_Linear_Address +; mov edx,ebx +; shr edx,12 +; and edx,(1024-1) +; mov eax,[eax+4*edx] +; and eax,not (4096-1) +; test eax,eax +; pop eax +; jz .failed1 +; add ebx,4096 +; sub ecx,4096 +; jg .loop +; pop edx +; pop ecx +; pop ebx +.ok: + mov eax, 1 + ret +; +;.failed1: +; pop edx +; pop ecx +; pop ebx +.failed: + xor eax, eax + ret + +align 4 +proc read_process_memory +;Input: +; eax - process slot +; ecx - buffer address +; edx - buffer size +; esi - start address in other process +;Output: +; eax - number of bytes read. + locals + slot dd ? + buff dd ? + r_count dd ? + offset dd ? + tmp_r_cnt dd ? + endl + + mov [slot], eax + mov [buff], ecx + and [r_count], 0 + mov [tmp_r_cnt], edx + mov [offset], esi + + pushad +.read_mem: + mov edx, [offset] + mov ebx, [tmp_r_cnt] + + mov ecx, 0x400000 + and edx, 0x3FFFFF + sub ecx, edx + cmp ecx, ebx + jbe @f + mov ecx, ebx +@@: + cmp ecx, 0x8000 + jna @F + mov ecx, 0x8000 +@@: + mov ebx, [offset] + + push ecx + stdcall map_memEx, [proc_mem_map], \ + [slot], ebx, ecx, PG_MAP + pop ecx + + mov esi, [offset] + and esi, 0xfff + sub eax, esi + jbe .ret + cmp ecx, eax + jbe @f + mov ecx, eax + mov [tmp_r_cnt], eax +@@: + add esi, [proc_mem_map] + mov edi, [buff] + mov edx, ecx + rep movsb + add [r_count], edx + + add [offset], edx + sub [tmp_r_cnt], edx + jnz .read_mem +.ret: + popad + mov eax, [r_count] + ret +endp + +align 4 +proc write_process_memory +;Input: +; eax - process slot +; ecx - buffer address +; edx - buffer size +; esi - start address in other process +;Output: +; eax - number of bytes written + + locals + slot dd ? + buff dd ? + w_count dd ? + offset dd ? + tmp_w_cnt dd ? + endl + + mov [slot], eax + mov [buff], ecx + and [w_count], 0 + mov [tmp_w_cnt], edx + mov [offset], esi + + pushad +.read_mem: + mov edx, [offset] + mov ebx, [tmp_w_cnt] + + mov ecx, 0x400000 + and edx, 0x3FFFFF + sub ecx, edx + cmp ecx, ebx + jbe @f + mov ecx, ebx +@@: + cmp ecx, 0x8000 + jna @F + mov ecx, 0x8000 +@@: + mov ebx, [offset] + ; add ebx, new_app_base + push ecx + stdcall map_memEx, [proc_mem_map], \ + [slot], ebx, ecx, PG_SW + pop ecx + + mov edi, [offset] + and edi, 0xfff + sub eax, edi + jbe .ret + cmp ecx, eax + jbe @f + mov ecx, eax + mov [tmp_w_cnt], eax +@@: + add edi, [proc_mem_map] + mov esi, [buff] + mov edx, ecx + rep movsb + + add [w_count], edx + add [offset], edx + sub [tmp_w_cnt], edx + jnz .read_mem +.ret: + popad + mov eax, [w_count] + ret +endp + +align 4 +proc new_sys_threads + locals + slot dd ? + app_cmdline dd ? ;0x00 + app_path dd ? ;0x04 + app_eip dd ? ;0x08 + app_esp dd ? ;0x0C + app_mem dd ? ;0x10 + endl + + cmp ebx, 1 + jne .failed ;other subfunctions + + xor eax, eax + mov [app_eip], ecx + mov [app_cmdline], eax + mov [app_esp], edx + mov [app_path], eax + ;mov esi,new_process_loading + ;call sys_msg_board_str +.wait_lock: + cmp [application_table_status], 0 + je .get_lock + call change_task + jmp .wait_lock + +.get_lock: + mov eax, 1 + xchg eax, [application_table_status] + test eax, eax + jnz .wait_lock + + call set_application_table_status + + call get_new_process_place + test eax, eax + jz .failed + + mov [slot], eax + + mov esi, [current_slot] + mov ebx, esi ;ebx=esi - pointer to extended information about current thread + + mov edi, eax + shl edi, 8 + add edi, SLOT_BASE + mov edx, edi ;edx=edi - pointer to extended infomation about new thread + mov ecx, 256/4 + xor eax, eax + cld + rep stosd ;clean extended information about new thread + mov esi, ebx + mov edi, edx + mov ecx, 11 + rep movsb ;copy process name + + mov eax, [ebx+APPDATA.heap_base] + mov [edx+APPDATA.heap_base], eax + + mov ecx, [ebx+APPDATA.heap_top] + mov [edx+APPDATA.heap_top], ecx + + mov eax, [ebx+APPDATA.mem_size] + mov [edx+APPDATA.mem_size], eax + + mov ecx, [ebx+APPDATA.dir_table] + mov [edx+APPDATA.dir_table], ecx;copy page directory + + mov eax, [ebx+APPDATA.dlls_list_ptr] + mov [edx+APPDATA.dlls_list_ptr], eax + + mov eax, [ebx+APPDATA.tls_base] + test eax, eax + jz @F + + push edx + stdcall user_alloc, 4096 + pop edx + test eax, eax + jz .failed1;eax=0 +@@: + mov [edx+APPDATA.tls_base], eax + + lea eax, [app_cmdline] + stdcall set_app_params , [slot], eax, dword 0, \ + dword 0,dword 0 + + ;mov esi,new_process_running + ;call sys_msg_board_str ;output information about succefull startup + xor eax, eax + mov [application_table_status], eax ;unlock application_table_status mutex + mov eax, [process_number] ;set result + ret +.failed: + xor eax, eax +.failed1: + mov [application_table_status], eax + dec eax ;-1 + ret +endp + +align 4 +tls_app_entry: + + call init_heap + stdcall user_alloc, 4096 + + mov edx, [current_slot] + mov [edx+APPDATA.tls_base], eax + mov [tls_data_l+2], ax + shr eax, 16 + mov [tls_data_l+4], al + mov [tls_data_l+7], ah + mov dx, app_tls + mov fs, dx + popad + iretd + + +EFL_IF equ 0x0200 +EFL_IOPL1 equ 0x1000 +EFL_IOPL2 equ 0x2000 +EFL_IOPL3 equ 0x3000 + + +align 4 +proc set_app_params stdcall,slot:dword, params:dword,\ + cmd_line:dword, app_path:dword, flags:dword + + locals + pl0_stack dd ? + endl + + stdcall kernel_alloc, RING0_STACK_SIZE+512 + mov [pl0_stack], eax + + lea edi, [eax+RING0_STACK_SIZE] + + mov eax, [slot] + mov ebx, eax + + shl eax, 8 + mov [eax+SLOT_BASE+APPDATA.fpu_state], edi + mov [eax+SLOT_BASE+APPDATA.exc_handler], 0 + mov [eax+SLOT_BASE+APPDATA.except_mask], 0 + +;set default io permission map + mov ecx, [SLOT_BASE+256+APPDATA.io_map] + mov [eax+SLOT_BASE+APPDATA.io_map], ecx + mov ecx, [SLOT_BASE+256+APPDATA.io_map+4] + mov [eax+SLOT_BASE+APPDATA.io_map+4], ecx + + mov esi, fpu_data + mov ecx, 512/4 + rep movsd + + cmp ebx, [TASK_COUNT] + jle .noinc + inc dword [TASK_COUNT] ;update number of processes +.noinc: + shl ebx, 8 + lea edx, [ebx+SLOT_BASE+APP_EV_OFFSET] + mov [SLOT_BASE+APPDATA.fd_ev+ebx], edx + mov [SLOT_BASE+APPDATA.bk_ev+ebx], edx + + add edx, APP_OBJ_OFFSET-APP_EV_OFFSET + mov [SLOT_BASE+APPDATA.fd_obj+ebx], edx + mov [SLOT_BASE+APPDATA.bk_obj+ebx], edx + + mov ecx, [def_cursor] + mov [SLOT_BASE+APPDATA.cursor+ebx], ecx + mov eax, [pl0_stack] + mov [SLOT_BASE+APPDATA.pl0_stack+ebx], eax + add eax, RING0_STACK_SIZE + mov [SLOT_BASE+APPDATA.saved_esp0+ebx], eax + + push ebx + stdcall kernel_alloc, 0x1000 + pop ebx + mov esi, [current_slot] + mov esi, [esi+APPDATA.cur_dir] + mov ecx, 0x1000/4 + mov edi, eax + mov [ebx+SLOT_BASE+APPDATA.cur_dir], eax + rep movsd + + shr ebx, 3 + mov eax, new_app_base + mov dword [CURRENT_TASK+ebx+0x10], eax + +.add_command_line: + mov edx, [params] + mov edx, [edx] ;app_cmdline + test edx, edx + jz @f ;application doesn't need parameters + + mov eax, edx + add eax, 256 + jc @f + + cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] + ja @f + + mov byte [edx], 0 ;force empty string if no cmdline given + mov eax, [cmd_line] + test eax, eax + jz @f + stdcall strncpy, edx, eax, 256 +@@: + mov edx, [params] + mov edx, [edx+4];app_path + test edx, edx + jz @F ;application don't need path of file + mov eax, edx + add eax, 1024 + jc @f + cmp eax, [SLOT_BASE+APPDATA.mem_size+ebx*8] + ja @f + stdcall strncpy, edx, [app_path], 1024 +@@: + mov ebx, [slot] + mov eax, ebx + shl ebx, 5 + lea ecx, [draw_data+ebx];ecx - pointer to draw data + + mov edx, irq0.return + cmp [ebx*8+SLOT_BASE+APPDATA.tls_base], -1 + jne @F + mov edx, tls_app_entry +@@: +; set window state to 'normal' (non-minimized/maximized/rolled-up) state + mov [ebx+window_data+WDATA.fl_wstate], WSTATE_NORMAL + mov [ebx+window_data+WDATA.fl_redraw], 1 + add ebx, CURRENT_TASK ;ebx - pointer to information about process + mov [ebx+TASKDATA.wnd_number], al;set window number on screen = process slot + + mov [ebx+TASKDATA.event_mask], dword 1+2+4;set default event flags (see 40 function) + + inc dword [process_number] + mov eax, [process_number] + mov [ebx+4], eax ;set PID + +;set draw data to full screen + xor eax, eax + mov [ecx+0], dword eax + mov [ecx+4], dword eax + mov eax, [Screen_Max_X] + mov [ecx+8], eax + mov eax, [Screen_Max_Y] + mov [ecx+12], eax + + mov ebx, [pl0_stack] + mov esi, [params] + lea ecx, [ebx+REG_EIP] + xor eax, eax + + mov [ebx+REG_RET], edx + mov [ebx+REG_EDI], eax + mov [ebx+REG_ESI], eax + mov [ebx+REG_EBP], eax + mov [ebx+REG_ESP], ecx;ebx+REG_EIP + mov [ebx+REG_EBX], eax + mov [ebx+REG_EDX], eax + mov [ebx+REG_ECX], eax + mov [ebx+REG_EAX], eax + + mov eax, [esi+0x08] ;app_eip + mov [ebx+REG_EIP], eax;app_entry + mov [ebx+REG_CS], dword app_code + mov [ebx+REG_EFLAGS], dword EFL_IOPL1+EFL_IF + + mov eax, [esi+0x0C] ;app_esp + mov [ebx+REG_APP_ESP], eax;app_stack + mov [ebx+REG_SS], dword app_data + + lea ecx, [ebx+REG_RET] + mov ebx, [slot] + shl ebx, 5 + mov [ebx*8+SLOT_BASE+APPDATA.saved_esp], ecx + + xor ecx, ecx; process state - running +; set if debuggee + test byte [flags], 1 + jz .no_debug + inc ecx ; process state - suspended + mov eax, [CURRENT_TASK] + mov [SLOT_BASE+ebx*8+APPDATA.debugger_slot], eax +.no_debug: + mov [CURRENT_TASK+ebx+TASKDATA.state], cl + ;mov esi,new_process_running + ;call sys_msg_board_str ;output information about succefull startup + ret +endp + + +align 4 + +get_stack_base: + mov eax, [current_slot] + mov eax, [eax+APPDATA.pl0_stack] + ret + + +include "debug.inc" diff --git a/kernel/trunk/core/test_malloc.asm b/kernel/trunk/core/test_malloc.asm index 56e7ef2ee..c7b430824 100644 --- a/kernel/trunk/core/test_malloc.asm +++ b/kernel/trunk/core/test_malloc.asm @@ -1,223 +1,223 @@ -; Tests of malloc()/free() from the kernel heap. -; This file is not included in the kernel, it is just test application. -use32 - db 'MENUET01' - dd 1, start, i_end, mem, mem, 0, 0 - -start: -; Zero-initialize uglobals (as in kernel at boot) - mov ecx, (zeroend - zerostart + 3) / 4 - xor eax, eax - mov edi, zerostart - rep stosd -; Initialize small heap (as in kernel at boot) - call init_malloc -; Run tests - call run_test1 - call run_test2 - call run_test3 -; All is OK, return - or eax, -1 - int 0x40 - -run_test1: -; basic test - mov eax, 1 - call malloc_with_test - mov byte [eax], 0xDD - mov esi, eax - mov eax, 1 - call malloc_with_test - cmp byte [esi], 0xDD - jnz memory_destroyed - mov byte [eax], 0xEE - xchg eax, esi - call free - cmp byte [esi], 0xEE - jnz memory_destroyed - xchg eax, esi - call free - ret - -run_test2: - ret - -run_test3: -; 1024000 times run random operation. -; Randomly select malloc(random size from 1 to 1023) -; or free(random of previously allocated areas) - mov edi, 0x12345678 - xor esi, esi ; 0 areas allocated - mov ebx, 1024000 -.loop: - imul edi, 1103515245 - add edi, 12345 - mov eax, edi - shr eax, 16 - test ebx, 64 - jz .prefer_free -.prefer_malloc: - test eax, 3 - jz .free - jmp @f -.prefer_free: - test eax, 3 - jnz .free -@@: - shr eax, 2 - and eax, 1023 - jz .loop - push ebx - push eax -; mov ecx, [saved_state_num] -; mov [saved_state+ecx*8], eax - call malloc_with_test -; mov ecx, [saved_state_num] -; mov [saved_state+ecx*8+4], eax -; inc [saved_state_num] - pop ecx - pop ebx - inc esi - push ecx eax - push edi - mov edi, eax - mov eax, esi - rep stosb - pop edi - jmp .common -.free: - test esi, esi - jz .loop - xor edx, edx - div esi - sub edx, esi - neg edx - dec edx - mov eax, [esp+edx*8] -; mov ecx, [saved_state_num] -; mov [saved_state+ecx*8], -1 -; mov [saved_state+ecx*8+4], eax -; inc [saved_state_num] - mov ecx, [esp+edx*8+4] - push edi eax - mov edi, eax - mov al, [edi] - repz scasb - jnz memory_destroyed - pop eax edi - push ebx edx - call free - pop edx ebx - dec esi - pop eax ecx - push edi - lea edi, [esp+4] -@@: - dec edx - js @f - xchg eax, [edi] - xchg ecx, [edi+4] - add edi, 8 - jmp @b -@@: - pop edi -.common: - dec ebx - jnz .loop -@@: - dec esi - js @f - pop eax ecx - call free - jmp @b -@@: - ret - -malloc_with_test: -; calls malloc() and checks returned value - call malloc - test eax, eax - jz generic_malloc_fail - call check_mutex - call check_range - ret - -; Stubs for kernel procedures used by heap code -wait_mutex: - inc dword [ebx] - ret - -kernel_alloc: - cmp dword [esp+4], bufsize - jnz error1 - mov eax, buffer - ret 4 - -macro $Revision [args] -{ -} - -; Error handlers -error1: - mov eax, 1 - jmp error_with_code - -generic_malloc_fail: - mov eax, 2 - jmp error_with_code - -check_mutex: - cmp [mst.mutex], 0 - jnz @f - ret -@@: - mov eax, 3 - jmp error_with_code - -check_range: - cmp eax, buffer - jb @f - cmp eax, buffer+bufsize - jae @f - ret -@@: - mov eax, 4 - jmp error_with_code - -memory_destroyed: - mov eax, 5 - jmp error_with_code - -error_with_code: - mov edx, saved_state_num -; eax = error code -; 1 signals error in testing code (wrong bufsize) -; 2 = malloc() returned NULL -; 3 = mutex not released -; 4 = weird returned value from malloc() -; 5 = memory destroyed by malloc() or free() - int3 ; simplest way to report error - jmp $-1 ; just in case - -; Include main heap code -include '../proc32.inc' -include '../const.inc' -include 'malloc.inc' - -i_end: - -align 4 -zerostart: -mst MEM_STATE - -align 16 -bufsize = 0x40000 ; change if malloc.inc changes -buffer rb bufsize -zeroend: - -saved_state_num dd ? -saved_state rd 0x10000 - -align 4 - rb 0x10000 ; for stack -mem: +; Tests of malloc()/free() from the kernel heap. +; This file is not included in the kernel, it is just test application. +use32 + db 'MENUET01' + dd 1, start, i_end, mem, mem, 0, 0 + +start: +; Zero-initialize uglobals (as in kernel at boot) + mov ecx, (zeroend - zerostart + 3) / 4 + xor eax, eax + mov edi, zerostart + rep stosd +; Initialize small heap (as in kernel at boot) + call init_malloc +; Run tests + call run_test1 + call run_test2 + call run_test3 +; All is OK, return + or eax, -1 + int 0x40 + +run_test1: +; basic test + mov eax, 1 + call malloc_with_test + mov byte [eax], 0xDD + mov esi, eax + mov eax, 1 + call malloc_with_test + cmp byte [esi], 0xDD + jnz memory_destroyed + mov byte [eax], 0xEE + xchg eax, esi + call free + cmp byte [esi], 0xEE + jnz memory_destroyed + xchg eax, esi + call free + ret + +run_test2: + ret + +run_test3: +; 1024000 times run random operation. +; Randomly select malloc(random size from 1 to 1023) +; or free(random of previously allocated areas) + mov edi, 0x12345678 + xor esi, esi ; 0 areas allocated + mov ebx, 1024000 +.loop: + imul edi, 1103515245 + add edi, 12345 + mov eax, edi + shr eax, 16 + test ebx, 64 + jz .prefer_free +.prefer_malloc: + test eax, 3 + jz .free + jmp @f +.prefer_free: + test eax, 3 + jnz .free +@@: + shr eax, 2 + and eax, 1023 + jz .loop + push ebx + push eax +; mov ecx, [saved_state_num] +; mov [saved_state+ecx*8], eax + call malloc_with_test +; mov ecx, [saved_state_num] +; mov [saved_state+ecx*8+4], eax +; inc [saved_state_num] + pop ecx + pop ebx + inc esi + push ecx eax + push edi + mov edi, eax + mov eax, esi + rep stosb + pop edi + jmp .common +.free: + test esi, esi + jz .loop + xor edx, edx + div esi + sub edx, esi + neg edx + dec edx + mov eax, [esp+edx*8] +; mov ecx, [saved_state_num] +; mov [saved_state+ecx*8], -1 +; mov [saved_state+ecx*8+4], eax +; inc [saved_state_num] + mov ecx, [esp+edx*8+4] + push edi eax + mov edi, eax + mov al, [edi] + repz scasb + jnz memory_destroyed + pop eax edi + push ebx edx + call free + pop edx ebx + dec esi + pop eax ecx + push edi + lea edi, [esp+4] +@@: + dec edx + js @f + xchg eax, [edi] + xchg ecx, [edi+4] + add edi, 8 + jmp @b +@@: + pop edi +.common: + dec ebx + jnz .loop +@@: + dec esi + js @f + pop eax ecx + call free + jmp @b +@@: + ret + +malloc_with_test: +; calls malloc() and checks returned value + call malloc + test eax, eax + jz generic_malloc_fail + call check_mutex + call check_range + ret + +; Stubs for kernel procedures used by heap code +wait_mutex: + inc dword [ebx] + ret + +kernel_alloc: + cmp dword [esp+4], bufsize + jnz error1 + mov eax, buffer + ret 4 + +macro $Revision [args] +{ +} + +; Error handlers +error1: + mov eax, 1 + jmp error_with_code + +generic_malloc_fail: + mov eax, 2 + jmp error_with_code + +check_mutex: + cmp [mst.mutex], 0 + jnz @f + ret +@@: + mov eax, 3 + jmp error_with_code + +check_range: + cmp eax, buffer + jb @f + cmp eax, buffer+bufsize + jae @f + ret +@@: + mov eax, 4 + jmp error_with_code + +memory_destroyed: + mov eax, 5 + jmp error_with_code + +error_with_code: + mov edx, saved_state_num +; eax = error code +; 1 signals error in testing code (wrong bufsize) +; 2 = malloc() returned NULL +; 3 = mutex not released +; 4 = weird returned value from malloc() +; 5 = memory destroyed by malloc() or free() + int3 ; simplest way to report error + jmp $-1 ; just in case + +; Include main heap code +include '../proc32.inc' +include '../const.inc' +include 'malloc.inc' + +i_end: + +align 4 +zerostart: +mst MEM_STATE + +align 16 +bufsize = 0x40000 ; change if malloc.inc changes +buffer rb bufsize +zeroend: + +saved_state_num dd ? +saved_state rd 0x10000 + +align 4 + rb 0x10000 ; for stack +mem: diff --git a/kernel/trunk/core/timers.inc b/kernel/trunk/core/timers.inc index 873855183..7e11c1f03 100644 --- a/kernel/trunk/core/timers.inc +++ b/kernel/trunk/core/timers.inc @@ -1,205 +1,205 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; Simple implementation of timers. All timers are organized in a double-linked -; list, and the OS loop after every timer tick processes the list. - -; This structure describes a timer for the kernel. -struct TIMER -.Next dd ? -.Prev dd ? -; These fields organize a double-linked list of all timers. -.TimerFunc dd ? -; Function to be called when the timer is activated. -.UserData dd ? -; The value that is passed as is to .TimerFunc. -.Time dd ? -; Time at which the timer should be activated. -.Interval dd ? -; Interval between activations of the timer, in 0.01s. -ends - -iglobal -align 4 -; The head of timer list. -timer_list: - dd timer_list - dd timer_list -endg -uglobal -; These two variables are used to synchronize access to the global list. -; Logically, they form an recursive mutex. Physically, the first variable holds -; the slot number of the current owner or 0, the second variable holds the -; recursion count. -; The mutex should be recursive to allow a timer function to add/delete other -; timers or itself. -timer_list_owner dd 0 -timer_list_numlocks dd 0 -; A timer function can delete any timer, including itself and the next timer in -; the chain. To handle such situation correctly, we keep the next timer in a -; global variable, so the removing operation can update it. -timer_next dd 0 -endg - -; This internal function acquires the lock for the global list. -lock_timer_list: - mov edx, [CURRENT_TASK] -@@: - xor eax, eax -lock cmpxchg [timer_list_owner], edx - jz @f - cmp eax, edx - jz @f - call change_task - jmp @b -@@: - inc [timer_list_numlocks] - ret - -; This internal function releases the lock for the global list. -unlock_timer_list: - dec [timer_list_numlocks] - jnz .nothing - mov [timer_list_owner], 0 -.nothing: - ret - -; This function adds a timer. -; If deltaStart is nonzero, the timer is activated after deltaStart hundredths -; of seconds starting from the current time. If interval is nonzero, the timer -; is activated every deltaWork hundredths of seconds starting from the first -; activation. The activated timer calls timerFunc as stdcall function with one -; argument userData. -; Return value is NULL if something has failed or some value which is opaque -; for the caller. Later this value can be used for cancel_timer_hs. -proc timer_hs stdcall uses ebx, deltaStart:dword, interval:dword, \ - timerFunc:dword, userData:dword -; 1. Allocate memory for the TIMER structure. -; 1a. Call the allocator. - push sizeof.TIMER - pop eax - call malloc -; 1b. If allocation failed, return (go to 5) with eax = 0. - test eax, eax - jz .nothing -; 2. Setup the TIMER structure. - xchg ebx, eax -; 2a. Copy values from the arguments. - mov ecx, [interval] - mov [ebx+TIMER.Interval], ecx - mov ecx, [timerFunc] - mov [ebx+TIMER.TimerFunc], ecx - mov ecx, [userData] - mov [ebx+TIMER.UserData], ecx -; 2b. Get time of the next activation. - mov ecx, [deltaStart] - test ecx, ecx - jnz @f - mov ecx, [interval] -@@: - add ecx, [timer_ticks] - mov [ebx+TIMER.Time], ecx -; 3. Insert the TIMER structure to the global list. -; 3a. Acquire the lock. - call lock_timer_list -; 3b. Insert an item at ebx to the tail of the timer_list. - mov eax, timer_list - mov ecx, [eax+TIMER.Prev] - mov [ebx+TIMER.Next], eax - mov [ebx+TIMER.Prev], ecx - mov [eax+TIMER.Prev], ebx - mov [ecx+TIMER.Next], ebx -; 3c. Release the lock. - call unlock_timer_list -; 4. Return with eax = pointer to TIMER structure. - xchg ebx, eax -.nothing: -; 5. Returning. - ret -endp - -; This function removes a timer. -; The only argument is [esp+4] = the value which was returned from timer_hs. -cancel_timer_hs: - push ebx ; save used register to be stdcall -; 1. Remove the TIMER structure from the global list. -; 1a. Acquire the lock. - call lock_timer_list - mov ebx, [esp+4+4] -; 1b. Delete an item at ebx from the double-linked list. - mov eax, [ebx+TIMER.Next] - mov ecx, [ebx+TIMER.Prev] - mov [eax+TIMER.Prev], ecx - mov [ecx+TIMER.Next], eax -; 1c. If we are removing the next timer in currently processing chain, -; the next timer for this timer becomes new next timer. - cmp ebx, [timer_next] - jnz @f - mov [timer_next], eax -@@: -; 1d. Release the lock. - call unlock_timer_list -; 2. Free the TIMER structure. - xchg eax, ebx - call free -; 3. Return. - pop ebx ; restore used register to be stdcall - ret 4 ; purge one dword argument to be stdcall - -; This function is regularly called from osloop. It processes the global list -; and activates the corresponding timers. -check_timers: -; 1. Acquire the lock. - call lock_timer_list -; 2. Loop over all registered timers, checking time. -; 2a. Get the first item. - mov eax, [timer_list+TIMER.Next] - mov [timer_next], eax -.loop: -; 2b. Check for end of list. - cmp eax, timer_list - jz .done -; 2c. Get and store the next timer. - mov edx, [eax+TIMER.Next] - mov [timer_next], edx -; 2d. Check time for timer activation. -; We can't just compare [timer_ticks] and [TIMER.Time], since overflows are -; possible: if the current time is 0FFFFFFFFh ticks and timer should be -; activated in 3 ticks, the simple comparison will produce incorrect result. -; So we calculate the difference [timer_ticks] - [TIMER.Time]; if it is -; non-negative, the time is over; if it is negative, then either the time is -; not over or we have not processed this timer for 2^31 ticks, what is very -; unlikely. - mov edx, [timer_ticks] - sub edx, [eax+TIMER.Time] - js .next -; The timer should be activated now. -; 2e. Store the timer data in the stack. This is required since 2f can delete -; the timer, invalidating the content. - push [eax+TIMER.UserData] ; parameter for TimerFunc - push [eax+TIMER.TimerFunc] ; to be restored in 2g -; 2f. Calculate time of next activation or delete the timer if it is one-shot. - mov ecx, [eax+TIMER.Interval] - add [eax+TIMER.Time], ecx - test ecx, ecx - jnz .nodelete - stdcall cancel_timer_hs, eax -.nodelete: -; 2g. Activate timer, using data from the stack. - pop eax - call eax -.next: -; 2h. Advance to the next timer and continue the loop. - mov eax, [timer_next] - jmp .loop -.done: -; 3. Release the lock. - call unlock_timer_list -; 4. Return. - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; Simple implementation of timers. All timers are organized in a double-linked +; list, and the OS loop after every timer tick processes the list. + +; This structure describes a timer for the kernel. +struct TIMER +.Next dd ? +.Prev dd ? +; These fields organize a double-linked list of all timers. +.TimerFunc dd ? +; Function to be called when the timer is activated. +.UserData dd ? +; The value that is passed as is to .TimerFunc. +.Time dd ? +; Time at which the timer should be activated. +.Interval dd ? +; Interval between activations of the timer, in 0.01s. +ends + +iglobal +align 4 +; The head of timer list. +timer_list: + dd timer_list + dd timer_list +endg +uglobal +; These two variables are used to synchronize access to the global list. +; Logically, they form an recursive mutex. Physically, the first variable holds +; the slot number of the current owner or 0, the second variable holds the +; recursion count. +; The mutex should be recursive to allow a timer function to add/delete other +; timers or itself. +timer_list_owner dd 0 +timer_list_numlocks dd 0 +; A timer function can delete any timer, including itself and the next timer in +; the chain. To handle such situation correctly, we keep the next timer in a +; global variable, so the removing operation can update it. +timer_next dd 0 +endg + +; This internal function acquires the lock for the global list. +lock_timer_list: + mov edx, [CURRENT_TASK] +@@: + xor eax, eax + lock cmpxchg [timer_list_owner], edx + jz @f + cmp eax, edx + jz @f + call change_task + jmp @b +@@: + inc [timer_list_numlocks] + ret + +; This internal function releases the lock for the global list. +unlock_timer_list: + dec [timer_list_numlocks] + jnz .nothing + mov [timer_list_owner], 0 +.nothing: + ret + +; This function adds a timer. +; If deltaStart is nonzero, the timer is activated after deltaStart hundredths +; of seconds starting from the current time. If interval is nonzero, the timer +; is activated every deltaWork hundredths of seconds starting from the first +; activation. The activated timer calls timerFunc as stdcall function with one +; argument userData. +; Return value is NULL if something has failed or some value which is opaque +; for the caller. Later this value can be used for cancel_timer_hs. +proc timer_hs stdcall uses ebx, deltaStart:dword, interval:dword, \ + timerFunc:dword, userData:dword +; 1. Allocate memory for the TIMER structure. +; 1a. Call the allocator. + push sizeof.TIMER + pop eax + call malloc +; 1b. If allocation failed, return (go to 5) with eax = 0. + test eax, eax + jz .nothing +; 2. Setup the TIMER structure. + xchg ebx, eax +; 2a. Copy values from the arguments. + mov ecx, [interval] + mov [ebx+TIMER.Interval], ecx + mov ecx, [timerFunc] + mov [ebx+TIMER.TimerFunc], ecx + mov ecx, [userData] + mov [ebx+TIMER.UserData], ecx +; 2b. Get time of the next activation. + mov ecx, [deltaStart] + test ecx, ecx + jnz @f + mov ecx, [interval] +@@: + add ecx, [timer_ticks] + mov [ebx+TIMER.Time], ecx +; 3. Insert the TIMER structure to the global list. +; 3a. Acquire the lock. + call lock_timer_list +; 3b. Insert an item at ebx to the tail of the timer_list. + mov eax, timer_list + mov ecx, [eax+TIMER.Prev] + mov [ebx+TIMER.Next], eax + mov [ebx+TIMER.Prev], ecx + mov [eax+TIMER.Prev], ebx + mov [ecx+TIMER.Next], ebx +; 3c. Release the lock. + call unlock_timer_list +; 4. Return with eax = pointer to TIMER structure. + xchg ebx, eax +.nothing: +; 5. Returning. + ret +endp + +; This function removes a timer. +; The only argument is [esp+4] = the value which was returned from timer_hs. +cancel_timer_hs: + push ebx ; save used register to be stdcall +; 1. Remove the TIMER structure from the global list. +; 1a. Acquire the lock. + call lock_timer_list + mov ebx, [esp+4+4] +; 1b. Delete an item at ebx from the double-linked list. + mov eax, [ebx+TIMER.Next] + mov ecx, [ebx+TIMER.Prev] + mov [eax+TIMER.Prev], ecx + mov [ecx+TIMER.Next], eax +; 1c. If we are removing the next timer in currently processing chain, +; the next timer for this timer becomes new next timer. + cmp ebx, [timer_next] + jnz @f + mov [timer_next], eax +@@: +; 1d. Release the lock. + call unlock_timer_list +; 2. Free the TIMER structure. + xchg eax, ebx + call free +; 3. Return. + pop ebx ; restore used register to be stdcall + ret 4 ; purge one dword argument to be stdcall + +; This function is regularly called from osloop. It processes the global list +; and activates the corresponding timers. +check_timers: +; 1. Acquire the lock. + call lock_timer_list +; 2. Loop over all registered timers, checking time. +; 2a. Get the first item. + mov eax, [timer_list+TIMER.Next] + mov [timer_next], eax +.loop: +; 2b. Check for end of list. + cmp eax, timer_list + jz .done +; 2c. Get and store the next timer. + mov edx, [eax+TIMER.Next] + mov [timer_next], edx +; 2d. Check time for timer activation. +; We can't just compare [timer_ticks] and [TIMER.Time], since overflows are +; possible: if the current time is 0FFFFFFFFh ticks and timer should be +; activated in 3 ticks, the simple comparison will produce incorrect result. +; So we calculate the difference [timer_ticks] - [TIMER.Time]; if it is +; non-negative, the time is over; if it is negative, then either the time is +; not over or we have not processed this timer for 2^31 ticks, what is very +; unlikely. + mov edx, [timer_ticks] + sub edx, [eax+TIMER.Time] + js .next +; The timer should be activated now. +; 2e. Store the timer data in the stack. This is required since 2f can delete +; the timer, invalidating the content. + push [eax+TIMER.UserData] ; parameter for TimerFunc + push [eax+TIMER.TimerFunc] ; to be restored in 2g +; 2f. Calculate time of next activation or delete the timer if it is one-shot. + mov ecx, [eax+TIMER.Interval] + add [eax+TIMER.Time], ecx + test ecx, ecx + jnz .nodelete + stdcall cancel_timer_hs, eax +.nodelete: +; 2g. Activate timer, using data from the stack. + pop eax + call eax +.next: +; 2h. Advance to the next timer and continue the loop. + mov eax, [timer_next] + jmp .loop +.done: +; 3. Release the lock. + call unlock_timer_list +; 4. Return. + ret diff --git a/kernel/trunk/core/v86.inc b/kernel/trunk/core/v86.inc index 1c96fe475..a941b9691 100644 --- a/kernel/trunk/core/v86.inc +++ b/kernel/trunk/core/v86.inc @@ -1,931 +1,932 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; Virtual-8086 mode manager -; diamond, 2007, 2008 - -DEBUG_SHOW_IO = 0 - -struc V86_machine -{ -; page directory - .pagedir dd ? -; translation table: V86 address -> flat linear address - .pages dd ? -; mutex to protect all data from writing by multiple threads at one time - .mutex dd ? -; i/o permission map - .iopm dd ? -.size = $ -} -virtual at 0 -V86_machine V86_machine -end virtual - -; Create V86 machine -; in: nothing -; out: eax = handle (pointer to struc V86_machine) -; eax = NULL => failure -; destroys: ebx, ecx, edx (due to malloc) -v86_create: -; allocate V86_machine structure - mov eax, V86_machine.size - call malloc - test eax, eax - jz .fail -; initialize mutex - and dword [eax+V86_machine.mutex], 0 -; allocate tables - mov ebx, eax -; We allocate 4 pages. -; First is main page directory for V86 mode. -; Second page: -; first half (0x800 bytes) is page table for addresses 0 - 0x100000, -; second half is for V86-to-linear translation. -; Third and fourth are for I/O permission map. - push 8000h ; blocks less than 8 pages are discontinuous - call kernel_alloc - test eax, eax - jz .fail2 - mov [ebx+V86_machine.pagedir], eax - push edi eax - mov edi, eax - add eax, 1800h - mov [ebx+V86_machine.pages], eax -; initialize tables - mov ecx, 2000h/4 - xor eax, eax - rep stosd - mov [ebx+V86_machine.iopm], edi - dec eax - mov ecx, 2000h/4 - rep stosd - pop eax -; page directory: first entry is page table... - mov edi, eax - add eax, 1000h - push eax - call get_pg_addr - or al, PG_UW - stosd -; ...and also copy system page tables -; thx to Serge, system is located at high addresses - add edi, (OS_BASE shr 20) - 4 - push esi - mov esi, (OS_BASE shr 20) + sys_pgdir - mov ecx, 0x80000000 shr 22 - rep movsd - - mov eax, [ebx+V86_machine.pagedir] ;root dir also is - call get_pg_addr ;used as page table - or al, PG_SW - mov [edi-4096+(page_tabs shr 20)], eax - - pop esi -; now V86 specific: initialize known addresses in first Mb - pop eax -; first page - BIOS data (shared between all machines!) -; physical address = 0 -; linear address = OS_BASE - mov dword [eax], 111b - mov dword [eax+800h], OS_BASE -; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!) -; physical address = 0x9C000 -; linear address = 0x8009C000 -; (I have seen one computer with EBDA segment = 0x9D80, -; all other computers use less memory) - mov ecx, 4 - mov edx, 0x9C000 - push eax - lea edi, [eax+0x9C*4] -@@: - lea eax, [edx + OS_BASE] - mov [edi+800h], eax - lea eax, [edx + 111b] - stosd - add edx, 0x1000 - loop @b - pop eax - pop edi -; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!) -; physical address = 0xC0000 -; linear address = 0x800C0000 - mov ecx, 0xC0 -@@: - mov edx, ecx - shl edx, 12 - push edx - or edx, 111b - mov [eax+ecx*4], edx - pop edx - add edx, OS_BASE - mov [eax+ecx*4+0x800], edx - inc cl - jnz @b - mov eax, ebx - ret -.fail2: - mov eax, ebx - call free -.fail: - xor eax, eax - ret - -; Destroy V86 machine -; in: eax = handle -; out: nothing -; destroys: eax, ebx, ecx, edx (due to free) -v86_destroy: - push eax - stdcall kernel_free, [eax+V86_machine.pagedir] - pop eax - jmp free - -; Translate V86-address to linear address -; in: eax=V86 address -; esi=handle -; out: eax=linear address -; destroys: nothing -v86_get_lin_addr: - push ecx edx - mov ecx, eax - mov edx, [esi+V86_machine.pages] - shr ecx, 12 - and eax, 0xFFF - add eax, [edx+ecx*4] ; atomic operation, no mutex needed - pop edx ecx - ret - -; Sets linear address for V86-page -; in: eax=linear address (must be page-aligned) -; ecx=V86 page (NOT address!) -; esi=handle -; out: nothing -; destroys: nothing -v86_set_page: - push eax ebx - mov ebx, [esi+V86_machine.pagedir] - mov [ebx+ecx*4+0x1800], eax - call get_pg_addr - or al, 111b - mov [ebx+ecx*4+0x1000], eax - pop ebx eax - ret - -; Allocate memory in V86 machine -; in: eax=size (in bytes) -; esi=handle -; out: eax=V86 address, para-aligned (0x10 multiple) -; destroys: nothing -; ­Ґ¤®ЇЁб ­ !!! -;v86_alloc: -; push ebx ecx edx edi -; lea ebx, [esi+V86_machine.mutex] -; call wait_mutex -; add eax, 0x1F -; shr eax, 4 -; mov ebx, 0x1000 ; start with address 0x1000 (second page) -; mov edi, [esi+V86_machine.tables] -;.l: -; mov ecx, ebx -; shr ecx, 12 -; mov edx, [edi+0x1000+ecx*4] ; get linear address -; test edx, edx ; page allocated? -; jz .unalloc -; mov ecx, ebx -; and ecx, 0xFFF -; add edx, ecx -; cmp dword [edx], 0 ; free block? -; jnz .n -; cmp dword [edx+4], -; and [esi+V86_machine.mutex], 0 -; pop edi edx ecx ebx -; ret - -uglobal -sys_v86_machine dd ? -endg - -; Called from kernel.asm at first stages of loading -; Initialize system V86 machine (used to simulate BIOS int 13h) -init_sys_v86: - call v86_create - mov [sys_v86_machine], eax - test eax, eax - jz .ret - mov byte [OS_BASE + 0x500], 0xCD - mov byte [OS_BASE + 0x501], 0x13 - mov byte [OS_BASE + 0x502], 0xF4 - mov byte [OS_BASE + 0x503], 0xCD - mov byte [OS_BASE + 0x504], 0x10 - mov byte [OS_BASE + 0x505], 0xF4 - mov esi, eax - mov ebx, [eax+V86_machine.pagedir] -; one page for stack, two pages for results (0x2000 bytes = 16 sectors) - mov dword [ebx+0x99*4+0x1000], 0x99000 or 111b - mov dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000 - mov dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b - mov dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000 - mov dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b - mov dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000 -if ~DEBUG_SHOW_IO -; allow access to all ports - mov ecx, [esi+V86_machine.iopm] - xor eax, eax - mov edi, ecx - mov ecx, 10000h/8/4 - rep stosd -end if -.ret: - ret - -struc v86_regs -{ -; don't change the order, it is important - .edi dd ? - .esi dd ? - .ebp dd ? - dd ? ; ignored - .ebx dd ? - .edx dd ? - .ecx dd ? - .eax dd ? - .eip dd ? - .cs dd ? - .eflags dd ? ; VM flag must be set! - .esp dd ? - .ss dd ? - .es dd ? - .ds dd ? - .fs dd ? - .gs dd ? -.size = $ -} -virtual at 0 -v86_regs v86_regs -end virtual - -; Run V86 machine -; in: ebx -> registers for V86 (two structures: in and out) -; esi = handle -; ecx = expected end address (CS:IP) -; edx = IRQ to hook or -1 if not required -; out: structure pointed to by ebx is filled with new values -; eax = 1 - exception has occured, cl contains code -; eax = 2 - access to disabled i/o port, ecx contains port address -; eax = 3 - IRQ is already hooked by another VM -; destroys: nothing -v86_start: - pushad - - cli - - mov ecx, [CURRENT_TASK] - shl ecx, 8 - add ecx, SLOT_BASE - - mov eax, [esi+V86_machine.iopm] - call get_pg_addr - inc eax - push dword [ecx+APPDATA.io_map] - push dword [ecx+APPDATA.io_map+4] - mov dword [ecx+APPDATA.io_map], eax - mov dword [page_tabs + (tss._io_map_0 shr 10)], eax - add eax, 0x1000 - mov dword [ecx+APPDATA.io_map+4], eax - mov dword [page_tabs + (tss._io_map_1 shr 10)], eax - - push [ecx+APPDATA.dir_table] - push [ecx+APPDATA.saved_esp0] - mov [ecx+APPDATA.saved_esp0], esp - mov [tss._esp0], esp - - mov eax, [esi+V86_machine.pagedir] - call get_pg_addr - mov [ecx+APPDATA.dir_table], eax - mov cr3, eax - -; mov [irq_tab+5*4], my05 - -; We do not enable interrupts, because V86 IRQ redirector assumes that -; machine is running -; They will be enabled by IRET. -; sti - - mov eax, esi - sub esp, v86_regs.size - mov esi, ebx - mov edi, esp - mov ecx, v86_regs.size/4 - rep movsd - - cmp edx, -1 - jz .noirqhook -uglobal -v86_irqhooks rd IRQ_RESERVED * 2 -endg - cmp [v86_irqhooks+edx*8], 0 - jz @f - cmp [v86_irqhooks+edx*8], eax - jz @f - mov esi, v86_irqerr - call sys_msg_board_str - inc [v86_irqhooks+edx*8+4] - mov eax, 3 - jmp v86_exc_c.exit -@@: - mov [v86_irqhooks+edx*8], eax - inc [v86_irqhooks+edx*8+4] -.noirqhook: - - popad - iretd - -; It is only possible to leave virtual-8086 mode by faulting to -; a protected-mode interrupt handler (typically the general-protection -; exception handler, which in turn calls the virtual 8086-mode monitor). - -iglobal - v86_exc_str1 db 'V86 : unexpected exception ',0 - v86_exc_str2 db ' at ',0 - v86_exc_str3 db ':',0 - v86_exc_str4 db 13,10,'V86 : faulted code:',0 - v86_exc_str5 db ' (unavailable)',0 - v86_newline db 13,10,0 - v86_io_str1 db 'V86 : access to disabled i/o port ',0 - v86_io_byte db ' (byte)',13,10,0 - v86_io_word db ' (word)',13,10,0 - v86_io_dword db ' (dword)',13,10,0 - v86_irqerr db 'V86 : IRQ already hooked',13,10,0 -endg - -v86_exc_c: -; Did we all that we have wanted to do? - cmp bl,1 - jne @f - xor eax, eax - mov dr6, eax - @@: mov eax, [esp+v86_regs.size+10h+18h] - cmp word [esp+v86_regs.eip], ax - jnz @f - shr eax, 16 - cmp word [esp+v86_regs.cs], ax - jz .done -@@: -; Various system events, which must be handled, result in #GP - cmp bl, 13 - jnz .nogp -; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error - cmp word [esp+v86_regs.eip+2], 0 - jnz .nogp -; Otherwise we can safely access byte at CS:IP -; (because it is #GP, not #PF handler) -; …б«Ё Ўл ¬л ¬®Ј«Ё бе«®Ї®в вм ЁбЄ«о祭ЁҐ в®«мЄ® Ё§-§  з⥭Ёп Ў ©в®ў Є®¤ , -; ¬л Ўл ҐЈ® 㦥 бе«®Ї®в «Ё Ё нв® Ўл«® Ўл ­Ґ #GP - movzx esi, word [esp+v86_regs.cs] - shl esi, 4 - add esi, [esp+v86_regs.eip] - lodsb - cmp al, 0xCD ; int xx command = CD xx - jz .handle_int - cmp al, 0xCF - jz .handle_iret - cmp al, 0xF3 - jz .handle_rep - cmp al, 0xEC - jz .handle_in - cmp al, 0xED - jz .handle_in_word - cmp al, 0xEE - jz .handle_out - cmp al, 0xEF - jz .handle_out_word - cmp al, 0xE4 - jz .handle_in_imm - cmp al, 0xE6 - jz .handle_out_imm - cmp al, 0x9C - jz .handle_pushf - cmp al, 0x9D - jz .handle_popf - cmp al, 0xFA - jz .handle_cli - cmp al, 0xFB - jz .handle_sti - cmp al, 0x66 - jz .handle_66 - jmp .nogp -.handle_int: - cmp word [esp+v86_regs.eip], 0xFFFF - jae .nogp - xor eax, eax - lodsb -; call sys_msg_board_byte -; simulate INT command -; N.B. It is possible that some checks need to be corrected, -; but at least in case of normal execution the code works. -.simulate_int: - cmp word [esp+v86_regs.esp], 6 - jae @f - mov bl, 12 ; #SS exception - jmp .nogp -@@: - movzx edx, word [esp+v86_regs.ss] - shl edx, 4 - push eax - movzx eax, word [esp+4+v86_regs.esp] - sub eax, 6 - add edx, eax - mov eax, edx - mov esi, [esp+4+v86_regs.size+10h+4] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 ; #PF exception - jmp .nogp -@@: - lea eax, [edx+5] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 ; #PF exception - jmp .nogp -@@: - sub word [esp+4+v86_regs.esp], 6 - mov eax, [esp+4+v86_regs.eip] - cmp byte [esp+1], 0 - jnz @f - inc eax - inc eax -@@: - mov word [edx], ax - mov eax, [esp+4+v86_regs.cs] - mov word [edx+2], ax - mov eax, [esp+4+v86_regs.eflags] - mov word [edx+4], ax - pop eax - mov ah, 0 - mov cx, [eax*4] - mov word [esp+v86_regs.eip], cx - mov cx, [eax*4+2] - mov word [esp+v86_regs.cs], cx -; note that interrupts will be disabled globally at IRET - and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags -; continue V86 execution - popad - iretd -.handle_iret: - cmp word [esp+v86_regs.esp], 0x10000 - 6 - jbe @f - mov bl, 12 - jmp .nogp -@@: - movzx edx, word [esp+v86_regs.ss] - shl edx, 4 - movzx eax, word [esp+v86_regs.esp] - add edx, eax - mov eax, edx - mov esi, [esp+v86_regs.size+10h+4] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 - jmp .nogp -@@: - lea eax, [edx+5] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 - jmp .nogp -@@: - mov ax, [edx] - mov word [esp+v86_regs.eip], ax - mov ax, [edx+2] - mov word [esp+v86_regs.cs], ax - mov ax, [edx+4] - mov word [esp+v86_regs.eflags], ax - add word [esp+v86_regs.esp], 6 - popad - iretd -.handle_pushf: - cmp word [esp+v86_regs.esp], 1 - jnz @f - mov bl, 12 - jmp .nogp -@@: - movzx edx, word [esp+v86_regs.ss] - shl edx, 4 - mov eax, [esp+v86_regs.esp] - sub eax, 2 - movzx eax, ax - add edx, eax - mov eax, edx - mov esi, [esp+v86_regs.size+10h+4] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 ; #PF exception - jmp .nogp -@@: - lea eax, [edx+1] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 - jmp .nogp -@@: - sub word [esp+v86_regs.esp], 2 - mov eax, [esp+v86_regs.eflags] - mov [edx], ax - inc word [esp+v86_regs.eip] - popad - iretd -.handle_pushfd: - cmp word [esp+v86_regs.esp], 4 - jae @f - mov bl, 12 ; #SS exception - jmp .nogp -@@: - movzx edx, word [esp+v86_regs.ss] - shl edx, 4 - movzx eax, word [esp+v86_regs.esp] - sub eax, 4 - add edx, eax - mov eax, edx - mov esi, [esp+v86_regs.size+10h+4] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 ; #PF exception - jmp .nogp -@@: - lea eax, [edx+3] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 ; #PF exception - jmp .nogp -@@: - sub word [esp+v86_regs.esp], 4 - movzx eax, word [esp+v86_regs.eflags] - mov [edx], eax - add word [esp+v86_regs.eip], 2 - popad - iretd -.handle_popf: - cmp word [esp+v86_regs.esp], 0xFFFF - jnz @f - mov bl, 12 - jmp .nogp -@@: - movzx edx, word [esp+v86_regs.ss] - shl edx, 4 - movzx eax, word [esp+v86_regs.esp] - add edx, eax - mov eax, edx - mov esi, [esp+v86_regs.size+10h+4] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 ; #PF exception - jmp .nogp -@@: - lea eax, [edx+1] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 - jmp .nogp -@@: - mov ax, [edx] - mov word [esp+v86_regs.eflags], ax - add word [esp+v86_regs.esp], 2 - inc word [esp+v86_regs.eip] - popad - iretd -.handle_popfd: - cmp word [esp+v86_regs.esp], 0x10000 - 4 - jbe @f - mov bl, 12 - jmp .nogp -@@: - movzx edx, word [esp+v86_regs.ss] - shl edx, 4 - movzx eax, word [esp+v86_regs.esp] - add edx, eax - mov eax, edx - mov esi, [esp+v86_regs.size+10h+4] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 - jmp .nogp -@@: - lea eax, [edx+3] - call v86_get_lin_addr - cmp eax, 0x1000 - jae @f - mov bl, 14 - jmp .nogp -@@: - mov eax, [edx] - mov word [esp+v86_regs.eflags], ax - add word [esp+v86_regs.esp], 4 - add word [esp+v86_regs.eip], 2 - popad - iretd -.handle_cli: - and byte [esp+v86_regs.eflags+1], not 2 - inc word [esp+v86_regs.eip] - popad - iretd -.handle_sti: - or byte [esp+v86_regs.eflags+1], 2 - inc word [esp+v86_regs.eip] - popad - iretd -.handle_rep: - cmp word [esp+v86_regs.eip], 0xFFFF - jae .nogp - lodsb - cmp al, 6Eh - jz .handle_rep_outsb - jmp .nogp -.handle_rep_outsb: -.handle_in: -.handle_out: -.invalid_io_byte: - movzx ebx, word [esp+v86_regs.edx] - mov ecx, 1 - jmp .invalid_io -.handle_in_imm: -.handle_out_imm: - cmp word [esp+v86_regs.eip], 0xFFFF - jae .nogp - lodsb - movzx ebx, al - mov ecx, 1 - jmp .invalid_io -.handle_66: - cmp word [esp+v86_regs.eip], 0xFFFF - jae .nogp - lodsb - cmp al, 0x9C - jz .handle_pushfd - cmp al, 0x9D - jz .handle_popfd - cmp al, 0xEF - jz .handle_out_dword - cmp al, 0xED - jz .handle_in_dword - jmp .nogp -.handle_in_word: -.handle_out_word: - movzx ebx, word [esp+v86_regs.edx] - mov ecx, 2 - jmp .invalid_io -.handle_in_dword: -.handle_out_dword: -.invalid_io_dword: - movzx ebx, word [esp+v86_regs.edx] - mov ecx, 4 -.invalid_io: - mov esi, v86_io_str1 - call sys_msg_board_str - mov eax, ebx - call sys_msg_board_dword - mov esi, v86_io_byte - cmp ecx, 1 - jz @f - mov esi, v86_io_word - cmp ecx, 2 - jz @f - mov esi, v86_io_dword -@@: - call sys_msg_board_str -if DEBUG_SHOW_IO - mov edx, ebx - mov ebx, 200 - call delay_hs - mov esi, [esp+v86_regs.size+10h+4] - mov eax, [esi+V86_machine.iopm] -@@: - btr [eax], edx - inc edx - loop @b - popad - iretd -else - mov eax, 2 - jmp .exit -end if -.nogp: - - mov esi, v86_exc_str1 - call sys_msg_board_str - mov al, bl - call sys_msg_board_byte - mov esi, v86_exc_str2 - call sys_msg_board_str - mov ax, [esp+32+4] - call sys_msg_board_word - mov esi, v86_exc_str3 - call sys_msg_board_str - mov ax, [esp+32] - call sys_msg_board_word - mov esi, v86_exc_str4 - call sys_msg_board_str - mov ecx, 8 - movzx edx, word [esp+32+4] - shl edx, 4 - add edx, [esp+32] -@@: - mov esi, [esp+v86_regs.size+10h+4] - mov eax, edx - call v86_get_lin_addr - cmp eax, 0x1000 - jb .nopage - mov esi, v86_exc_str3-2 - call sys_msg_board_str - mov al, [edx] - call sys_msg_board_byte - inc edx - loop @b - jmp @f -.nopage: - mov esi, v86_exc_str5 - call sys_msg_board_str -@@: - mov esi, v86_newline - call sys_msg_board_str - mov eax, 1 - jmp .exit - -.done: - xor eax, eax - -.exit: - mov [esp+v86_regs.size+10h+1Ch], eax - mov [esp+v86_regs.size+10h+18h], ebx - - mov edx, [esp+v86_regs.size+10h+14h] - cmp edx, -1 - jz @f - dec [v86_irqhooks+edx*8+4] - jnz @f - and [v86_irqhooks+edx*8], 0 -@@: - - mov esi, esp - mov edi, [esi+v86_regs.size+10h+10h] - add edi, v86_regs.size - mov ecx, v86_regs.size/4 - rep movsd - mov esp, esi - - cli - mov ecx, [CURRENT_TASK] - shl ecx, 8 - pop eax - mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax - mov [tss._esp0], eax - pop eax - mov [SLOT_BASE+ecx+APPDATA.dir_table], eax - pop ebx - mov dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx - mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx - pop ebx - mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx - mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx - mov cr3, eax - sti - - popad - ret - -;my05: -; mov dx, 30C2h -; mov cx, 4 -;.0: -; in al, dx -; cmp al, 0FFh -; jz @f -; test al, 4 -; jnz .1 -;@@: -; add dx, 8 -; in al, dx -; cmp al, 0FFh -; jz @f -; test al, 4 -; jnz .1 -;@@: -; loop .0 -; ret -;.1: -; or al, 84h -; out dx, al -;.2: -; mov dx, 30F7h -; in al, dx -; mov byte [BOOT_VAR + 48Eh], 0FFh -; ret - -align 4 -v86_irq: -; push irq/pushad/jmp v86_irq -; ebp = irq - lea esi, [esp+1Ch] - lea edi, [esi+4] - mov ecx, 8 - std - rep movsd - cld - mov edi, ebp - pop eax -v86_irq2: - mov esi, [v86_irqhooks+edi*8] ; get VM handle - mov eax, [esi+V86_machine.pagedir] - call get_pg_addr - mov ecx, [CURRENT_TASK] - shl ecx, 8 - cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax - jnz .notcurrent - lea eax, [edi+8] - cmp al, 10h - mov ah, 1 - jb @f - add al, 60h -@@: - jmp v86_exc_c.simulate_int -.notcurrent: - mov ebx, SLOT_BASE + 0x100 - mov ecx, [TASK_COUNT] -.scan: - cmp [ebx+APPDATA.dir_table], eax - jnz .cont - push ecx - mov ecx, [ebx+APPDATA.saved_esp0] - cmp word [ecx-v86_regs.size+v86_regs.esp], 6 - jb .cont2 - movzx edx, word [ecx-v86_regs.size+v86_regs.ss] - shl edx, 4 - push eax - movzx eax, word [ecx-v86_regs.size+v86_regs.esp] - sub eax, 6 - add edx, eax - mov eax, edx - call v86_get_lin_addr - cmp eax, 0x1000 - jb .cont3 - lea eax, [edx+5] - call v86_get_lin_addr - cmp eax, 0x1000 - jb .cont3 - pop eax - pop ecx - jmp .found -.cont3: - pop eax -.cont2: - pop ecx -.cont: - loop .scan - mov ecx, edi - call irq_eoi - popad - iretd -.found: - mov cr3, eax - sub word [esi-v86_regs.size+v86_regs.esp], 6 - mov ecx, [esi-v86_regs.size+v86_regs.eip] - mov word [edx], cx - mov ecx, [esi-v86_regs.size+v86_regs.cs] - mov word [edx+2], cx - mov ecx, [esi-v86_regs.size+v86_regs.eflags] - mov word [edx+4], cx - lea eax, [edi+8] - cmp al, 10h - jb @f - add al, 60h -@@: - mov cx, [eax*4] - mov word [esi-v86_regs.size+v86_regs.eip], cx - mov cx, [eax*4+2] - mov word [esi-v86_regs.size+v86_regs.cs], cx - and byte [esi-v86_regs.size+v86_regs.eflags+1], not 3 - call update_counters - lea edi, [ebx + 0x100000000 - SLOT_BASE] - shr edi, 3 - add edi, TASK_DATA - call find_next_task.found - call do_change_task - popad - iretd +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; Virtual-8086 mode manager +; diamond, 2007, 2008 + +DEBUG_SHOW_IO = 0 + +struc V86_machine +{ +; page directory + .pagedir dd ? +; translation table: V86 address -> flat linear address + .pages dd ? +; mutex to protect all data from writing by multiple threads at one time + .mutex dd ? +; i/o permission map + .iopm dd ? +.size = $ +} +virtual at 0 +V86_machine V86_machine +end virtual + +; Create V86 machine +; in: nothing +; out: eax = handle (pointer to struc V86_machine) +; eax = NULL => failure +; destroys: ebx, ecx, edx (due to malloc) +v86_create: +; allocate V86_machine structure + mov eax, V86_machine.size + call malloc + test eax, eax + jz .fail +; initialize mutex + and dword [eax+V86_machine.mutex], 0 +; allocate tables + mov ebx, eax +; We allocate 4 pages. +; First is main page directory for V86 mode. +; Second page: +; first half (0x800 bytes) is page table for addresses 0 - 0x100000, +; second half is for V86-to-linear translation. +; Third and fourth are for I/O permission map. + push 8000h ; blocks less than 8 pages are discontinuous + call kernel_alloc + test eax, eax + jz .fail2 + mov [ebx+V86_machine.pagedir], eax + push edi eax + mov edi, eax + add eax, 1800h + mov [ebx+V86_machine.pages], eax +; initialize tables + mov ecx, 2000h/4 + xor eax, eax + rep stosd + mov [ebx+V86_machine.iopm], edi + dec eax + mov ecx, 2000h/4 + rep stosd + pop eax +; page directory: first entry is page table... + mov edi, eax + add eax, 1000h + push eax + call get_pg_addr + or al, PG_UW + stosd +; ...and also copy system page tables +; thx to Serge, system is located at high addresses + add edi, (OS_BASE shr 20) - 4 + push esi + mov esi, (OS_BASE shr 20) + sys_pgdir + mov ecx, 0x80000000 shr 22 + rep movsd + + mov eax, [ebx+V86_machine.pagedir] ;root dir also is + call get_pg_addr ;used as page table + or al, PG_SW + mov [edi-4096+(page_tabs shr 20)], eax + + pop esi +; now V86 specific: initialize known addresses in first Mb + pop eax +; first page - BIOS data (shared between all machines!) +; physical address = 0 +; linear address = OS_BASE + mov dword [eax], 111b + mov dword [eax+800h], OS_BASE +; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!) +; physical address = 0x9C000 +; linear address = 0x8009C000 +; (I have seen one computer with EBDA segment = 0x9D80, +; all other computers use less memory) + mov ecx, 4 + mov edx, 0x9C000 + push eax + lea edi, [eax+0x9C*4] +@@: + lea eax, [edx + OS_BASE] + mov [edi+800h], eax + lea eax, [edx + 111b] + stosd + add edx, 0x1000 + loop @b + pop eax + pop edi +; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!) +; physical address = 0xC0000 +; linear address = 0x800C0000 + mov ecx, 0xC0 +@@: + mov edx, ecx + shl edx, 12 + push edx + or edx, 111b + mov [eax+ecx*4], edx + pop edx + add edx, OS_BASE + mov [eax+ecx*4+0x800], edx + inc cl + jnz @b + mov eax, ebx + ret +.fail2: + mov eax, ebx + call free +.fail: + xor eax, eax + ret + +; Destroy V86 machine +; in: eax = handle +; out: nothing +; destroys: eax, ebx, ecx, edx (due to free) +v86_destroy: + push eax + stdcall kernel_free, [eax+V86_machine.pagedir] + pop eax + jmp free + +; Translate V86-address to linear address +; in: eax=V86 address +; esi=handle +; out: eax=linear address +; destroys: nothing +v86_get_lin_addr: + push ecx edx + mov ecx, eax + mov edx, [esi+V86_machine.pages] + shr ecx, 12 + and eax, 0xFFF + add eax, [edx+ecx*4] ; atomic operation, no mutex needed + pop edx ecx + ret + +; Sets linear address for V86-page +; in: eax=linear address (must be page-aligned) +; ecx=V86 page (NOT address!) +; esi=handle +; out: nothing +; destroys: nothing +v86_set_page: + push eax ebx + mov ebx, [esi+V86_machine.pagedir] + mov [ebx+ecx*4+0x1800], eax + call get_pg_addr + or al, 111b + mov [ebx+ecx*4+0x1000], eax + pop ebx eax + ret + +; Allocate memory in V86 machine +; in: eax=size (in bytes) +; esi=handle +; out: eax=V86 address, para-aligned (0x10 multiple) +; destroys: nothing +; ­Ґ¤®ЇЁб ­ !!! +;v86_alloc: +; push ebx ecx edx edi +; lea ebx, [esi+V86_machine.mutex] +; call wait_mutex +; add eax, 0x1F +; shr eax, 4 +; mov ebx, 0x1000 ; start with address 0x1000 (second page) +; mov edi, [esi+V86_machine.tables] +;.l: +; mov ecx, ebx +; shr ecx, 12 +; mov edx, [edi+0x1000+ecx*4] ; get linear address +; test edx, edx ; page allocated? +; jz .unalloc +; mov ecx, ebx +; and ecx, 0xFFF +; add edx, ecx +; cmp dword [edx], 0 ; free block? +; jnz .n +; cmp dword [edx+4], +; and [esi+V86_machine.mutex], 0 +; pop edi edx ecx ebx +; ret + +uglobal +sys_v86_machine dd ? +endg + +; Called from kernel.asm at first stages of loading +; Initialize system V86 machine (used to simulate BIOS int 13h) +init_sys_v86: + call v86_create + mov [sys_v86_machine], eax + test eax, eax + jz .ret + mov byte [OS_BASE + 0x500], 0xCD + mov byte [OS_BASE + 0x501], 0x13 + mov byte [OS_BASE + 0x502], 0xF4 + mov byte [OS_BASE + 0x503], 0xCD + mov byte [OS_BASE + 0x504], 0x10 + mov byte [OS_BASE + 0x505], 0xF4 + mov esi, eax + mov ebx, [eax+V86_machine.pagedir] +; one page for stack, two pages for results (0x2000 bytes = 16 sectors) + mov dword [ebx+0x99*4+0x1000], 0x99000 or 111b + mov dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000 + mov dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b + mov dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000 + mov dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b + mov dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000 +if ~DEBUG_SHOW_IO +; allow access to all ports + mov ecx, [esi+V86_machine.iopm] + xor eax, eax + mov edi, ecx + mov ecx, 10000h/8/4 + rep stosd +end if +.ret: + ret + +struc v86_regs +{ +; don't change the order, it is important + .edi dd ? + .esi dd ? + .ebp dd ? + dd ? ; ignored + .ebx dd ? + .edx dd ? + .ecx dd ? + .eax dd ? + .eip dd ? + .cs dd ? + .eflags dd ? ; VM flag must be set! + .esp dd ? + .ss dd ? + .es dd ? + .ds dd ? + .fs dd ? + .gs dd ? +.size = $ +} +virtual at 0 +v86_regs v86_regs +end virtual + +; Run V86 machine +; in: ebx -> registers for V86 (two structures: in and out) +; esi = handle +; ecx = expected end address (CS:IP) +; edx = IRQ to hook or -1 if not required +; out: structure pointed to by ebx is filled with new values +; eax = 1 - exception has occured, cl contains code +; eax = 2 - access to disabled i/o port, ecx contains port address +; eax = 3 - IRQ is already hooked by another VM +; destroys: nothing +v86_start: + pushad + + cli + + mov ecx, [CURRENT_TASK] + shl ecx, 8 + add ecx, SLOT_BASE + + mov eax, [esi+V86_machine.iopm] + call get_pg_addr + inc eax + push dword [ecx+APPDATA.io_map] + push dword [ecx+APPDATA.io_map+4] + mov dword [ecx+APPDATA.io_map], eax + mov dword [page_tabs + (tss._io_map_0 shr 10)], eax + add eax, 0x1000 + mov dword [ecx+APPDATA.io_map+4], eax + mov dword [page_tabs + (tss._io_map_1 shr 10)], eax + + push [ecx+APPDATA.dir_table] + push [ecx+APPDATA.saved_esp0] + mov [ecx+APPDATA.saved_esp0], esp + mov [tss._esp0], esp + + mov eax, [esi+V86_machine.pagedir] + call get_pg_addr + mov [ecx+APPDATA.dir_table], eax + mov cr3, eax + +; mov [irq_tab+5*4], my05 + +; We do not enable interrupts, because V86 IRQ redirector assumes that +; machine is running +; They will be enabled by IRET. +; sti + + mov eax, esi + sub esp, v86_regs.size + mov esi, ebx + mov edi, esp + mov ecx, v86_regs.size/4 + rep movsd + + cmp edx, -1 + jz .noirqhook +uglobal +v86_irqhooks rd IRQ_RESERVED * 2 +endg + cmp [v86_irqhooks+edx*8], 0 + jz @f + cmp [v86_irqhooks+edx*8], eax + jz @f + mov esi, v86_irqerr + call sys_msg_board_str + inc [v86_irqhooks+edx*8+4] + mov eax, 3 + jmp v86_exc_c.exit +@@: + mov [v86_irqhooks+edx*8], eax + inc [v86_irqhooks+edx*8+4] +.noirqhook: + + popad + iretd + +; It is only possible to leave virtual-8086 mode by faulting to +; a protected-mode interrupt handler (typically the general-protection +; exception handler, which in turn calls the virtual 8086-mode monitor). + +iglobal + v86_exc_str1 db 'V86 : unexpected exception ',0 + v86_exc_str2 db ' at ',0 + v86_exc_str3 db ':',0 + v86_exc_str4 db 13,10,'V86 : faulted code:',0 + v86_exc_str5 db ' (unavailable)',0 + v86_newline db 13,10,0 + v86_io_str1 db 'V86 : access to disabled i/o port ',0 + v86_io_byte db ' (byte)',13,10,0 + v86_io_word db ' (word)',13,10,0 + v86_io_dword db ' (dword)',13,10,0 + v86_irqerr db 'V86 : IRQ already hooked',13,10,0 +endg + +v86_exc_c: +; Did we all that we have wanted to do? + cmp bl, 1 + jne @f + xor eax, eax + mov dr6, eax + @@: + mov eax, [esp+v86_regs.size+10h+18h] + cmp word [esp+v86_regs.eip], ax + jnz @f + shr eax, 16 + cmp word [esp+v86_regs.cs], ax + jz .done +@@: +; Various system events, which must be handled, result in #GP + cmp bl, 13 + jnz .nogp +; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error + cmp word [esp+v86_regs.eip+2], 0 + jnz .nogp +; Otherwise we can safely access byte at CS:IP +; (because it is #GP, not #PF handler) +; …б«Ё Ўл ¬л ¬®Ј«Ё бе«®Ї®в вм ЁбЄ«о祭ЁҐ в®«мЄ® Ё§-§  з⥭Ёп Ў ©в®ў Є®¤ , +; ¬л Ўл ҐЈ® 㦥 бе«®Ї®в «Ё Ё нв® Ўл«® Ўл ­Ґ #GP + movzx esi, word [esp+v86_regs.cs] + shl esi, 4 + add esi, [esp+v86_regs.eip] + lodsb + cmp al, 0xCD ; int xx command = CD xx + jz .handle_int + cmp al, 0xCF + jz .handle_iret + cmp al, 0xF3 + jz .handle_rep + cmp al, 0xEC + jz .handle_in + cmp al, 0xED + jz .handle_in_word + cmp al, 0xEE + jz .handle_out + cmp al, 0xEF + jz .handle_out_word + cmp al, 0xE4 + jz .handle_in_imm + cmp al, 0xE6 + jz .handle_out_imm + cmp al, 0x9C + jz .handle_pushf + cmp al, 0x9D + jz .handle_popf + cmp al, 0xFA + jz .handle_cli + cmp al, 0xFB + jz .handle_sti + cmp al, 0x66 + jz .handle_66 + jmp .nogp +.handle_int: + cmp word [esp+v86_regs.eip], 0xFFFF + jae .nogp + xor eax, eax + lodsb +; call sys_msg_board_byte +; simulate INT command +; N.B. It is possible that some checks need to be corrected, +; but at least in case of normal execution the code works. +.simulate_int: + cmp word [esp+v86_regs.esp], 6 + jae @f + mov bl, 12 ; #SS exception + jmp .nogp +@@: + movzx edx, word [esp+v86_regs.ss] + shl edx, 4 + push eax + movzx eax, word [esp+4+v86_regs.esp] + sub eax, 6 + add edx, eax + mov eax, edx + mov esi, [esp+4+v86_regs.size+10h+4] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 ; #PF exception + jmp .nogp +@@: + lea eax, [edx+5] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 ; #PF exception + jmp .nogp +@@: + sub word [esp+4+v86_regs.esp], 6 + mov eax, [esp+4+v86_regs.eip] + cmp byte [esp+1], 0 + jnz @f + inc eax + inc eax +@@: + mov word [edx], ax + mov eax, [esp+4+v86_regs.cs] + mov word [edx+2], ax + mov eax, [esp+4+v86_regs.eflags] + mov word [edx+4], ax + pop eax + mov ah, 0 + mov cx, [eax*4] + mov word [esp+v86_regs.eip], cx + mov cx, [eax*4+2] + mov word [esp+v86_regs.cs], cx +; note that interrupts will be disabled globally at IRET + and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags +; continue V86 execution + popad + iretd +.handle_iret: + cmp word [esp+v86_regs.esp], 0x10000 - 6 + jbe @f + mov bl, 12 + jmp .nogp +@@: + movzx edx, word [esp+v86_regs.ss] + shl edx, 4 + movzx eax, word [esp+v86_regs.esp] + add edx, eax + mov eax, edx + mov esi, [esp+v86_regs.size+10h+4] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 + jmp .nogp +@@: + lea eax, [edx+5] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 + jmp .nogp +@@: + mov ax, [edx] + mov word [esp+v86_regs.eip], ax + mov ax, [edx+2] + mov word [esp+v86_regs.cs], ax + mov ax, [edx+4] + mov word [esp+v86_regs.eflags], ax + add word [esp+v86_regs.esp], 6 + popad + iretd +.handle_pushf: + cmp word [esp+v86_regs.esp], 1 + jnz @f + mov bl, 12 + jmp .nogp +@@: + movzx edx, word [esp+v86_regs.ss] + shl edx, 4 + mov eax, [esp+v86_regs.esp] + sub eax, 2 + movzx eax, ax + add edx, eax + mov eax, edx + mov esi, [esp+v86_regs.size+10h+4] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 ; #PF exception + jmp .nogp +@@: + lea eax, [edx+1] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 + jmp .nogp +@@: + sub word [esp+v86_regs.esp], 2 + mov eax, [esp+v86_regs.eflags] + mov [edx], ax + inc word [esp+v86_regs.eip] + popad + iretd +.handle_pushfd: + cmp word [esp+v86_regs.esp], 4 + jae @f + mov bl, 12 ; #SS exception + jmp .nogp +@@: + movzx edx, word [esp+v86_regs.ss] + shl edx, 4 + movzx eax, word [esp+v86_regs.esp] + sub eax, 4 + add edx, eax + mov eax, edx + mov esi, [esp+v86_regs.size+10h+4] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 ; #PF exception + jmp .nogp +@@: + lea eax, [edx+3] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 ; #PF exception + jmp .nogp +@@: + sub word [esp+v86_regs.esp], 4 + movzx eax, word [esp+v86_regs.eflags] + mov [edx], eax + add word [esp+v86_regs.eip], 2 + popad + iretd +.handle_popf: + cmp word [esp+v86_regs.esp], 0xFFFF + jnz @f + mov bl, 12 + jmp .nogp +@@: + movzx edx, word [esp+v86_regs.ss] + shl edx, 4 + movzx eax, word [esp+v86_regs.esp] + add edx, eax + mov eax, edx + mov esi, [esp+v86_regs.size+10h+4] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 ; #PF exception + jmp .nogp +@@: + lea eax, [edx+1] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 + jmp .nogp +@@: + mov ax, [edx] + mov word [esp+v86_regs.eflags], ax + add word [esp+v86_regs.esp], 2 + inc word [esp+v86_regs.eip] + popad + iretd +.handle_popfd: + cmp word [esp+v86_regs.esp], 0x10000 - 4 + jbe @f + mov bl, 12 + jmp .nogp +@@: + movzx edx, word [esp+v86_regs.ss] + shl edx, 4 + movzx eax, word [esp+v86_regs.esp] + add edx, eax + mov eax, edx + mov esi, [esp+v86_regs.size+10h+4] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 + jmp .nogp +@@: + lea eax, [edx+3] + call v86_get_lin_addr + cmp eax, 0x1000 + jae @f + mov bl, 14 + jmp .nogp +@@: + mov eax, [edx] + mov word [esp+v86_regs.eflags], ax + add word [esp+v86_regs.esp], 4 + add word [esp+v86_regs.eip], 2 + popad + iretd +.handle_cli: + and byte [esp+v86_regs.eflags+1], not 2 + inc word [esp+v86_regs.eip] + popad + iretd +.handle_sti: + or byte [esp+v86_regs.eflags+1], 2 + inc word [esp+v86_regs.eip] + popad + iretd +.handle_rep: + cmp word [esp+v86_regs.eip], 0xFFFF + jae .nogp + lodsb + cmp al, 6Eh + jz .handle_rep_outsb + jmp .nogp +.handle_rep_outsb: +.handle_in: +.handle_out: +.invalid_io_byte: + movzx ebx, word [esp+v86_regs.edx] + mov ecx, 1 + jmp .invalid_io +.handle_in_imm: +.handle_out_imm: + cmp word [esp+v86_regs.eip], 0xFFFF + jae .nogp + lodsb + movzx ebx, al + mov ecx, 1 + jmp .invalid_io +.handle_66: + cmp word [esp+v86_regs.eip], 0xFFFF + jae .nogp + lodsb + cmp al, 0x9C + jz .handle_pushfd + cmp al, 0x9D + jz .handle_popfd + cmp al, 0xEF + jz .handle_out_dword + cmp al, 0xED + jz .handle_in_dword + jmp .nogp +.handle_in_word: +.handle_out_word: + movzx ebx, word [esp+v86_regs.edx] + mov ecx, 2 + jmp .invalid_io +.handle_in_dword: +.handle_out_dword: +.invalid_io_dword: + movzx ebx, word [esp+v86_regs.edx] + mov ecx, 4 +.invalid_io: + mov esi, v86_io_str1 + call sys_msg_board_str + mov eax, ebx + call sys_msg_board_dword + mov esi, v86_io_byte + cmp ecx, 1 + jz @f + mov esi, v86_io_word + cmp ecx, 2 + jz @f + mov esi, v86_io_dword +@@: + call sys_msg_board_str +if DEBUG_SHOW_IO + mov edx, ebx + mov ebx, 200 + call delay_hs + mov esi, [esp+v86_regs.size+10h+4] + mov eax, [esi+V86_machine.iopm] +@@: + btr [eax], edx + inc edx + loop @b + popad + iretd +else + mov eax, 2 + jmp .exit +end if +.nogp: + + mov esi, v86_exc_str1 + call sys_msg_board_str + mov al, bl + call sys_msg_board_byte + mov esi, v86_exc_str2 + call sys_msg_board_str + mov ax, [esp+32+4] + call sys_msg_board_word + mov esi, v86_exc_str3 + call sys_msg_board_str + mov ax, [esp+32] + call sys_msg_board_word + mov esi, v86_exc_str4 + call sys_msg_board_str + mov ecx, 8 + movzx edx, word [esp+32+4] + shl edx, 4 + add edx, [esp+32] +@@: + mov esi, [esp+v86_regs.size+10h+4] + mov eax, edx + call v86_get_lin_addr + cmp eax, 0x1000 + jb .nopage + mov esi, v86_exc_str3-2 + call sys_msg_board_str + mov al, [edx] + call sys_msg_board_byte + inc edx + loop @b + jmp @f +.nopage: + mov esi, v86_exc_str5 + call sys_msg_board_str +@@: + mov esi, v86_newline + call sys_msg_board_str + mov eax, 1 + jmp .exit + +.done: + xor eax, eax + +.exit: + mov [esp+v86_regs.size+10h+1Ch], eax + mov [esp+v86_regs.size+10h+18h], ebx + + mov edx, [esp+v86_regs.size+10h+14h] + cmp edx, -1 + jz @f + dec [v86_irqhooks+edx*8+4] + jnz @f + and [v86_irqhooks+edx*8], 0 +@@: + + mov esi, esp + mov edi, [esi+v86_regs.size+10h+10h] + add edi, v86_regs.size + mov ecx, v86_regs.size/4 + rep movsd + mov esp, esi + + cli + mov ecx, [CURRENT_TASK] + shl ecx, 8 + pop eax + mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax + mov [tss._esp0], eax + pop eax + mov [SLOT_BASE+ecx+APPDATA.dir_table], eax + pop ebx + mov dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx + mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx + pop ebx + mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx + mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx + mov cr3, eax + sti + + popad + ret + +;my05: +; mov dx, 30C2h +; mov cx, 4 +;.0: +; in al, dx +; cmp al, 0FFh +; jz @f +; test al, 4 +; jnz .1 +;@@: +; add dx, 8 +; in al, dx +; cmp al, 0FFh +; jz @f +; test al, 4 +; jnz .1 +;@@: +; loop .0 +; ret +;.1: +; or al, 84h +; out dx, al +;.2: +; mov dx, 30F7h +; in al, dx +; mov byte [BOOT_VAR + 48Eh], 0FFh +; ret + +align 4 +v86_irq: +; push irq/pushad/jmp v86_irq +; ebp = irq + lea esi, [esp+1Ch] + lea edi, [esi+4] + mov ecx, 8 + std + rep movsd + cld + mov edi, ebp + pop eax +v86_irq2: + mov esi, [v86_irqhooks+edi*8] ; get VM handle + mov eax, [esi+V86_machine.pagedir] + call get_pg_addr + mov ecx, [CURRENT_TASK] + shl ecx, 8 + cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax + jnz .notcurrent + lea eax, [edi+8] + cmp al, 10h + mov ah, 1 + jb @f + add al, 60h +@@: + jmp v86_exc_c.simulate_int +.notcurrent: + mov ebx, SLOT_BASE + 0x100 + mov ecx, [TASK_COUNT] +.scan: + cmp [ebx+APPDATA.dir_table], eax + jnz .cont + push ecx + mov ecx, [ebx+APPDATA.saved_esp0] + cmp word [ecx-v86_regs.size+v86_regs.esp], 6 + jb .cont2 + movzx edx, word [ecx-v86_regs.size+v86_regs.ss] + shl edx, 4 + push eax + movzx eax, word [ecx-v86_regs.size+v86_regs.esp] + sub eax, 6 + add edx, eax + mov eax, edx + call v86_get_lin_addr + cmp eax, 0x1000 + jb .cont3 + lea eax, [edx+5] + call v86_get_lin_addr + cmp eax, 0x1000 + jb .cont3 + pop eax + pop ecx + jmp .found +.cont3: + pop eax +.cont2: + pop ecx +.cont: + loop .scan + mov ecx, edi + call irq_eoi + popad + iretd +.found: + mov cr3, eax + sub word [esi-v86_regs.size+v86_regs.esp], 6 + mov ecx, [esi-v86_regs.size+v86_regs.eip] + mov word [edx], cx + mov ecx, [esi-v86_regs.size+v86_regs.cs] + mov word [edx+2], cx + mov ecx, [esi-v86_regs.size+v86_regs.eflags] + mov word [edx+4], cx + lea eax, [edi+8] + cmp al, 10h + jb @f + add al, 60h +@@: + mov cx, [eax*4] + mov word [esi-v86_regs.size+v86_regs.eip], cx + mov cx, [eax*4+2] + mov word [esi-v86_regs.size+v86_regs.cs], cx + and byte [esi-v86_regs.size+v86_regs.eflags+1], not 3 + call update_counters + lea edi, [ebx + 0x100000000 - SLOT_BASE] + shr edi, 3 + add edi, TASK_DATA + call find_next_task.found + call do_change_task + popad + iretd diff --git a/kernel/trunk/data16.inc b/kernel/trunk/data16.inc index b81d8fbee..b72722d5a 100644 --- a/kernel/trunk/data16.inc +++ b/kernel/trunk/data16.inc @@ -1,90 +1,91 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -flm db 0 -preboot_lfb db 0 -preboot_bootlog db 0 -boot_drive db 0 -bx_from_load: dw 'r1' ; структура для хранения параметров- откуда гашрузились, берется ниже из bx ; {SPraid}[13.03.2007] - ; a,b,c,d - винчестеры, r - рам диск - ; # диска... символ, а не байт. '1', а не 1 - -align 4 -old_ints_h: - dw 0x400 - dd 0 - dw 0 - -if ~ defined extended_primary_loader ; restart from memory is not supported in extended primary loader cfg -kernel_restart_bootblock: - db 1 ; version - dw 1 ; floppy image is in memory - dd 0 ; cannot save parameters -end if - -; table for move to extended memory (int 15h, ah=87h) -align 8 -movedesc: - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - - db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 - db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 - - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - -fwmovedesc: - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - - db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 - db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 - - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - -if defined extended_primary_loader -; look in PrimaryLoader.txt for the description -bootdevice dw 0 ; ax from primary loader -bootfs dw 0 ; bx from primary loader -bootcallback dd 0 ; ds:si from primary loader -; data for configuration file loading, look in PrimaryLoader.txt -config_file_struct: - dw 0, 4000h ; load to 4000:0000 - dw 16 ; read no more than 16*4K = 64K - db 'config.ini',0 -; data for configuration file parsing -macro config_variable string,parser -{ -local len -len dw 0 - db string -store word $ - len - 2 at len - dw parser -} -config_file_variables: - config_variable 'timeout', parse_timeout - config_variable 'resolution', parse_resolution - config_variable 'vbemode', parse_vbemode -; config_variable 'vrr', parse_vrr - config_variable 'biosdisks', parse_biosdisks - config_variable 'imgfrom', parse_imgfrom - dw 0 -; data for image file loading, look in PrimaryLoader.txt -image_file_struct: - dw 0, 4000h ; load to 4000:0000 - dw 16 ; read no more than 16*4K = 64K - db 'kolibri.img',0 -end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +flm db 0 +preboot_lfb db 0 +preboot_bootlog db 0 +boot_drive db 0 +bx_from_load: + dw 'r1' ; структура для хранения параметров- откуда гашрузились, берется ниже из bx ; {SPraid}[13.03.2007] + ; a,b,c,d - винчестеры, r - рам диск + ; # диска... символ, а не байт. '1', а не 1 + +align 4 +old_ints_h: + dw 0x400 + dd 0 + dw 0 + +if ~ defined extended_primary_loader ; restart from memory is not supported in extended primary loader cfg +kernel_restart_bootblock: + db 1 ; version + dw 1 ; floppy image is in memory + dd 0 ; cannot save parameters +end if + +; table for move to extended memory (int 15h, ah=87h) +align 8 +movedesc: + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + + db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 + db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 + + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + +fwmovedesc: + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + + db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 + db 0xff,0xff,0x0,0xa0,0x00,0x93,0x0,0x0 + + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + +if defined extended_primary_loader +; look in PrimaryLoader.txt for the description +bootdevice dw 0 ; ax from primary loader +bootfs dw 0 ; bx from primary loader +bootcallback dd 0 ; ds:si from primary loader +; data for configuration file loading, look in PrimaryLoader.txt +config_file_struct: + dw 0, 4000h ; load to 4000:0000 + dw 16 ; read no more than 16*4K = 64K + db 'config.ini',0 +; data for configuration file parsing +macro config_variable string,parser +{ +local len +len dw 0 + db string +store word $ - len - 2 at len + dw parser +} +config_file_variables: + config_variable 'timeout', parse_timeout + config_variable 'resolution', parse_resolution + config_variable 'vbemode', parse_vbemode +; config_variable 'vrr', parse_vrr + config_variable 'biosdisks', parse_biosdisks + config_variable 'imgfrom', parse_imgfrom + dw 0 +; data for image file loading, look in PrimaryLoader.txt +image_file_struct: + dw 0, 4000h ; load to 4000:0000 + dw 16 ; read no more than 16*4K = 64K + db 'kolibri.img',0 +end if diff --git a/kernel/trunk/data32.inc b/kernel/trunk/data32.inc index 21e4e4686..8797b4fd7 100644 --- a/kernel/trunk/data32.inc +++ b/kernel/trunk/data32.inc @@ -83,7 +83,7 @@ else boot_bgr db 'Calculating background',0 boot_resirqports db 'Reserving IRQs & ports',0 boot_setostask db 'Setting OS task',0 - boot_allirqs db 'Unmasking IRQs',0 + boot_allirqs db 'Unmasking IRQs',0 boot_tsc db 'Reading TSC',0 boot_cpufreq db 'CPU frequency is ',' ',' MHz',0 boot_pal_ega db 'Setting EGA/CGA 320x200 palette',0 @@ -95,8 +95,8 @@ if preboot_blogesc end if end if - boot_APIC_found db 'APIC enabled', 0 - boot_APIC_nfound db 'APIC not found', 0 + boot_APIC_found db 'APIC enabled', 0 + boot_APIC_nfound db 'APIC not found', 0 ;new_process_loading db 'K : New Process - loading',13,10,0 ;new_process_running db 'K : New Process - done',13,10,0 @@ -293,7 +293,8 @@ gdte: align 16 cur_saved_data rb 4096 -fpu_data: rb 512 +fpu_data: + rb 512 mem_block_list rd 64*2 mem_used_list rd 64*2 diff --git a/kernel/trunk/detect/biosdisk.inc b/kernel/trunk/detect/biosdisk.inc index 2fc98039b..35eb17ec5 100644 --- a/kernel/trunk/detect/biosdisk.inc +++ b/kernel/trunk/detect/biosdisk.inc @@ -1,81 +1,81 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Detect all BIOS hard drives. -; diamond, 2008 - - xor cx, cx - mov es, cx - mov di, 0x9080 - mov byte [es:di-1], cl - cmp [preboot_biosdisk], 1 - jnz bdde - mov dl, 80h -bdds: - mov ah, 15h - push cx dx di - int 13h - pop di dx cx - jc bddc - test ah, ah - jz bddc - inc cx - mov ah, 48h - push ds - push es - pop ds - mov si, 0xA000 - mov word [si], 1Eh - mov ah, 48h - int 13h - pop ds - jc bddc2 - inc byte [es:0x907F] - cmp word [es:si], 1Eh - jb bddl - cmp word [es:si+1Ah], 0xFFFF - jz bddl - mov al, dl - stosb - push ds - lds si, [es:si+1Ah] - mov al, [si+6] - and al, 0xF - stosb - mov al, byte [si+4] - shr al, 4 - and ax, 1 - cmp word [si], 1F0h - jz @f - inc ax - inc ax - cmp word [si], 170h - jz @f - or ax,-1 -; mov ax, -1 -@@: - stosw - pop ds - jmp bddc2 -bddl: - mov al, dl - stosb - xor ax,ax - stosb - dec ax - stosw -; mov al, 0 -; stosb -; mov ax, -1 -; stosw -bddc2: - cmp cl, [es:0x475] - jae bdde -bddc: - inc dl - jnz bdds -bdde: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Detect all BIOS hard drives. +; diamond, 2008 + + xor cx, cx + mov es, cx + mov di, 0x9080 + mov byte [es:di-1], cl + cmp [preboot_biosdisk], 1 + jnz bdde + mov dl, 80h +bdds: + mov ah, 15h + push cx dx di + int 13h + pop di dx cx + jc bddc + test ah, ah + jz bddc + inc cx + mov ah, 48h + push ds + push es + pop ds + mov si, 0xA000 + mov word [si], 1Eh + mov ah, 48h + int 13h + pop ds + jc bddc2 + inc byte [es:0x907F] + cmp word [es:si], 1Eh + jb bddl + cmp word [es:si+1Ah], 0xFFFF + jz bddl + mov al, dl + stosb + push ds + lds si, [es:si+1Ah] + mov al, [si+6] + and al, 0xF + stosb + mov al, byte [si+4] + shr al, 4 + and ax, 1 + cmp word [si], 1F0h + jz @f + inc ax + inc ax + cmp word [si], 170h + jz @f + or ax, -1 +; mov ax, -1 +@@: + stosw + pop ds + jmp bddc2 +bddl: + mov al, dl + stosb + xor ax, ax + stosb + dec ax + stosw +; mov al, 0 +; stosb +; mov ax, -1 +; stosw +bddc2: + cmp cl, [es:0x475] + jae bdde +bddc: + inc dl + jnz bdds +bdde: diff --git a/kernel/trunk/detect/biosmem.inc b/kernel/trunk/detect/biosmem.inc index 7b66cd4b6..21cf994f5 100644 --- a/kernel/trunk/detect/biosmem.inc +++ b/kernel/trunk/detect/biosmem.inc @@ -1,43 +1,43 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Query physical memory map from BIOS. -; diamond, 2009 - - push ds -; first call to fn E820 - mov eax, 0xE820 - xor ebx, ebx - mov es, bx - mov ds, bx - mov di, 0x9104 - mov [di-4], ebx ; no blocks yet - mov ecx, 20 - mov edx, 0x534D4150 - int 15h - jc no_E820 - cmp eax, 0x534D4150 - jnz no_E820 -e820_mem_loop: - cmp byte [di+16], 1 ; ignore non-free areas - jnz e820_mem_next - inc byte [0x9100] - add di, 20 -e820_mem_next: -; consequent calls to fn E820 - test ebx, ebx - jz e820_test_done - cmp byte [0x9100], 32 - jae e820_test_done - mov eax, 0xE820 - int 15h - jc e820_test_done - jmp e820_mem_loop -no_E820: -; let's hope for mem_test from init.inc -e820_test_done: - pop ds +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Query physical memory map from BIOS. +; diamond, 2009 + + push ds +; first call to fn E820 + mov eax, 0xE820 + xor ebx, ebx + mov es, bx + mov ds, bx + mov di, 0x9104 + mov [di-4], ebx ; no blocks yet + mov ecx, 20 + mov edx, 0x534D4150 + int 15h + jc no_E820 + cmp eax, 0x534D4150 + jnz no_E820 +e820_mem_loop: + cmp byte [di+16], 1 ; ignore non-free areas + jnz e820_mem_next + inc byte [0x9100] + add di, 20 +e820_mem_next: +; consequent calls to fn E820 + test ebx, ebx + jz e820_test_done + cmp byte [0x9100], 32 + jae e820_test_done + mov eax, 0xE820 + int 15h + jc e820_test_done + jmp e820_mem_loop +no_E820: +; let's hope for mem_test from init.inc +e820_test_done: + pop ds diff --git a/kernel/trunk/detect/dev_fd.inc b/kernel/trunk/detect/dev_fd.inc index ff49678d2..0c717a318 100644 --- a/kernel/trunk/detect/dev_fd.inc +++ b/kernel/trunk/detect/dev_fd.inc @@ -1,37 +1,37 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;*************************************************** -; предварительная очистка области таблицы -; поиск и занесение в таблицу приводов FDD -; автор Mario79 -;*************************************************** - xor eax,eax - mov edi,DRIVE_DATA - mov ecx,16384 - cld - rep stosd - - mov al,0x10 - out 0x70,al - mov cx,0xff -wait_cmos: - dec cx - test cx,cx - jnz wait_cmos - in al,0x71 - mov [DRIVE_DATA],al - test al,al - jz @f - in al,0x21 - and al,10111111b ; Enable IRQ6 - out 0x21,al -@@: - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;*************************************************** +; предварительная очистка области таблицы +; поиск и занесение в таблицу приводов FDD +; автор Mario79 +;*************************************************** + xor eax, eax + mov edi, DRIVE_DATA + mov ecx, 16384 + cld + rep stosd + + mov al, 0x10 + out 0x70, al + mov cx, 0xff +wait_cmos: + dec cx + test cx, cx + jnz wait_cmos + in al, 0x71 + mov [DRIVE_DATA], al + test al, al + jz @f + in al, 0x21 + and al, 10111111b ; Enable IRQ6 + out 0x21, al +@@: + diff --git a/kernel/trunk/detect/dev_hdcd.inc b/kernel/trunk/detect/dev_hdcd.inc index 64b9327f3..cadef3b42 100644 --- a/kernel/trunk/detect/dev_hdcd.inc +++ b/kernel/trunk/detect/dev_hdcd.inc @@ -1,385 +1,394 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;****************************************************** -; поиск приводов HDD и CD -; автор исходного текста Кулаков Владимир Геннадьевич. -; адаптация и доработка Mario79 -;****************************************************** - -;**************************************************** -;* ПОИСК HDD и CD * -;**************************************************** -FindHDD: - mov [ChannelNumber],1 - mov [DiskNumber],0 - call FindHDD_3 -; mov ax,[Sector512+176] -; mov [DRIVE_DATA+6],ax -; mov ax,[Sector512+126] -; mov [DRIVE_DATA+8],ax -; mov ax,[Sector512+128] -; mov [DRIVE_DATA+8],ax - mov [DiskNumber],1 - call FindHDD_3 -; mov al,[Sector512+176] -; mov [DRIVE_DATA+7],al - inc [ChannelNumber] - mov [DiskNumber],0 - call FindHDD_3 -; mov al,[Sector512+176] -; mov [DRIVE_DATA+8],al - mov [DiskNumber],1 - call FindHDD_1 -; mov al,[Sector512+176] -; mov [DRIVE_DATA+9],al - - jmp EndFindHDD - -FindHDD_1: - call ReadHDD_ID - cmp [DevErrorCode],0 - jne FindHDD_2 - cmp [Sector512+6],word 16 - ja FindHDD_2 - cmp [Sector512+12],word 255 - ja FindHDD_2 - inc byte [DRIVE_DATA+1] - jmp FindHDD_2_2 - FindHDD_2: - call DeviceReset - cmp [DevErrorCode],0 - jne FindHDD_2_2 - call ReadCD_ID - cmp [DevErrorCode],0 - jne FindHDD_2_2 - inc byte [DRIVE_DATA+1] - inc byte [DRIVE_DATA+1] - FindHDD_2_2: - ret - -FindHDD_3: - call FindHDD_1 - shl byte [DRIVE_DATA+1],2 - ret - - -; Адрес считываемого сектора в режиме LBA -uglobal -SectorAddress DD ? -endg -;************************************************* -;* ЧТЕНИЕ ИДЕНТИФИКАТОРА ЖЕСТКОГО ДИСКА * -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала (1 или 2); * -;* DiskNumber - номер диска на канале (0 или 1). * -;* Идентификационный блок данных считывается * -;* в массив Sector512. * -;************************************************* -ReadHDD_ID: -; Задать режим CHS - mov [ATAAddressMode],0 -; Послать команду идентификации устройства - mov [ATAFeatures],0 - mov [ATAHead],0 - mov [ATACommand],0ECh - call SendCommandToHDD - cmp [DevErrorCode],0 ;проверить код ошибки - jne @@End ;закончить, сохранив код ошибки - mov DX,[ATABasePortAddr] - add DX,7 ;адрес регистра состояни - mov ecx,0xffff -@@WaitCompleet: - ; Проверить время выполнения команды - dec ecx -; cmp ecx,0 - jz @@Error1 ;ошибка тайм-аута - ; Проверить готовность - in AL,DX - test AL,80h ;состояние сигнала BSY - jnz @@WaitCompleet - test AL,1 ;состояние сигнала ERR - jnz @@Error6 - test AL,08h ;состояние сигнала DRQ - jz @@WaitCompleet -; Принять блок данных от контроллера -; mov AX,DS -; mov ES,AX - mov EDI,Sector512 ;offset Sector512 - mov DX,[ATABasePortAddr] ;регистр данных - mov CX,256 ;число считываемых слов - rep insw ;принять блок данных - ret -; Записать код ошибки -@@Error1: - mov [DevErrorCode],1 - ret -@@Error6: - mov [DevErrorCode],6 -@@End: ret - - -iglobal -; Стандартные базовые адреса каналов 1 и 2 -StandardATABases DW 1F0h, 170h -endg -uglobal -; Номер канала -ChannelNumber DW ? -; Номер диска -DiskNumber DB ? -; Базовый адрес группы портов контроллера ATA -ATABasePortAddr DW ? -; Параметры ATA-команды -ATAFeatures DB ? ;особенности -ATASectorCount DB ? ;количество обрабатываемых секторов -ATASectorNumber DB ? ;номер начального сектора -ATACylinder DW ? ;номер начального цилиндра -ATAHead DB ? ;номер начальной головки -ATAAddressMode DB ? ;режим адресации (0 - CHS, 1 - LBA) -ATACommand DB ? ;код команды, подлежащей выполнению -; Код ошибки (0 - нет ошибок, 1 - превышен допустимый -; интервал ожидания, 2 - неверный код режима адресации, -; 3 - неверный номер канала, 4 - неверный номер диска, -; 5 - неверный номер головки, 6 - ошибка при выполнении -; команды) -DevErrorCode dd ? -endg -;**************************************************** -;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ * -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала (1 или 2); * -;* DiskNumber - номер диска (0 или 1); * -;* ATAFeatures - "особенности"; * -;* ATASectorCount - количество секторов; * -;* ATASectorNumber - номер начального сектора; * -;* ATACylinder - номер начального цилиндра; * -;* ATAHead - номер начальной головки; * -;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); * -;* ATACommand - код команды. * -;* После успешного выполнения функции: * -;* в ATABasePortAddr - базовый адрес HDD; * -;* в DevErrorCode - ноль. * -;* При возникновении ошибки в DevErrorCode будет * -;* возвращен код ошибки. * -;**************************************************** -SendCommandToHDD: -; Проверить значение кода режима - cmp [ATAAddressMode],1 - ja @@Err2 -; Проверить корректность номера канала - mov BX,[ChannelNumber] - cmp BX,1 - jb @@Err3 - cmp BX,2 - ja @@Err3 -; Установить базовый адрес - dec BX - shl BX,1 - movzx ebx,bx - mov AX,[ebx+StandardATABases] - mov [ATABasePortAddr],AX -; Ожидание готовности HDD к приему команды - ; Выбрать нужный диск - mov DX,[ATABasePortAddr] - add DX,6 ;адрес регистра головок - mov AL,[DiskNumber] - cmp AL,1 ;проверить номера диска - ja @@Err4 - shl AL,4 - or AL,10100000b - out DX,AL - ; Ожидать, пока диск не будет готов - inc DX - mov ecx,0xfff -; mov eax,[timer_ticks] -; mov [TickCounter_1],eax -@@WaitHDReady: - ; Проверить время ожидани - dec ecx -; cmp ecx,0 - jz @@Err1 -; mov eax,[timer_ticks] -; sub eax,[TickCounter_1] -; cmp eax,300 ;ожидать 300 тиков -; ja @@Err1 ;ошибка тайм-аута - ; Прочитать регистр состояни - in AL,DX - ; Проверить состояние сигнала BSY - test AL,80h - jnz @@WaitHDReady - ; Проверить состояние сигнала DRQ - test AL,08h - jnz @@WaitHDReady -; Загрузить команду в регистры контроллера - cli - mov DX,[ATABasePortAddr] - inc DX ;регистр "особенностей" - mov AL,[ATAFeatures] - out DX,AL - inc DX ;счетчик секторов - mov AL,[ATASectorCount] - out DX,AL - inc DX ;регистр номера сектора - mov AL,[ATASectorNumber] - out DX,AL - inc DX ;номер цилиндра (младший байт) - mov AX,[ATACylinder] - out DX,AL - inc DX ;номер цилиндра (старший байт) - mov AL,AH - out DX,AL - inc DX ;номер головки/номер диска - mov AL,[DiskNumber] - shl AL,4 - cmp [ATAHead],0Fh ;проверить номер головки - ja @@Err5 - or AL,[ATAHead] - or AL,10100000b - mov AH,[ATAAddressMode] - shl AH,6 - or AL,AH - out DX,AL -; Послать команду - mov AL,[ATACommand] - inc DX ;регистр команд - out DX,AL - sti -; Сбросить признак ошибки - mov [DevErrorCode],0 - ret -; Записать код ошибки -@@Err1: mov [DevErrorCode],1 - ret -@@Err2: mov [DevErrorCode],2 - ret -@@Err3: mov [DevErrorCode],3 - ret -@@Err4: mov [DevErrorCode],4 - ret -@@Err5: mov [DevErrorCode],5 -; Завершение работы программы - ret - -;************************************************* -;* ЧТЕНИЕ ИДЕНТИФИКАТОРА УСТРОЙСТВА ATAPI * -;* Входные параметры передаются через глобальные * -;* перменные: * -;* ChannelNumber - номер канала; * -;* DiskNumber - номер диска на канале. * -;* Идентификационный блок данных считывается * -;* в массив Sector512. * -;************************************************* -ReadCD_ID: -; Задать режим CHS - mov [ATAAddressMode],0 -; Послать команду идентификации устройства - mov [ATAFeatures],0 - mov [ATASectorCount],0 - mov [ATASectorNumber],0 - mov [ATACylinder],0 - mov [ATAHead],0 - mov [ATACommand],0A1h - call SendCommandToHDD - cmp [DevErrorCode],0 ;проверить код ошибки - jne @@End_1 ;закончить, сохранив код ошибки -; Ожидать готовность данных HDD - mov DX,[ATABasePortAddr] - add DX,7 ;порт 1х7h - mov ecx,0xffff -@@WaitCompleet_1: - ; Проверить врем - dec ecx -; cmp ecx,0 - jz @@Error1_1 ;ошибка тайм-аута - ; Проверить готовность - in AL,DX - test AL,80h ;состояние сигнала BSY - jnz @@WaitCompleet_1 - test AL,1 ;состояние сигнала ERR - jnz @@Error6_1 - test AL,08h ;состояние сигнала DRQ - jz @@WaitCompleet_1 -; Принять блок данных от контроллера -; mov AX,DS -; mov ES,AX - mov EDI,Sector512 ;offset Sector512 - mov DX,[ATABasePortAddr] ;порт 1x0h - mov CX,256 ;число считываемых слов - rep insw - ret -; Записать код ошибки -@@Error1_1: - mov [DevErrorCode],1 - ret -@@Error6_1: - mov [DevErrorCode],6 -@@End_1: - ret - -;************************************************* -;* СБРОС УСТРОЙСТВА * -;* Входные параметры передаются через глобальные * -;* переменные: * -;* ChannelNumber - номер канала (1 или 2); * -;* DiskNumber - номер диска (0 или 1). * -;************************************************* -DeviceReset: -; Проверить корректность номера канала - mov BX,[ChannelNumber] - cmp BX,1 - jb @@Err3_2 - cmp BX,2 - ja @@Err3_2 -; Установить базовый адрес - dec BX - shl BX,1 - movzx ebx,bx - mov DX,[ebx+StandardATABases] - mov [ATABasePortAddr],DX -; Выбрать нужный диск - add DX,6 ;адрес регистра головок - mov AL,[DiskNumber] - cmp AL,1 ;проверить номера диска - ja @@Err4_2 - shl AL,4 - or AL,10100000b - out DX,AL -; Послать команду "Сброс" - mov AL,08h - inc DX ;регистр команд - out DX,AL - mov ecx,0x80000 -@@WaitHDReady_1: - ; Проверить время ожидани - dec ecx -; cmp ecx,0 - je @@Err1_2 ;ошибка тайм-аута - ; Прочитать регистр состояни - in AL,DX - ; Проверить состояние сигнала BSY - test AL,80h - jnz @@WaitHDReady_1 -; Сбросить признак ошибки - mov [DevErrorCode],0 - ret -; Обработка ошибок -@@Err1_2: mov [DevErrorCode],1 - ret -@@Err3_2: mov [DevErrorCode],3 - ret -@@Err4_2: mov [DevErrorCode],4 -; Записать код ошибки - ret - -EndFindHDD: - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;****************************************************** +; поиск приводов HDD и CD +; автор исходного текста Кулаков Владимир Геннадьевич. +; адаптация и доработка Mario79 +;****************************************************** + +;**************************************************** +;* ПОИСК HDD и CD * +;**************************************************** +FindHDD: + mov [ChannelNumber], 1 + mov [DiskNumber], 0 + call FindHDD_3 +; mov ax,[Sector512+176] +; mov [DRIVE_DATA+6],ax +; mov ax,[Sector512+126] +; mov [DRIVE_DATA+8],ax +; mov ax,[Sector512+128] +; mov [DRIVE_DATA+8],ax + mov [DiskNumber], 1 + call FindHDD_3 +; mov al,[Sector512+176] +; mov [DRIVE_DATA+7],al + inc [ChannelNumber] + mov [DiskNumber], 0 + call FindHDD_3 +; mov al,[Sector512+176] +; mov [DRIVE_DATA+8],al + mov [DiskNumber], 1 + call FindHDD_1 +; mov al,[Sector512+176] +; mov [DRIVE_DATA+9],al + + jmp EndFindHDD + +FindHDD_1: + call ReadHDD_ID + cmp [DevErrorCode], 0 + jne FindHDD_2 + cmp [Sector512+6], word 16 + ja FindHDD_2 + cmp [Sector512+12], word 255 + ja FindHDD_2 + inc byte [DRIVE_DATA+1] + jmp FindHDD_2_2 + FindHDD_2: + call DeviceReset + cmp [DevErrorCode], 0 + jne FindHDD_2_2 + call ReadCD_ID + cmp [DevErrorCode], 0 + jne FindHDD_2_2 + inc byte [DRIVE_DATA+1] + inc byte [DRIVE_DATA+1] + FindHDD_2_2: + ret + +FindHDD_3: + call FindHDD_1 + shl byte [DRIVE_DATA+1], 2 + ret + + +; Адрес считываемого сектора в режиме LBA +uglobal +SectorAddress DD ? +endg +;************************************************* +;* ЧТЕНИЕ ИДЕНТИФИКАТОРА ЖЕСТКОГО ДИСКА * +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала (1 или 2); * +;* DiskNumber - номер диска на канале (0 или 1). * +;* Идентификационный блок данных считывается * +;* в массив Sector512. * +;************************************************* +ReadHDD_ID: +; Задать режим CHS + mov [ATAAddressMode], 0 +; Послать команду идентификации устройства + mov [ATAFeatures], 0 + mov [ATAHead], 0 + mov [ATACommand], 0ECh + call SendCommandToHDD + cmp [DevErrorCode], 0;проверить код ошибки + jne @@End ;закончить, сохранив код ошибки + mov DX, [ATABasePortAddr] + add DX, 7 ;адрес регистра состояни + mov ecx, 0xffff +@@WaitCompleet: + ; Проверить время выполнения команды + dec ecx +; cmp ecx,0 + jz @@Error1 ;ошибка тайм-аута + ; Проверить готовность + in AL, DX + test AL, 80h ;состояние сигнала BSY + jnz @@WaitCompleet + test AL, 1 ;состояние сигнала ERR + jnz @@Error6 + test AL, 08h ;состояние сигнала DRQ + jz @@WaitCompleet +; Принять блок данных от контроллера +; mov AX,DS +; mov ES,AX + mov EDI, Sector512 ;offset Sector512 + mov DX, [ATABasePortAddr];регистр данных + mov CX, 256 ;число считываемых слов + rep insw ;принять блок данных + ret +; Записать код ошибки +@@Error1: + mov [DevErrorCode], 1 + ret +@@Error6: + mov [DevErrorCode], 6 +@@End: + ret + + +iglobal +; Стандартные базовые адреса каналов 1 и 2 +StandardATABases DW 1F0h, 170h +endg +uglobal +; Номер канала +ChannelNumber DW ? +; Номер диска +DiskNumber DB ? +; Базовый адрес группы портов контроллера ATA +ATABasePortAddr DW ? +; Параметры ATA-команды +ATAFeatures DB ? ;особенности +ATASectorCount DB ? ;количество обрабатываемых секторов +ATASectorNumber DB ? ;номер начального сектора +ATACylinder DW ? ;номер начального цилиндра +ATAHead DB ? ;номер начальной головки +ATAAddressMode DB ? ;режим адресации (0 - CHS, 1 - LBA) +ATACommand DB ? ;код команды, подлежащей выполнению +; Код ошибки (0 - нет ошибок, 1 - превышен допустимый +; интервал ожидания, 2 - неверный код режима адресации, +; 3 - неверный номер канала, 4 - неверный номер диска, +; 5 - неверный номер головки, 6 - ошибка при выполнении +; команды) +DevErrorCode dd ? +endg +;**************************************************** +;* ПОСЛАТЬ КОМАНДУ ЗАДАННОМУ ДИСКУ * +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала (1 или 2); * +;* DiskNumber - номер диска (0 или 1); * +;* ATAFeatures - "особенности"; * +;* ATASectorCount - количество секторов; * +;* ATASectorNumber - номер начального сектора; * +;* ATACylinder - номер начального цилиндра; * +;* ATAHead - номер начальной головки; * +;* ATAAddressMode - режим адресации (0-CHS, 1-LBA); * +;* ATACommand - код команды. * +;* После успешного выполнения функции: * +;* в ATABasePortAddr - базовый адрес HDD; * +;* в DevErrorCode - ноль. * +;* При возникновении ошибки в DevErrorCode будет * +;* возвращен код ошибки. * +;**************************************************** +SendCommandToHDD: +; Проверить значение кода режима + cmp [ATAAddressMode], 1 + ja @@Err2 +; Проверить корректность номера канала + mov BX, [ChannelNumber] + cmp BX, 1 + jb @@Err3 + cmp BX, 2 + ja @@Err3 +; Установить базовый адрес + dec BX + shl BX, 1 + movzx ebx, bx + mov AX, [ebx+StandardATABases] + mov [ATABasePortAddr], AX +; Ожидание готовности HDD к приему команды + ; Выбрать нужный диск + mov DX, [ATABasePortAddr] + add DX, 6 ;адрес регистра головок + mov AL, [DiskNumber] + cmp AL, 1 ;проверить номера диска + ja @@Err4 + shl AL, 4 + or AL, 10100000b + out DX, AL + ; Ожидать, пока диск не будет готов + inc DX + mov ecx, 0xfff +; mov eax,[timer_ticks] +; mov [TickCounter_1],eax +@@WaitHDReady: + ; Проверить время ожидани + dec ecx +; cmp ecx,0 + jz @@Err1 +; mov eax,[timer_ticks] +; sub eax,[TickCounter_1] +; cmp eax,300 ;ожидать 300 тиков +; ja @@Err1 ;ошибка тайм-аута + ; Прочитать регистр состояни + in AL, DX + ; Проверить состояние сигнала BSY + test AL, 80h + jnz @@WaitHDReady + ; Проверить состояние сигнала DRQ + test AL, 08h + jnz @@WaitHDReady +; Загрузить команду в регистры контроллера + cli + mov DX, [ATABasePortAddr] + inc DX ;регистр "особенностей" + mov AL, [ATAFeatures] + out DX, AL + inc DX ;счетчик секторов + mov AL, [ATASectorCount] + out DX, AL + inc DX ;регистр номера сектора + mov AL, [ATASectorNumber] + out DX, AL + inc DX ;номер цилиндра (младший байт) + mov AX, [ATACylinder] + out DX, AL + inc DX ;номер цилиндра (старший байт) + mov AL, AH + out DX, AL + inc DX ;номер головки/номер диска + mov AL, [DiskNumber] + shl AL, 4 + cmp [ATAHead], 0Fh;проверить номер головки + ja @@Err5 + or AL, [ATAHead] + or AL, 10100000b + mov AH, [ATAAddressMode] + shl AH, 6 + or AL, AH + out DX, AL +; Послать команду + mov AL, [ATACommand] + inc DX ;регистр команд + out DX, AL + sti +; Сбросить признак ошибки + mov [DevErrorCode], 0 + ret +; Записать код ошибки +@@Err1: + mov [DevErrorCode], 1 + ret +@@Err2: + mov [DevErrorCode], 2 + ret +@@Err3: + mov [DevErrorCode], 3 + ret +@@Err4: + mov [DevErrorCode], 4 + ret +@@Err5: + mov [DevErrorCode], 5 +; Завершение работы программы + ret + +;************************************************* +;* ЧТЕНИЕ ИДЕНТИФИКАТОРА УСТРОЙСТВА ATAPI * +;* Входные параметры передаются через глобальные * +;* перменные: * +;* ChannelNumber - номер канала; * +;* DiskNumber - номер диска на канале. * +;* Идентификационный блок данных считывается * +;* в массив Sector512. * +;************************************************* +ReadCD_ID: +; Задать режим CHS + mov [ATAAddressMode], 0 +; Послать команду идентификации устройства + mov [ATAFeatures], 0 + mov [ATASectorCount], 0 + mov [ATASectorNumber], 0 + mov [ATACylinder], 0 + mov [ATAHead], 0 + mov [ATACommand], 0A1h + call SendCommandToHDD + cmp [DevErrorCode], 0;проверить код ошибки + jne @@End_1 ;закончить, сохранив код ошибки +; Ожидать готовность данных HDD + mov DX, [ATABasePortAddr] + add DX, 7 ;порт 1х7h + mov ecx, 0xffff +@@WaitCompleet_1: + ; Проверить врем + dec ecx +; cmp ecx,0 + jz @@Error1_1 ;ошибка тайм-аута + ; Проверить готовность + in AL, DX + test AL, 80h ;состояние сигнала BSY + jnz @@WaitCompleet_1 + test AL, 1 ;состояние сигнала ERR + jnz @@Error6_1 + test AL, 08h ;состояние сигнала DRQ + jz @@WaitCompleet_1 +; Принять блок данных от контроллера +; mov AX,DS +; mov ES,AX + mov EDI, Sector512 ;offset Sector512 + mov DX, [ATABasePortAddr];порт 1x0h + mov CX, 256;число считываемых слов + rep insw + ret +; Записать код ошибки +@@Error1_1: + mov [DevErrorCode], 1 + ret +@@Error6_1: + mov [DevErrorCode], 6 +@@End_1: + ret + +;************************************************* +;* СБРОС УСТРОЙСТВА * +;* Входные параметры передаются через глобальные * +;* переменные: * +;* ChannelNumber - номер канала (1 или 2); * +;* DiskNumber - номер диска (0 или 1). * +;************************************************* +DeviceReset: +; Проверить корректность номера канала + mov BX, [ChannelNumber] + cmp BX, 1 + jb @@Err3_2 + cmp BX, 2 + ja @@Err3_2 +; Установить базовый адрес + dec BX + shl BX, 1 + movzx ebx, bx + mov DX, [ebx+StandardATABases] + mov [ATABasePortAddr], DX +; Выбрать нужный диск + add DX, 6 ;адрес регистра головок + mov AL, [DiskNumber] + cmp AL, 1 ;проверить номера диска + ja @@Err4_2 + shl AL, 4 + or AL, 10100000b + out DX, AL +; Послать команду "Сброс" + mov AL, 08h + inc DX ;регистр команд + out DX, AL + mov ecx, 0x80000 +@@WaitHDReady_1: + ; Проверить время ожидани + dec ecx +; cmp ecx,0 + je @@Err1_2 ;ошибка тайм-аута + ; Прочитать регистр состояни + in AL, DX + ; Проверить состояние сигнала BSY + test AL, 80h + jnz @@WaitHDReady_1 +; Сбросить признак ошибки + mov [DevErrorCode], 0 + ret +; Обработка ошибок +@@Err1_2: + mov [DevErrorCode], 1 + ret +@@Err3_2: + mov [DevErrorCode], 3 + ret +@@Err4_2: + mov [DevErrorCode], 4 +; Записать код ошибки + ret + +EndFindHDD: + diff --git a/kernel/trunk/detect/disks.inc b/kernel/trunk/detect/disks.inc index aba4571cf..38afc9186 100644 --- a/kernel/trunk/detect/disks.inc +++ b/kernel/trunk/detect/disks.inc @@ -1,15 +1,15 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -include 'dev_fd.inc' -include 'dev_hdcd.inc' -include 'getcache.inc' -include 'sear_par.inc' - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +include 'dev_fd.inc' +include 'dev_hdcd.inc' +include 'getcache.inc' +include 'sear_par.inc' + diff --git a/kernel/trunk/detect/getcache.inc b/kernel/trunk/detect/getcache.inc index d554bfaec..935734b36 100644 --- a/kernel/trunk/detect/getcache.inc +++ b/kernel/trunk/detect/getcache.inc @@ -1,212 +1,212 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - pusha - - mov eax,[pg_data.pages_free] -; 1/32 - shr eax,5 -; round off up to 8 pages - shr eax,3 - shl eax,3 -; translate pages in butes *4096 - shl eax,12 -; check a upper size of the cache, no more than 1 Mb on the physical device - cmp eax,1024*1024 - jbe @f - mov eax,1024*1024 - jmp .continue -@@: -; check a lower size of the cache, not less than 128 Kb on the physical device - cmp eax,128*1024 - jae @f - mov eax,128*1024 -@@: -.continue: - mov [cache_ide0_size],eax - mov [cache_ide1_size],eax - mov [cache_ide2_size],eax - mov [cache_ide3_size],eax - xor eax,eax - mov [hdd_appl_data],1 ;al - mov [cd_appl_data],1 - - mov ch,[DRIVE_DATA+1] - mov cl,ch - and cl,11b - je .ide2 - mov esi,cache_ide3 - call get_cache_ide -.ide2: - mov cl,ch - shr cl,2 - and cl,11b - je .ide1 - mov esi,cache_ide2 - call get_cache_ide -.ide1: - mov cl,ch - shr cl,4 - and cl,11b - je .ide0 - mov esi,cache_ide1 - call get_cache_ide -.ide0: - mov cl,ch - shr cl,6 - and cl,11b - je @f - mov esi,cache_ide0 - call get_cache_ide -@@: - xor ecx,ecx - cmp [NumBiosDisks],ecx - jz .endbd - mov esi,BiosDiskCaches -.loopbd: - push ecx - movsx ecx,byte [BiosDisksData+ecx*4+2] - inc ecx - jz .getbd - add ecx,ecx - movzx eax,byte [DRIVE_DATA+1] - shl eax,cl - and ah,3 - cmp ah,1 - jz .contbd - pop ecx - mov byte [BiosDisksData+ecx*4+2], -1 - push ecx -.getbd: - mov eax,[cache_ide0_size] - mov [esi+cache_ide0_size-cache_ide0],eax - mov cl,1 - call get_cache_ide -.contbd: - pop ecx - add esi,cache_ide1-cache_ide0 - inc ecx - cmp ecx,[NumBiosDisks] - jb .loopbd -.endbd: - jmp end_get_cache - -get_cache_ide: - and [esi+cache_ide0_search_start-cache_ide0],0 - and [esi+cache_ide0_appl_search_start-cache_ide0],0 - push ecx - stdcall kernel_alloc,[esi+cache_ide0_size-cache_ide0] - mov [esi+cache_ide0_pointer-cache_ide0],eax - pop ecx - mov edx,eax - mov eax,[esi+cache_ide0_size-cache_ide0] - shr eax,3 - mov [esi+cache_ide0_system_data_size-cache_ide0],eax - mov ebx,eax - imul eax,7 - mov [esi+cache_ide0_appl_data_size-cache_ide0],eax - add ebx,edx - mov [esi+cache_ide0_data_pointer-cache_ide0],ebx - - cmp cl,10b - je .cd - push ecx - mov eax,[esi+cache_ide0_system_data_size-cache_ide0] - call calculate_for_hd - add eax,[esi+cache_ide0_pointer-cache_ide0] - mov [esi+cache_ide0_system_data-cache_ide0],eax - mov [esi+cache_ide0_system_sad_size-cache_ide0],ecx - - push edi - mov edi,[esi+cache_ide0_pointer-cache_ide0] - call clear_ide_cache - pop edi - - mov eax,[esi+cache_ide0_appl_data_size-cache_ide0] - call calculate_for_hd - add eax,[esi+cache_ide0_data_pointer-cache_ide0] - mov [esi+cache_ide0_appl_data-cache_ide0],eax - mov [esi+cache_ide0_appl_sad_size-cache_ide0],ecx - - push edi - mov edi,[esi+cache_ide0_data_pointer-cache_ide0] - call clear_ide_cache - pop edi - - pop ecx - ret -.cd: - push ecx - mov eax,[esi+cache_ide0_system_data_size-cache_ide0] - call calculate_for_cd - add eax,[esi+cache_ide0_pointer-cache_ide0] - mov [esi+cache_ide0_system_data-cache_ide0],eax - mov [esi+cache_ide0_system_sad_size-cache_ide0],ecx - - push edi - mov edi,[esi+cache_ide0_pointer-cache_ide0] - call clear_ide_cache - pop edi - - mov eax,[esi+cache_ide0_appl_data_size-cache_ide0] - call calculate_for_cd - add eax,[esi+cache_ide0_data_pointer-cache_ide0] - mov [esi+cache_ide0_appl_data-cache_ide0],eax - mov [esi+cache_ide0_appl_sad_size-cache_ide0],ecx - - push edi - mov edi,[esi+cache_ide0_data_pointer-cache_ide0] - call clear_ide_cache - pop edi - - pop ecx - ret - -calculate_for_hd: - push eax - mov ebx,eax - shr eax,9 - shl eax,3 - sub ebx,eax - shr ebx,9 - mov ecx,ebx - shl ebx,9 - pop eax - sub eax,ebx - dec ecx - ret - -calculate_for_cd: - push eax - mov ebx,eax - shr eax,11 - shl eax,3 - sub ebx,eax - shr ebx,11 - mov ecx,ebx - shl ebx,11 - pop eax - sub eax,ebx - dec ecx - ret - -clear_ide_cache: - push eax - shl ecx,1 - xor eax,eax - cld - rep stosd - pop eax - ret - -end_get_cache: -; mov [cache_ide0_pointer],HD_CACHE -; mov [cache_ide0_system_data],HD_CACHE+65536 -; mov [cache_ide0_system_sad_size],1919 - popa \ No newline at end of file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + pusha + + mov eax, [pg_data.pages_free] +; 1/32 + shr eax, 5 +; round off up to 8 pages + shr eax, 3 + shl eax, 3 +; translate pages in butes *4096 + shl eax, 12 +; check a upper size of the cache, no more than 1 Mb on the physical device + cmp eax, 1024*1024 + jbe @f + mov eax, 1024*1024 + jmp .continue +@@: +; check a lower size of the cache, not less than 128 Kb on the physical device + cmp eax, 128*1024 + jae @f + mov eax, 128*1024 +@@: +.continue: + mov [cache_ide0_size], eax + mov [cache_ide1_size], eax + mov [cache_ide2_size], eax + mov [cache_ide3_size], eax + xor eax, eax + mov [hdd_appl_data], 1;al + mov [cd_appl_data], 1 + + mov ch, [DRIVE_DATA+1] + mov cl, ch + and cl, 11b + je .ide2 + mov esi, cache_ide3 + call get_cache_ide +.ide2: + mov cl, ch + shr cl, 2 + and cl, 11b + je .ide1 + mov esi, cache_ide2 + call get_cache_ide +.ide1: + mov cl, ch + shr cl, 4 + and cl, 11b + je .ide0 + mov esi, cache_ide1 + call get_cache_ide +.ide0: + mov cl, ch + shr cl, 6 + and cl, 11b + je @f + mov esi, cache_ide0 + call get_cache_ide +@@: + xor ecx, ecx + cmp [NumBiosDisks], ecx + jz .endbd + mov esi, BiosDiskCaches +.loopbd: + push ecx + movsx ecx, byte [BiosDisksData+ecx*4+2] + inc ecx + jz .getbd + add ecx, ecx + movzx eax, byte [DRIVE_DATA+1] + shl eax, cl + and ah, 3 + cmp ah, 1 + jz .contbd + pop ecx + mov byte [BiosDisksData+ecx*4+2], -1 + push ecx +.getbd: + mov eax, [cache_ide0_size] + mov [esi+cache_ide0_size-cache_ide0], eax + mov cl, 1 + call get_cache_ide +.contbd: + pop ecx + add esi, cache_ide1-cache_ide0 + inc ecx + cmp ecx, [NumBiosDisks] + jb .loopbd +.endbd: + jmp end_get_cache + +get_cache_ide: + and [esi+cache_ide0_search_start-cache_ide0], 0 + and [esi+cache_ide0_appl_search_start-cache_ide0], 0 + push ecx + stdcall kernel_alloc, [esi+cache_ide0_size-cache_ide0] + mov [esi+cache_ide0_pointer-cache_ide0], eax + pop ecx + mov edx, eax + mov eax, [esi+cache_ide0_size-cache_ide0] + shr eax, 3 + mov [esi+cache_ide0_system_data_size-cache_ide0], eax + mov ebx, eax + imul eax, 7 + mov [esi+cache_ide0_appl_data_size-cache_ide0], eax + add ebx, edx + mov [esi+cache_ide0_data_pointer-cache_ide0], ebx + + cmp cl, 10b + je .cd + push ecx + mov eax, [esi+cache_ide0_system_data_size-cache_ide0] + call calculate_for_hd + add eax, [esi+cache_ide0_pointer-cache_ide0] + mov [esi+cache_ide0_system_data-cache_ide0], eax + mov [esi+cache_ide0_system_sad_size-cache_ide0], ecx + + push edi + mov edi, [esi+cache_ide0_pointer-cache_ide0] + call clear_ide_cache + pop edi + + mov eax, [esi+cache_ide0_appl_data_size-cache_ide0] + call calculate_for_hd + add eax, [esi+cache_ide0_data_pointer-cache_ide0] + mov [esi+cache_ide0_appl_data-cache_ide0], eax + mov [esi+cache_ide0_appl_sad_size-cache_ide0], ecx + + push edi + mov edi, [esi+cache_ide0_data_pointer-cache_ide0] + call clear_ide_cache + pop edi + + pop ecx + ret +.cd: + push ecx + mov eax, [esi+cache_ide0_system_data_size-cache_ide0] + call calculate_for_cd + add eax, [esi+cache_ide0_pointer-cache_ide0] + mov [esi+cache_ide0_system_data-cache_ide0], eax + mov [esi+cache_ide0_system_sad_size-cache_ide0], ecx + + push edi + mov edi, [esi+cache_ide0_pointer-cache_ide0] + call clear_ide_cache + pop edi + + mov eax, [esi+cache_ide0_appl_data_size-cache_ide0] + call calculate_for_cd + add eax, [esi+cache_ide0_data_pointer-cache_ide0] + mov [esi+cache_ide0_appl_data-cache_ide0], eax + mov [esi+cache_ide0_appl_sad_size-cache_ide0], ecx + + push edi + mov edi, [esi+cache_ide0_data_pointer-cache_ide0] + call clear_ide_cache + pop edi + + pop ecx + ret + +calculate_for_hd: + push eax + mov ebx, eax + shr eax, 9 + shl eax, 3 + sub ebx, eax + shr ebx, 9 + mov ecx, ebx + shl ebx, 9 + pop eax + sub eax, ebx + dec ecx + ret + +calculate_for_cd: + push eax + mov ebx, eax + shr eax, 11 + shl eax, 3 + sub ebx, eax + shr ebx, 11 + mov ecx, ebx + shl ebx, 11 + pop eax + sub eax, ebx + dec ecx + ret + +clear_ide_cache: + push eax + shl ecx, 1 + xor eax, eax + cld + rep stosd + pop eax + ret + +end_get_cache: +; mov [cache_ide0_pointer],HD_CACHE +; mov [cache_ide0_system_data],HD_CACHE+65536 +; mov [cache_ide0_system_sad_size],1919 + popa diff --git a/kernel/trunk/detect/sear_par.inc b/kernel/trunk/detect/sear_par.inc index 920505d59..913556542 100644 --- a/kernel/trunk/detect/sear_par.inc +++ b/kernel/trunk/detect/sear_par.inc @@ -1,157 +1,157 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;**************************************************** -; поиск логических дисков на обнаруженных HDD -; и занесение данных в область таблицы -; автор Mario79 -;**************************************************** - mov [transfer_adress],DRIVE_DATA+0xa - search_partitions_ide0: - test [DRIVE_DATA+1],byte 0x40 - jz search_partitions_ide1 - mov [hdbase],0x1f0 - mov [hdid],0x0 - mov [hdpos],1 - mov [known_part],1 - search_partitions_ide0_1: - call set_PARTITION_variables - test [problem_partition],2 - jnz search_partitions_ide1 ; not found part - test [problem_partition],1 - jnz @F ; not found known_part - ;cmp [problem_partition],0 - ;jne search_partitions_ide1 - inc byte [DRIVE_DATA+2] - call partition_data_transfer - add [transfer_adress],100 - @@: - inc [known_part] - jmp search_partitions_ide0_1 - - search_partitions_ide1: - test [DRIVE_DATA+1],byte 0x10 - jz search_partitions_ide2 - mov [hdbase],0x1f0 - mov [hdid],0x10 - mov [hdpos],2 - mov [known_part],1 - search_partitions_ide1_1: - call set_PARTITION_variables - test [problem_partition],2 - jnz search_partitions_ide2 - test [problem_partition],1 - jnz @F - ;cmp [problem_partition],0 - ;jne search_partitions_ide2 - inc byte [DRIVE_DATA+3] - call partition_data_transfer - add [transfer_adress],100 - @@: - inc [known_part] - jmp search_partitions_ide1_1 - - search_partitions_ide2: - test [DRIVE_DATA+1],byte 0x4 - jz search_partitions_ide3 - mov [hdbase],0x170 - mov [hdid],0x0 - mov [hdpos],3 - mov [known_part],1 - search_partitions_ide2_1: - call set_PARTITION_variables - test [problem_partition],2 - jnz search_partitions_ide3 - test [problem_partition],1 - jnz @F - ;cmp [problem_partition],0 - ;jne search_partitions_ide3 - inc byte [DRIVE_DATA+4] - call partition_data_transfer - add [transfer_adress],100 - @@: - inc [known_part] - jmp search_partitions_ide2_1 - - search_partitions_ide3: - test [DRIVE_DATA+1],byte 0x1 - jz end_search_partitions_ide - mov [hdbase],0x170 - mov [hdid],0x10 - mov [hdpos],4 - mov [known_part],1 - search_partitions_ide3_1: - call set_PARTITION_variables - test [problem_partition],2 - jnz end_search_partitions_ide - test [problem_partition],1 - jnz @F - ;cmp [problem_partition],0 - ;jne end_search_partitions_ide - inc byte [DRIVE_DATA+5] - call partition_data_transfer - add [transfer_adress],100 - @@: - inc [known_part] - jmp search_partitions_ide3_1 - -end_search_partitions_ide: - mov [hdpos], 80h - mov ecx, [NumBiosDisks] - test ecx, ecx - jz end_search_partitions -start_search_partitions_bd: - push ecx - mov eax, [hdpos] - and [BiosDiskPartitions+(eax-80h)*4], 0 - mov [known_part], 1 -search_partitions_bd: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;**************************************************** +; поиск логических дисков на обнаруженных HDD +; и занесение данных в область таблицы +; автор Mario79 +;**************************************************** + mov [transfer_adress], DRIVE_DATA+0xa + search_partitions_ide0: + test [DRIVE_DATA+1], byte 0x40 + jz search_partitions_ide1 + mov [hdbase], 0x1f0 + mov [hdid], 0x0 + mov [hdpos], 1 + mov [known_part], 1 + search_partitions_ide0_1: call set_PARTITION_variables - test [problem_partition],2 - jnz end_search_partitions_bd - test [problem_partition],1 - jnz @F - ;cmp [problem_partition], 0 - ;jne end_search_partitions_bd - mov eax, [hdpos] - inc [BiosDiskPartitions+(eax-80h)*4] - call partition_data_transfer + test [problem_partition], 2 + jnz search_partitions_ide1 ; not found part + test [problem_partition], 1 + jnz @F ; not found known_part + ;cmp [problem_partition],0 + ;jne search_partitions_ide1 + inc byte [DRIVE_DATA+2] + call partition_data_transfer add [transfer_adress], 100 - @@: - inc [known_part] - jmp search_partitions_bd -end_search_partitions_bd: - pop ecx - inc [hdpos] - loop start_search_partitions_bd - jmp end_search_partitions - -partition_data_transfer: - mov edi,[transfer_adress] - mov esi,PARTITION_START ;start of file_system_data - mov ecx,(file_system_data_size+3)/4 - rep movsd - ret -uglobal -transfer_adress dd 0 -endg -partition_data_transfer_1: -; cli - push edi - mov edi,PARTITION_START - mov esi,[transfer_adress] - mov ecx,(file_system_data_size+3)/4 - rep movsd - pop edi -; sti - ret - + @@: + inc [known_part] + jmp search_partitions_ide0_1 + + search_partitions_ide1: + test [DRIVE_DATA+1], byte 0x10 + jz search_partitions_ide2 + mov [hdbase], 0x1f0 + mov [hdid], 0x10 + mov [hdpos], 2 + mov [known_part], 1 + search_partitions_ide1_1: + call set_PARTITION_variables + test [problem_partition], 2 + jnz search_partitions_ide2 + test [problem_partition], 1 + jnz @F + ;cmp [problem_partition],0 + ;jne search_partitions_ide2 + inc byte [DRIVE_DATA+3] + call partition_data_transfer + add [transfer_adress], 100 + @@: + inc [known_part] + jmp search_partitions_ide1_1 + + search_partitions_ide2: + test [DRIVE_DATA+1], byte 0x4 + jz search_partitions_ide3 + mov [hdbase], 0x170 + mov [hdid], 0x0 + mov [hdpos], 3 + mov [known_part], 1 + search_partitions_ide2_1: + call set_PARTITION_variables + test [problem_partition], 2 + jnz search_partitions_ide3 + test [problem_partition], 1 + jnz @F + ;cmp [problem_partition],0 + ;jne search_partitions_ide3 + inc byte [DRIVE_DATA+4] + call partition_data_transfer + add [transfer_adress], 100 + @@: + inc [known_part] + jmp search_partitions_ide2_1 + + search_partitions_ide3: + test [DRIVE_DATA+1], byte 0x1 + jz end_search_partitions_ide + mov [hdbase], 0x170 + mov [hdid], 0x10 + mov [hdpos], 4 + mov [known_part], 1 + search_partitions_ide3_1: + call set_PARTITION_variables + test [problem_partition], 2 + jnz end_search_partitions_ide + test [problem_partition], 1 + jnz @F + ;cmp [problem_partition],0 + ;jne end_search_partitions_ide + inc byte [DRIVE_DATA+5] + call partition_data_transfer + add [transfer_adress], 100 + @@: + inc [known_part] + jmp search_partitions_ide3_1 + +end_search_partitions_ide: + mov [hdpos], 80h + mov ecx, [NumBiosDisks] + test ecx, ecx + jz end_search_partitions +start_search_partitions_bd: + push ecx + mov eax, [hdpos] + and [BiosDiskPartitions+(eax-80h)*4], 0 + mov [known_part], 1 +search_partitions_bd: + call set_PARTITION_variables + test [problem_partition], 2 + jnz end_search_partitions_bd + test [problem_partition], 1 + jnz @F + ;cmp [problem_partition], 0 + ;jne end_search_partitions_bd + mov eax, [hdpos] + inc [BiosDiskPartitions+(eax-80h)*4] + call partition_data_transfer + add [transfer_adress], 100 + @@: + inc [known_part] + jmp search_partitions_bd +end_search_partitions_bd: + pop ecx + inc [hdpos] + loop start_search_partitions_bd + jmp end_search_partitions + +partition_data_transfer: + mov edi, [transfer_adress] + mov esi, PARTITION_START ;start of file_system_data + mov ecx, (file_system_data_size+3)/4 + rep movsd + ret +uglobal +transfer_adress dd 0 +endg +partition_data_transfer_1: +; cli + push edi + mov edi, PARTITION_START + mov esi, [transfer_adress] + mov ecx, (file_system_data_size+3)/4 + rep movsd + pop edi +; sti + ret + end_search_partitions: diff --git a/kernel/trunk/drivers/apm.asm b/kernel/trunk/drivers/apm.asm index 060d9fb93..ac78b4973 100644 --- a/kernel/trunk/drivers/apm.asm +++ b/kernel/trunk/drivers/apm.asm @@ -1,295 +1,343 @@ -; 11.09.2009 staper@inbox.ru -; see kernel\docs\apm.txt - -use32 - - org 0x0 - - db 'MENUET01' - dd 0x1 - dd START - dd I_END - dd (I_END+100) and not 3 - dd (I_END+100) and not 3 - dd 0x0,0x0 - -include 'macros.inc' - -START: - mcall 40,0x7 - - mcall 49,0x0001,0x0001,0x5308 ;CX = FFFFh APM v1.0 -; mcall 49,0x0001,0x0001,0x530d -; mcall 49,0x0001,0x0001,0x530f - -; mcall 49,0x0000,,0x5310 ;bl - number of batteries -redraw: - mcall 49,0x0000,,0x530c - dec cl - jz still - mcall 49,0x0001,0x0001,0x5308 - mcall 49,0x01ff,,0x530c - test cl,cl - jz @f - mcall 49,0x0000,0x0001,0x530d - mcall 49,0x0000,0x0000,0x5307 - mcall 49,0x0000,0x0001,0x5308 - @@: - mcall 12,1 - mcall 0,100*65536+235,100*65536+90,0x34ffffff,0x000000,title - mcall 49,0x0000,,0x5300 - jnc @f - mcall 4,10*65536+3,0x80000000,text.4 - bts [flags],1 - jmp .end - @@: cmp al,0 - jne @f - mov edx,text.1 - jmp .0 - @@: cmp al,1 - jne @f - mov edx,text.2 - jmp .0 - @@: mov edx,text.3 - .0: push edx - mcall 4,169*65536+3,0x80dddddd,text.0 - pop edx - add ebx,47*65536 - mcall - mcall 49,0x0001,,0x530a - jc .error - push si dx cx bx ;time of battery life, b. flag, b. status, AC line status - - ;AC line status - cmp bh,0 - jne @f - mov edx,text.01 - jmp .1 - @@: cmp bh,1 - jne @f - mov edx,text.02 - jmp .1 - @@: cmp bh,2 - jne @f - mov edx,text.03 - jmp .1 - @@: mov edx,text.04 - .1: push edx - mcall 4,10*65536+10,0x80000000,text.00 - pop edx - mcall ,100*65536+10,;0x80000000 - - ;battery status - pop bx - cmp bl,0 - jne @f - mov edx,text.11 - jmp .2 - @@: cmp bl,1 - jne @f - mov edx,text.12 - jmp .2 - @@: cmp bl,2 - jne @f - mov edx,text.13 - jmp .2 - @@: cmp bl,3 - jne @f - mov edx,text.14 - jmp .2 - @@: mov edx,text.04 - .2: push edx - mcall 4,10*65536+20,0x80000000,text.10 - pop edx - mcall ,100*65536+20, - - ;battery life, percentage and minutes/seconds - mcall ,10*65536+30,,text.20 - pop cx - cmp cl,0xff - jne @f - mcall ,100*65536+30,0x80000000,text.04 - pop eax - jmp .end - @@: shl ecx,24 - shr ecx,24 - mcall 47,0x80030000,,100*65536+30,0x347636 - .3: mcall 4,115*65536+30,0x80000000,text.15 - mov dx,[esp] - shl edx,17 - shr edx,17 - mov ecx,edx - mcall 47,0x80030000,,140*65536+30 - pop cx - mov edx,text.21 - bt cx,15 - jc @f - mov edx,text.22 - @@: mcall 4,160*65536+30,0x80000000 - pop si - .error: - .end: - ;buttons - mcall 8,148*65536+16,45*65536+15,3,0x00677ab0 - mcall ,166*65536+16,,4, - mcall ,184*65536+16,,5, - mcall ,202*65536+16,,6, - bt [flags],1 - jc @f - mcall ,65*65536+45,,2, - @@: mcall 4,10*65536+50,0x80564242,text.30 - mcall 12,2 - -still: -; mcall 10 - mcall 23,12000 - test eax,eax - jz redraw - - dec al - jz redraw - dec al - jz key - dec al - jz button - jmp still - - - - -key: - mcall 2 - jmp still - -button: - mcall 17 - cmp ah,1 - jne @f - mcall -1 - - @@: cmp ah,2 - jne @f - mcall 5,50 - mcall 49,0x0001,0x0001,0x5307 - jmp redraw - - @@: cmp ah,4 - jg @f - mov edx,0x01f7 ;primary chan. - call reserv_ports - jc redraw - sub bh,3 - .1: call set_drive - btc [flags],2 - jnc .2 - call device_reset - jmp .3 - .2: call standby_hdd - .3: call free_ports - jmp redraw - - @@: cmp ah,6 - jg redraw - mov edx,0x0177 ;secondary chan. - call reserv_ports - jc redraw - sub bh,5 - jmp .1 - -set_drive: - dec dx - in al,dx - test bh,bh - jnz @f - btr ax,4 -.1: out dx,al - inc dx - ret -@@: bts ax,4 - jmp .1 - - -standby_hdd: -; 94h E0h nondata standby immediate -; 95h E1h nondata idle immediate -; 96h E2h nondata standby -; 97h E3h nondata idle -; 98h E5h nondata check power mode -; 99h E6h nondata set sleep mode - xor ecx,ecx - @@: in al,dx - dec cx - jz @f - bt ax,6 - jnc @b - mov al,0x96 - out dx,al - mov al,0xe2 - out dx,al -@@: -ret - -reserv_ports: - mov ecx,edx - dec ecx - push ax - mcall 46,0 - test al,al - jnz @f - pop bx - clc - ret -@@: pop bx - stc -ret - -device_reset: - xor ecx,ecx - @@: in al,dx - dec cx - jz @f - bt ax,6 - jnc @b - mov al,0x10 - out dx,al -@@: -ret - -free_ports: - mov ecx,edx - dec ecx - mcall 46,1 -ret - - -; „ЂЌЌ›… ЏђЋѓђЂЊЊ› -title db '',0 -flags dw 0 - -text: -.0: db 'APM v.1.',0 -.1: db '0',0 -.2: db '1',0 -.3: db '2',0 -.4: db 'APM not supported',0 - -.00: db 'power status:',0 -.01: db 'off-line',0 -.02: db 'on-line',0 -.03: db 'on backup power',0 -.04: db 'unknown',0 - -.10: db 'battery flag:',0 -.11: db 'high',0 -.12: db 'low',0 -.13: db 'critical',0 -.14: db 'charging',0 -.15: db ' % ,',0 - -.20: db 'battery life:',0 -.21: db 'min',0 -.22: db 'sec',0 - -.30: db 'STAND-BY: SYSTEM HDD: 0 1 2 3',0 - -I_END: +; 11.09.2009 staper@inbox.ru +; see kernel\docs\apm.txt + +use32 + + org 0x0 + + db 'MENUET01' + dd 0x1 + dd START + dd I_END + dd (I_END+100) and not 3 + dd (I_END+100) and not 3 + dd 0x0,0x0 + +include 'macros.inc' + +START: + mcall 40,0x7 + + mcall 49,0x0001,0x0001,0x5308 ;CX = FFFFh APM v1.0 +; mcall 49,0x0001,0x0001,0x530d +; mcall 49,0x0001,0x0001,0x530f + +; mcall 49,0x0000,,0x5310 ;bl - number of batteries +redraw: + mcall 49,0x0000,,0x530c + dec cl + jz still + mcall 49,0x0001,0x0001,0x5308 + mcall 49,0x01ff,,0x530c + test cl, cl + jz @f + mcall 49,0x0000,0x0001,0x530d + mcall 49,0x0000,0x0000,0x5307 + mcall 49,0x0000,0x0001,0x5308 + @@: + mcall 12,1 + mcall 0,100*65536+235,100*65536+90,0x34ffffff,0x000000,title + mcall 49,0x0000,,0x5300 + jnc @f + mcall 4,10*65536+3,0x80000000,text.4 + bts [flags], 1 + jmp .end + @@: + cmp al, 0 + jne @f + mov edx, text.1 + jmp .0 + @@: + cmp al, 1 + jne @f + mov edx, text.2 + jmp .0 + @@: + mov edx, text.3 + .0: + push edx + mcall 4,169*65536+3,0x80dddddd,text.0 + pop edx + add ebx, 47*65536 + mcall + mcall 49,0x0001,,0x530a + jc .error + push si dx cx bx ;time of battery life, b. flag, b. status, AC line status + + ;AC line status + cmp bh, 0 + jne @f + mov edx, text.01 + jmp .1 + @@: + cmp bh, 1 + jne @f + mov edx, text.02 + jmp .1 + @@: + cmp bh, 2 + jne @f + mov edx, text.03 + jmp .1 + @@: + mov edx, text.04 + .1: + push edx + mcall 4,10*65536+10,0x80000000,text.00 + pop edx + mcall ,100*65536+10,;0x80000000 + + ;battery status + pop bx + cmp bl, 0 + jne @f + mov edx, text.11 + jmp .2 + @@: + cmp bl, 1 + jne @f + mov edx, text.12 + jmp .2 + @@: + cmp bl, 2 + jne @f + mov edx, text.13 + jmp .2 + @@: + cmp bl, 3 + jne @f + mov edx, text.14 + jmp .2 + @@: + mov edx, text.04 + .2: + push edx + mcall 4,10*65536+20,0x80000000,text.10 + pop edx + mcall ,100*65536+20, + + ;battery life, percentage and minutes/seconds + mcall ,10*65536+30,,text.20 + pop cx + cmp cl, 0xff + jne @f + mcall ,100*65536+30,0x80000000,text.04 + pop eax + jmp .end + @@: + shl ecx, 24 + shr ecx, 24 + mcall 47,0x80030000,,100*65536+30,0x347636 + .3: + mcall 4,115*65536+30,0x80000000,text.15 + mov dx, [esp] + shl edx, 17 + shr edx, 17 + mov ecx, edx + mcall 47,0x80030000,,140*65536+30 + pop cx + mov edx, text.21 + bt cx, 15 + jc @f + mov edx, text.22 + @@: + mcall 4,160*65536+30,0x80000000 + pop si + .error: + .end: + ;buttons + mcall 8,148*65536+16,45*65536+15,3,0x00677ab0 + mcall ,166*65536+16,,4, + mcall ,184*65536+16,,5, + mcall ,202*65536+16,,6, + bt [flags], 1 + jc @f + mcall ,65*65536+45,,2, + @@: + mcall 4,10*65536+50,0x80564242,text.30 + mcall 12,2 + +still: +; mcall 10 + mcall 23,12000 + test eax, eax + jz redraw + + dec al + jz redraw + dec al + jz key + dec al + jz button + jmp still + + + + +key: + mcall 2 + jmp still + +button: + mcall 17 + cmp ah, 1 + jne @f + mcall -1 + + @@: + cmp ah, 2 + jne @f + mcall 5,50 + mcall 49,0x0001,0x0001,0x5307 + jmp redraw + + @@: + cmp ah, 4 + jg @f + mov edx, 0x01f7 ;primary chan. + call reserv_ports + jc redraw + sub bh, 3 + .1: + call set_drive + btc [flags], 2 + jnc .2 + call device_reset + jmp .3 + .2: + call standby_hdd + .3: + call free_ports + jmp redraw + + @@: + cmp ah, 6 + jg redraw + mov edx, 0x0177 ;secondary chan. + call reserv_ports + jc redraw + sub bh, 5 + jmp .1 + +set_drive: + dec dx + in al, dx + test bh, bh + jnz @f + btr ax, 4 +.1: + out dx, al + inc dx + ret +@@: + bts ax, 4 + jmp .1 + + +standby_hdd: +; 94h E0h nondata standby immediate +; 95h E1h nondata idle immediate +; 96h E2h nondata standby +; 97h E3h nondata idle +; 98h E5h nondata check power mode +; 99h E6h nondata set sleep mode + xor ecx, ecx + @@: + in al, dx + dec cx + jz @f + bt ax, 6 + jnc @b + mov al, 0x96 + out dx, al + mov al, 0xe2 + out dx, al +@@: + ret + +reserv_ports: + mov ecx, edx + dec ecx + push ax + mcall 46,0 + test al, al + jnz @f + pop bx + clc + ret +@@: + pop bx + stc + ret + +device_reset: + xor ecx, ecx + @@: + in al, dx + dec cx + jz @f + bt ax, 6 + jnc @b + mov al, 0x10 + out dx, al +@@: + ret + +free_ports: + mov ecx, edx + dec ecx + mcall 46,1 + ret + + +; „ЂЌЌ›… ЏђЋѓђЂЊЊ› +title db '',0 +flags dw 0 + +text: +.0: + db 'APM v.1.',0 +.1: + db '0',0 +.2: + db '1',0 +.3: + db '2',0 +.4: + db 'APM not supported',0 + +.00: + db 'power status:',0 +.01: + db 'off-line',0 +.02: + db 'on-line',0 +.03: + db 'on backup power',0 +.04: + db 'unknown',0 + +.10: + db 'battery flag:',0 +.11: + db 'high',0 +.12: + db 'low',0 +.13: + db 'critical',0 +.14: + db 'charging',0 +.15: + db ' % ,',0 + +.20: + db 'battery life:',0 +.21: + db 'min',0 +.22: + db 'sec',0 + +.30: + db 'STAND-BY: SYSTEM HDD: 0 1 2 3',0 + +I_END: diff --git a/kernel/trunk/drivers/codec.inc b/kernel/trunk/drivers/codec.inc index 80a6661be..8c6bf751a 100644 --- a/kernel/trunk/drivers/codec.inc +++ b/kernel/trunk/drivers/codec.inc @@ -1,326 +1,326 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -AD_LOSEL equ BIT5 -AD_HPSEL equ BIT10 - -align 4 -proc detect_codec - locals - codec_id dd ? - endl - - stdcall codec_read, dword 0x7C - shl eax, 16 - mov [codec_id], eax - - stdcall codec_read, dword 0x7E - or eax, [codec_id] - - mov [codec.chip_id], eax - and eax, 0xFFFFFF00 - - mov edi, codecs -@@: - mov ebx, [edi] - test ebx, ebx - jz .unknown - - cmp eax, ebx - jne .next - mov eax, [edi+4] - mov [codec.ac_vendor_ids], eax - mov esi, eax - call SysMsgBoardStr - stdcall detect_chip, [edi+8] - - ret -.next: - add edi, 12 - jmp @B -.unknown: - mov [codec.ac_vendor_ids], ac_unknown - mov [codec.chip_ids], chip_unknown - - mov esi, chip_unknown - call SysMsgBoardStr - mov eax, [codec.chip_id] - call dword2str - call SysMsgBoardStr - ret -endp - -align 4 -proc detect_chip stdcall, chip_tab:dword - - mov eax, [codec.chip_id] - and eax, 0xFF - - mov edi, [chip_tab] -@@: - mov ebx, [edi] - cmp ebx, 0xFF - je .unknown - - cmp eax,ebx - jne .next - mov eax, [edi+4] - mov [codec.chip_ids], eax - mov esi, eax - call SysMsgBoardStr - ret -.next: - add edi, 8 - jmp @b -.unknown: - mov [codec.chip_ids], chip_unknown - mov esi, chip_unknown - call SysMsgBoardStr - mov eax, [codec.chip_id] - call dword2str - call SysMsgBoardStr - ret -endp - -align 4 -proc setup_codec - - xor eax, eax - stdcall codec_write, dword CODEC_AUX_VOL - - mov eax, 0x0B0B - stdcall codec_write, dword CODEC_MASTER_VOL_REG - - mov ax, 0x08 - stdcall codec_write, dword 0x0C - - mov ax, 0x0808 - stdcall codec_write, dword CODEC_PCM_OUT_REG - - mov ax, 0x0808 - stdcall codec_write, dword 0x10 - - mov ax, 0x0808 - stdcall codec_write, dword 0x12 - - mov ax, 0x0808 - stdcall codec_write, dword 0x16 - - - stdcall codec_read, dword CODEC_EXT_AUDIO_CTRL_REG - and eax, 0FFFFh - BIT1 ; clear DRA (BIT1) - or eax, BIT0 ; set VRA (BIT0) - stdcall codec_write, dword CODEC_EXT_AUDIO_CTRL_REG - - stdcall set_sample_rate, dword 48000 - -.init_error: - xor eax, eax ; exit with error - ret -endp - - -; param -; eax= volume -10000 - 0 for both channels - -align 4 -set_master_vol: - cmp eax, 0 - jl @F - xor eax, eax - jmp .set -@@: - cmp eax, -9450 - jg .set - mov eax, -9450 ;clamp into 6 bits -.set: - cdq - mov ebx, -150 - idiv ebx - mov ah, al - stdcall codec_write, dword CODEC_MASTER_VOL_REG - xor eax, eax - ret - -align 4 -proc get_master_vol stdcall, pvol:dword - - stdcall codec_read, dword CODEC_MASTER_VOL_REG - and eax, 0x3F - imul eax, -150 - mov ebx, [pvol] - mov [ebx], eax - xor eax, eax - ret -endp - -align 4 -proc set_sample_rate stdcall, rate:dword - mov eax, [rate] - stdcall codec_write, dword CODEC_PCM_FRONT_DACRATE_REG - ret -endp - -patch_AD: - stdcall codec_read, 0x76 - or ax, BIT5+BIT10 - stdcall codec_write, 0x76 - ret - - -align 16 -ac_unknown db 'unknown manufacturer',13,10,0 -ac_Realtek db 'Realtek Semiconductor',13,10,0 -ac_Analog db 'Analog Devices',13,10,0 -ac_CMedia db 'C-Media Electronics',13,10,0 -ac_Cirrus db 'Cirrus Logic',13,10,0 -ac_Wolfson db 'Wolfson Microelectronics',13,10,0 -ac_VIA db 'VIA Technologies',13,10,0 -ac_SigmaTel db 'SigmaTel',13,10,0 -ac_eMicro db 'eMicro',13,10,0 - -chip_unknown db 'unknown codec id ', 0 - -CHIP_ANALOG equ 0x41445300 -CHIP_REALTEK equ 0x414C4700 -CHIP_CMEDIA equ 0x434D4900 -CHIP_CIRRUS equ 0x43525900 -CHIP_WOLFSON equ 0x574D4C00 -CHIP_VIA equ 0x56494100 -CHIP_SIGMATEL equ 0x83847600 -CHIP_EMICRO equ 0x454D4300 - -align 16 -codecs dd CHIP_ANALOG, ac_Analog, chips_Analog - dd CHIP_CMEDIA, ac_CMedia, chips_CMedia - dd CHIP_REALTEK,ac_Realtek, chips_Realtek - dd CHIP_CIRRUS, ac_Cirrus, chips_Cirrus - dd CHIP_WOLFSON,ac_Wolfson, chips_Wolfson - dd CHIP_VIA, ac_VIA, chips_VIA - dd CHIP_SIGMATEL, ac_SigmaTel, chips_SigmaTel - dd CHIP_EMICRO, ac_eMicro, chips_eMicro - dd 0 - -align 16 -chips_Analog dd 0x03, chip_AD1819 - dd 0x40, chip_AD1881 - dd 0x48, chip_AD1881A - dd 0x60, chip_AD1884 - dd 0x61, chip_AD1886 - dd 0x62, chip_AD1887 - dd 0x63, chip_AD1886A - dd 0x70, chip_AD1980 - dd 0x72, chip_AD1981A - dd 0x74, chip_AD1981B - dd 0x75, chip_AD1985 - dd 0xFF - -chips_Realtek: - dd 0x10, chip_ALC201a - dd 0x20, chip_ALC650 - dd 0x21, chip_ALC650D - dd 0x22, chip_ALC650E - dd 0x23, chip_ALC650F - dd 0x60, chip_ALC655 - dd 0x80, chip_ALC658 - dd 0x81, chip_ALC658D - dd 0x90, chip_ALC850 - dd 0xFF - -chips_CMedia dd 0x41, chip_CM9738 - dd 0x61, chip_CM9739 - dd 0x69, chip_CM9780 - dd 0x78, chip_CM9761 - dd 0x82, chip_CM9761 - dd 0x83, chip_CM9761 - dd 0xFF - -chips_Cirrus dd 0x00, chip_CS4297 - dd 0x10, chip_CS4297A - dd 0x20, chip_CS4298 - dd 0x28, chip_CS4294 - dd 0x30, chip_CS4299 - dd 0x34, chip_CS4299D - dd 0x48, chip_CS4201 - dd 0x58, chip_CS4205 - dd 0x60, chip_CS4291 - dd 0x70, chip_CS4202 - dd 0xFF - -chips_Wolfson dd 0x00, chip_WM9700 - dd 0x03, chip_WM9703 - dd 0x04, chip_WM9704 - dd 0xFF - -chips_VIA dd 0x61, chip_VIA1612A - dd 0xFF - -chips_SigmaTel dd 0x58, chip_STAC9758 - dd 0xFF - -chips_eMicro dd 0x28, chip_EM28028 - dd 0xFF - -align 16 -;Analog Devices -chip_AD1819 db 'AD1819 ',0dh,0ah,00h -chip_AD1881 db 'AD1881 ',0dh,0ah,00h -chip_AD1881A db 'AD1881A',0dh,0ah,00h -chip_AD1884 db 'AD1885 ',0dh,0ah,00h -chip_AD1885 db 'AD1885 ',0dh,0ah,00h -chip_AD1886 db 'AD1886 ',0dh,0ah,00h -chip_AD1886A db 'AD1886A',0dh,0ah,00h -chip_AD1887 db 'AD1887 ',0dh,0ah,00h -chip_AD1980 db 'AD1980 ',0dh,0ah,00h -chip_AD1981A db 'AD1981A',0dh,0ah,00h -chip_AD1981B db 'AD1981B',0dh,0ah,00h -chip_AD1985 db 'AD1985 ',0dh,0ah,00h - -;Realtek -chip_ALC201a db 'ALC201a',0dh,0ah,00h -chip_ALC650 db 'ALC650 ',0dh,0ah,00h -chip_ALC650D db 'ALC650D',0dh,0ah,00h -chip_ALC650E db 'ALC650E',0dh,0ah,00h -chip_ALC650F db 'ALC650F',0dh,0ah,00h -chip_ALC655 db 'ALC655 ',0dh,0ah,00h -chip_ALC658 db 'ALC658 ',0dh,0ah,00h -chip_ALC658D db 'ALC658D',0dh,0ah,00h -chip_ALC850 db 'ALC850 ',0dh,0ah,00h - -;CMedia -chip_CM9738 db 'CMI9738', 0dh,0ah,0 -chip_CM9739 db 'CMI9739', 0dh,0ah,0 -chip_CM9780 db 'CMI9780', 0dh,0ah,0 -chip_CM9761 db 'CMI9761', 0dh,0ah,0 - -;Cirrus -chip_CS4297 db 'CS4297',13,10,0 -chip_CS4297A db 'CS4297A',13,10,0 -chip_CS4298 db 'CS4298',13,10,0 -chip_CS4294 db 'CS4294',13,10,0 -chip_CS4299 db 'CS4299',13,10,0 -chip_CS4299D db 'CS4299D',13,10,0 -chip_CS4201 db 'CS4201',13,10,0 -chip_CS4205 db 'CS4205',13,10,0 -chip_CS4291 db 'CS4291',13,10,0 -chip_CS4202 db 'CS4202',13,10,0 - -;Wolfson -chip_WM9700 db 'WM9704',13,10,0 -chip_WM9703 db 'WM9703/9704',13,10,0 -chip_WM9704 db 'WM9704 (quad)',13,10,0 - -;VIA -chip_VIA1612A db 'VIA1612A',13,10,0 - -;SigmaTel -chip_STAC9758 db 'STAC9758,59',13,10,0 - -;eMicro -chip_EM28028 db 'EM28028',13,10,0 - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +AD_LOSEL equ BIT5 +AD_HPSEL equ BIT10 + +align 4 +proc detect_codec + locals + codec_id dd ? + endl + + stdcall codec_read, dword 0x7C + shl eax, 16 + mov [codec_id], eax + + stdcall codec_read, dword 0x7E + or eax, [codec_id] + + mov [codec.chip_id], eax + and eax, 0xFFFFFF00 + + mov edi, codecs +@@: + mov ebx, [edi] + test ebx, ebx + jz .unknown + + cmp eax, ebx + jne .next + mov eax, [edi+4] + mov [codec.ac_vendor_ids], eax + mov esi, eax + call SysMsgBoardStr + stdcall detect_chip, [edi+8] + + ret +.next: + add edi, 12 + jmp @B +.unknown: + mov [codec.ac_vendor_ids], ac_unknown + mov [codec.chip_ids], chip_unknown + + mov esi, chip_unknown + call SysMsgBoardStr + mov eax, [codec.chip_id] + call dword2str + call SysMsgBoardStr + ret +endp + +align 4 +proc detect_chip stdcall, chip_tab:dword + + mov eax, [codec.chip_id] + and eax, 0xFF + + mov edi, [chip_tab] +@@: + mov ebx, [edi] + cmp ebx, 0xFF + je .unknown + + cmp eax, ebx + jne .next + mov eax, [edi+4] + mov [codec.chip_ids], eax + mov esi, eax + call SysMsgBoardStr + ret +.next: + add edi, 8 + jmp @b +.unknown: + mov [codec.chip_ids], chip_unknown + mov esi, chip_unknown + call SysMsgBoardStr + mov eax, [codec.chip_id] + call dword2str + call SysMsgBoardStr + ret +endp + +align 4 +proc setup_codec + + xor eax, eax + stdcall codec_write, dword CODEC_AUX_VOL + + mov eax, 0x0B0B + stdcall codec_write, dword CODEC_MASTER_VOL_REG + + mov ax, 0x08 + stdcall codec_write, dword 0x0C + + mov ax, 0x0808 + stdcall codec_write, dword CODEC_PCM_OUT_REG + + mov ax, 0x0808 + stdcall codec_write, dword 0x10 + + mov ax, 0x0808 + stdcall codec_write, dword 0x12 + + mov ax, 0x0808 + stdcall codec_write, dword 0x16 + + + stdcall codec_read, dword CODEC_EXT_AUDIO_CTRL_REG + and eax, 0FFFFh - BIT1 ; clear DRA (BIT1) + or eax, BIT0 ; set VRA (BIT0) + stdcall codec_write, dword CODEC_EXT_AUDIO_CTRL_REG + + stdcall set_sample_rate, dword 48000 + +.init_error: + xor eax, eax ; exit with error + ret +endp + + +; param +; eax= volume -10000 - 0 for both channels + +align 4 +set_master_vol: + cmp eax, 0 + jl @F + xor eax, eax + jmp .set +@@: + cmp eax, -9450 + jg .set + mov eax, -9450 ;clamp into 6 bits +.set: + cdq + mov ebx, -150 + idiv ebx + mov ah, al + stdcall codec_write, dword CODEC_MASTER_VOL_REG + xor eax, eax + ret + +align 4 +proc get_master_vol stdcall, pvol:dword + + stdcall codec_read, dword CODEC_MASTER_VOL_REG + and eax, 0x3F + imul eax, -150 + mov ebx, [pvol] + mov [ebx], eax + xor eax, eax + ret +endp + +align 4 +proc set_sample_rate stdcall, rate:dword + mov eax, [rate] + stdcall codec_write, dword CODEC_PCM_FRONT_DACRATE_REG + ret +endp + +patch_AD: + stdcall codec_read, 0x76 + or ax, BIT5+BIT10 + stdcall codec_write, 0x76 + ret + + +align 16 +ac_unknown db 'unknown manufacturer',13,10,0 +ac_Realtek db 'Realtek Semiconductor',13,10,0 +ac_Analog db 'Analog Devices',13,10,0 +ac_CMedia db 'C-Media Electronics',13,10,0 +ac_Cirrus db 'Cirrus Logic',13,10,0 +ac_Wolfson db 'Wolfson Microelectronics',13,10,0 +ac_VIA db 'VIA Technologies',13,10,0 +ac_SigmaTel db 'SigmaTel',13,10,0 +ac_eMicro db 'eMicro',13,10,0 + +chip_unknown db 'unknown codec id ', 0 + +CHIP_ANALOG equ 0x41445300 +CHIP_REALTEK equ 0x414C4700 +CHIP_CMEDIA equ 0x434D4900 +CHIP_CIRRUS equ 0x43525900 +CHIP_WOLFSON equ 0x574D4C00 +CHIP_VIA equ 0x56494100 +CHIP_SIGMATEL equ 0x83847600 +CHIP_EMICRO equ 0x454D4300 + +align 16 +codecs dd CHIP_ANALOG, ac_Analog, chips_Analog + dd CHIP_CMEDIA, ac_CMedia, chips_CMedia + dd CHIP_REALTEK,ac_Realtek, chips_Realtek + dd CHIP_CIRRUS, ac_Cirrus, chips_Cirrus + dd CHIP_WOLFSON,ac_Wolfson, chips_Wolfson + dd CHIP_VIA, ac_VIA, chips_VIA + dd CHIP_SIGMATEL, ac_SigmaTel, chips_SigmaTel + dd CHIP_EMICRO, ac_eMicro, chips_eMicro + dd 0 + +align 16 +chips_Analog dd 0x03, chip_AD1819 + dd 0x40, chip_AD1881 + dd 0x48, chip_AD1881A + dd 0x60, chip_AD1884 + dd 0x61, chip_AD1886 + dd 0x62, chip_AD1887 + dd 0x63, chip_AD1886A + dd 0x70, chip_AD1980 + dd 0x72, chip_AD1981A + dd 0x74, chip_AD1981B + dd 0x75, chip_AD1985 + dd 0xFF + +chips_Realtek: + dd 0x10, chip_ALC201a + dd 0x20, chip_ALC650 + dd 0x21, chip_ALC650D + dd 0x22, chip_ALC650E + dd 0x23, chip_ALC650F + dd 0x60, chip_ALC655 + dd 0x80, chip_ALC658 + dd 0x81, chip_ALC658D + dd 0x90, chip_ALC850 + dd 0xFF + +chips_CMedia dd 0x41, chip_CM9738 + dd 0x61, chip_CM9739 + dd 0x69, chip_CM9780 + dd 0x78, chip_CM9761 + dd 0x82, chip_CM9761 + dd 0x83, chip_CM9761 + dd 0xFF + +chips_Cirrus dd 0x00, chip_CS4297 + dd 0x10, chip_CS4297A + dd 0x20, chip_CS4298 + dd 0x28, chip_CS4294 + dd 0x30, chip_CS4299 + dd 0x34, chip_CS4299D + dd 0x48, chip_CS4201 + dd 0x58, chip_CS4205 + dd 0x60, chip_CS4291 + dd 0x70, chip_CS4202 + dd 0xFF + +chips_Wolfson dd 0x00, chip_WM9700 + dd 0x03, chip_WM9703 + dd 0x04, chip_WM9704 + dd 0xFF + +chips_VIA dd 0x61, chip_VIA1612A + dd 0xFF + +chips_SigmaTel dd 0x58, chip_STAC9758 + dd 0xFF + +chips_eMicro dd 0x28, chip_EM28028 + dd 0xFF + +align 16 +;Analog Devices +chip_AD1819 db 'AD1819 ',0dh,0ah,00h +chip_AD1881 db 'AD1881 ',0dh,0ah,00h +chip_AD1881A db 'AD1881A',0dh,0ah,00h +chip_AD1884 db 'AD1885 ',0dh,0ah,00h +chip_AD1885 db 'AD1885 ',0dh,0ah,00h +chip_AD1886 db 'AD1886 ',0dh,0ah,00h +chip_AD1886A db 'AD1886A',0dh,0ah,00h +chip_AD1887 db 'AD1887 ',0dh,0ah,00h +chip_AD1980 db 'AD1980 ',0dh,0ah,00h +chip_AD1981A db 'AD1981A',0dh,0ah,00h +chip_AD1981B db 'AD1981B',0dh,0ah,00h +chip_AD1985 db 'AD1985 ',0dh,0ah,00h + +;Realtek +chip_ALC201a db 'ALC201a',0dh,0ah,00h +chip_ALC650 db 'ALC650 ',0dh,0ah,00h +chip_ALC650D db 'ALC650D',0dh,0ah,00h +chip_ALC650E db 'ALC650E',0dh,0ah,00h +chip_ALC650F db 'ALC650F',0dh,0ah,00h +chip_ALC655 db 'ALC655 ',0dh,0ah,00h +chip_ALC658 db 'ALC658 ',0dh,0ah,00h +chip_ALC658D db 'ALC658D',0dh,0ah,00h +chip_ALC850 db 'ALC850 ',0dh,0ah,00h + +;CMedia +chip_CM9738 db 'CMI9738', 0dh,0ah,0 +chip_CM9739 db 'CMI9739', 0dh,0ah,0 +chip_CM9780 db 'CMI9780', 0dh,0ah,0 +chip_CM9761 db 'CMI9761', 0dh,0ah,0 + +;Cirrus +chip_CS4297 db 'CS4297',13,10,0 +chip_CS4297A db 'CS4297A',13,10,0 +chip_CS4298 db 'CS4298',13,10,0 +chip_CS4294 db 'CS4294',13,10,0 +chip_CS4299 db 'CS4299',13,10,0 +chip_CS4299D db 'CS4299D',13,10,0 +chip_CS4201 db 'CS4201',13,10,0 +chip_CS4205 db 'CS4205',13,10,0 +chip_CS4291 db 'CS4291',13,10,0 +chip_CS4202 db 'CS4202',13,10,0 + +;Wolfson +chip_WM9700 db 'WM9704',13,10,0 +chip_WM9703 db 'WM9703/9704',13,10,0 +chip_WM9704 db 'WM9704 (quad)',13,10,0 + +;VIA +chip_VIA1612A db 'VIA1612A',13,10,0 + +;SigmaTel +chip_STAC9758 db 'STAC9758,59',13,10,0 + +;eMicro +chip_EM28028 db 'EM28028',13,10,0 + diff --git a/kernel/trunk/drivers/com_mouse.asm b/kernel/trunk/drivers/com_mouse.asm index eb77ac3bc..2a0b1366b 100644 --- a/kernel/trunk/drivers/com_mouse.asm +++ b/kernel/trunk/drivers/com_mouse.asm @@ -1,382 +1,382 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; Includes source code by Kulakov Vladimir Gennadievich. ;; -;; Modified by Mario79 and Rus. ;; -;; 02.12.2009 ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;driver sceletone - -format MS COFF - -DEBUG equ 0 - -include 'proc32.inc' -include 'imports.inc' - -API_VERSION equ 5 ;debug - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -public START -public version - - -DRV_ENTRY equ 1 -DRV_EXIT equ -1 -STRIDE equ 4 ;size of row in devices table - -SRV_GETVERSION equ 0 - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .exit -.entry: - ;Detect_COM_Mouse: -if DEBUG - mov esi, msgInit - call Boot_Log -end if - mov bx, 0x3f8 - call MSMouseSearch - cmp AL,'M' - jne @f - ;mov [com1_mouse_detected],1 - ;mov [irq_owner+4*4], 1 ; IRQ4 owner is System - - mov dx, bx - inc dx ; 0x3f8 + 1 - mov al, 1 - out dx, al - - stdcall AttachIntHandler, 4, irq4_handler, dword 0 -if DEBUG - test eax, eax - jne .label1 - - mov esi, msg_error_attach_int_handler - call Boot_Log -end if - .label1: -; mov eax, 0 -; mov ebx, 0x3F8 -; mov ecx, 0x3FF - xor ebx,ebx - mov ecx, 0x3F8 - mov edx, 0x3FF - call ReservePortArea - -if DEBUG - cmp eax, 1 - jne .go - - mov esi, msg_error_reserve_ports - call Boot_Log - - .go: - mov esi,boot_setmouse_type - call Boot_Log -end if - @@: - mov bx, 0x2f8 - call MSMouseSearch - cmp AL,'M' - jne .resume - ;mov [com2_mouse_detected],1 - ;mov [irq_owner+3*4], 1 ; IRQ3 owner is System - - stdcall AttachIntHandler, 3, irq3_handler, dword 0 - -; mov eax, 0 -; mov ebx, 0x2F8 -; mov ecx, 0x3F8 - xor ebx,ebx - mov ecx, 0x2F8 - mov edx, 0x3F8 - - call ReservePortArea -if DEBUG - cmp eax, 1 - jne @f - - mov esi, msg_error_reserve_ports - call Boot_Log - @@: - - mov esi,boot_setmouse_type + 22 - call Boot_Log -end if - .resume: - - stdcall RegService, my_service, service_proc -if DEBUG - test eax, eax - jne @f - - mov esi, msg_exit - call Boot_Log -end if - @@: - ret -.fail: -.exit: -if DEBUG - mov esi, msg_exit - call Boot_Log -end if - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - - mov ebx, [ioctl] - mov eax, [ebx+io_code] - cmp eax, SRV_GETVERSION - jne @F - - mov eax, [ebx+output] - cmp [ebx+out_size], 4 - jne .fail - mov [eax], dword API_VERSION - xor eax, eax - ret -@@: -.fail: - or eax, -1 - ret -endp - -align 4 -MSMouseSearch: - ; ПОИСК МЫШИ ЧЕРЕЗ COM-ПОРТЫ -MouseSearch: - ; Устанавливаем скорость - ; приема/передачи 1200 бод - ; in bx COM Port Base Address - mov DX, bx - add DX,3 - in AL,DX - or AL,80h ;установить бит DLAB - out DX,AL - mov DX, bx - mov AL,60h ;1200 бод - out DX,AL - inc DX - mov AL,0 - out DX,AL - ; Установить длину слова 7 бит, 1 стоповый бит, - ; четность не контролировать - mov DX, bx - add DX,3 - mov AL,00000010b - out DX,AL - ; Запретить все прерывани - mov dx, bx - inc dx - mov AL,0 - out DX,AL -; Проверить, что устройство подключено и являетс -; мышью типа MSMouse - ; Отключить питание мыши и прерывани - mov DX, bx - add EDX,4 ;регистр управления модемом - mov AL,0 ;сбросить DTR, RTS и OUT2 - out DX,AL - ; Ожидать 5 "тиков" (0,2 с) - mov ecx, 0xFFFF - loop $ - ; Включить питание мыши - mov al, 1 - out dx, al - mov ecx, 0xFFFF - loop $ - ; Очистить регистр данных - mov dx, bx - in AL,DX - add edx, 4 - mov AL, 1011b ;установить DTR и RTS и OUT2 - out DX,AL - mov ecx, 0x1FFFF -; Цикл опроса порта -WaitData: - ; Ожидать еще 10 "тиков" - dec ecx -; cmp ecx,0 - jz NoMouse - ; Проверить наличие идентификационного байта - mov DX, bx - add DX,5 - in AL,DX - test AL,1 ;Данные готовы? - jz WaitData - ; Ввести данные - mov DX, bx - in AL,DX -NoMouse: - ret - -align 4 -irq3_handler: - mov dx, 0x2f8 - mov esi, com2_mouse - jmp irq_handler - -align 4 -irq4_handler: - mov dx, 0x3f8 - mov esi, com1_mouse - -irq_handler: - -; in: esi -> COM_MOUSE_DATA struc, dx = base port (xF8h) - add edx, 5 ; xFDh - in al, dx - test al, 1 ; Данные готовы? - jz .Error -; Ввести данные - sub edx, 5 - in al, dx -; Сбросить старший незначащий бит - and al, 01111111b - -; Определить порядковый номер принимаемого байта - cmp [esi+COM_MOUSE_DATA.MouseByteNumber], 2 - ja .Error - jz .ThirdByte - jp .SecondByte -; Сохранить первый байт данных -.FirstByte: - test al, 1000000b ; Первый байт посылки? - jz .Error - mov [esi+COM_MOUSE_DATA.FirstByte], al - inc [esi+COM_MOUSE_DATA.MouseByteNumber] - jmp .EndMouseInterrupt -; Сохранить второй байт данных -.SecondByte: - test al, 1000000b - jnz .Error - mov [esi+COM_MOUSE_DATA.SecondByte], al - inc [esi+COM_MOUSE_DATA.MouseByteNumber] - jmp .EndMouseInterrupt -; Сохранить третий байт данных -.ThirdByte: - test al, 1000000b - jnz .Error - mov [esi+COM_MOUSE_DATA.ThirdByte], al - mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 -; (Пакет данных от мыши принят полностью). -; Записать новое значение состояния кнопок мыши - mov al, [esi+COM_MOUSE_DATA.FirstByte] - mov ah, al - shr al, 3 - and al, 2 - shr ah, 5 - and ah, 1 - add al, ah - movzx eax, al - mov [BTN_DOWN], eax - -; Прибавить перемещение по X к координате X - mov al, [esi+COM_MOUSE_DATA.FirstByte] - shl al, 6 - or al, [esi+COM_MOUSE_DATA.SecondByte] - - cbw - movzx eax, ax - mov [MOUSE_X], eax - -; Прибавить перемещение по Y к координате Y - mov al, [esi+COM_MOUSE_DATA.FirstByte] - and al, 00001100b - shl al, 4 - or al, [esi+COM_MOUSE_DATA.ThirdByte] - - cbw - movzx eax, ax - neg eax - mov [MOUSE_Y], eax - - stdcall SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0 - - jmp .EndMouseInterrupt - -.Error: -; Произошел сбой в порядке передачи информации от -; мыши, обнулить счетчик байтов пакета данных - - mov [esi+COM_MOUSE_DATA.MouseByteNumber],0 -.EndMouseInterrupt: - mov al, 1 - ret - -;all initialized data place here - -align 4 - -struc COM_MOUSE_DATA { -; Номер принимаемого от мыши байта - .MouseByteNumber db ? -; Трехбайтовая структура данных, передаваемая мышью - .FirstByte db ? - .SecondByte db ? - .ThirdByte db ? - ;.timer_ticks_com dd ? -} -virtual at 0 - COM_MOUSE_DATA COM_MOUSE_DATA -end virtual - -com1_mouse COM_MOUSE_DATA -com2_mouse COM_MOUSE_DATA - -MOUSE_X dd 0 -MOUSE_Y dd 0 -BTN_DOWN dd 0 - -COMPortBaseAddr dw 3F8h - - - -version dd (5 shl 16) or (API_VERSION and 0xFFFF) - -my_service db 'COM_Mouse',0 ;max 16 chars include zero - -if DEBUG -msgInit db 'Preved bugoga!',13,10,0 -boot_setmouse_type db 'Detected - COM1 mouse',13,10,0 - db 'Detected - COM2 mouse',13,10,0 -msg_error_reserve_ports db 'Error reserving ports!',13,10,0 -msg_error_attach_int_handler db 'Error attach interrupt handler!',13,10,0 -msg_exit db 'Exit!',13,10,0 -end if - -section '.data' data readable writable align 16 - -;all uninitialized data place here - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; Includes source code by Kulakov Vladimir Gennadievich. ;; +;; Modified by Mario79 and Rus. ;; +;; 02.12.2009 ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;driver sceletone + +format MS COFF + +DEBUG equ 0 + +include 'proc32.inc' +include 'imports.inc' + +API_VERSION equ 5 ;debug + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +public START +public version + + +DRV_ENTRY equ 1 +DRV_EXIT equ -1 +STRIDE equ 4 ;size of row in devices table + +SRV_GETVERSION equ 0 + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .exit +.entry: + ;Detect_COM_Mouse: +if DEBUG + mov esi, msgInit + call Boot_Log +end if + mov bx, 0x3f8 + call MSMouseSearch + cmp AL, 'M' + jne @f + ;mov [com1_mouse_detected],1 + ;mov [irq_owner+4*4], 1 ; IRQ4 owner is System + + mov dx, bx + inc dx ; 0x3f8 + 1 + mov al, 1 + out dx, al + + stdcall AttachIntHandler, 4, irq4_handler, dword 0 +if DEBUG + test eax, eax + jne .label1 + + mov esi, msg_error_attach_int_handler + call Boot_Log +end if + .label1: +; mov eax, 0 +; mov ebx, 0x3F8 +; mov ecx, 0x3FF + xor ebx, ebx + mov ecx, 0x3F8 + mov edx, 0x3FF + call ReservePortArea + +if DEBUG + cmp eax, 1 + jne .go + + mov esi, msg_error_reserve_ports + call Boot_Log + + .go: + mov esi, boot_setmouse_type + call Boot_Log +end if + @@: + mov bx, 0x2f8 + call MSMouseSearch + cmp AL, 'M' + jne .resume + ;mov [com2_mouse_detected],1 + ;mov [irq_owner+3*4], 1 ; IRQ3 owner is System + + stdcall AttachIntHandler, 3, irq3_handler, dword 0 + +; mov eax, 0 +; mov ebx, 0x2F8 +; mov ecx, 0x3F8 + xor ebx, ebx + mov ecx, 0x2F8 + mov edx, 0x3F8 + + call ReservePortArea +if DEBUG + cmp eax, 1 + jne @f + + mov esi, msg_error_reserve_ports + call Boot_Log + @@: + + mov esi, boot_setmouse_type + 22 + call Boot_Log +end if + .resume: + + stdcall RegService, my_service, service_proc +if DEBUG + test eax, eax + jne @f + + mov esi, msg_exit + call Boot_Log +end if + @@: + ret +.fail: +.exit: +if DEBUG + mov esi, msg_exit + call Boot_Log +end if + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + + mov ebx, [ioctl] + mov eax, [ebx+io_code] + cmp eax, SRV_GETVERSION + jne @F + + mov eax, [ebx+output] + cmp [ebx+out_size], 4 + jne .fail + mov [eax], dword API_VERSION + xor eax, eax + ret +@@: +.fail: + or eax, -1 + ret +endp + +align 4 +MSMouseSearch: + ; ПОИСК МЫШИ ЧЕРЕЗ COM-ПОРТЫ +MouseSearch: + ; Устанавливаем скорость + ; приема/передачи 1200 бод + ; in bx COM Port Base Address + mov DX, bx + add DX, 3 + in AL, DX + or AL, 80h ;установить бит DLAB + out DX, AL + mov DX, bx + mov AL, 60h ;1200 бод + out DX, AL + inc DX + mov AL, 0 + out DX, AL + ; Установить длину слова 7 бит, 1 стоповый бит, + ; четность не контролировать + mov DX, bx + add DX, 3 + mov AL, 00000010b + out DX, AL + ; Запретить все прерывани + mov dx, bx + inc dx + mov AL, 0 + out DX, AL +; Проверить, что устройство подключено и являетс +; мышью типа MSMouse + ; Отключить питание мыши и прерывани + mov DX, bx + add EDX, 4 ;регистр управления модемом + mov AL, 0 ;сбросить DTR, RTS и OUT2 + out DX, AL + ; Ожидать 5 "тиков" (0,2 с) + mov ecx, 0xFFFF + loop $ + ; Включить питание мыши + mov al, 1 + out dx, al + mov ecx, 0xFFFF + loop $ + ; Очистить регистр данных + mov dx, bx + in AL, DX + add edx, 4 + mov AL, 1011b ;установить DTR и RTS и OUT2 + out DX, AL + mov ecx, 0x1FFFF +; Цикл опроса порта +WaitData: + ; Ожидать еще 10 "тиков" + dec ecx +; cmp ecx,0 + jz NoMouse + ; Проверить наличие идентификационного байта + mov DX, bx + add DX, 5 + in AL, DX + test AL, 1 ;Данные готовы? + jz WaitData + ; Ввести данные + mov DX, bx + in AL, DX +NoMouse: + ret + +align 4 +irq3_handler: + mov dx, 0x2f8 + mov esi, com2_mouse + jmp irq_handler + +align 4 +irq4_handler: + mov dx, 0x3f8 + mov esi, com1_mouse + +irq_handler: + +; in: esi -> COM_MOUSE_DATA struc, dx = base port (xF8h) + add edx, 5 ; xFDh + in al, dx + test al, 1 ; Данные готовы? + jz .Error +; Ввести данные + sub edx, 5 + in al, dx +; Сбросить старший незначащий бит + and al, 01111111b + +; Определить порядковый номер принимаемого байта + cmp [esi+COM_MOUSE_DATA.MouseByteNumber], 2 + ja .Error + jz .ThirdByte + jp .SecondByte +; Сохранить первый байт данных +.FirstByte: + test al, 1000000b ; Первый байт посылки? + jz .Error + mov [esi+COM_MOUSE_DATA.FirstByte], al + inc [esi+COM_MOUSE_DATA.MouseByteNumber] + jmp .EndMouseInterrupt +; Сохранить второй байт данных +.SecondByte: + test al, 1000000b + jnz .Error + mov [esi+COM_MOUSE_DATA.SecondByte], al + inc [esi+COM_MOUSE_DATA.MouseByteNumber] + jmp .EndMouseInterrupt +; Сохранить третий байт данных +.ThirdByte: + test al, 1000000b + jnz .Error + mov [esi+COM_MOUSE_DATA.ThirdByte], al + mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 +; (Пакет данных от мыши принят полностью). +; Записать новое значение состояния кнопок мыши + mov al, [esi+COM_MOUSE_DATA.FirstByte] + mov ah, al + shr al, 3 + and al, 2 + shr ah, 5 + and ah, 1 + add al, ah + movzx eax, al + mov [BTN_DOWN], eax + +; Прибавить перемещение по X к координате X + mov al, [esi+COM_MOUSE_DATA.FirstByte] + shl al, 6 + or al, [esi+COM_MOUSE_DATA.SecondByte] + + cbw + movzx eax, ax + mov [MOUSE_X], eax + +; Прибавить перемещение по Y к координате Y + mov al, [esi+COM_MOUSE_DATA.FirstByte] + and al, 00001100b + shl al, 4 + or al, [esi+COM_MOUSE_DATA.ThirdByte] + + cbw + movzx eax, ax + neg eax + mov [MOUSE_Y], eax + + stdcall SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0 + + jmp .EndMouseInterrupt + +.Error: +; Произошел сбой в порядке передачи информации от +; мыши, обнулить счетчик байтов пакета данных + + mov [esi+COM_MOUSE_DATA.MouseByteNumber], 0 +.EndMouseInterrupt: + mov al, 1 + ret + +;all initialized data place here + +align 4 + +struc COM_MOUSE_DATA { +; Номер принимаемого от мыши байта + .MouseByteNumber db ? +; Трехбайтовая структура данных, передаваемая мышью + .FirstByte db ? + .SecondByte db ? + .ThirdByte db ? + ;.timer_ticks_com dd ? +} +virtual at 0 + COM_MOUSE_DATA COM_MOUSE_DATA +end virtual + +com1_mouse COM_MOUSE_DATA +com2_mouse COM_MOUSE_DATA + +MOUSE_X dd 0 +MOUSE_Y dd 0 +BTN_DOWN dd 0 + +COMPortBaseAddr dw 3F8h + + + +version dd (5 shl 16) or (API_VERSION and 0xFFFF) + +my_service db 'COM_Mouse',0 ;max 16 chars include zero + +if DEBUG +msgInit db 'Preved bugoga!',13,10,0 +boot_setmouse_type db 'Detected - COM1 mouse',13,10,0 + db 'Detected - COM2 mouse',13,10,0 +msg_error_reserve_ports db 'Error reserving ports!',13,10,0 +msg_error_attach_int_handler db 'Error attach interrupt handler!',13,10,0 +msg_exit db 'Exit!',13,10,0 +end if + +section '.data' data readable writable align 16 + +;all uninitialized data place here + diff --git a/kernel/trunk/drivers/emu10k1x.asm b/kernel/trunk/drivers/emu10k1x.asm index 90833e87f..61491c55d 100644 --- a/kernel/trunk/drivers/emu10k1x.asm +++ b/kernel/trunk/drivers/emu10k1x.asm @@ -7,43 +7,43 @@ format MS COFF -DEBUG equ 1 +DEBUG equ 1 include 'proc32.inc' include 'imports.inc' -API_VERSION equ 0x01000100 +API_VERSION equ 0x01000100 -USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices -IRQ_REMAP equ 0 -IRQ_LINE equ 0 +USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices +IRQ_REMAP equ 0 +IRQ_LINE equ 0 ;irq 0,1,2,8,12,13 ­Ґ¤®бвгЇ­л ; FEDCBA9876543210 -VALID_IRQ equ 1100111011111000b -ATTCH_IRQ equ 0000111010100000b +VALID_IRQ equ 1100111011111000b +ATTCH_IRQ equ 0000111010100000b if USE_COM_IRQ -ATTCH_IRQ equ 0000111010111000b +ATTCH_IRQ equ 0000111010111000b end if -CPU_FREQ equ 2600d +CPU_FREQ equ 2600d BIT0 EQU 0x00000001 BIT1 EQU 0x00000002 BIT5 EQU 0x00000020 BIT10 EQU 0x00000400 -VID_Creative equ 0x1102 +VID_Creative equ 0x1102 -CTRL_CT0200 equ 0x0006 ; Dell OEM version (EMU10K1X) +CTRL_CT0200 equ 0x0006 ; Dell OEM version (EMU10K1X) -CODEC_MASTER_VOL_REG equ 0x02 -CODEC_AUX_VOL equ 0x04 ; -CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume -CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio +CODEC_MASTER_VOL_REG equ 0x02 +CODEC_AUX_VOL equ 0x04 ; +CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume +CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate @@ -57,278 +57,278 @@ CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate ;; PCI function 0 registers, address = + PCIBASE0 ;; ;;**********************************************************************************************;; -PTR equ 0x00 ;; Indexed register set pointer register ;; - ;; NOTE: The CHANNELNUM and ADDRESS words can ;; - ;; be modified independently of each other. ;; +PTR equ 0x00 ;; Indexed register set pointer register ;; + ;; NOTE: The CHANNELNUM and ADDRESS words can ;; + ;; be modified independently of each other. ;; -DATA equ 0x04 ;; Indexed register set data register ;; +DATA equ 0x04 ;; Indexed register set data register ;; -IPR equ 0x08 ;; Global interrupt pending register ;; - ;; Clear pending interrupts by writing a 1 to ;; - ;; the relevant bits and zero to the other bits ;; -IPR_MIDITRANSBUFEMPTY equ 0x00000001 ;; MIDI UART transmit buffer empty ;; -IPR_MIDIRECVBUFEMPTY equ 0x00000002 ;; MIDI UART receive buffer empty ;; -IPR_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; -IPR_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; -IPR_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; -IPR_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; +IPR equ 0x08 ;; Global interrupt pending register ;; + ;; Clear pending interrupts by writing a 1 to ;; + ;; the relevant bits and zero to the other bits ;; +IPR_MIDITRANSBUFEMPTY equ 0x00000001 ;; MIDI UART transmit buffer empty ;; +IPR_MIDIRECVBUFEMPTY equ 0x00000002 ;; MIDI UART receive buffer empty ;; +IPR_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; +IPR_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; +IPR_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; +IPR_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; -INTE equ 0x0c ;; Interrupt enable register ;; -INTE_MIDITXENABLE equ 0x00000001 ;; Enable MIDI transmit-buffer-empty interrupts ;; -INTE_MIDIRXENABLE equ 0x00000002 ;; Enable MIDI receive-buffer-empty interrupts ;; -INTE_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; -INTE_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; -INTE_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; -INTE_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; +INTE equ 0x0c ;; Interrupt enable register ;; +INTE_MIDITXENABLE equ 0x00000001 ;; Enable MIDI transmit-buffer-empty interrupts ;; +INTE_MIDIRXENABLE equ 0x00000002 ;; Enable MIDI receive-buffer-empty interrupts ;; +INTE_CH_0_LOOP equ 0x00000800 ;; Channel 0 loop ;; +INTE_CH_0_HALF_LOOP equ 0x00000100 ;; Channel 0 half loop ;; +INTE_CAP_0_LOOP equ 0x00080000 ;; Channel capture loop ;; +INTE_CAP_0_HALF_LOOP equ 0x00010000 ;; Channel capture half loop ;; -HCFG equ 0x14 ;; Hardware config register ;; +HCFG equ 0x14 ;; Hardware config register ;; -HCFG_LOCKSOUNDCACHE equ 0x00000008 ;; 1 = Cancel bustmaster accesses to soundcache ;; - ;; NOTE: This should generally never be used. ;; -HCFG_AUDIOENABLE equ 0x00000001 ;; 0 = CODECs transmit zero-valued samples ;; - ;; Should be set to 1 when the EMU10K1 is ;; - ;; completely initialized. ;; -GPIO equ 0x18 ;; Defaults: 00001080-Analog, 00001000-SPDIF. ;; +HCFG_LOCKSOUNDCACHE equ 0x00000008 ;; 1 = Cancel bustmaster accesses to soundcache ;; + ;; NOTE: This should generally never be used. ;; +HCFG_AUDIOENABLE equ 0x00000001 ;; 0 = CODECs transmit zero-valued samples ;; + ;; Should be set to 1 when the EMU10K1 is ;; + ;; completely initialized. ;; +GPIO equ 0x18 ;; Defaults: 00001080-Analog, 00001000-SPDIF. ;; -AC97DATA equ 0x1c ;; AC97 register set data register (16 bit) ;; +AC97DATA equ 0x1c ;; AC97 register set data register (16 bit) ;; -AC97ADDRESS equ 0x1e ;; AC97 register set address register (8 bit) ;; +AC97ADDRESS equ 0x1e ;; AC97 register set address register (8 bit) ;; ;;******************************************************************************************************;; ;; Emu10k1x pointer-offset register set, accessed through the PTR and DATA registers ;; ;;******************************************************************************************************;; -PLAYBACK_LIST_ADDR equ 0x00 ;; Base DMA address of a list of pointers to each period/size ;; - ;; One list entry: 4 bytes for DMA address, - ;; 4 bytes for period_size << 16. - ;; One list entry is 8 bytes long. - ;; One list entry for each period in the buffer. - ;; -PLAYBACK_LIST_SIZE equ 0x01 ;; Size of list in bytes << 19. E.g. 8 periods -> 0x00380000 ;; -PLAYBACK_LIST_PTR equ 0x02 ;; Pointer to the current period being played ;; -PLAYBACK_DMA_ADDR equ 0x04 ;; Playback DMA addresss ;; -PLAYBACK_PERIOD_SIZE equ 0x05 ;; Playback period size ;; -PLAYBACK_POINTER equ 0x06 ;; Playback period pointer. Sample currently in DAC ;; -PLAYBACK_UNKNOWN1 equ 0x07 -PLAYBACK_UNKNOWN2 equ 0x08 +PLAYBACK_LIST_ADDR equ 0x00 ;; Base DMA address of a list of pointers to each period/size ;; + ;; One list entry: 4 bytes for DMA address, + ;; 4 bytes for period_size << 16. + ;; One list entry is 8 bytes long. + ;; One list entry for each period in the buffer. + ;; +PLAYBACK_LIST_SIZE equ 0x01 ;; Size of list in bytes << 19. E.g. 8 periods -> 0x00380000 ;; +PLAYBACK_LIST_PTR equ 0x02 ;; Pointer to the current period being played ;; +PLAYBACK_DMA_ADDR equ 0x04 ;; Playback DMA addresss ;; +PLAYBACK_PERIOD_SIZE equ 0x05 ;; Playback period size ;; +PLAYBACK_POINTER equ 0x06 ;; Playback period pointer. Sample currently in DAC ;; +PLAYBACK_UNKNOWN1 equ 0x07 +PLAYBACK_UNKNOWN2 equ 0x08 ;; Only one capture channel supported ;; -CAPTURE_DMA_ADDR equ 0x10 ;; Capture DMA address ;; -CAPTURE_BUFFER_SIZE equ 0x11 ;; Capture buffer size ;; -CAPTURE_POINTER equ 0x12 ;; Capture buffer pointer. Sample currently in ADC ;; -CAPTURE_UNKNOWN equ 0x13 +CAPTURE_DMA_ADDR equ 0x10 ;; Capture DMA address ;; +CAPTURE_BUFFER_SIZE equ 0x11 ;; Capture buffer size ;; +CAPTURE_POINTER equ 0x12 ;; Capture buffer pointer. Sample currently in ADC ;; +CAPTURE_UNKNOWN equ 0x13 ;; From 0x20 - 0x3f, last samples played on each channel ;; -TRIGGER_CHANNEL equ 0x40 ;; Trigger channel playback ;; -TRIGGER_CHANNEL_0 equ 0x00000001 ;; Trigger channel 0 ;; -TRIGGER_CHANNEL_1 equ 0x00000002 ;; Trigger channel 1 ;; -TRIGGER_CHANNEL_2 equ 0x00000004 ;; Trigger channel 2 ;; -TRIGGER_CAPTURE equ 0x00000100 ;; Trigger capture channel ;; +TRIGGER_CHANNEL equ 0x40 ;; Trigger channel playback ;; +TRIGGER_CHANNEL_0 equ 0x00000001 ;; Trigger channel 0 ;; +TRIGGER_CHANNEL_1 equ 0x00000002 ;; Trigger channel 1 ;; +TRIGGER_CHANNEL_2 equ 0x00000004 ;; Trigger channel 2 ;; +TRIGGER_CAPTURE equ 0x00000100 ;; Trigger capture channel ;; -ROUTING equ 0x41 ;; Setup sound routing ? ;; -ROUTING_FRONT_LEFT equ 0x00000001 -ROUTING_FRONT_RIGHT equ 0x00000002 -ROUTING_REAR_LEFT equ 0x00000004 -ROUTING_REAR_RIGHT equ 0x00000008 -ROUTING_CENTER_LFE equ 0x00010000 +ROUTING equ 0x41 ;; Setup sound routing ? ;; +ROUTING_FRONT_LEFT equ 0x00000001 +ROUTING_FRONT_RIGHT equ 0x00000002 +ROUTING_REAR_LEFT equ 0x00000004 +ROUTING_REAR_RIGHT equ 0x00000008 +ROUTING_CENTER_LFE equ 0x00010000 -SPCS0 equ 0x42 ;; SPDIF output Channel Status 0 register ;; -SPCS1 equ 0x43 ;; SPDIF output Channel Status 1 register ;; -SPCS2 equ 0x44 ;; SPDIF output Channel Status 2 register ;; +SPCS0 equ 0x42 ;; SPDIF output Channel Status 0 register ;; +SPCS1 equ 0x43 ;; SPDIF output Channel Status 1 register ;; +SPCS2 equ 0x44 ;; SPDIF output Channel Status 2 register ;; -SPCS_CLKACCYMASK equ 0x30000000 ;; Clock accuracy ;; -SPCS_CLKACCY_1000PPM equ 0x00000000 ;; 1000 parts per million ;; -SPCS_CLKACCY_50PPM equ 0x10000000 ;; 50 parts per million ;; -SPCS_CLKACCY_VARIABLE equ 0x20000000 ;; Variable accuracy ;; -SPCS_SAMPLERATEMASK equ 0x0f000000 ;; Sample rate ;; -SPCS_SAMPLERATE_44 equ 0x00000000 ;; 44.1kHz sample rate ;; -SPCS_SAMPLERATE_48 equ 0x02000000 ;; 48kHz sample rate ;; -SPCS_SAMPLERATE_32 equ 0x03000000 ;; 32kHz sample rate ;; -SPCS_CHANNELNUMMASK equ 0x00f00000 ;; Channel number ;; -SPCS_CHANNELNUM_UNSPEC equ 0x00000000 ;; Unspecified channel number ;; -SPCS_CHANNELNUM_LEFT equ 0x00100000 ;; Left channel ;; -SPCS_CHANNELNUM_RIGHT equ 0x00200000 ;; Right channel ;; -SPCS_SOURCENUMMASK equ 0x000f0000 ;; Source number ;; -SPCS_SOURCENUM_UNSPEC equ 0x00000000 ;; Unspecified source number ;; -SPCS_GENERATIONSTATUS equ 0x00008000 ;; Originality flag (see IEC-958 spec) ;; -SPCS_CATEGORYCODEMASK equ 0x00007f00 ;; Category code (see IEC-958 spec) ;; -SPCS_MODEMASK equ 0x000000c0 ;; Mode (see IEC-958 spec) ;; -SPCS_EMPHASISMASK equ 0x00000038 ;; Emphasis ;; -SPCS_EMPHASIS_NONE equ 0x00000000 ;; No emphasis ;; -SPCS_EMPHASIS_50_15 equ 0x00000008 ;; 50/15 usec 2 channel ;; -SPCS_COPYRIGHT equ 0x00000004 ;; Copyright asserted flag -- do not modify ;; -SPCS_NOTAUDIODATA equ 0x00000002 ;; 0 = Digital audio, 1 = not audio ;; -SPCS_PROFESSIONAL equ 0x00000001 ;; 0 = Consumer (IEC-958), 1 = pro (AES3-1992) ;; +SPCS_CLKACCYMASK equ 0x30000000 ;; Clock accuracy ;; +SPCS_CLKACCY_1000PPM equ 0x00000000 ;; 1000 parts per million ;; +SPCS_CLKACCY_50PPM equ 0x10000000 ;; 50 parts per million ;; +SPCS_CLKACCY_VARIABLE equ 0x20000000 ;; Variable accuracy ;; +SPCS_SAMPLERATEMASK equ 0x0f000000 ;; Sample rate ;; +SPCS_SAMPLERATE_44 equ 0x00000000 ;; 44.1kHz sample rate ;; +SPCS_SAMPLERATE_48 equ 0x02000000 ;; 48kHz sample rate ;; +SPCS_SAMPLERATE_32 equ 0x03000000 ;; 32kHz sample rate ;; +SPCS_CHANNELNUMMASK equ 0x00f00000 ;; Channel number ;; +SPCS_CHANNELNUM_UNSPEC equ 0x00000000 ;; Unspecified channel number ;; +SPCS_CHANNELNUM_LEFT equ 0x00100000 ;; Left channel ;; +SPCS_CHANNELNUM_RIGHT equ 0x00200000 ;; Right channel ;; +SPCS_SOURCENUMMASK equ 0x000f0000 ;; Source number ;; +SPCS_SOURCENUM_UNSPEC equ 0x00000000 ;; Unspecified source number ;; +SPCS_GENERATIONSTATUS equ 0x00008000 ;; Originality flag (see IEC-958 spec) ;; +SPCS_CATEGORYCODEMASK equ 0x00007f00 ;; Category code (see IEC-958 spec) ;; +SPCS_MODEMASK equ 0x000000c0 ;; Mode (see IEC-958 spec) ;; +SPCS_EMPHASISMASK equ 0x00000038 ;; Emphasis ;; +SPCS_EMPHASIS_NONE equ 0x00000000 ;; No emphasis ;; +SPCS_EMPHASIS_50_15 equ 0x00000008 ;; 50/15 usec 2 channel ;; +SPCS_COPYRIGHT equ 0x00000004 ;; Copyright asserted flag -- do not modify ;; +SPCS_NOTAUDIODATA equ 0x00000002 ;; 0 = Digital audio, 1 = not audio ;; +SPCS_PROFESSIONAL equ 0x00000001 ;; 0 = Consumer (IEC-958), 1 = pro (AES3-1992) ;; -SPDIF_SELECT equ 0x45 ;; Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF ;; +SPDIF_SELECT equ 0x45 ;; Enables SPDIF or Analogue outputs 0-Analogue, 0x700-SPDIF ;; ;; This is the MPU port on the card ;; -MUDATA equ 0x47 -MUCMD equ 0x48 -MUSTAT equ MUCMD +MUDATA equ 0x47 +MUCMD equ 0x48 +MUSTAT equ MUCMD ;; From 0x50 - 0x5f, last samples captured ;; -SRV_GETVERSION equ 0 -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_SET_BUFF equ 4 -DEV_NOTIFY equ 5 +SRV_GETVERSION equ 0 +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_SET_BUFF equ 4 +DEV_NOTIFY equ 5 DEV_SET_MASTERVOL equ 6 DEV_GET_MASTERVOL equ 7 -DEV_GET_INFO equ 8 +DEV_GET_INFO equ 8 -struc AC_CNTRL ;AC controller base class -{ .bus dd ? - .devfn dd ? +struc AC_CNTRL ;AC controller base class +{ .bus dd ? + .devfn dd ? - .vendor dd ? - .dev_id dd ? - .pci_cmd dd ? - .pci_stat dd ? + .vendor dd ? + .dev_id dd ? + .pci_cmd dd ? + .pci_stat dd ? .codec_io_base dd ? .codec_mem_base dd ? .ctrl_io_base dd ? .ctrl_mem_base dd ? - .cfg_reg dd ? - .int_line dd ? + .cfg_reg dd ? + .int_line dd ? - .vendor_ids dd ? ;vendor id string - .ctrl_ids dd ? ;hub id string + .vendor_ids dd ? ;vendor id string + .ctrl_ids dd ? ;hub id string - .buffer dd ? + .buffer dd ? - .notify_pos dd ? - .notify_task dd ? + .notify_pos dd ? + .notify_task dd ? - .lvi_reg dd ? - .ctrl_setup dd ? + .lvi_reg dd ? + .ctrl_setup dd ? .user_callback dd ? .codec_read16 dd ? .codec_write16 dd ? - .ctrl_read8 dd ? - .ctrl_read16 dd ? - .ctrl_read32 dd ? + .ctrl_read8 dd ? + .ctrl_read16 dd ? + .ctrl_read32 dd ? - .ctrl_write8 dd ? + .ctrl_write8 dd ? .ctrl_write16 dd ? .ctrl_write32 dd ? } -struc CODEC ;Audio Chip base class +struc CODEC ;Audio Chip base class { - .chip_id dd ? - .flags dd ? - .status dd ? + .chip_id dd ? + .flags dd ? + .status dd ? .ac_vendor_ids dd ? ;ac vendor id string - .chip_ids dd ? ;chip model string + .chip_ids dd ? ;chip model string - .shadow_flag dd ? - dd ? + .shadow_flag dd ? + dd ? - .regs dw ? ; codec registers + .regs dw ? ; codec registers .reg_master_vol dw ? ;0x02 .reg_aux_out_vol dw ? ;0x04 .reg_mone_vol dw ? ;0x06 .reg_master_tone dw ? ;0x08 .reg_beep_vol dw ? ;0x0A .reg_phone_vol dw ? ;0x0C - .reg_mic_vol dw ? ;0x0E + .reg_mic_vol dw ? ;0x0E .reg_line_in_vol dw ? ;0x10 - .reg_cd_vol dw ? ;0x12 + .reg_cd_vol dw ? ;0x12 .reg_video_vol dw ? ;0x14 .reg_aux_in_vol dw ? ;0x16 .reg_pcm_out_vol dw ? ;0x18 .reg_rec_select dw ? ;0x1A .reg_rec_gain dw ? ;0x1C .reg_rec_gain_mic dw ? ;0x1E - .reg_gen dw ? ;0x20 - .reg_3d_ctrl dw ? ;0X22 - .reg_page dw ? ;0X24 + .reg_gen dw ? ;0x20 + .reg_3d_ctrl dw ? ;0X22 + .reg_page dw ? ;0X24 .reg_powerdown dw ? ;0x26 .reg_ext_audio dw ? ;0x28 - .reg_ext_st dw ? ;0x2a + .reg_ext_st dw ? ;0x2a .reg_pcm_front_rate dw ? ;0x2c .reg_pcm_surr_rate dw ? ;0x2e .reg_lfe_rate dw ? ;0x30 .reg_pcm_in_rate dw ? ;0x32 - dw ? ;0x34 + dw ? ;0x34 .reg_cent_lfe_vol dw ? ;0x36 .reg_surr_vol dw ? ;0x38 .reg_spdif_ctrl dw ? ;0x3A - dw ? ;0x3C - dw ? ;0x3E - dw ? ;0x40 - dw ? ;0x42 - dw ? ;0x44 - dw ? ;0x46 - dw ? ;0x48 - dw ? ;0x4A - dw ? ;0x4C - dw ? ;0x4E - dw ? ;0x50 - dw ? ;0x52 - dw ? ;0x54 - dw ? ;0x56 - dw ? ;0x58 - dw ? ;0x5A - dw ? ;0x5C - dw ? ;0x5E - .reg_page_0 dw ? ;0x60 - .reg_page_1 dw ? ;0x62 - .reg_page_2 dw ? ;0x64 - .reg_page_3 dw ? ;0x66 - .reg_page_4 dw ? ;0x68 - .reg_page_5 dw ? ;0x6A - .reg_page_6 dw ? ;0x6C - .reg_page_7 dw ? ;0x6E - dw ? ;0x70 - dw ? ;0x72 - dw ? ;0x74 - dw ? ;0x76 - dw ? ;0x78 - dw ? ;0x7A + dw ? ;0x3C + dw ? ;0x3E + dw ? ;0x40 + dw ? ;0x42 + dw ? ;0x44 + dw ? ;0x46 + dw ? ;0x48 + dw ? ;0x4A + dw ? ;0x4C + dw ? ;0x4E + dw ? ;0x50 + dw ? ;0x52 + dw ? ;0x54 + dw ? ;0x56 + dw ? ;0x58 + dw ? ;0x5A + dw ? ;0x5C + dw ? ;0x5E + .reg_page_0 dw ? ;0x60 + .reg_page_1 dw ? ;0x62 + .reg_page_2 dw ? ;0x64 + .reg_page_3 dw ? ;0x66 + .reg_page_4 dw ? ;0x68 + .reg_page_5 dw ? ;0x6A + .reg_page_6 dw ? ;0x6C + .reg_page_7 dw ? ;0x6E + dw ? ;0x70 + dw ? ;0x72 + dw ? ;0x74 + dw ? ;0x76 + dw ? ;0x78 + dw ? ;0x7A .reg_vendor_id_1 dw ? ;0x7C .reg_vendor_id_2 dw ? ;0x7E - .reset dd ? ;virual + .reset dd ? ;virual .set_master_vol dd ? } struc CTRL_INFO -{ .pci_cmd dd ? - .irq dd ? +{ .pci_cmd dd ? + .irq dd ? .glob_cntrl dd ? - .glob_sta dd ? + .glob_sta dd ? .codec_io_base dd ? .ctrl_io_base dd ? .codec_mem_base dd ? .ctrl_mem_base dd ? - .codec_id dd ? + .codec_id dd ? } struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? } virtual at 0 IOCTL IOCTL end virtual -EVENT_NOTIFY equ 0x00000200 +EVENT_NOTIFY equ 0x00000200 public START public service_proc @@ -338,172 +338,172 @@ section '.flat' code readable align 16 proc START stdcall, state:dword - cmp [state], 1 - jne .stop + cmp [state], 1 + jne .stop if DEBUG - mov esi, msgInit - call SysMsgBoardStr + mov esi, msgInit + call SysMsgBoardStr end if - call detect_controller - test eax, eax - jz .fail + call detect_controller + test eax, eax + jz .fail if DEBUG - mov esi,[ctrl.vendor_ids] - call SysMsgBoardStr - mov esi, [ctrl.ctrl_ids] - call SysMsgBoardStr + mov esi, [ctrl.vendor_ids] + call SysMsgBoardStr + mov esi, [ctrl.ctrl_ids] + call SysMsgBoardStr end if - call init_controller - test eax, eax - jz .fail + call init_controller + test eax, eax + jz .fail - call init_codec - test eax, eax - jz .fail + call init_codec + test eax, eax + jz .fail - call setup_codec + call setup_codec - mov esi, msgPrimBuff - call SysMsgBoardStr - call create_primary_buff - mov esi, msgDone - call SysMsgBoardStr + mov esi, msgPrimBuff + call SysMsgBoardStr + call create_primary_buff + mov esi, msgDone + call SysMsgBoardStr if IRQ_REMAP - pushf - cli + pushf + cli - mov ebx, [ctrl.int_line] - in al, 0xA1 - mov ah, al - in al, 0x21 - test ebx, ebx - jz .skip - bts ax, bx ;mask old line + mov ebx, [ctrl.int_line] + in al, 0xA1 + mov ah, al + in al, 0x21 + test ebx, ebx + jz .skip + bts ax, bx ;mask old line .skip: - bts ax, IRQ_LINE ;mask new ine - out 0x21, al - mov al, ah - out 0xA1, al + bts ax, IRQ_LINE ;mask new ine + out 0x21, al + mov al, ah + out 0xA1, al - stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ + stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ - mov dx, 0x4d0 ;8259 ELCR1 - in al, dx - bts ax, IRQ_LINE - out dx, al ;set level-triggered mode - mov [ctrl.int_line], IRQ_LINE - popf - mov esi, msgRemap - call SysMsgBoardStr + mov dx, 0x4d0 ;8259 ELCR1 + in al, dx + bts ax, IRQ_LINE + out dx, al ;set level-triggered mode + mov [ctrl.int_line], IRQ_LINE + popf + mov esi, msgRemap + call SysMsgBoardStr end if - mov eax, VALID_IRQ - mov ebx, [ctrl.int_line] - mov esi, msgInvIRQ - bt eax, ebx - jnc .fail_msg - mov eax, ATTCH_IRQ - mov esi, msgAttchIRQ - bt eax, ebx - jnc .fail_msg + mov eax, VALID_IRQ + mov ebx, [ctrl.int_line] + mov esi, msgInvIRQ + bt eax, ebx + jnc .fail_msg + mov eax, ATTCH_IRQ + mov esi, msgAttchIRQ + bt eax, ebx + jnc .fail_msg - stdcall AttachIntHandler, ebx, ac97_irq, dword 0 - stdcall create + stdcall AttachIntHandler, ebx, ac97_irq, dword 0 + stdcall create .reg: - stdcall RegService, sz_sound_srv, service_proc - ret + stdcall RegService, sz_sound_srv, service_proc + ret .fail: if DEBUG - mov esi, msgFail - call SysMsgBoardStr + mov esi, msgFail + call SysMsgBoardStr end if - xor eax, eax - ret + xor eax, eax + ret .fail_msg: - call SysMsgBoardStr - xor eax, eax - ret + call SysMsgBoardStr + xor eax, eax + ret .stop: - call stop - xor eax, eax - ret + call stop + xor eax, eax + ret endp -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size align 4 proc service_proc stdcall, ioctl:dword - mov edi, [ioctl] - mov eax, [edi+io_code] + mov edi, [ioctl] + mov eax, [edi+io_code] - cmp eax, SRV_GETVERSION - jne @F - mov eax, [edi+output] - cmp [edi+out_size], 4 - jne .fail + cmp eax, SRV_GETVERSION + jne @F + mov eax, [edi+output] + cmp [edi+out_size], 4 + jne .fail - mov [eax], dword API_VERSION - xor eax, eax - ret + mov [eax], dword API_VERSION + xor eax, eax + ret @@: - cmp eax, DEV_PLAY - jne @F + cmp eax, DEV_PLAY + jne @F if DEBUG - mov esi, msgPlay - call SysMsgBoardStr + mov esi, msgPlay + call SysMsgBoardStr end if - call play - ret + call play + ret @@: - cmp eax, DEV_STOP - jne @F + cmp eax, DEV_STOP + jne @F if DEBUG - mov esi, msgStop - call SysMsgBoardStr + mov esi, msgStop + call SysMsgBoardStr end if - call stop - ret + call stop + ret @@: - cmp eax, DEV_CALLBACK - jne @F - mov ebx, [edi+input] - stdcall set_callback, [ebx] - ret + cmp eax, DEV_CALLBACK + jne @F + mov ebx, [edi+input] + stdcall set_callback, [ebx] + ret @@: - cmp eax, DEV_SET_MASTERVOL - jne @F - mov eax, [edi+input] - mov eax, [eax] - call set_master_vol ;eax= vol - ret + cmp eax, DEV_SET_MASTERVOL + jne @F + mov eax, [edi+input] + mov eax, [eax] + call set_master_vol ;eax= vol + ret @@: - cmp eax, DEV_GET_MASTERVOL - jne @F - mov ebx, [edi+output] - stdcall get_master_vol, ebx - ret + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + stdcall get_master_vol, ebx + ret @@: - cmp eax, DEV_GET_INFO - jne @F - mov ebx, [edi+output] - stdcall get_dev_info, ebx - ret + cmp eax, DEV_GET_INFO + jne @F + mov ebx, [edi+output] + stdcall get_dev_info, ebx + ret @@: .fail: - or eax, -1 - ret + or eax, -1 + ret endp restore handle @@ -516,517 +516,517 @@ restore out_size align 4 proc ac97_irq - locals - status dd 0 - endl + locals + status dd 0 + endl ; status = inl(chip->port + IPR); - mov edx, IPR - call [ctrl.ctrl_read32] - test eax, eax - jz @f + mov edx, IPR + call [ctrl.ctrl_read32] + test eax, eax + jz @f - mov dword [status], eax + mov dword [status], eax - mov ebx, dword [buff_list] - cmp [ctrl.user_callback], 0 - je @f - stdcall [ctrl.user_callback], ebx + mov ebx, dword [buff_list] + cmp [ctrl.user_callback], 0 + je @f + stdcall [ctrl.user_callback], ebx @@: - mov eax, dword [status] ;; ack ;; - mov edx, IPR - call [ctrl.ctrl_write32] - ret + mov eax, dword [status] ;; ack ;; + mov edx, IPR + call [ctrl.ctrl_write32] + ret endp align 4 proc create_primary_buff - stdcall KernelAlloc, 0x10000 - mov [ctrl.buffer], eax + stdcall KernelAlloc, 0x10000 + mov [ctrl.buffer], eax - mov edi, eax - mov ecx, 0x10000/4 - xor eax, eax - cld - rep stosd + mov edi, eax + mov ecx, 0x10000/4 + xor eax, eax + cld + rep stosd - mov eax, [ctrl.buffer] - call GetPgAddr + mov eax, [ctrl.buffer] + call GetPgAddr - mov edi, pcmout_bdl - stosd - mov eax, 0x4000000 - stosd + mov edi, pcmout_bdl + stosd + mov eax, 0x4000000 + stosd - mov edi, buff_list - mov eax, [ctrl.buffer] - stosd ;1.] + mov edi, buff_list + mov eax, [ctrl.buffer] + stosd ;1.] - mov eax, [ctrl.buffer] - call GetPgAddr + mov eax, [ctrl.buffer] + call GetPgAddr - stdcall ptr_write, PLAYBACK_POINTER, 0, 0 - stdcall ptr_write, PLAYBACK_UNKNOWN1, 0, 0 - stdcall ptr_write, PLAYBACK_UNKNOWN2, 0, 0 - stdcall ptr_write, PLAYBACK_DMA_ADDR, 0, eax + stdcall ptr_write, PLAYBACK_POINTER, 0, 0 + stdcall ptr_write, PLAYBACK_UNKNOWN1, 0, 0 + stdcall ptr_write, PLAYBACK_UNKNOWN2, 0, 0 + stdcall ptr_write, PLAYBACK_DMA_ADDR, 0, eax - mov eax, pcmout_bdl - mov ebx, eax - call GetPgAddr - and ebx, 0xFFF - add eax, ebx + mov eax, pcmout_bdl + mov ebx, eax + call GetPgAddr + and ebx, 0xFFF + add eax, ebx - stdcall ptr_write, PLAYBACK_LIST_ADDR, 0, eax - stdcall ptr_write, PLAYBACK_LIST_SIZE, 0, 0 - stdcall ptr_write, PLAYBACK_LIST_PTR, 0, 0 + stdcall ptr_write, PLAYBACK_LIST_ADDR, 0, eax + stdcall ptr_write, PLAYBACK_LIST_SIZE, 0, 0 + stdcall ptr_write, PLAYBACK_LIST_PTR, 0, 0 - ;mov eax, 0x00004000 - ;shl eax, 16 - stdcall ptr_write, PLAYBACK_PERIOD_SIZE, 0, 0x40000000;eax + ;mov eax, 0x00004000 + ;shl eax, 16 + stdcall ptr_write, PLAYBACK_PERIOD_SIZE, 0, 0x40000000 ;eax - ret + ret endp align 4 proc detect_controller - locals - last_bus dd ? - bus dd ? - devfn dd ? - endl + locals + last_bus dd ? + bus dd ? + devfn dd ? + endl - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err - mov [last_bus], eax + mov [last_bus], eax .next_bus: - and [devfn], 0 + and [devfn], 0 .next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next - mov edi, devices + mov edi, devices @@: - mov ebx, [edi] - test ebx, ebx - jz .next + mov ebx, [edi] + test ebx, ebx + jz .next - cmp eax, ebx - je .found - add edi, 12 - jmp @B + cmp eax, ebx + je .found + add edi, 12 + jmp @B .next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret .found: - mov ebx, [bus] - mov [ctrl.bus], ebx + mov ebx, [bus] + mov [ctrl.bus], ebx - mov ecx, [devfn] - mov [ctrl.devfn], ecx + mov ecx, [devfn] + mov [ctrl.devfn], ecx - mov edx, eax - and edx, 0xFFFF - mov [ctrl.vendor], edx - shr eax, 16 - mov [ctrl.dev_id], eax + mov edx, eax + and edx, 0xFFFF + mov [ctrl.vendor], edx + shr eax, 16 + mov [ctrl.dev_id], eax - mov ebx, [edi+4] - mov [ctrl.ctrl_ids], ebx - mov esi, [edi+8] - mov [ctrl.ctrl_setup], esi + mov ebx, [edi+4] + mov [ctrl.ctrl_ids], ebx + mov esi, [edi+8] + mov [ctrl.ctrl_setup], esi - cmp edx, VID_Creative - jne @F - mov [ctrl.vendor_ids], msg_Creative - ret + cmp edx, VID_Creative + jne @F + mov [ctrl.vendor_ids], msg_Creative + ret @@: .err: - xor eax, eax - mov [ctrl.vendor_ids], eax ;something wrong ? - ret + xor eax, eax + mov [ctrl.vendor_ids], eax ;something wrong ? + ret endp align 4 proc init_controller - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x2C - mov esi, msgPciSubsys - call SysMsgBoardStr - call dword2str - call SysMsgBoardStr + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x2C + mov esi, msgPciSubsys + call SysMsgBoardStr + call dword2str + call SysMsgBoardStr - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 - mov ebx, eax - and eax, 0xFFFF - mov [ctrl.pci_cmd], eax - shr ebx, 16 - mov [ctrl.pci_stat], ebx + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 + mov ebx, eax + and eax, 0xFFFF + mov [ctrl.pci_cmd], eax + shr ebx, 16 + mov [ctrl.pci_stat], ebx - mov esi, msgPciCmd - call SysMsgBoardStr - call dword2str - call SysMsgBoardStr + mov esi, msgPciCmd + call SysMsgBoardStr + call dword2str + call SysMsgBoardStr - mov esi, msgPciStat - call SysMsgBoardStr - mov eax, [ctrl.pci_stat] - call dword2str - call SysMsgBoardStr + mov esi, msgPciStat + call SysMsgBoardStr + mov eax, [ctrl.pci_stat] + call dword2str + call SysMsgBoardStr - mov esi, msgCtrlIsaIo - call SysMsgBoardStr - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 - call dword2str - call SysMsgBoardStr + mov esi, msgCtrlIsaIo + call SysMsgBoardStr + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 + call dword2str + call SysMsgBoardStr - and eax, 0xFFC0 - mov [ctrl.ctrl_io_base], eax + and eax, 0xFFC0 + mov [ctrl.ctrl_io_base], eax .default: - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C - and eax, 0xFF + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C + and eax, 0xFF @@: - mov [ctrl.int_line], eax + mov [ctrl.int_line], eax - call [ctrl.ctrl_setup] - xor eax, eax - inc eax - ret + call [ctrl.ctrl_setup] + xor eax, eax + inc eax + ret endp align 4 proc set_Creative - mov [ctrl.codec_read16], codec_io_r16 ;virtual - mov [ctrl.codec_write16], codec_io_w16 ;virtual + mov [ctrl.codec_read16], codec_io_r16 ;virtual + mov [ctrl.codec_write16], codec_io_w16 ;virtual - mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual - mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual - mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual + mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual + mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual + mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual - mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual - mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual - mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual - ret + mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual + mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual + mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual + ret endp align 4 proc init_codec - call reset_codec - test eax, eax - jz .err - call detect_codec - xor eax, eax - inc eax - ret + call reset_codec + test eax, eax + jz .err + call detect_codec + xor eax, eax + inc eax + ret .err: - xor eax, eax - ret + xor eax, eax + ret endp align 4 proc reset_codec - locals - counter dd ? - endl + locals + counter dd ? + endl if DEBUG - mov esi, msgCold - call SysMsgBoardStr + mov esi, msgCold + call SysMsgBoardStr end if - mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms - call StallExec + mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms + call StallExec - stdcall ptr_read, TRIGGER_CHANNEL, 0 + stdcall ptr_read, TRIGGER_CHANNEL, 0 - mov [counter], 16 ; total 20*100 ms = 2s + mov [counter], 16 ; total 20*100 ms = 2s .wait: - stdcall codec_read, dword 0x26 - test eax, 1 - jnz .ok + stdcall codec_read, dword 0x26 + test eax, 1 + jnz .ok - mov eax, 100000 ; wait 100 ms - call StallExec + mov eax, 100000 ; wait 100 ms + call StallExec - dec [counter] - jnz .wait + dec [counter] + jnz .wait if DEBUG - mov esi, msgCRFail - call SysMsgBoardStr + mov esi, msgCRFail + call SysMsgBoardStr end if .fail: - stc - ret + stc + ret .ok: - xor eax, eax - inc eax - ret + xor eax, eax + inc eax + ret endp align 4 play: - mov eax, INTE_CH_0_LOOP - stdcall intr_enable, eax + mov eax, INTE_CH_0_LOOP + stdcall intr_enable, eax - stdcall ptr_read, TRIGGER_CHANNEL, 0 - mov ebx, TRIGGER_CHANNEL_0 - or eax, ebx - stdcall ptr_write, TRIGGER_CHANNEL, 0, eax + stdcall ptr_read, TRIGGER_CHANNEL, 0 + mov ebx, TRIGGER_CHANNEL_0 + or eax, ebx + stdcall ptr_write, TRIGGER_CHANNEL, 0, eax - xor eax, eax - ret + xor eax, eax + ret align 4 stop: - mov eax, INTE_CH_0_LOOP or INTE_CH_0_HALF_LOOP - stdcall intr_disable, eax + mov eax, INTE_CH_0_LOOP or INTE_CH_0_HALF_LOOP + stdcall intr_disable, eax - stdcall ptr_read, TRIGGER_CHANNEL, 0 - mov ebx, TRIGGER_CHANNEL_0 - xor ebx, -1 - or eax, ebx - stdcall ptr_write, TRIGGER_CHANNEL, 0, eax - xor eax, eax - ret + stdcall ptr_read, TRIGGER_CHANNEL, 0 + mov ebx, TRIGGER_CHANNEL_0 + xor ebx, -1 + or eax, ebx + stdcall ptr_write, TRIGGER_CHANNEL, 0, eax + xor eax, eax + ret align 4 proc get_dev_info stdcall, p_info:dword - virtual at esi - CTRL_INFO CTRL_INFO - end virtual + virtual at esi + CTRL_INFO CTRL_INFO + end virtual - mov esi, [p_info] - mov eax, [ctrl.int_line] - mov ecx, [ctrl.ctrl_io_base] - mov [CTRL_INFO.irq], eax - mov [CTRL_INFO.ctrl_io_base], ecx - mov eax, [codec.chip_id] - mov [CTRL_INFO.codec_id], eax - mov ebx, [ctrl.pci_cmd] - mov [CTRL_INFO.pci_cmd], ebx + mov esi, [p_info] + mov eax, [ctrl.int_line] + mov ecx, [ctrl.ctrl_io_base] + mov [CTRL_INFO.irq], eax + mov [CTRL_INFO.ctrl_io_base], ecx + mov eax, [codec.chip_id] + mov [CTRL_INFO.codec_id], eax + mov ebx, [ctrl.pci_cmd] + mov [CTRL_INFO.pci_cmd], ebx - xor eax, eax - mov [CTRL_INFO.codec_io_base], eax - mov [CTRL_INFO.codec_mem_base], eax - mov [CTRL_INFO.ctrl_mem_base], eax - mov [CTRL_INFO.glob_cntrl], eax - mov [CTRL_INFO.glob_sta], eax - ret + xor eax, eax + mov [CTRL_INFO.codec_io_base], eax + mov [CTRL_INFO.codec_mem_base], eax + mov [CTRL_INFO.ctrl_mem_base], eax + mov [CTRL_INFO.glob_cntrl], eax + mov [CTRL_INFO.glob_sta], eax + ret endp align 4 proc set_callback stdcall, handler:dword - mov eax, [handler] - mov [ctrl.user_callback], eax - ret + mov eax, [handler] + mov [ctrl.user_callback], eax + ret endp align 4 proc create stdcall - stdcall PciRead16, [ctrl.bus], [ctrl.devfn], dword 4 - test eax, 4 ; test master bit - jnz @f - or eax, 4 - stdcall PciWrite16, [ctrl.bus], [ctrl.devfn], dword 4, eax ; set master bit - @@: + stdcall PciRead16, [ctrl.bus], [ctrl.devfn], dword 4 + test eax, 4 ; test master bit + jnz @f + or eax, 4 + stdcall PciWrite16, [ctrl.bus], [ctrl.devfn], dword 4, eax ; set master bit + @@: - xor eax, eax - mov edx, INTE - call [ctrl.ctrl_write32] + xor eax, eax + mov edx, INTE + call [ctrl.ctrl_write32] - stdcall ptr_write, SPCS0, 0, \ - SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ - SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ - SPCS_GENERATIONSTATUS or 0x00001200 or \ - 0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT - stdcall ptr_write, SPCS1, 0, \ - SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ - SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ - SPCS_GENERATIONSTATUS or 0x00001200 or \ - 0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT - stdcall ptr_write, SPCS2, 0, \ - SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ - SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ - SPCS_GENERATIONSTATUS or 0x00001200 or \ - 0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT + stdcall ptr_write, SPCS0, 0, \ + SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ + SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ + SPCS_GENERATIONSTATUS or 0x00001200 or \ + 0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT + stdcall ptr_write, SPCS1, 0, \ + SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ + SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ + SPCS_GENERATIONSTATUS or 0x00001200 or \ + 0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT + stdcall ptr_write, SPCS2, 0, \ + SPCS_CLKACCY_1000PPM or SPCS_SAMPLERATE_48 or \ + SPCS_CHANNELNUM_LEFT or SPCS_SOURCENUM_UNSPEC or \ + SPCS_GENERATIONSTATUS or 0x00001200 or \ + 0x00000000 or SPCS_EMPHASIS_NONE or SPCS_COPYRIGHT - stdcall ptr_write, SPDIF_SELECT, 0, 0x700 ; disable SPDIF - stdcall ptr_write, ROUTING, 0, 0x1003F ; routing - stdcall gpio_write, 0x1080 ; analog mode + stdcall ptr_write, SPDIF_SELECT, 0, 0x700 ; disable SPDIF + stdcall ptr_write, ROUTING, 0, 0x1003F ; routing + stdcall gpio_write, 0x1080 ; analog mode - mov eax, dword HCFG_LOCKSOUNDCACHE or HCFG_AUDIOENABLE - mov edx, HCFG - call [ctrl.ctrl_write32] - ret + mov eax, dword HCFG_LOCKSOUNDCACHE or HCFG_AUDIOENABLE + mov edx, HCFG + call [ctrl.ctrl_write32] + ret endp align 4 proc codec_read stdcall, reg:dword - stdcall ac97_read, dword [reg] - ret + stdcall ac97_read, dword [reg] + ret endp align 4 proc codec_write stdcall, reg:dword - stdcall ac97_write, dword [reg], eax - ret + stdcall ac97_write, dword [reg], eax + ret endp align 4 proc ac97_read stdcall, reg:dword - push edx - mov eax, dword [reg] - mov edx, AC97ADDRESS - call [ctrl.ctrl_write8] + push edx + mov eax, dword [reg] + mov edx, AC97ADDRESS + call [ctrl.ctrl_write8] - mov edx, AC97DATA - call [ctrl.ctrl_read16] - and eax, 0xFFFF - pop edx - ret + mov edx, AC97DATA + call [ctrl.ctrl_read16] + and eax, 0xFFFF + pop edx + ret endp align 4 proc ac97_write stdcall, reg:dword, val:dword - push eax edx - mov eax, dword [reg] - mov edx, AC97ADDRESS - call [ctrl.ctrl_write8] + push eax edx + mov eax, dword [reg] + mov edx, AC97ADDRESS + call [ctrl.ctrl_write8] - mov eax, dword [val] - mov edx, AC97DATA - call [ctrl.ctrl_write16] - pop edx eax - ret + mov eax, dword [val] + mov edx, AC97DATA + call [ctrl.ctrl_write16] + pop edx eax + ret endp align 4 proc ptr_read stdcall, reg:dword, chn:dword - push edx - mov eax, dword [reg] - shl eax, 16 - or eax, dword [chn] + push edx + mov eax, dword [reg] + shl eax, 16 + or eax, dword [chn] - mov edx, PTR - call [ctrl.ctrl_write32] + mov edx, PTR + call [ctrl.ctrl_write32] - mov edx, DATA - call [ctrl.ctrl_read32] - pop edx - ret + mov edx, DATA + call [ctrl.ctrl_read32] + pop edx + ret endp align 4 proc ptr_write stdcall, reg:dword, chn:dword, data:dword - push eax edx - mov eax, dword [reg] - shl eax, 16 - or eax, dword [chn] + push eax edx + mov eax, dword [reg] + shl eax, 16 + or eax, dword [chn] - mov edx, PTR - call [ctrl.ctrl_write32] + mov edx, PTR + call [ctrl.ctrl_write32] - mov eax, dword [data] - mov edx, DATA - call [ctrl.ctrl_write32] - pop edx eax - ret + mov eax, dword [data] + mov edx, DATA + call [ctrl.ctrl_write32] + pop edx eax + ret endp align 4 proc intr_enable stdcall, intrenb:dword - push edx - mov edx, INTE - call [ctrl.ctrl_read32] + push edx + mov edx, INTE + call [ctrl.ctrl_read32] - or eax, dword [intrenb] - mov edx, INTE - call [ctrl.ctrl_write32] - pop edx - ret + or eax, dword [intrenb] + mov edx, INTE + call [ctrl.ctrl_write32] + pop edx + ret endp align 4 proc intr_disable stdcall, intrenb:dword - push eax ebx edx - mov edx, INTE - call [ctrl.ctrl_read32] + push eax ebx edx + mov edx, INTE + call [ctrl.ctrl_read32] - mov ebx, dword [intrenb] - xor ebx, -1 - and eax, ebx - mov edx, INTE - call [ctrl.ctrl_write32] - pop edx ebx eax - ret + mov ebx, dword [intrenb] + xor ebx, -1 + and eax, ebx + mov edx, INTE + call [ctrl.ctrl_write32] + pop edx ebx eax + ret endp align 4 proc gpio_write stdcall, value:dword - push eax edx - mov eax, dword [value] - mov edx, GPIO - call [ctrl.ctrl_write32] - pop edx eax - ret + push eax edx + mov eax, dword [value] + mov edx, GPIO + call [ctrl.ctrl_write32] + pop edx eax + ret endp align 4 proc StallExec - push ecx - push edx - push ebx - push eax + push ecx + push edx + push ebx + push eax - mov ecx, CPU_FREQ - mul ecx - mov ebx, eax ;low - mov ecx, edx ;high - rdtsc - add ebx, eax - adc ecx, edx + mov ecx, CPU_FREQ + mul ecx + mov ebx, eax ;low + mov ecx, edx ;high + rdtsc + add ebx, eax + adc ecx, edx @@: - rdtsc - sub eax, ebx - sbb edx, ecx - js @B + rdtsc + sub eax, ebx + sbb edx, ecx + js @B - pop eax - pop ebx - pop edx - pop ecx - ret + pop eax + pop ebx + pop edx + pop ecx + ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1035,76 +1035,76 @@ endp align 4 proc codec_io_r16 ;Not used. - ;mov edx, [ctrl.ctrl_io_base] - ;in eax, dx - ret + ;mov edx, [ctrl.ctrl_io_base] + ;in eax, dx + ret endp align 4 proc codec_io_w16 ;Not used. - ;mov edx, [ctrl.ctrl_io_base] - ;out dx, eax - ret + ;mov edx, [ctrl.ctrl_io_base] + ;out dx, eax + ret endp align 4 proc ctrl_io_r8 - add edx, [ctrl.ctrl_io_base] - in al, dx - ret + add edx, [ctrl.ctrl_io_base] + in al, dx + ret endp align 4 proc ctrl_io_r16 - add edx, [ctrl.ctrl_io_base] - in ax, dx - ret + add edx, [ctrl.ctrl_io_base] + in ax, dx + ret endp align 4 proc ctrl_io_r32 - add edx, [ctrl.ctrl_io_base] - in eax, dx - ret + add edx, [ctrl.ctrl_io_base] + in eax, dx + ret endp align 4 proc ctrl_io_w8 - add edx, [ctrl.ctrl_io_base] - out dx, al - ret + add edx, [ctrl.ctrl_io_base] + out dx, al + ret endp align 4 proc ctrl_io_w16 - add edx, [ctrl.ctrl_io_base] - out dx, ax - ret + add edx, [ctrl.ctrl_io_base] + out dx, ax + ret endp align 4 proc ctrl_io_w32 - add edx, [ctrl.ctrl_io_base] - out dx, eax - ret + add edx, [ctrl.ctrl_io_base] + out dx, eax + ret endp align 4 dword2str: - push eax ebx ecx - mov esi, hex_buff - mov ecx, -8 + push eax ebx ecx + mov esi, hex_buff + mov ecx, -8 @@: - rol eax, 4 - mov ebx, eax - and ebx, 0x0F - mov bl, [ebx+hexletters] - mov [8+esi+ecx], bl - inc ecx - jnz @B - pop ecx ebx eax - ret + rol eax, 4 + mov ebx, eax + and ebx, 0x0F + mov bl, [ebx+hexletters] + mov [8+esi+ecx], bl + inc ecx + jnz @B + pop ecx ebx eax + ret hexletters db '0123456789ABCDEF' hex_buff db 8 dup(0),13,10,0 @@ -1114,16 +1114,16 @@ include "codec.inc" align 4 devices dd (CTRL_CT0200 shl 16)+VID_Creative,msg_CT_EMU10K1X,set_Creative - dd 0 ;terminator + dd 0 ;terminator version dd (5 shl 16) or (API_VERSION and 0xFFFF) msg_CT_EMU10K1X db 'SB Live! Dell OEM', 13,10, 0 -msg_Creative db 'Creative ', 0 +msg_Creative db 'Creative ', 0 -szKernel db 'KERNEL', 0 -sz_sound_srv db 'SOUND',0 +szKernel db 'KERNEL', 0 +sz_sound_srv db 'SOUND',0 msgInit db 'detect hardware...',13,10,0 msgFail db 'device not found',13,10,0 @@ -1131,7 +1131,7 @@ msgAttchIRQ db 'IRQ line not supported', 13,10, 0 msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 msgPlay db 'start play', 13,10,0 msgStop db 'stop play', 13,10,0 -msgIRQ db 'AC97 IRQ', 13,10,0 +msgIRQ db 'AC97 IRQ', 13,10,0 ;msgInitCtrl db 'init controller',13,10,0 ;msgInitCodec db 'init codec',13,10,0 msgPrimBuff db 'create primary buffer ...',0 @@ -1159,8 +1159,8 @@ msgCtrlIsaIo db 'controller io base ',0 section '.data' data readable writable align 16 -pcmout_bdl rq 32 -buff_list rd 32 +pcmout_bdl rq 32 +buff_list rd 32 codec CODEC ctrl AC_CNTRL diff --git a/kernel/trunk/drivers/ensoniq.asm b/kernel/trunk/drivers/ensoniq.asm index d5fe56fc3..ca9a69f31 100644 --- a/kernel/trunk/drivers/ensoniq.asm +++ b/kernel/trunk/drivers/ensoniq.asm @@ -1,1177 +1,1177 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;alpha version - -format MS COFF - -DEBUG equ 1 - - -include 'proc32.inc' -include 'imports.inc' - -REMAP_IRQ equ 0 - -;irq 0,1,2,8,12,13 недоступны -; FEDCBA9876543210 -VALID_IRQ equ 1100111011111000b -ATTCH_IRQ equ 0000111010101000b - -IRQ_LINE equ 0 - -CPU_FREQ equ 2600d - -BIT0 EQU 0x00000001 -BIT1 EQU 0x00000002 -BIT2 EQU 0x00000004 -BIT3 EQU 0x00000008 -BIT4 EQU 0x00000010 -BIT5 EQU 0x00000020 -BIT6 EQU 0x00000040 -BIT7 EQU 0x00000080 -BIT8 EQU 0x00000100 -BIT9 EQU 0x00000200 -BIT10 EQU 0x00000400 -BIT11 EQU 0x00000800 -BIT12 EQU 0x00001000 -BIT13 EQU 0x00002000 -BIT14 EQU 0x00004000 -BIT15 EQU 0x00008000 -BIT16 EQU 0x00010000 -BIT17 EQU 0x00020000 -BIT18 EQU 0x00040000 -BIT19 EQU 0x00080000 -BIT20 EQU 0x00100000 -BIT21 EQU 0x00200000 -BIT22 EQU 0x00400000 -BIT23 EQU 0x00800000 -BIT24 EQU 0x00100000 -BIT25 EQU 0x02000000 -BIT26 EQU 0x04000000 -BIT27 EQU 0x08000000 -BIT28 EQU 0x10000000 -BIT29 EQU 0x20000000 -BIT30 EQU 0x40000000 -BIT31 EQU 0x80000000 - - -PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list -PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register -PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index -PCM_OUT_SR_REG equ 0x16 ; PCM out Status register -PCM_OUT_PIV_REG equ 0x1a -PCM_OUT_CIV_REG equ 0x14 ; PCM out current index - -PCM_IN_CR_REG equ 0x0b ; PCM in Control Register -MC_IN_CR_REG equ 0x2b ; MIC in Control Register -RR equ BIT1 ; reset registers. Nukes all regs - -CODEC_MASTER_VOL_REG equ 0x02 -CODEC_AUX_VOL equ 0x04 ; -CODEC_PCM_OUT_REG equ 18h ; PCM output volume -CODEC_EXT_AUDIO_REG equ 28h ; extended audio -CODEC_EXT_AUDIO_CTRL_REG equ 2ah ; extended audio control -CODEC_PCM_FRONT_DACRATE_REG equ 2ch ; PCM out sample rate -CODEC_PCM_SURND_DACRATE_REG equ 2eh ; surround sound sample rate -CODEC_PCM_LFE_DACRATE_REG equ 30h ; LFE sample rate - -GLOB_CTRL equ 0x2C ; Global Control -CTRL_STAT equ 0x30 ; Global Status -CTRL_CAS equ 0x34 ; Codec Access Semiphore - -CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit - -CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready - -CTRL_ST_RCS equ 0x00008000 ; Read Completion Status - -CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable -CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off -CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset -CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset -CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable - -CODEC_REG_POWERDOWN equ 0x26 -CODEC_REG_ST equ 0x26 - -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_SET_BUFF equ 4 -DEV_NOTIFY equ 5 -DEV_SET_MASTERVOL equ 6 -DEV_GET_MASTERVOL equ 7 -DEV_GET_INFO equ 8 - -struc AC_CNTRL ;AC controller base class -{ .bus dd ? - .devfn dd ? - - .vendor dd ? - .dev_id dd ? - .pci_cmd dd ? - .pci_stat dd ? - - .codec_io_base dd ? - .codec_mem_base dd ? - - .ctrl_io_base dd ? - .ctrl_mem_base dd ? - .cfg_reg dd ? - .int_line dd ? - - .vendor_ids dd ? ;vendor id string - .ctrl_ids dd ? ;hub id string - - .buffer dd ? - - .notify_pos dd ? - .notify_task dd ? - - .lvi_reg dd ? - .ctrl_setup dd ? - .user_callback dd ? - .codec_read16 dd ? - .codec_write16 dd ? - - .ctrl_read8 dd ? - .ctrl_read16 dd ? - .ctrl_read32 dd ? - - .ctrl_write8 dd ? - .ctrl_write16 dd ? - .ctrl_write32 dd ? -} - -struc CODEC ;Audio Chip base class -{ - .chip_id dd ? - .flags dd ? - .status dd ? - - .ac_vendor_ids dd ? ;ac vendor id string - .chip_ids dd ? ;chip model string - - .shadow_flag dd ? - dd ? - - .regs dw ? ; codec registers - .reg_master_vol dw ? ;0x02 - .reg_aux_out_vol dw ? ;0x04 - .reg_mone_vol dw ? ;0x06 - .reg_master_tone dw ? ;0x08 - .reg_beep_vol dw ? ;0x0A - .reg_phone_vol dw ? ;0x0C - .reg_mic_vol dw ? ;0x0E - .reg_line_in_vol dw ? ;0x10 - .reg_cd_vol dw ? ;0x12 - .reg_video_vol dw ? ;0x14 - .reg_aux_in_vol dw ? ;0x16 - .reg_pcm_out_vol dw ? ;0x18 - .reg_rec_select dw ? ;0x1A - .reg_rec_gain dw ? ;0x1C - .reg_rec_gain_mic dw ? ;0x1E - .reg_gen dw ? ;0x20 - .reg_3d_ctrl dw ? ;0X22 - .reg_page dw ? ;0X24 - .reg_powerdown dw ? ;0x26 - .reg_ext_audio dw ? ;0x28 - .reg_ext_st dw ? ;0x2a - .reg_pcm_front_rate dw ? ;0x2c - .reg_pcm_surr_rate dw ? ;0x2e - .reg_lfe_rate dw ? ;0x30 - .reg_pcm_in_rate dw ? ;0x32 - dw ? ;0x34 - .reg_cent_lfe_vol dw ? ;0x36 - .reg_surr_vol dw ? ;0x38 - .reg_spdif_ctrl dw ? ;0x3A - dw ? ;0x3C - dw ? ;0x3E - dw ? ;0x40 - dw ? ;0x42 - dw ? ;0x44 - dw ? ;0x46 - dw ? ;0x48 - dw ? ;0x4A - dw ? ;0x4C - dw ? ;0x4E - dw ? ;0x50 - dw ? ;0x52 - dw ? ;0x54 - dw ? ;0x56 - dw ? ;0x58 - dw ? ;0x5A - dw ? ;0x5C - dw ? ;0x5E - .reg_page_0 dw ? ;0x60 - .reg_page_1 dw ? ;0x62 - .reg_page_2 dw ? ;0x64 - .reg_page_3 dw ? ;0x66 - .reg_page_4 dw ? ;0x68 - .reg_page_5 dw ? ;0x6A - .reg_page_6 dw ? ;0x6C - .reg_page_7 dw ? ;0x6E - dw ? ;0x70 - dw ? ;0x72 - dw ? ;0x74 - dw ? ;0x76 - dw ? ;0x78 - dw ? ;0x7A - .reg_vendor_id_1 dw ? ;0x7C - .reg_vendor_id_2 dw ? ;0x7E - - - .reset dd ? ;virual - .set_master_vol dd ? -} - -struc CTRL_INFO -{ .pci_cmd dd ? - .irq dd ? - .glob_cntrl dd ? - .glob_sta dd ? - .codec_io_base dd ? - .ctrl_io_base dd ? - .codec_mem_base dd ? - .ctrl_mem_base dd ? - .codec_id dd ? -} - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -EVENT_NOTIFY equ 0x00000200 - -OS_BASE equ 0x80000000 -SLOT_BASE equ OS_BASE+0x0080000 -new_app_base equ 0 - -public START -public service_proc -public version - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .stop - - if DEBUG - mov esi, msgDetect - call SysMsgBoardStr - end if - - call detect_controller - test eax, eax - jz .fail - - if DEBUG - mov esi,[ctrl.vendor_ids] - call SysMsgBoardStr - mov esi, [ctrl.ctrl_ids] - call SysMsgBoardStr - - end if - call init_controller - test eax, eax - jz .fail - - jmp .fail ;force fail - - if DEBUG - mov esi, msgInitCodec - call SysMsgBoardStr - end if - - call init_codec - test eax, eax - jz .fail - - if DEBUG - mov esi, [codec.ac_vendor_ids] - call SysMsgBoardStr - - mov esi, [codec.chip_ids] - call SysMsgBoardStr - end if - - call reset_controller - call setup_codec - - mov esi, msgPrimBuff - call SysMsgBoardStr - - call create_primary_buff - - mov eax, VALID_IRQ - mov ebx, [ctrl.int_line] - mov esi, msgInvIRQ - bt eax, ebx - jnc .fail - mov eax, ATTCH_IRQ - mov esi, msgAttchIRQ - bt eax, ebx - jnc .fail - - stdcall AttachIntHandler, ebx, ac97_irq, dword 0 - stdcall RegService, sz_sound_srv, service_proc - ret -.fail: - if DEBUG - mov esi, msgFail - call SysMsgBoardStr - end if - xor eax, eax - ret -.stop: - call stop - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - - mov edi, [ioctl] - mov eax, [edi+io_code] - cmp eax, DEV_PLAY - jne @F - if DEBUG - mov esi, msgPlay - call SysMsgBoardStr - end if - call play - ret -@@: - cmp eax, DEV_STOP - jne @F - if DEBUG - mov esi, msgStop - call SysMsgBoardStr - end if - call stop - ret -@@: - cmp eax, DEV_CALLBACK - jne @F - mov ebx, [edi+input] - stdcall set_callback, [ebx] - ret -@@: - cmp eax, DEV_SET_MASTERVOL - jne @F - mov eax, [edi+input] - mov eax, [eax] - call set_master_vol ;eax= vol - ret -@@: - cmp eax, DEV_GET_MASTERVOL - jne @F - mov ebx, [edi+output] - stdcall get_master_vol, ebx - ret -;@@: -; cmp eax, DEV_GET_INFO -; jne @F -; mov ebx, [edi+output] -; stdcall get_dev_info, ebx -; ret -@@: -.fail: - or eax, -1 - ret -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - - -align 4 -proc ac97_irq - -; if DEBUG -; mov esi, msgIRQ -; call SysMsgBoardStr -; end if - - - cmp [ctrl.user_callback], 0 - je @f - - stdcall [ctrl.user_callback], ebx -@@: - ret - -.skip: - mov edx, PCM_OUT_CR_REG - mov ax, 0x11 ;0x1D - call [ctrl.ctrl_write8] - ret -endp - -align 4 -proc create_primary_buff - - stdcall KernelAlloc, 0x10000 - mov [ctrl.buffer], eax - - mov edi, eax - mov ecx, 0x10000/4 - xor eax, eax - cld - rep stosd - - mov eax, [ctrl.buffer] - call GetPgAddr - - mov ebx, 0xC0002000 - mov ecx, 4 - mov edi, pcmout_bdl -@@: - mov [edi], eax - mov [edi+4], ebx - - mov [edi+32], eax - mov [edi+4+32], ebx - - mov [edi+64], eax - mov [edi+4+64], ebx - - mov [edi+96], eax - mov [edi+4+96], ebx - - mov [edi+128], eax - mov [edi+4+128], ebx - - mov [edi+160], eax - mov [edi+4+160], ebx - - mov [edi+192], eax - mov [edi+4+192], ebx - - mov [edi+224], eax - mov [edi+4+224], ebx - - add eax, 0x4000 - add edi, 8 - loop @B - - mov edi, buff_list - mov eax, [ctrl.buffer] - mov ecx, 4 -@@: - mov [edi], eax - mov [edi+16], eax - mov [edi+32], eax - mov [edi+48], eax - mov [edi+64], eax - mov [edi+80], eax - mov [edi+96], eax - mov [edi+112], eax - - add eax, 0x4000 - add edi, 4 - loop @B - - mov eax, pcmout_bdl - mov ebx, eax - call GetPgAddr ;eax - and ebx, 0xFFF - add eax, ebx - - mov edx, PCM_OUT_BDL - call [ctrl.ctrl_write32] - - mov eax, 16 - mov [ctrl.lvi_reg], eax - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - ret -endp - -align 4 -proc detect_controller - locals - last_bus dd ? - bus dd ? - devfn dd ? - endl - - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err - - mov [last_bus], eax - -.next_bus: - and [devfn], 0 -.next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next - - mov edi, devices -@@: - mov ebx, [edi] - test ebx, ebx - jz .next - - cmp eax, ebx - je .found - add edi, 12 - jmp @B - -.next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret -.found: - mov ebx, [bus] - mov [ctrl.bus], ebx - - mov ecx, [devfn] - mov [ctrl.devfn], ecx - - mov edx, eax - and edx, 0xFFFF - mov [ctrl.vendor], edx - shr eax, 16 - mov [ctrl.dev_id], eax - - mov ebx, [edi+4] - mov [ctrl.ctrl_ids], ebx - mov esi, [edi+8] - mov [ctrl.ctrl_setup], esi - - cmp ebx, 0x1274 - jne @F - mov [ctrl.vendor_ids], msgEnsoniq - ret -@@: - mov [ctrl.vendor_ids], 0 ;something wrong ? - ret -.err: - xor eax, eax - ret -endp - -align 4 -proc init_controller - - mov esi, msgPCIcmd - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 - mov ebx, eax - and eax, 0xFFFF - mov [ctrl.pci_cmd], eax - shr ebx, 16 - mov [ctrl.pci_stat], ebx - - call dword2str - call SysMsgBoardStr - - mov esi, msgIObase - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 -; and eax, -16 - mov [ctrl.ctrl_io_base], eax - - call dword2str - call SysMsgBoardStr - - mov esi, msgIRQline - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C - and eax, 0xFF - mov [ctrl.int_line], eax - - call dword2str - call SysMsgBoardStr - - call [ctrl.ctrl_setup] - xor eax, eax - inc eax - ret -endp - -align 4 -proc set_ICH - mov [ctrl.codec_read16], codec_io_r16 ;virtual - mov [ctrl.codec_write16], codec_io_w16 ;virtual - - mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual - mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual - mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual - - mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual - mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual - mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual - ret -endp - -align 4 -proc reset_controller - - xor eax, eax - mov edx, PCM_IN_CR_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - call [ctrl.ctrl_write8] - - mov edx, MC_IN_CR_REG - call [ctrl.ctrl_write8] - - mov eax, RR - mov edx, PCM_IN_CR_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - call [ctrl.ctrl_write8] - - mov edx, MC_IN_CR_REG - call [ctrl.ctrl_write8] - ret -endp - -align 4 -proc init_codec - locals - counter dd ? - endl - - mov esi, msgControl - call SysMsgBoardStr - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - call dword2str - call SysMsgBoardStr - - mov esi, msgStatus - call SysMsgBoardStr - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - - call dword2str - call SysMsgBoardStr - - test eax, CTRL_ST_CREADY - jnz .ready - - call reset_codec - and eax, eax - jz .err - - xor edx, edx ;ac_reg_0 - call [ctrl.codec_write16] - - xor eax, eax - mov edx, CODEC_REG_POWERDOWN - call [ctrl.codec_write16] - - mov [counter], 200 ; total 200*5 ms = 1s -.wait: - mov edx, CODEC_REG_POWERDOWN - call [ctrl.codec_read16] - and eax, 0x0F - cmp eax, 0x0F - jz .ready - - mov eax, 5000 ; wait 5 ms - call StallExec - sub [counter] , 1 - jnz .wait -.err: - xor eax, eax ; timeout error - ret -.ready: - call detect_codec - - xor eax, eax - inc eax - ret -endp - -align 4 -proc reset_codec - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - - test eax, 0x02 - jz .cold - - call warm_reset - jnc .ok -.cold: - call cold_reset - jnc .ok - - if DEBUG - mov esi, msgCFail - call SysMsgBoardStr - end if - xor eax, eax ; timeout error - ret -.ok: - if DEBUG - mov esi, msgResetOk - call SysMsgBoardStr - end if - - xor eax, eax - inc eax - ret -endp - -align 4 -proc warm_reset - locals - counter dd ? - endl - - mov eax, 0x06 - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - if DEBUG - mov esi, msgWarm - call SysMsgBoardStr - end if - - mov [counter], 10 ; total 10*100 ms = 1s -.wait: - mov eax, 100000 ; wait 100 ms - call StallExec - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - test eax, 4 - jz .ok - sub [counter], 1 - jnz .wait - - if DEBUG - mov esi, msgWRFail - call SysMsgBoardStr - end if - - stc - ret -.ok: - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - and eax, CTRL_ST_CREADY - jz .fail - clc - ret -.fail: - stc - ret -endp - -align 4 -proc cold_reset - locals - counter dd ? - endl - - xor eax, eax - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - if DEBUG - mov esi, msgCold - call SysMsgBoardStr - end if - - mov eax, 1000000 ; wait 1 s - call StallExec - - mov eax, 2 - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - mov [counter], 10 ; total 10*100 ms = 1s -.wait: - mov eax, 100000 ; wait 100 ms - call StallExec - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - test eax, 4 - jz .ok - sub [counter], 1 - jnz .wait - - if DEBUG - mov esi, msgCRFail - call SysMsgBoardStr - end if - stc - ret -.ok: - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - and eax, CTRL_ST_CREADY - jz .fail - clc - ret -.fail: - stc - ret -endp - -align 4 -play: - mov eax, 16 - mov [ctrl.lvi_reg], eax - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - mov ax, 0x1D - call [ctrl.ctrl_write8] - xor eax, eax - ret - -align 4 -stop: - mov edx, PCM_OUT_CR_REG - mov ax, 0x0 - call [ctrl.ctrl_write8] - - mov ax, 0x1c - mov edx, PCM_OUT_SR_REG - call [ctrl.ctrl_write16] - xor eax, eax - ret - -align 4 -proc get_dev_info stdcall, p_info:dword - virtual at esi - CTRL_INFO CTRL_INFO - end virtual - - mov esi, [p_info] - mov eax, [ctrl.int_line] - mov ebx, [ctrl.codec_io_base] - mov ecx, [ctrl.ctrl_io_base] - mov edx, [ctrl.codec_mem_base] - mov edi, [ctrl.ctrl_mem_base] - - mov [CTRL_INFO.irq], eax - mov [CTRL_INFO.codec_io_base], ebx - mov [CTRL_INFO.ctrl_io_base], ecx - mov [CTRL_INFO.codec_mem_base], edx - mov [CTRL_INFO.ctrl_mem_base], edi - - mov eax, [codec.chip_id] - mov [CTRL_INFO.codec_id], eax - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - mov [CTRL_INFO.glob_cntrl], eax - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - mov [CTRL_INFO.glob_sta], eax - - mov ebx, [ctrl.pci_cmd] - mov [CTRL_INFO.pci_cmd], ebx - ret -endp - -align 4 -proc set_callback stdcall, handler:dword - mov eax, [handler] - mov [ctrl.user_callback], eax - ret -endp - -align 4 -proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax - - mov edx, [ac_reg] - - mov ebx, edx - shr ebx, 1 - bt [codec.shadow_flag], ebx - jc .use_shadow - - call [ctrl.codec_read16] ;change edx !!! - mov ecx, eax - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - test eax, CTRL_ST_RCS - jz .read_ok - - mov edx, CTRL_STAT - call [ctrl.ctrl_write32] - xor eax,eax - not eax ;timeout - ret -.read_ok: - mov edx, [ac_reg] - mov [codec.regs+edx], cx - bts [codec.shadow_flag], ebx - mov eax, ecx - ret -.use_shadow: - movzx eax, word [codec.regs+edx] - ret -endp - -align 4 -proc codec_write stdcall, ac_reg:dword - push eax - call check_semafore - and eax, eax - jz .err - pop eax - - mov esi, [ac_reg] - mov edx, esi - call [ctrl.codec_write16] - mov [codec.regs+esi], ax - shr esi, 1 - bts [codec.shadow_flag], esi - ret -.err: - pop eax - ret -endp - -align 4 -proc codec_check_ready - - mov edx, CTRL_ST - call [ctrl.ctrl_read32] - and eax, CTRL_ST_CREADY - jz .not_ready - - xor eax, wax - inc eax - ret -.not_ready: - xor eax, eax - ret -endp - -align 4 -proc check_semafore - local counter:DWORD - - mov [counter], 100 -.l1: - mov edx, CTRL_CAS - call [ctrl.ctrl_read8] - and eax, CAS_FLAG - jz .ok - - mov eax, 1 - call StallExec - sub [counter], 1 - jnz .l1 - xor eax, eax - ret -align 4 -.ok: - xor eax,eax - inc eax - ret -endp - -align 4 -proc StallExec - push ecx - push edx - push ebx - push eax - - mov ecx, CPU_FREQ - mul ecx - mov ebx, eax ;low - mov ecx, edx ;high - rdtsc - add ebx, eax - adc ecx,edx -@@: - rdtsc - sub eax, ebx - sbb edx, ecx - js @B - - pop eax - pop ebx - pop edx - pop ecx - ret -endp - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; CONTROLLER IO functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -align 4 -codec_io_r16: - add edx, [ctrl.codec_io_base] - in ax, dx - ret - -align 4 -codec_io_w16: - add edx, [ctrl.codec_io_base] - out dx, ax - ret - -align 4 -ctrl_io_r8: - add edx, [ctrl.ctrl_io_base] - in al, dx - ret - -align 4 -ctrl_io_r16: - add edx, [ctrl.ctrl_io_base] - in ax, dx - ret - -align 4 -ctrl_io_r32: - add edx, [ctrl.ctrl_io_base] - in eax, dx - ret - -align 4 -ctrl_io_w8: - add edx, [ctrl.ctrl_io_base] - out dx, al - ret - -align 4 -ctrl_io_w16: - add edx, [ctrl.ctrl_io_base] - out dx, ax - ret - -align 4 -ctrl_io_w32: - add edx, [ctrl.ctrl_io_base] - out dx, eax - ret - - -align 4 -dword2str: - mov esi, hex_buff - mov ecx, -8 -@@: - rol eax, 4 - mov ebx, eax - and ebx, 0x0F - mov bl, [ebx+hexletters] - mov [8+esi+ecx], bl - inc ecx - jnz @B - ret - -hexletters db '0123456789ABCDEF' -hex_buff db 8 dup(0),13,10,0 - - -include "codec.inc" - -align 4 -devices dd (0x5000 shl 16)+0x1274,msgEnsoniq,set_ICH - dd (0x5880 shl 16)+0x1274,msgVibra128,set_ICH - dd 0 ;terminator - -version dd 0x00040004 - -msgEnsoniq db 'Ensonic 1371',13,10,0 -msgVibra128 db 'Sound Blaster AudioPCI Vibra 128',13,10,0 - -sz_sound_srv db 'SOUND',0 - -msgDetect db 'detect hardware...',13,10,0 -msgFail db 'device not found',13,10,0 -msgAttchIRQ db 'IRQ line not supported', 13,10, 0 -msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 -msgPlay db 'start play', 13,10,0 -msgStop db 'stop play', 13,10,0 -msgNotify db 'call notify',13,10,0 -msgIRQ db 'AC97 IRQ', 13,10,0 -msgInitCtrl db 'init controller',13,10,0 -msgInitCodec db 'init codec',13,10,0 -msgPrimBuff db 'create primary buffer',13,10,0 -msgReg db 'set service handler',13,10,0 -msgOk db 'service installed',13,10,0 -msgCold db 'cold reset',13,10,0 -msgWarm db 'warm reset',13,10,0 -msgWRFail db 'warm reset failed',13,10,0 -msgCRFail db 'cold reset failed',13,10,0 -msgCFail db 'codec not ready',13,10,0 -msgResetOk db 'reset complete',13,10,0 -msgStatus db 'global status ',0 -msgControl db 'global control ',0 -msgPCIcmd db 'PCI command ',0 -msgIObase db 'IO base ',0 -msgIRQline db 'IRQ line ',0 - -section '.data' data readable writable align 16 - -pcmout_bdl rq 32 -buff_list rd 32 - -codec CODEC -ctrl AC_CNTRL - -lpc_bus rd 1 -civ_val rd 1 - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;alpha version + +format MS COFF + +DEBUG equ 1 + + +include 'proc32.inc' +include 'imports.inc' + +REMAP_IRQ equ 0 + +;irq 0,1,2,8,12,13 недоступны +; FEDCBA9876543210 +VALID_IRQ equ 1100111011111000b +ATTCH_IRQ equ 0000111010101000b + +IRQ_LINE equ 0 + +CPU_FREQ equ 2600d + +BIT0 EQU 0x00000001 +BIT1 EQU 0x00000002 +BIT2 EQU 0x00000004 +BIT3 EQU 0x00000008 +BIT4 EQU 0x00000010 +BIT5 EQU 0x00000020 +BIT6 EQU 0x00000040 +BIT7 EQU 0x00000080 +BIT8 EQU 0x00000100 +BIT9 EQU 0x00000200 +BIT10 EQU 0x00000400 +BIT11 EQU 0x00000800 +BIT12 EQU 0x00001000 +BIT13 EQU 0x00002000 +BIT14 EQU 0x00004000 +BIT15 EQU 0x00008000 +BIT16 EQU 0x00010000 +BIT17 EQU 0x00020000 +BIT18 EQU 0x00040000 +BIT19 EQU 0x00080000 +BIT20 EQU 0x00100000 +BIT21 EQU 0x00200000 +BIT22 EQU 0x00400000 +BIT23 EQU 0x00800000 +BIT24 EQU 0x00100000 +BIT25 EQU 0x02000000 +BIT26 EQU 0x04000000 +BIT27 EQU 0x08000000 +BIT28 EQU 0x10000000 +BIT29 EQU 0x20000000 +BIT30 EQU 0x40000000 +BIT31 EQU 0x80000000 + + +PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list +PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register +PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index +PCM_OUT_SR_REG equ 0x16 ; PCM out Status register +PCM_OUT_PIV_REG equ 0x1a +PCM_OUT_CIV_REG equ 0x14 ; PCM out current index + +PCM_IN_CR_REG equ 0x0b ; PCM in Control Register +MC_IN_CR_REG equ 0x2b ; MIC in Control Register +RR equ BIT1 ; reset registers. Nukes all regs + +CODEC_MASTER_VOL_REG equ 0x02 +CODEC_AUX_VOL equ 0x04 ; +CODEC_PCM_OUT_REG equ 18h ; PCM output volume +CODEC_EXT_AUDIO_REG equ 28h ; extended audio +CODEC_EXT_AUDIO_CTRL_REG equ 2ah ; extended audio control +CODEC_PCM_FRONT_DACRATE_REG equ 2ch ; PCM out sample rate +CODEC_PCM_SURND_DACRATE_REG equ 2eh ; surround sound sample rate +CODEC_PCM_LFE_DACRATE_REG equ 30h ; LFE sample rate + +GLOB_CTRL equ 0x2C ; Global Control +CTRL_STAT equ 0x30 ; Global Status +CTRL_CAS equ 0x34 ; Codec Access Semiphore + +CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit + +CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready + +CTRL_ST_RCS equ 0x00008000 ; Read Completion Status + +CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable +CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off +CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset +CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset +CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable + +CODEC_REG_POWERDOWN equ 0x26 +CODEC_REG_ST equ 0x26 + +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_SET_BUFF equ 4 +DEV_NOTIFY equ 5 +DEV_SET_MASTERVOL equ 6 +DEV_GET_MASTERVOL equ 7 +DEV_GET_INFO equ 8 + +struc AC_CNTRL ;AC controller base class +{ .bus dd ? + .devfn dd ? + + .vendor dd ? + .dev_id dd ? + .pci_cmd dd ? + .pci_stat dd ? + + .codec_io_base dd ? + .codec_mem_base dd ? + + .ctrl_io_base dd ? + .ctrl_mem_base dd ? + .cfg_reg dd ? + .int_line dd ? + + .vendor_ids dd ? ;vendor id string + .ctrl_ids dd ? ;hub id string + + .buffer dd ? + + .notify_pos dd ? + .notify_task dd ? + + .lvi_reg dd ? + .ctrl_setup dd ? + .user_callback dd ? + .codec_read16 dd ? + .codec_write16 dd ? + + .ctrl_read8 dd ? + .ctrl_read16 dd ? + .ctrl_read32 dd ? + + .ctrl_write8 dd ? + .ctrl_write16 dd ? + .ctrl_write32 dd ? +} + +struc CODEC ;Audio Chip base class +{ + .chip_id dd ? + .flags dd ? + .status dd ? + + .ac_vendor_ids dd ? ;ac vendor id string + .chip_ids dd ? ;chip model string + + .shadow_flag dd ? + dd ? + + .regs dw ? ; codec registers + .reg_master_vol dw ? ;0x02 + .reg_aux_out_vol dw ? ;0x04 + .reg_mone_vol dw ? ;0x06 + .reg_master_tone dw ? ;0x08 + .reg_beep_vol dw ? ;0x0A + .reg_phone_vol dw ? ;0x0C + .reg_mic_vol dw ? ;0x0E + .reg_line_in_vol dw ? ;0x10 + .reg_cd_vol dw ? ;0x12 + .reg_video_vol dw ? ;0x14 + .reg_aux_in_vol dw ? ;0x16 + .reg_pcm_out_vol dw ? ;0x18 + .reg_rec_select dw ? ;0x1A + .reg_rec_gain dw ? ;0x1C + .reg_rec_gain_mic dw ? ;0x1E + .reg_gen dw ? ;0x20 + .reg_3d_ctrl dw ? ;0X22 + .reg_page dw ? ;0X24 + .reg_powerdown dw ? ;0x26 + .reg_ext_audio dw ? ;0x28 + .reg_ext_st dw ? ;0x2a + .reg_pcm_front_rate dw ? ;0x2c + .reg_pcm_surr_rate dw ? ;0x2e + .reg_lfe_rate dw ? ;0x30 + .reg_pcm_in_rate dw ? ;0x32 + dw ? ;0x34 + .reg_cent_lfe_vol dw ? ;0x36 + .reg_surr_vol dw ? ;0x38 + .reg_spdif_ctrl dw ? ;0x3A + dw ? ;0x3C + dw ? ;0x3E + dw ? ;0x40 + dw ? ;0x42 + dw ? ;0x44 + dw ? ;0x46 + dw ? ;0x48 + dw ? ;0x4A + dw ? ;0x4C + dw ? ;0x4E + dw ? ;0x50 + dw ? ;0x52 + dw ? ;0x54 + dw ? ;0x56 + dw ? ;0x58 + dw ? ;0x5A + dw ? ;0x5C + dw ? ;0x5E + .reg_page_0 dw ? ;0x60 + .reg_page_1 dw ? ;0x62 + .reg_page_2 dw ? ;0x64 + .reg_page_3 dw ? ;0x66 + .reg_page_4 dw ? ;0x68 + .reg_page_5 dw ? ;0x6A + .reg_page_6 dw ? ;0x6C + .reg_page_7 dw ? ;0x6E + dw ? ;0x70 + dw ? ;0x72 + dw ? ;0x74 + dw ? ;0x76 + dw ? ;0x78 + dw ? ;0x7A + .reg_vendor_id_1 dw ? ;0x7C + .reg_vendor_id_2 dw ? ;0x7E + + + .reset dd ? ;virual + .set_master_vol dd ? +} + +struc CTRL_INFO +{ .pci_cmd dd ? + .irq dd ? + .glob_cntrl dd ? + .glob_sta dd ? + .codec_io_base dd ? + .ctrl_io_base dd ? + .codec_mem_base dd ? + .ctrl_mem_base dd ? + .codec_id dd ? +} + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +EVENT_NOTIFY equ 0x00000200 + +OS_BASE equ 0x80000000 +SLOT_BASE equ OS_BASE+0x0080000 +new_app_base equ 0 + +public START +public service_proc +public version + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .stop + + if DEBUG + mov esi, msgDetect + call SysMsgBoardStr + end if + + call detect_controller + test eax, eax + jz .fail + + if DEBUG + mov esi, [ctrl.vendor_ids] + call SysMsgBoardStr + mov esi, [ctrl.ctrl_ids] + call SysMsgBoardStr + + end if + call init_controller + test eax, eax + jz .fail + + jmp .fail ;force fail + + if DEBUG + mov esi, msgInitCodec + call SysMsgBoardStr + end if + + call init_codec + test eax, eax + jz .fail + + if DEBUG + mov esi, [codec.ac_vendor_ids] + call SysMsgBoardStr + + mov esi, [codec.chip_ids] + call SysMsgBoardStr + end if + + call reset_controller + call setup_codec + + mov esi, msgPrimBuff + call SysMsgBoardStr + + call create_primary_buff + + mov eax, VALID_IRQ + mov ebx, [ctrl.int_line] + mov esi, msgInvIRQ + bt eax, ebx + jnc .fail + mov eax, ATTCH_IRQ + mov esi, msgAttchIRQ + bt eax, ebx + jnc .fail + + stdcall AttachIntHandler, ebx, ac97_irq, dword 0 + stdcall RegService, sz_sound_srv, service_proc + ret +.fail: + if DEBUG + mov esi, msgFail + call SysMsgBoardStr + end if + xor eax, eax + ret +.stop: + call stop + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + + mov edi, [ioctl] + mov eax, [edi+io_code] + cmp eax, DEV_PLAY + jne @F + if DEBUG + mov esi, msgPlay + call SysMsgBoardStr + end if + call play + ret +@@: + cmp eax, DEV_STOP + jne @F + if DEBUG + mov esi, msgStop + call SysMsgBoardStr + end if + call stop + ret +@@: + cmp eax, DEV_CALLBACK + jne @F + mov ebx, [edi+input] + stdcall set_callback, [ebx] + ret +@@: + cmp eax, DEV_SET_MASTERVOL + jne @F + mov eax, [edi+input] + mov eax, [eax] + call set_master_vol ;eax= vol + ret +@@: + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + stdcall get_master_vol, ebx + ret +;@@: +; cmp eax, DEV_GET_INFO +; jne @F +; mov ebx, [edi+output] +; stdcall get_dev_info, ebx +; ret +@@: +.fail: + or eax, -1 + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + + +align 4 +proc ac97_irq + +; if DEBUG +; mov esi, msgIRQ +; call SysMsgBoardStr +; end if + + + cmp [ctrl.user_callback], 0 + je @f + + stdcall [ctrl.user_callback], ebx +@@: + ret + +.skip: + mov edx, PCM_OUT_CR_REG + mov ax, 0x11 ;0x1D + call [ctrl.ctrl_write8] + ret +endp + +align 4 +proc create_primary_buff + + stdcall KernelAlloc, 0x10000 + mov [ctrl.buffer], eax + + mov edi, eax + mov ecx, 0x10000/4 + xor eax, eax + cld + rep stosd + + mov eax, [ctrl.buffer] + call GetPgAddr + + mov ebx, 0xC0002000 + mov ecx, 4 + mov edi, pcmout_bdl +@@: + mov [edi], eax + mov [edi+4], ebx + + mov [edi+32], eax + mov [edi+4+32], ebx + + mov [edi+64], eax + mov [edi+4+64], ebx + + mov [edi+96], eax + mov [edi+4+96], ebx + + mov [edi+128], eax + mov [edi+4+128], ebx + + mov [edi+160], eax + mov [edi+4+160], ebx + + mov [edi+192], eax + mov [edi+4+192], ebx + + mov [edi+224], eax + mov [edi+4+224], ebx + + add eax, 0x4000 + add edi, 8 + loop @B + + mov edi, buff_list + mov eax, [ctrl.buffer] + mov ecx, 4 +@@: + mov [edi], eax + mov [edi+16], eax + mov [edi+32], eax + mov [edi+48], eax + mov [edi+64], eax + mov [edi+80], eax + mov [edi+96], eax + mov [edi+112], eax + + add eax, 0x4000 + add edi, 4 + loop @B + + mov eax, pcmout_bdl + mov ebx, eax + call GetPgAddr ;eax + and ebx, 0xFFF + add eax, ebx + + mov edx, PCM_OUT_BDL + call [ctrl.ctrl_write32] + + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + ret +endp + +align 4 +proc detect_controller + locals + last_bus dd ? + bus dd ? + devfn dd ? + endl + + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err + + mov [last_bus], eax + +.next_bus: + and [devfn], 0 +.next_dev: + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next + + mov edi, devices +@@: + mov ebx, [edi] + test ebx, ebx + jz .next + + cmp eax, ebx + je .found + add edi, 12 + jmp @B + +.next: + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret +.found: + mov ebx, [bus] + mov [ctrl.bus], ebx + + mov ecx, [devfn] + mov [ctrl.devfn], ecx + + mov edx, eax + and edx, 0xFFFF + mov [ctrl.vendor], edx + shr eax, 16 + mov [ctrl.dev_id], eax + + mov ebx, [edi+4] + mov [ctrl.ctrl_ids], ebx + mov esi, [edi+8] + mov [ctrl.ctrl_setup], esi + + cmp ebx, 0x1274 + jne @F + mov [ctrl.vendor_ids], msgEnsoniq + ret +@@: + mov [ctrl.vendor_ids], 0 ;something wrong ? + ret +.err: + xor eax, eax + ret +endp + +align 4 +proc init_controller + + mov esi, msgPCIcmd + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 + mov ebx, eax + and eax, 0xFFFF + mov [ctrl.pci_cmd], eax + shr ebx, 16 + mov [ctrl.pci_stat], ebx + + call dword2str + call SysMsgBoardStr + + mov esi, msgIObase + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 +; and eax, -16 + mov [ctrl.ctrl_io_base], eax + + call dword2str + call SysMsgBoardStr + + mov esi, msgIRQline + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C + and eax, 0xFF + mov [ctrl.int_line], eax + + call dword2str + call SysMsgBoardStr + + call [ctrl.ctrl_setup] + xor eax, eax + inc eax + ret +endp + +align 4 +proc set_ICH + mov [ctrl.codec_read16], codec_io_r16 ;virtual + mov [ctrl.codec_write16], codec_io_w16 ;virtual + + mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual + mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual + mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual + + mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual + mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual + mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual + ret +endp + +align 4 +proc reset_controller + + xor eax, eax + mov edx, PCM_IN_CR_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + call [ctrl.ctrl_write8] + + mov edx, MC_IN_CR_REG + call [ctrl.ctrl_write8] + + mov eax, RR + mov edx, PCM_IN_CR_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + call [ctrl.ctrl_write8] + + mov edx, MC_IN_CR_REG + call [ctrl.ctrl_write8] + ret +endp + +align 4 +proc init_codec + locals + counter dd ? + endl + + mov esi, msgControl + call SysMsgBoardStr + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + call dword2str + call SysMsgBoardStr + + mov esi, msgStatus + call SysMsgBoardStr + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + + call dword2str + call SysMsgBoardStr + + test eax, CTRL_ST_CREADY + jnz .ready + + call reset_codec + and eax, eax + jz .err + + xor edx, edx ;ac_reg_0 + call [ctrl.codec_write16] + + xor eax, eax + mov edx, CODEC_REG_POWERDOWN + call [ctrl.codec_write16] + + mov [counter], 200 ; total 200*5 ms = 1s +.wait: + mov edx, CODEC_REG_POWERDOWN + call [ctrl.codec_read16] + and eax, 0x0F + cmp eax, 0x0F + jz .ready + + mov eax, 5000 ; wait 5 ms + call StallExec + sub [counter] , 1 + jnz .wait +.err: + xor eax, eax ; timeout error + ret +.ready: + call detect_codec + + xor eax, eax + inc eax + ret +endp + +align 4 +proc reset_codec + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + + test eax, 0x02 + jz .cold + + call warm_reset + jnc .ok +.cold: + call cold_reset + jnc .ok + + if DEBUG + mov esi, msgCFail + call SysMsgBoardStr + end if + xor eax, eax ; timeout error + ret +.ok: + if DEBUG + mov esi, msgResetOk + call SysMsgBoardStr + end if + + xor eax, eax + inc eax + ret +endp + +align 4 +proc warm_reset + locals + counter dd ? + endl + + mov eax, 0x06 + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + if DEBUG + mov esi, msgWarm + call SysMsgBoardStr + end if + + mov [counter], 10 ; total 10*100 ms = 1s +.wait: + mov eax, 100000 ; wait 100 ms + call StallExec + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + test eax, 4 + jz .ok + sub [counter], 1 + jnz .wait + + if DEBUG + mov esi, msgWRFail + call SysMsgBoardStr + end if + + stc + ret +.ok: + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + and eax, CTRL_ST_CREADY + jz .fail + clc + ret +.fail: + stc + ret +endp + +align 4 +proc cold_reset + locals + counter dd ? + endl + + xor eax, eax + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + if DEBUG + mov esi, msgCold + call SysMsgBoardStr + end if + + mov eax, 1000000 ; wait 1 s + call StallExec + + mov eax, 2 + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + mov [counter], 10 ; total 10*100 ms = 1s +.wait: + mov eax, 100000 ; wait 100 ms + call StallExec + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + test eax, 4 + jz .ok + sub [counter], 1 + jnz .wait + + if DEBUG + mov esi, msgCRFail + call SysMsgBoardStr + end if + stc + ret +.ok: + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + and eax, CTRL_ST_CREADY + jz .fail + clc + ret +.fail: + stc + ret +endp + +align 4 +play: + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + mov ax, 0x1D + call [ctrl.ctrl_write8] + xor eax, eax + ret + +align 4 +stop: + mov edx, PCM_OUT_CR_REG + mov ax, 0x0 + call [ctrl.ctrl_write8] + + mov ax, 0x1c + mov edx, PCM_OUT_SR_REG + call [ctrl.ctrl_write16] + xor eax, eax + ret + +align 4 +proc get_dev_info stdcall, p_info:dword + virtual at esi + CTRL_INFO CTRL_INFO + end virtual + + mov esi, [p_info] + mov eax, [ctrl.int_line] + mov ebx, [ctrl.codec_io_base] + mov ecx, [ctrl.ctrl_io_base] + mov edx, [ctrl.codec_mem_base] + mov edi, [ctrl.ctrl_mem_base] + + mov [CTRL_INFO.irq], eax + mov [CTRL_INFO.codec_io_base], ebx + mov [CTRL_INFO.ctrl_io_base], ecx + mov [CTRL_INFO.codec_mem_base], edx + mov [CTRL_INFO.ctrl_mem_base], edi + + mov eax, [codec.chip_id] + mov [CTRL_INFO.codec_id], eax + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + mov [CTRL_INFO.glob_cntrl], eax + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + mov [CTRL_INFO.glob_sta], eax + + mov ebx, [ctrl.pci_cmd] + mov [CTRL_INFO.pci_cmd], ebx + ret +endp + +align 4 +proc set_callback stdcall, handler:dword + mov eax, [handler] + mov [ctrl.user_callback], eax + ret +endp + +align 4 +proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax + + mov edx, [ac_reg] + + mov ebx, edx + shr ebx, 1 + bt [codec.shadow_flag], ebx + jc .use_shadow + + call [ctrl.codec_read16] ;change edx !!! + mov ecx, eax + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + test eax, CTRL_ST_RCS + jz .read_ok + + mov edx, CTRL_STAT + call [ctrl.ctrl_write32] + xor eax, eax + not eax ;timeout + ret +.read_ok: + mov edx, [ac_reg] + mov [codec.regs+edx], cx + bts [codec.shadow_flag], ebx + mov eax, ecx + ret +.use_shadow: + movzx eax, word [codec.regs+edx] + ret +endp + +align 4 +proc codec_write stdcall, ac_reg:dword + push eax + call check_semafore + and eax, eax + jz .err + pop eax + + mov esi, [ac_reg] + mov edx, esi + call [ctrl.codec_write16] + mov [codec.regs+esi], ax + shr esi, 1 + bts [codec.shadow_flag], esi + ret +.err: + pop eax + ret +endp + +align 4 +proc codec_check_ready + + mov edx, CTRL_ST + call [ctrl.ctrl_read32] + and eax, CTRL_ST_CREADY + jz .not_ready + + xor eax, wax + inc eax + ret +.not_ready: + xor eax, eax + ret +endp + +align 4 +proc check_semafore + local counter:DWORD + + mov [counter], 100 +.l1: + mov edx, CTRL_CAS + call [ctrl.ctrl_read8] + and eax, CAS_FLAG + jz .ok + + mov eax, 1 + call StallExec + sub [counter], 1 + jnz .l1 + xor eax, eax + ret +align 4 +.ok: + xor eax, eax + inc eax + ret +endp + +align 4 +proc StallExec + push ecx + push edx + push ebx + push eax + + mov ecx, CPU_FREQ + mul ecx + mov ebx, eax ;low + mov ecx, edx ;high + rdtsc + add ebx, eax + adc ecx, edx +@@: + rdtsc + sub eax, ebx + sbb edx, ecx + js @B + + pop eax + pop ebx + pop edx + pop ecx + ret +endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; CONTROLLER IO functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +codec_io_r16: + add edx, [ctrl.codec_io_base] + in ax, dx + ret + +align 4 +codec_io_w16: + add edx, [ctrl.codec_io_base] + out dx, ax + ret + +align 4 +ctrl_io_r8: + add edx, [ctrl.ctrl_io_base] + in al, dx + ret + +align 4 +ctrl_io_r16: + add edx, [ctrl.ctrl_io_base] + in ax, dx + ret + +align 4 +ctrl_io_r32: + add edx, [ctrl.ctrl_io_base] + in eax, dx + ret + +align 4 +ctrl_io_w8: + add edx, [ctrl.ctrl_io_base] + out dx, al + ret + +align 4 +ctrl_io_w16: + add edx, [ctrl.ctrl_io_base] + out dx, ax + ret + +align 4 +ctrl_io_w32: + add edx, [ctrl.ctrl_io_base] + out dx, eax + ret + + +align 4 +dword2str: + mov esi, hex_buff + mov ecx, -8 +@@: + rol eax, 4 + mov ebx, eax + and ebx, 0x0F + mov bl, [ebx+hexletters] + mov [8+esi+ecx], bl + inc ecx + jnz @B + ret + +hexletters db '0123456789ABCDEF' +hex_buff db 8 dup(0),13,10,0 + + +include "codec.inc" + +align 4 +devices dd (0x5000 shl 16)+0x1274,msgEnsoniq,set_ICH + dd (0x5880 shl 16)+0x1274,msgVibra128,set_ICH + dd 0 ;terminator + +version dd 0x00040004 + +msgEnsoniq db 'Ensonic 1371',13,10,0 +msgVibra128 db 'Sound Blaster AudioPCI Vibra 128',13,10,0 + +sz_sound_srv db 'SOUND',0 + +msgDetect db 'detect hardware...',13,10,0 +msgFail db 'device not found',13,10,0 +msgAttchIRQ db 'IRQ line not supported', 13,10, 0 +msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 +msgPlay db 'start play', 13,10,0 +msgStop db 'stop play', 13,10,0 +msgNotify db 'call notify',13,10,0 +msgIRQ db 'AC97 IRQ', 13,10,0 +msgInitCtrl db 'init controller',13,10,0 +msgInitCodec db 'init codec',13,10,0 +msgPrimBuff db 'create primary buffer',13,10,0 +msgReg db 'set service handler',13,10,0 +msgOk db 'service installed',13,10,0 +msgCold db 'cold reset',13,10,0 +msgWarm db 'warm reset',13,10,0 +msgWRFail db 'warm reset failed',13,10,0 +msgCRFail db 'cold reset failed',13,10,0 +msgCFail db 'codec not ready',13,10,0 +msgResetOk db 'reset complete',13,10,0 +msgStatus db 'global status ',0 +msgControl db 'global control ',0 +msgPCIcmd db 'PCI command ',0 +msgIObase db 'IO base ',0 +msgIRQline db 'IRQ line ',0 + +section '.data' data readable writable align 16 + +pcmout_bdl rq 32 +buff_list rd 32 + +codec CODEC +ctrl AC_CNTRL + +lpc_bus rd 1 +civ_val rd 1 + + diff --git a/kernel/trunk/drivers/fm801.asm b/kernel/trunk/drivers/fm801.asm index 95f283ab9..242cdaa2d 100644 --- a/kernel/trunk/drivers/fm801.asm +++ b/kernel/trunk/drivers/fm801.asm @@ -7,26 +7,26 @@ format MS COFF -DEBUG equ 1 -DEBUG_IRQ equ 0 +DEBUG equ 1 +DEBUG_IRQ equ 0 include 'proc32.inc' include 'imports.inc' -API_VERSION equ 0x01000100 +API_VERSION equ 0x01000100 -USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices +USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices ;irq 0,1,2,8,12,13 недоступны ; FEDCBA9876543210 -VALID_IRQ equ 1100111011111000b -ATTCH_IRQ equ 0000111010100000b +VALID_IRQ equ 1100111011111000b +ATTCH_IRQ equ 0000111010100000b if USE_COM_IRQ -ATTCH_IRQ equ 0000111010111000b +ATTCH_IRQ equ 0000111010111000b end if -CPU_FREQ equ 2000d +CPU_FREQ equ 2000d BIT0 EQU 0x00000001 BIT1 EQU 0x00000002 @@ -61,8 +61,8 @@ BIT29 EQU 0x20000000 BIT30 EQU 0x40000000 BIT31 EQU 0x80000000 -VID_FM801 equ 0x1319 -CTRL_FM801 equ 0x0801 +VID_FM801 equ 0x1319 +CTRL_FM801 equ 0x0801 FM_PCM_VOLUME equ 0x00 FM_FM_VOLUME equ 0x02 @@ -123,173 +123,173 @@ FM_INTSTATUS_REC equ 0x0200 FM_INTSTATUS_VOL equ 0x4000 FM_INTSTATUS_MPU equ 0x8000 -CODEC_MASTER_VOL_REG equ 0x02 ; -CODEC_AUX_VOL equ 0x04 ; -CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume -CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio +CODEC_MASTER_VOL_REG equ 0x02 ; +CODEC_AUX_VOL equ 0x04 ; +CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume +CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate -SRV_GETVERSION equ 0 -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_SET_BUFF equ 4 -DEV_NOTIFY equ 5 +SRV_GETVERSION equ 0 +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_SET_BUFF equ 4 +DEV_NOTIFY equ 5 DEV_SET_MASTERVOL equ 6 DEV_GET_MASTERVOL equ 7 -DEV_GET_INFO equ 8 +DEV_GET_INFO equ 8 -struc AC_CNTRL ;AC controller base class -{ .bus dd ? - .devfn dd ? +struc AC_CNTRL ;AC controller base class +{ .bus dd ? + .devfn dd ? - .vendor dd ? - .dev_id dd ? - .pci_cmd dd ? - .pci_stat dd ? + .vendor dd ? + .dev_id dd ? + .pci_cmd dd ? + .pci_stat dd ? .codec_io_base dd ? .codec_mem_base dd ? .ctrl_io_base dd ? .ctrl_mem_base dd ? - .cfg_reg dd ? - .int_line dd ? + .cfg_reg dd ? + .int_line dd ? - .vendor_ids dd ? ;vendor id string - .ctrl_ids dd ? ;hub id string + .vendor_ids dd ? ;vendor id string + .ctrl_ids dd ? ;hub id string - .buffer dd ? + .buffer dd ? - .notify_pos dd ? - .notify_task dd ? + .notify_pos dd ? + .notify_task dd ? - .lvi_reg dd ? - .ctrl_setup dd ? + .lvi_reg dd ? + .ctrl_setup dd ? .user_callback dd ? .codec_read16 dd ? .codec_write16 dd ? - .ctrl_read8 dd ? - .ctrl_read16 dd ? - .ctrl_read32 dd ? + .ctrl_read8 dd ? + .ctrl_read16 dd ? + .ctrl_read32 dd ? - .ctrl_write8 dd ? + .ctrl_write8 dd ? .ctrl_write16 dd ? .ctrl_write32 dd ? } struc CODEC ;Audio Chip base class { - .chip_id dd ? - .flags dd ? - .status dd ? + .chip_id dd ? + .flags dd ? + .status dd ? .ac_vendor_ids dd ? ;ac vendor id string - .chip_ids dd ? ;chip model string + .chip_ids dd ? ;chip model string - .shadow_flag dd ? - dd ? + .shadow_flag dd ? + dd ? - .regs dw ? ; codec registers + .regs dw ? ; codec registers .reg_master_vol dw ? ;0x02 .reg_aux_out_vol dw ? ;0x04 .reg_mone_vol dw ? ;0x06 .reg_master_tone dw ? ;0x08 .reg_beep_vol dw ? ;0x0A .reg_phone_vol dw ? ;0x0C - .reg_mic_vol dw ? ;0x0E + .reg_mic_vol dw ? ;0x0E .reg_line_in_vol dw ? ;0x10 - .reg_cd_vol dw ? ;0x12 + .reg_cd_vol dw ? ;0x12 .reg_video_vol dw ? ;0x14 .reg_aux_in_vol dw ? ;0x16 .reg_pcm_out_vol dw ? ;0x18 .reg_rec_select dw ? ;0x1A .reg_rec_gain dw ? ;0x1C .reg_rec_gain_mic dw ? ;0x1E - .reg_gen dw ? ;0x20 - .reg_3d_ctrl dw ? ;0X22 - .reg_page dw ? ;0X24 + .reg_gen dw ? ;0x20 + .reg_3d_ctrl dw ? ;0X22 + .reg_page dw ? ;0X24 .reg_powerdown dw ? ;0x26 .reg_ext_audio dw ? ;0x28 - .reg_ext_st dw ? ;0x2a + .reg_ext_st dw ? ;0x2a .reg_pcm_front_rate dw ? ;0x2c .reg_pcm_surr_rate dw ? ;0x2e .reg_lfe_rate dw ? ;0x30 .reg_pcm_in_rate dw ? ;0x32 - dw ? ;0x34 + dw ? ;0x34 .reg_cent_lfe_vol dw ? ;0x36 .reg_surr_vol dw ? ;0x38 .reg_spdif_ctrl dw ? ;0x3A - dw ? ;0x3C - dw ? ;0x3E - dw ? ;0x40 - dw ? ;0x42 - dw ? ;0x44 - dw ? ;0x46 - dw ? ;0x48 - dw ? ;0x4A - dw ? ;0x4C - dw ? ;0x4E - dw ? ;0x50 - dw ? ;0x52 - dw ? ;0x54 - dw ? ;0x56 - dw ? ;0x58 - dw ? ;0x5A - dw ? ;0x5C - dw ? ;0x5E - .reg_page_0 dw ? ;0x60 - .reg_page_1 dw ? ;0x62 - .reg_page_2 dw ? ;0x64 - .reg_page_3 dw ? ;0x66 - .reg_page_4 dw ? ;0x68 - .reg_page_5 dw ? ;0x6A - .reg_page_6 dw ? ;0x6C - .reg_page_7 dw ? ;0x6E - dw ? ;0x70 - dw ? ;0x72 - dw ? ;0x74 - dw ? ;0x76 - dw ? ;0x78 - dw ? ;0x7A + dw ? ;0x3C + dw ? ;0x3E + dw ? ;0x40 + dw ? ;0x42 + dw ? ;0x44 + dw ? ;0x46 + dw ? ;0x48 + dw ? ;0x4A + dw ? ;0x4C + dw ? ;0x4E + dw ? ;0x50 + dw ? ;0x52 + dw ? ;0x54 + dw ? ;0x56 + dw ? ;0x58 + dw ? ;0x5A + dw ? ;0x5C + dw ? ;0x5E + .reg_page_0 dw ? ;0x60 + .reg_page_1 dw ? ;0x62 + .reg_page_2 dw ? ;0x64 + .reg_page_3 dw ? ;0x66 + .reg_page_4 dw ? ;0x68 + .reg_page_5 dw ? ;0x6A + .reg_page_6 dw ? ;0x6C + .reg_page_7 dw ? ;0x6E + dw ? ;0x70 + dw ? ;0x72 + dw ? ;0x74 + dw ? ;0x76 + dw ? ;0x78 + dw ? ;0x7A .reg_vendor_id_1 dw ? ;0x7C .reg_vendor_id_2 dw ? ;0x7E - .reset dd ? ;virual + .reset dd ? ;virual .set_master_vol dd ? } struc CTRL_INFO -{ .pci_cmd dd ? - .irq dd ? +{ .pci_cmd dd ? + .irq dd ? .glob_cntrl dd ? - .glob_sta dd ? + .glob_sta dd ? .codec_io_base dd ? .ctrl_io_base dd ? .codec_mem_base dd ? .ctrl_mem_base dd ? - .codec_id dd ? + .codec_id dd ? } struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? } virtual at 0 IOCTL IOCTL end virtual -EVENT_NOTIFY equ 0x00000200 +EVENT_NOTIFY equ 0x00000200 public START public service_proc @@ -299,139 +299,139 @@ section '.flat' code readable align 16 proc START stdcall, state:dword - cmp [state], 1 - jne .stop + cmp [state], 1 + jne .stop if DEBUG - mov eax, START - call dword2str - call SysMsgBoardStr - mov esi, msgInit - call SysMsgBoardStr + mov eax, START + call dword2str + call SysMsgBoardStr + mov esi, msgInit + call SysMsgBoardStr end if - call detect_controller - test eax, eax - jz .fail + call detect_controller + test eax, eax + jz .fail if DEBUG - mov esi, [ctrl.vendor_ids] - call SysMsgBoardStr - mov esi, [ctrl.ctrl_ids] - call SysMsgBoardStr + mov esi, [ctrl.vendor_ids] + call SysMsgBoardStr + mov esi, [ctrl.ctrl_ids] + call SysMsgBoardStr end if - call init_controller - test eax, eax - jz .fail + call init_controller + test eax, eax + jz .fail - call init_codec - test eax, eax - jz .fail + call init_codec + test eax, eax + jz .fail - call reset_controller - call setup_codec + call reset_controller + call setup_codec - mov esi, msgPrimBuff - call SysMsgBoardStr - call create_primary_buff + mov esi, msgPrimBuff + call SysMsgBoardStr + call create_primary_buff - mov esi, msgDone - call SysMsgBoardStr + mov esi, msgDone + call SysMsgBoardStr - mov eax, VALID_IRQ - mov ebx, [ctrl.int_line] - mov esi, msgInvIRQ - bt eax, ebx - jnc .fail_msg - mov eax, ATTCH_IRQ - mov esi, msgAttchIRQ - bt eax, ebx - jnc .fail_msg + mov eax, VALID_IRQ + mov ebx, [ctrl.int_line] + mov esi, msgInvIRQ + bt eax, ebx + jnc .fail_msg + mov eax, ATTCH_IRQ + mov esi, msgAttchIRQ + bt eax, ebx + jnc .fail_msg - stdcall AttachIntHandler, ebx, ac97_irq, dword 0 + stdcall AttachIntHandler, ebx, ac97_irq, dword 0 .reg: - stdcall RegService, sz_sound_srv, service_proc - ret + stdcall RegService, sz_sound_srv, service_proc + ret .fail: if DEBUG - mov esi, msgFail - call SysMsgBoardStr + mov esi, msgFail + call SysMsgBoardStr end if - xor eax, eax - ret + xor eax, eax + ret .fail_msg: - call SysMsgBoardStr - xor eax, eax - ret + call SysMsgBoardStr + xor eax, eax + ret .stop: - call stop - xor eax, eax - ret + call stop + xor eax, eax + ret endp -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size align 4 proc service_proc stdcall, ioctl:dword - mov edi, [ioctl] - mov eax, [edi+io_code] + mov edi, [ioctl] + mov eax, [edi+io_code] - cmp eax, SRV_GETVERSION - jne @F + cmp eax, SRV_GETVERSION + jne @F - mov eax, [edi+output] - cmp [edi+out_size], 4 - jne .fail + mov eax, [edi+output] + cmp [edi+out_size], 4 + jne .fail - mov [eax], dword API_VERSION - xor eax, eax - ret + mov [eax], dword API_VERSION + xor eax, eax + ret @@: - cmp eax, DEV_PLAY - jne @F + cmp eax, DEV_PLAY + jne @F if DEBUG - mov esi, msgPlay - call SysMsgBoardStr + mov esi, msgPlay + call SysMsgBoardStr end if - call play - ret + call play + ret @@: - cmp eax, DEV_STOP - jne @F + cmp eax, DEV_STOP + jne @F if DEBUG - mov esi, msgStop - call SysMsgBoardStr + mov esi, msgStop + call SysMsgBoardStr end if - call stop - ret + call stop + ret @@: - cmp eax, DEV_CALLBACK - jne @F - mov ebx, [edi+input] - stdcall set_callback, [ebx] - ret + cmp eax, DEV_CALLBACK + jne @F + mov ebx, [edi+input] + stdcall set_callback, [ebx] + ret @@: - cmp eax, DEV_SET_MASTERVOL - jne @F - mov eax, [edi+input] - mov eax, [eax] - call set_master_vol ;eax= vol - ret + cmp eax, DEV_SET_MASTERVOL + jne @F + mov eax, [edi+input] + mov eax, [eax] + call set_master_vol ;eax= vol + ret @@: - cmp eax, DEV_GET_MASTERVOL - jne @F - mov ebx, [edi+output] - stdcall get_master_vol, ebx - ret + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + stdcall get_master_vol, ebx + ret ;@@: ; cmp eax, DEV_GET_INFO ; jne @F @@ -440,8 +440,8 @@ proc service_proc stdcall, ioctl:dword ; ret @@: .fail: - or eax, -1 - ret + or eax, -1 + ret endp restore handle @@ -454,448 +454,449 @@ restore out_size align 4 proc fill_buffer - cmp [ctrl.user_callback], 0 - je .exit + cmp [ctrl.user_callback], 0 + je .exit - mov esi, [ctrl.buffer] - mov eax, int_flip_flop - inc dword [eax] - test dword [eax],1 - je @f - add esi, 0x4000 + mov esi, [ctrl.buffer] + mov eax, int_flip_flop + inc dword [eax] + test dword [eax], 1 + je @f + add esi, 0x4000 @@: - stdcall [ctrl.user_callback], esi + stdcall [ctrl.user_callback], esi - mov edx, FM_PLAY_DMABUF1 - mov eax, [buffer_pgaddr] - mov esi, int_flip_flop - test dword [esi],1 - je @f - mov edx, FM_PLAY_DMABUF2 - add eax, 0x4000 + mov edx, FM_PLAY_DMABUF1 + mov eax, [buffer_pgaddr] + mov esi, int_flip_flop + test dword [esi], 1 + je @f + mov edx, FM_PLAY_DMABUF2 + add eax, 0x4000 @@: - call [ctrl.ctrl_write32] + call [ctrl.ctrl_write32] .exit: - ret + ret endp align 4 proc ac97_irq if DEBUG_IRQ - mov esi, msgIRQ - call SysMsgBoardStr + mov esi, msgIRQ + call SysMsgBoardStr end if - mov edx, FM_INTSTATUS - call [ctrl.ctrl_read16] + mov edx, FM_INTSTATUS + call [ctrl.ctrl_read16] - test eax, FM_INTSTATUS_PLAY - je .exit + test eax, FM_INTSTATUS_PLAY + je .exit - push eax - call fill_buffer - pop eax + push eax + call fill_buffer + pop eax .exit: - mov edx, FM_INTSTATUS - call [ctrl.ctrl_write16] + mov edx, FM_INTSTATUS + call [ctrl.ctrl_write16] - ret + ret endp align 4 proc create_primary_buff - stdcall KernelAlloc, 0x10000 - mov [ctrl.buffer], eax + stdcall KernelAlloc, 0x10000 + mov [ctrl.buffer], eax - mov edi, eax - mov ecx, 0x10000/4 - xor eax, eax - cld - rep stosd + mov edi, eax + mov ecx, 0x10000/4 + xor eax, eax + cld + rep stosd - mov eax, [ctrl.buffer] - call GetPgAddr - mov [buffer_pgaddr], eax + mov eax, [ctrl.buffer] + call GetPgAddr + mov [buffer_pgaddr], eax - ret + ret endp align 4 proc detect_controller - locals - last_bus dd ? - bus dd ? - devfn dd ? - endl + locals + last_bus dd ? + bus dd ? + devfn dd ? + endl - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err - mov [last_bus], eax + mov [last_bus], eax .next_bus: - and [devfn], 0 + and [devfn], 0 .next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next - push eax - stdcall PciRead32, [bus], [devfn], dword 0x09 - and eax,0xffffff - cmp eax, 0x060100 ;pci-isa - jne .no_bridge + push eax + stdcall PciRead32, [bus], [devfn], dword 0x09 + and eax, 0xffffff + cmp eax, 0x060100 ;pci-isa + jne .no_bridge - mov eax, [bus] - mov [brg_bus], eax - mov eax, [devfn] - mov [brg_devfn],eax -.no_bridge:pop eax + mov eax, [bus] + mov [brg_bus], eax + mov eax, [devfn] + mov [brg_devfn], eax +.no_bridge: + pop eax - mov edi, devices + mov edi, devices @@: - mov ebx, [edi] - test ebx, ebx - jz .next + mov ebx, [edi] + test ebx, ebx + jz .next - cmp eax, ebx - je .found - add edi, 12 - jmp @B + cmp eax, ebx + je .found + add edi, 12 + jmp @B .next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret .found: - mov ebx, [bus] - mov [ctrl.bus], ebx + mov ebx, [bus] + mov [ctrl.bus], ebx - mov ecx, [devfn] - mov [ctrl.devfn], ecx + mov ecx, [devfn] + mov [ctrl.devfn], ecx - mov edx, eax - and edx, 0xFFFF - mov [ctrl.vendor], edx - shr eax, 16 - mov [ctrl.dev_id], eax + mov edx, eax + and edx, 0xFFFF + mov [ctrl.vendor], edx + shr eax, 16 + mov [ctrl.dev_id], eax - mov ebx, [edi+4] - mov [ctrl.ctrl_ids], ebx - mov [ctrl.vendor_ids], msg_FM + mov ebx, [edi+4] + mov [ctrl.ctrl_ids], ebx + mov [ctrl.vendor_ids], msg_FM - mov esi, [edi+8] - mov [ctrl.ctrl_setup], esi - ret + mov esi, [edi+8] + mov [ctrl.ctrl_setup], esi + ret .err: - xor eax, eax - ret + xor eax, eax + ret endp align 4 proc init_controller - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 - mov ebx, eax - and eax, 0xFFFF - mov [ctrl.pci_cmd], eax - shr ebx, 16 - mov [ctrl.pci_stat], ebx + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 + mov ebx, eax + and eax, 0xFFFF + mov [ctrl.pci_cmd], eax + shr ebx, 16 + mov [ctrl.pci_stat], ebx - mov esi, msgPciCmd - call SysMsgBoardStr - call dword2str - call SysMsgBoardStr + mov esi, msgPciCmd + call SysMsgBoardStr + call dword2str + call SysMsgBoardStr - mov esi, msgPciStat - call SysMsgBoardStr - mov eax, [ctrl.pci_stat] - call dword2str - call SysMsgBoardStr + mov esi, msgPciStat + call SysMsgBoardStr + mov eax, [ctrl.pci_stat] + call dword2str + call SysMsgBoardStr - mov esi, msgCtrlIsaIo - call SysMsgBoardStr + mov esi, msgCtrlIsaIo + call SysMsgBoardStr - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 - call dword2str - call SysMsgBoardStr + call dword2str + call SysMsgBoardStr - and eax,0xFFFE - mov [ctrl.ctrl_io_base], eax + and eax, 0xFFFE + mov [ctrl.ctrl_io_base], eax - mov esi, msgIrqNum - call SysMsgBoardStr + mov esi, msgIrqNum + call SysMsgBoardStr - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C - and eax, 0xFF - mov [ctrl.int_line], eax + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C + and eax, 0xFF + mov [ctrl.int_line], eax - call dword2str - call SysMsgBoardStr + call dword2str + call SysMsgBoardStr - call [ctrl.ctrl_setup] - xor eax, eax - inc eax - ret + call [ctrl.ctrl_setup] + xor eax, eax + inc eax + ret endp align 4 proc set_FM - mov [ctrl.codec_read16], codec_io_r16 ;virtual - mov [ctrl.codec_write16], codec_io_w16 ;virtual + mov [ctrl.codec_read16], codec_io_r16 ;virtual + mov [ctrl.codec_write16], codec_io_w16 ;virtual - mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual - mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual - mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual + mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual + mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual + mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual - mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual - mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual - mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual - ret + mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual + mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual + mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual + ret endp align 4 proc reset_controller - mov esi, msgInitCtrl - call SysMsgBoardStr + mov esi, msgInitCtrl + call SysMsgBoardStr - mov edx, FM_CARD_CTL - call [ctrl.ctrl_read8] - push eax - or al,1 - mov edx, FM_CARD_CTL - call [ctrl.ctrl_write8] - mov eax, 10 - call StallExec - pop eax - and al,0xFE - mov edx, FM_CARD_CTL - call [ctrl.ctrl_write8] - mov eax, 10 - call StallExec + mov edx, FM_CARD_CTL + call [ctrl.ctrl_read8] + push eax + or al, 1 + mov edx, FM_CARD_CTL + call [ctrl.ctrl_write8] + mov eax, 10 + call StallExec + pop eax + and al, 0xFE + mov edx, FM_CARD_CTL + call [ctrl.ctrl_write8] + mov eax, 10 + call StallExec - mov eax, 0x0404 - mov edx, FM_PCM_VOLUME - call [ctrl.ctrl_write16] - mov edx, FM_FM_VOLUME - call [ctrl.ctrl_write16] - mov edx, FM_I2S_VOLUME - call [ctrl.ctrl_write16] + mov eax, 0x0404 + mov edx, FM_PCM_VOLUME + call [ctrl.ctrl_write16] + mov edx, FM_FM_VOLUME + call [ctrl.ctrl_write16] + mov edx, FM_I2S_VOLUME + call [ctrl.ctrl_write16] - mov edx, FM_INTMASK - call [ctrl.ctrl_read16] - and eax, not FM_INTMASK_PLAY - or eax, FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL - mov edx, FM_INTMASK - call [ctrl.ctrl_write16] + mov edx, FM_INTMASK + call [ctrl.ctrl_read16] + and eax, not FM_INTMASK_PLAY + or eax, FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL + mov edx, FM_INTMASK + call [ctrl.ctrl_write16] - mov eax, FM_INTMASK_PLAY or FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL - mov edx, FM_INTSTATUS - call [ctrl.ctrl_write16] + mov eax, FM_INTMASK_PLAY or FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL + mov edx, FM_INTSTATUS + call [ctrl.ctrl_write16] - ret + ret endp align 4 proc init_codec - mov esi, msgInitCodec - call SysMsgBoardStr + mov esi, msgInitCodec + call SysMsgBoardStr - mov al, FM_CODEC_CMD_READ - mov edx, FM_CODEC_CMD - call [ctrl.ctrl_write8] + mov al, FM_CODEC_CMD_READ + mov edx, FM_CODEC_CMD + call [ctrl.ctrl_write8] - call reset_codec + call reset_codec - call detect_codec + call detect_codec - xor eax, eax - inc eax - ret + xor eax, eax + inc eax + ret endp align 4 proc reset_codec - mov ecx, 255 + mov ecx, 255 .L1: - mov edx, FM_CODEC_CMD - call [ctrl.ctrl_read16] - test ah, FM_CODEC_CMD_VALID shr 8 - jne .L2 - loop .L1 + mov edx, FM_CODEC_CMD + call [ctrl.ctrl_read16] + test ah, FM_CODEC_CMD_VALID shr 8 + jne .L2 + loop .L1 .L2: - mov edx, FM_CODEC_CTL - call [ctrl.ctrl_read8] - push eax - or al, 0x20 - mov edx, FM_CODEC_CTL - call [ctrl.ctrl_write8] - pop eax - and al,0xDF - mov edx, FM_CODEC_CTL - call [ctrl.ctrl_write8] + mov edx, FM_CODEC_CTL + call [ctrl.ctrl_read8] + push eax + or al, 0x20 + mov edx, FM_CODEC_CTL + call [ctrl.ctrl_write8] + pop eax + and al, 0xDF + mov edx, FM_CODEC_CTL + call [ctrl.ctrl_write8] - xor eax, eax - inc eax - ret + xor eax, eax + inc eax + ret endp align 4 play: - mov eax, 0x4000-1 - mov edx, FM_PLAY_DMALEN - call [ctrl.ctrl_write16] + mov eax, 0x4000-1 + mov edx, FM_PLAY_DMALEN + call [ctrl.ctrl_write16] - call fill_buffer + call fill_buffer - mov eax, FM_PLAY_START or FM_PLAY_STOPNOW or FM_PLAY_STEREO or FM_PLAY_16BIT or 0xA00 - mov edx, FM_PLAY_CTL - call [ctrl.ctrl_write16] + mov eax, FM_PLAY_START or FM_PLAY_STOPNOW or FM_PLAY_STEREO or FM_PLAY_16BIT or 0xA00 + mov edx, FM_PLAY_CTL + call [ctrl.ctrl_write16] - xor eax, eax - ret + xor eax, eax + ret align 4 stop: - mov edx, FM_PLAY_CTL - call [ctrl.ctrl_read16] - and eax, not (FM_PLAY_START or FM_PLAY_STOPNOW) - or eax, FM_PLAY_BUF1_LAST or FM_PLAY_BUF2_LAST - mov edx, FM_PLAY_CTL - call [ctrl.ctrl_write16] + mov edx, FM_PLAY_CTL + call [ctrl.ctrl_read16] + and eax, not (FM_PLAY_START or FM_PLAY_STOPNOW) + or eax, FM_PLAY_BUF1_LAST or FM_PLAY_BUF2_LAST + mov edx, FM_PLAY_CTL + call [ctrl.ctrl_write16] - xor eax, eax - ret + xor eax, eax + ret align 4 proc get_dev_info stdcall, p_info:dword - virtual at esi - CTRL_INFO CTRL_INFO - end virtual + virtual at esi + CTRL_INFO CTRL_INFO + end virtual - mov esi, [p_info] - mov eax, [ctrl.int_line] - mov ebx, [ctrl.codec_io_base] - mov ecx, [ctrl.ctrl_io_base] - mov edx, [ctrl.codec_mem_base] - mov edi, [ctrl.ctrl_mem_base] + mov esi, [p_info] + mov eax, [ctrl.int_line] + mov ebx, [ctrl.codec_io_base] + mov ecx, [ctrl.ctrl_io_base] + mov edx, [ctrl.codec_mem_base] + mov edi, [ctrl.ctrl_mem_base] - mov [CTRL_INFO.irq], eax - mov [CTRL_INFO.codec_io_base], ebx - mov [CTRL_INFO.ctrl_io_base], ecx - mov [CTRL_INFO.codec_mem_base], edx - mov [CTRL_INFO.ctrl_mem_base], edi + mov [CTRL_INFO.irq], eax + mov [CTRL_INFO.codec_io_base], ebx + mov [CTRL_INFO.ctrl_io_base], ecx + mov [CTRL_INFO.codec_mem_base], edx + mov [CTRL_INFO.ctrl_mem_base], edi - mov eax, [codec.chip_id] - mov [CTRL_INFO.codec_id], eax + mov eax, [codec.chip_id] + mov [CTRL_INFO.codec_id], eax - mov ebx, [ctrl.pci_cmd] - mov [CTRL_INFO.pci_cmd], ebx - ret + mov ebx, [ctrl.pci_cmd] + mov [CTRL_INFO.pci_cmd], ebx + ret endp align 4 proc set_callback stdcall, handler:dword - mov eax, [handler] - mov [ctrl.user_callback], eax - ret + mov eax, [handler] + mov [ctrl.user_callback], eax + ret endp align 4 -proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax +proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax - mov edx, [ac_reg] + mov edx, [ac_reg] - mov ebx, edx - shr ebx, 1 - bt [codec.shadow_flag], ebx - jc .use_shadow + mov ebx, edx + shr ebx, 1 + bt [codec.shadow_flag], ebx + jc .use_shadow - call [ctrl.codec_read16] ;change edx !!! - mov ecx, eax + call [ctrl.codec_read16] ;change edx !!! + mov ecx, eax .read_ok: - mov edx, [ac_reg] - mov [codec.regs+edx], cx - bts [codec.shadow_flag], ebx - mov eax, ecx - ret + mov edx, [ac_reg] + mov [codec.regs+edx], cx + bts [codec.shadow_flag], ebx + mov eax, ecx + ret .use_shadow: - movzx eax, word [codec.regs+edx] - ret + movzx eax, word [codec.regs+edx] + ret endp align 4 proc codec_write stdcall, ac_reg:dword - mov esi, [ac_reg] + mov esi, [ac_reg] - mov edx, esi + mov edx, esi - call [ctrl.codec_write16] + call [ctrl.codec_write16] - mov [codec.regs+esi], ax - shr esi, 1 - bts [codec.shadow_flag], esi + mov [codec.regs+esi], ax + shr esi, 1 + bts [codec.shadow_flag], esi - ret + ret endp align 4 proc check_semafore align 4 .ok: - xor eax,eax - inc eax - ret + xor eax, eax + inc eax + ret endp align 4 proc StallExec - push ecx - push edx - push ebx - push eax + push ecx + push edx + push ebx + push eax - mov ecx, CPU_FREQ - mul ecx - mov ebx, eax ;low - mov ecx, edx ;high - rdtsc - add ebx, eax - adc ecx, edx + mov ecx, CPU_FREQ + mul ecx + mov ebx, eax ;low + mov ecx, edx ;high + rdtsc + add ebx, eax + adc ecx, edx @@: - rdtsc - sub eax, ebx - sbb edx, ecx - js @B + rdtsc + sub eax, ebx + sbb edx, ecx + js @B - pop eax - pop ebx - pop edx - pop ecx - ret + pop eax + pop ebx + pop edx + pop ecx + ret endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -905,113 +906,113 @@ endp align 4 proc codec_io_r16 - push edx - mov ecx, 255 + push edx + mov ecx, 255 .L1: - mov edx, FM_CODEC_CMD - call [ctrl.ctrl_read16] - test ah, FM_CODEC_CMD_BUSY shr 8 - je .L2 - loop .L1 + mov edx, FM_CODEC_CMD + call [ctrl.ctrl_read16] + test ah, FM_CODEC_CMD_BUSY shr 8 + je .L2 + loop .L1 .L2: - pop eax - or al, FM_CODEC_CMD_READ - mov edx, FM_CODEC_CMD - call [ctrl.ctrl_write8] + pop eax + or al, FM_CODEC_CMD_READ + mov edx, FM_CODEC_CMD + call [ctrl.ctrl_write8] - mov ecx, 255 + mov ecx, 255 .L3: - mov edx, FM_CODEC_CMD - call [ctrl.ctrl_read16] - test ah, FM_CODEC_CMD_VALID shr 8 - jne .L4 - loop .L3 + mov edx, FM_CODEC_CMD + call [ctrl.ctrl_read16] + test ah, FM_CODEC_CMD_VALID shr 8 + jne .L4 + loop .L3 .L4: - mov edx, FM_CODEC_DATA - call [ctrl.ctrl_read16] + mov edx, FM_CODEC_DATA + call [ctrl.ctrl_read16] - ret + ret endp align 4 proc codec_io_w16 - push edx - push eax - mov ecx, 255 + push edx + push eax + mov ecx, 255 .L1: - mov edx, FM_CODEC_CMD - call [ctrl.ctrl_read16] - test ah, FM_CODEC_CMD_BUSY shr 8 - je .L2 - loop .L1 + mov edx, FM_CODEC_CMD + call [ctrl.ctrl_read16] + test ah, FM_CODEC_CMD_BUSY shr 8 + je .L2 + loop .L1 .L2: - pop eax - mov edx, FM_CODEC_DATA - call [ctrl.ctrl_write16] + pop eax + mov edx, FM_CODEC_DATA + call [ctrl.ctrl_write16] - pop eax - mov edx, FM_CODEC_CMD - call [ctrl.ctrl_write16] + pop eax + mov edx, FM_CODEC_CMD + call [ctrl.ctrl_write16] - ret + ret endp align 4 proc ctrl_io_r8 - add edx, [ctrl.ctrl_io_base] - in al, dx - ret + add edx, [ctrl.ctrl_io_base] + in al, dx + ret endp align 4 proc ctrl_io_r16 - add edx, [ctrl.ctrl_io_base] - in ax, dx - ret + add edx, [ctrl.ctrl_io_base] + in ax, dx + ret endp align 4 proc ctrl_io_r32 - add edx, [ctrl.ctrl_io_base] - in eax, dx - ret + add edx, [ctrl.ctrl_io_base] + in eax, dx + ret endp align 4 proc ctrl_io_w8 - add edx, [ctrl.ctrl_io_base] - out dx, al - ret + add edx, [ctrl.ctrl_io_base] + out dx, al + ret endp align 4 proc ctrl_io_w16 - add edx, [ctrl.ctrl_io_base] - out dx, ax - ret + add edx, [ctrl.ctrl_io_base] + out dx, ax + ret endp align 4 proc ctrl_io_w32 - add edx, [ctrl.ctrl_io_base] - out dx, eax - ret + add edx, [ctrl.ctrl_io_base] + out dx, eax + ret endp align 4 dword2str: - mov esi, hex_buff - mov ecx, -8 + mov esi, hex_buff + mov ecx, -8 @@: - rol eax, 4 - mov ebx, eax - and ebx, 0x0F - mov bl, [ebx+hexletters] - mov [8+esi+ecx], bl - inc ecx - jnz @B - ret + rol eax, 4 + mov ebx, eax + and ebx, 0x0F + mov bl, [ebx+hexletters] + mov [8+esi+ecx], bl + inc ecx + jnz @B + ret hexletters db '0123456789ABCDEF' hex_buff db 8 dup(0),13,10,0 @@ -1021,7 +1022,7 @@ include "codec.inc" align 4 devices dd (CTRL_FM801 shl 16)+VID_FM801, msg_FM801, set_FM - dd 0 + dd 0 version dd (5 shl 16) or (API_VERSION and 0xFFFF) @@ -1037,13 +1038,13 @@ msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 msgPlay db 'start play', 13,10,0 msgStop db 'stop play', 13,10,0 ;msgNotify db 'call notify',13,10,0 -msgIRQ db 'AC97 IRQ', 13,10,0 +msgIRQ db 'AC97 IRQ', 13,10,0 msgInitCtrl db 'init controller',13,10,0 msgInitCodec db 'init codec',13,10,0 msgPrimBuff db 'create primary buffer ...',0 msgDone db 'done',13,10,0 ;msgReg db 'set service handler',13,10,0 -;msgOk db 'service installed',13,10,0 +;msgOk db 'service installed',13,10,0 ;msgStatus db 'global status ',0 ;msgControl db 'global control ',0 msgPciCmd db 'PCI command ',0 @@ -1057,5 +1058,5 @@ section '.data' data readable writable align 16 codec CODEC ctrl AC_CNTRL -int_flip_flop rd 1 +int_flip_flop rd 1 buffer_pgaddr rd 1 diff --git a/kernel/trunk/drivers/imports.inc b/kernel/trunk/drivers/imports.inc index cb703a092..7ddb93665 100644 --- a/kernel/trunk/drivers/imports.inc +++ b/kernel/trunk/drivers/imports.inc @@ -1,95 +1,95 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -macro kernel_export [name]{ -forward - if used name - if DEBUG - display 'uses: ',`name,#13,#10 - end if - extrn name - end if -} -; all exported kernel functions and data - - -kernel_export \ - RegService,\ - GetService,\ - ServiceHandler,\ - AttachIntHandler,\ - GetIntHandler,\ - FpuSave,\ - FpuRestore,\ - ReservePortArea,\ - Boot_Log,\ -\ - MutexInit,\ - MutexLock,\ - MutexUnlock,\ -\ - PciApi,\ - PciRead32,\ - PciRead16,\ - PciRead8,\ - PciWrite8,\ - PciWrite16,\ - PciWrite32,\ -\ - AllocPage,\ - AllocPages,\ - FreePage,\ - MapPage,\ - MapSpace,\ - MapIoMem,\ - GetPgAddr,\ - CommitPages,\ - ReleasePages,\ -\ - AllocKernelSpace,\ - FreeKernelSpace,\ - KernelAlloc,\ - KernelFree,\ - UserAlloc,\ - UserFree,\ - Kmalloc,\ - Kfree,\ - CreateRingBuffer,\ -\ - GetPid,\ - CreateObject,\ - DestroyObject,\ - CreateEvent,\ - RaiseEvent,\ - WaitEvent,\ - DestroyEvent,\ - ClearEvent,\ -\ - LoadCursor,\ - SelectHwCursor,\ - SetHwCursor,\ - HwCursorRestore,\ - HwCursorCreate,\ -\ - SysMsgBoardStr,\ - SysMsgBoardChar,\ - GetCurrentTask,\ - LoadFile,\ - SendEvent,\ - SetMouseData,\ - Sleep,\ - GetTimerTicks,\ -\ - strncat,\ - strncpy,\ - strncmp,\ - strnlen,\ - strchr,\ - strrchr,\ -\ - LFBAddress,\ - GetDisplay,\ - SetScreen +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +macro kernel_export [name]{ +forward + if used name + if DEBUG + display 'uses: ',`name,#13,#10 + end if + extrn name + end if +} +; all exported kernel functions and data + + +kernel_export \ + RegService,\ + GetService,\ + ServiceHandler,\ + AttachIntHandler,\ + GetIntHandler,\ + FpuSave,\ + FpuRestore,\ + ReservePortArea,\ + Boot_Log,\ +\ + MutexInit,\ + MutexLock,\ + MutexUnlock,\ +\ + PciApi,\ + PciRead32,\ + PciRead16,\ + PciRead8,\ + PciWrite8,\ + PciWrite16,\ + PciWrite32,\ +\ + AllocPage,\ + AllocPages,\ + FreePage,\ + MapPage,\ + MapSpace,\ + MapIoMem,\ + GetPgAddr,\ + CommitPages,\ + ReleasePages,\ +\ + AllocKernelSpace,\ + FreeKernelSpace,\ + KernelAlloc,\ + KernelFree,\ + UserAlloc,\ + UserFree,\ + Kmalloc,\ + Kfree,\ + CreateRingBuffer,\ +\ + GetPid,\ + CreateObject,\ + DestroyObject,\ + CreateEvent,\ + RaiseEvent,\ + WaitEvent,\ + DestroyEvent,\ + ClearEvent,\ +\ + LoadCursor,\ + SelectHwCursor,\ + SetHwCursor,\ + HwCursorRestore,\ + HwCursorCreate,\ +\ + SysMsgBoardStr,\ + SysMsgBoardChar,\ + GetCurrentTask,\ + LoadFile,\ + SendEvent,\ + SetMouseData,\ + Sleep,\ + GetTimerTicks,\ +\ + strncat,\ + strncpy,\ + strncmp,\ + strnlen,\ + strchr,\ + strrchr,\ +\ + LFBAddress,\ + GetDisplay,\ + SetScreen diff --git a/kernel/trunk/drivers/infinity.asm b/kernel/trunk/drivers/infinity.asm index 03708e2b0..8f0081b32 100644 --- a/kernel/trunk/drivers/infinity.asm +++ b/kernel/trunk/drivers/infinity.asm @@ -1,1435 +1,1435 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Serge 2006-2008 -; email: infinity_sound@mail.ru - -format MS COFF - -DEBUG equ 1 - - -include 'proc32.inc' -include 'main.inc' -include 'imports.inc' - - -CURRENT_API equ 0x0101 ;1.01 -COMPATIBLE_API equ 0x0100 ;1.00 - -API_VERSION equ (COMPATIBLE_API shl 16) or CURRENT_API -SOUND_VERSION equ CURRENT_API - - -FORCE_MMX equ 0 ;set to 1 to force use mmx or -FORCE_MMX_128 equ 0 ;integer sse2 extensions - ;and reduce driver size - -;USE_SSE equ 0 - -USE_SSE2_MIXER equ 0 ;floating point mixer. Disabled by default - -OS_BASE equ 0x80000000 - -CAPS_SSE2 equ 26 -PG_SW equ 0x003 - -public START -public service_proc -public version - -RT_INP_EMPTY equ 0xFF000001 -RT_OUT_EMPTY equ 0xFF000002 -RT_INP_FULL equ 0xFF000003 -RT_OUT_FULL equ 0xFF000004 - -EVENT_WATCHED equ 0x10000000 -EVENT_SIGNALED equ 0x20000000 -MANUAL_RESET equ 0x40000000 -MANUAL_DESTROY equ 0x80000000 - -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_GET_POS equ 9 - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .exit - - stdcall GetService, szSound - test eax, eax - jz .fail - mov [hSound], eax - - stdcall KernelAlloc, 16*512 - test eax, eax - jz .out_of_mem - mov [mix_buff], eax - - mov eax, str.fd-FD_OFFSET - mov [str.fd], eax - mov [str.bk], eax - -if FORCE_MMX - if FORCE_MMX_128 - display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 - stop - end if - mov [mix_2_core], mmx_mix_2 - mov [mix_3_core], mmx_mix_3 - mov [mix_4_core], mmx_mix_4 -end if - -if FORCE_MMX_128 - if FORCE_MMX - display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 - stop - end if - mov [mix_2_core], mmx128_mix_2 - mov [mix_3_core], mmx128_mix_3 - mov [mix_4_core], mmx128_mix_4 -end if - -if 0 - -if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect - mov eax, 1 - cpuid - bt edx, CAPS_SSE2 - jc .mmx128 - ;old 64-bit mmx - mov [mix_2_core], mmx_mix_2 - mov [mix_3_core], mmx_mix_3 - mov [mix_4_core], mmx_mix_4 - jmp @F -.mmx128: ;128-bit integer sse2 extensions - mov [mix_2_core], mmx128_mix_2 - mov [mix_3_core], mmx128_mix_3 - mov [mix_4_core], mmx128_mix_4 -@@: -end if - -end if - stdcall set_handler, [hSound], new_mix - mov [eng_state], SND_STOP - stdcall RegService, szInfinity, service_proc - ret -.fail: - if DEBUG - mov esi, msgFail - call SysMsgBoardStr - end if -.exit: - xor eax, eax - ret - -.out_of_mem: - if DEBUG - mov esi, msgMem - call SysMsgBoardStr - end if - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - - - -align 4 - -srv_calls dd service_proc.srv_getversion ; 0 - dd service_proc.snd_create_buff ; 1 - dd service_proc.snd_destroy_buff ; 2 - dd service_proc.snd_setformat ; 3 - dd service_proc.snd_getformat ; 4 - dd service_proc.snd_reset ; 5 - dd service_proc.snd_setpos ; 6 - dd service_proc.snd_getpos ; 7 - dd service_proc.snd_setbuff ; 8 - dd service_proc.snd_out ; 9 - dd service_proc.snd_play ; 10 - dd service_proc.snd_stop ; 11 - dd service_proc.snd_setvolume ; 12 - dd service_proc.snd_getvolume ; 13 - dd service_proc.snd_setpan ; 14 - dd service_proc.snd_getpan ; 15 - dd service_proc.snd_getbuffsize ; 16 - dd service_proc.snd_getfreespace ; 17 - dd service_proc.snd_settimebase ; 18 - dd service_proc.snd_gettimestamp ; 19 -srv_calls_end: - -proc service_proc stdcall, ioctl:dword - - mov edi, [ioctl] - mov eax, [edi+io_code] - - cmp eax, (srv_calls_end-srv_calls)/4 - ja .fail - - cmp eax, SND_DESTROY_BUFF - jb @F - -; cmp [edi+inp_size], 4 -; jb .fali - - mov ebx, [edi+input] - mov edx, [ebx] - - cmp [edx+STREAM.magic], 'WAVE' - jne .fail - - cmp [edx+STREAM.size], STREAM.sizeof - jne .fail - -@@: - jmp [srv_calls+eax*4] - - -.fail: - mov eax, -1 - ret - -align 4 -.srv_getversion: - mov eax, [edi+output] - cmp [edi+out_size], 4 - jne .fail - mov eax, [eax] - mov [eax], dword API_VERSION - xor eax, eax - ret - -align 4 -.snd_create_buff: - mov ebx, [edi+input] - stdcall CreateBuffer,[ebx],[ebx+4] - mov edi, [ioctl] - mov ecx, [edi+output] - mov ecx, [ecx] - mov [ecx], ebx - ret - -align 4 -.snd_destroy_buff: - mov eax, edx - call DestroyBuffer - ret - -align 4 -.snd_setformat: - stdcall SetFormat, edx,[ebx+4] - ret - -align 4 -.snd_getformat: - movzx eax, word [edx+STREAM.format] - mov ecx, [edi+output] - mov ecx, [ecx] - mov [ecx], eax - xor eax, eax - ret - -align 4 -.snd_reset: - stdcall ResetBuffer,edx,[ebx+4] - ret - -align 4 -.snd_setpos: - stdcall SetBufferPos,edx,[ebx+4] - ret - -align 4 -.snd_getpos: - stdcall GetBufferPos, edx - mov edi, [ioctl] - mov ecx, [edi+output] - mov ecx, [ecx] - mov [ecx], ebx - ret - -align 4 -.snd_setbuff: - mov eax, [ebx+4] - stdcall set_buffer, edx,eax,[ebx+8],[ebx+12] - ret - -align 4 -.snd_out: - mov eax, [ebx+4] - stdcall wave_out, edx,eax,[ebx+8] - ret - -align 4 -.snd_play: - stdcall play_buffer, edx,[ebx+4] - ret - -align 4 -.snd_stop: - stdcall stop_buffer, edx - ret - -align 4 -.snd_setvolume: - stdcall SetBufferVol,edx,[ebx+4],[ebx+8] - ret - -align 4 -.snd_getvolume: - mov eax, [edi+output] - mov ecx, [eax] - mov eax, [eax+4] - stdcall GetBufferVol,edx,ecx,eax - ret -align 4 -.snd_setpan: - stdcall SetBufferPan,edx,[ebx+4] - ret - -align 4 -.snd_getpan: - mov eax, [edx+STREAM.pan] - mov ebx, [edi+output] - mov ebx, [ebx] - mov [ebx], eax - xor eax, eax - ret - -align 4 -.snd_getbuffsize: - mov eax, [edx+STREAM.in_size] - mov ecx, [edi+output] - mov ecx, [ecx] - mov [ecx], eax - xor eax, eax - ret - -align 4 -.snd_getfreespace: - test [edx+STREAM.format], PCM_OUT - jz .fail - - mov ebx, [edx+STREAM.in_free] - mov ecx, [edi+output] - mov [ecx], ebx - xor eax, eax - ret -align 4 -.snd_settimebase: - cmp [edi+inp_size], 12 - jne .fail - - mov eax, [ebx] - mov ebx, [ebx+4] - mov dword [edx+STREAM.time_base], eax - mov dword [edx+STREAM.time_base+4], ebx - xor eax, eax - ret - -.snd_gettimestamp: - cmp [edi+out_size], 8 - jne .fail - - pushfd - cli - - xor ebx, ebx - push 48 - push ebx ; local storage - - cmp [edx+STREAM.flags], SND_STOP - je @F - - mov eax, esp - - push edx - push edi - - push 4 ;.out_size - push eax ;.output - push ebx ;.inp_size - push ebx ;.input - push DEV_GET_POS ;.code - push dword [hSound] ;.handle - mov eax, esp - - stdcall ServiceHandler, eax - add esp, 6*4 - - pop edi - pop edx - - test eax, eax - jz @F - - mov dword [esp], 0 ; clear offset -@@: - mov edi, [edi+output] - - emms - fild qword [edx+STREAM.time_stamp] - fiadd dword [esp] ; primary buffer offset - fidiv dword [esp+4] ; total_samples / frequency - fadd qword [edx+STREAM.time_base] - fstp qword [edi] - add esp, 8 - - popfd - - xor eax, eax - ret -endp - - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - -align 4 -proc CreateBuffer stdcall, format:dword, size:dword - locals - str dd ? - ring_size dd ? - ring_pages dd ? - endl - - mov eax, [format] - cmp ax, PCM_1_8_8 - ja .fail - - test eax, PCM_OUT - jnz .test_out - test eax, PCM_RING - jnz .test_ring -;staic - test eax, PCM_STATIC - jz .test_out ;use PCM_OUT as default format - jmp .test_ok -.test_out: - test eax, PCM_RING+PCM_STATIC - jnz .fail - or [format], PCM_OUT ;force set - jmp .test_ok -.test_ring: - test eax, PCM_OUT+PCM_STATIC - jnz .fail -.test_ok: - - call GetPid - mov ebx, eax - mov eax, STREAM.sizeof - - call CreateObject - test eax, eax - jz .fail - mov [str], eax - - mov ebx, [format] - mov [eax+STREAM.format], ebx - - xor ecx, ecx - movzx ebx, bx - cmp ebx, 19 - jb @f - mov ecx, 0x80808080 -@@: - mov [eax+STREAM.r_silence], ecx - - shl ebx, 2 - lea ebx, [ebx+ebx*2] ;ebx*=12 - - mov ecx, [resampler_params+ebx] - mov edx, [resampler_params+ebx+4] - mov esi, [resampler_params+ebx+8] - - mov [eax+STREAM.r_size],ecx - mov [eax+STREAM.r_dt], edx - mov [eax+STREAM.resample], esi - xor ecx, ecx - mov [eax+STREAM.l_vol], ecx - mov [eax+STREAM.r_vol], ecx - mov dword [eax+STREAM.l_amp], 0x7FFF7FFF - mov [eax+STREAM.pan], ecx - - test [format], PCM_STATIC - jnz .static - -; ring and waveout - - mov ebx, 0x10000 - test [format], PCM_RING - jz .waveout - - mov ebx, [eax+STREAM.r_size] - add ebx, 4095 - and ebx, -4096 - add ebx, ebx -.waveout: - mov [ring_size], ebx - mov eax, ebx - shr ebx, 12 - mov [ring_pages], ebx - - stdcall CreateRingBuffer, eax, PG_SW - - mov edi, [str] - mov ecx, [ring_size] - mov [edi+STREAM.in_base], eax - mov [edi+STREAM.in_size], ecx - add eax, 128 - mov [edi+STREAM.in_wp], eax - mov [edi+STREAM.in_rp], eax - mov [edi+STREAM.in_count], 0 - - mov [edi+STREAM.in_free], ecx - add eax, ecx - mov [edi+STREAM.in_top], eax - - jmp .out_buff -.static: - mov ecx, [size] - add ecx, 128 ;resampler required - mov [eax+STREAM.in_size], ecx - stdcall KernelAlloc, ecx - - mov edi, [str] - mov [edi+STREAM.in_base], eax - add eax, 128 - mov [edi+STREAM.in_wp], eax - mov [edi+STREAM.in_rp], eax - mov ebx, [size] - mov [edi+STREAM.in_count], ebx - mov [edi+STREAM.in_free], ebx - add eax, ebx - mov [edi+STREAM.in_top], eax - -.out_buff: - stdcall AllocKernelSpace, dword 128*1024 - - mov edi, [str] - xor ebx, ebx - - mov [edi+STREAM.out_base], eax - mov [edi+STREAM.out_wp], eax - mov [edi+STREAM.out_rp], eax - mov [edi+STREAM.out_count], ebx - add eax, 64*1024 - mov [edi+STREAM.out_top], eax - - mov dword [edi+STREAM.time_base], ebx - mov dword [edi+STREAM.time_base+4], ebx - - mov dword [edi+STREAM.time_stamp], ebx - mov dword [edi+STREAM.time_stamp+4], ebx - mov dword [edi+STREAM.last_ts], ebx - - stdcall AllocPages, dword 64/4 - mov edi, [str] - mov ebx, [edi+STREAM.out_base] - mov ecx, 16 - or eax, PG_SW - push eax - push ebx - call CommitPages ;eax, ebx, ecx - mov ecx, 16 - pop ebx - pop eax - add ebx, 64*1024 - call CommitPages ;double mapped - - mov edi, [str] - mov ecx, [edi+STREAM.in_top] - mov edi, [edi+STREAM.in_base] - sub ecx, edi - xor eax, eax - shr ecx, 2 - cld - rep stosd - - mov edi, [str] - mov edi, [edi+STREAM.out_base] - mov ecx, (64*1024)/4 - rep stosd - - xor esi, esi - mov ecx, MANUAL_DESTROY - call CreateEvent - - mov ebx, [str] - mov [ebx+STREAM.notify_event], eax - mov [ebx+STREAM.notify_id], edx - - mov [ebx+STREAM.magic], 'WAVE' - mov [ebx+STREAM.destroy], DestroyBuffer.destroy - mov [ebx+STREAM.size], STREAM.sizeof - mov [ebx+STREAM.flags], SND_STOP - - pushf - cli - mov eax, str.fd-FD_OFFSET - mov edx, [eax+STREAM.str_fd] - mov [ebx+STREAM.str_fd], edx - mov [ebx+STREAM.str_bk], eax - mov [eax+STREAM.str_fd], ebx - mov [edx+STREAM.str_bk], ebx - popf - - xor eax, eax - ret -.fail: - xor ebx, ebx - or eax, -1 - ret -endp - -;param -; eax= buffer handle - -align 4 -DestroyBuffer: - .handle equ esp ;local - - mov [eax+STREAM.flags], SND_STOP -.destroy: - push eax - - pushfd - cli - mov ebx, [eax+STREAM.str_fd] - mov ecx, [eax+STREAM.str_bk] - mov [ebx+STREAM.str_bk], ecx - mov [ecx+STREAM.str_fd], ebx - popf - - stdcall KernelFree, [eax+STREAM.in_base] - mov eax, [.handle] - stdcall KernelFree, [eax+STREAM.out_base] - - pop eax ;restore stack - call DestroyObject ;eax= stream - xor eax, eax - ret -.fail: - or eax, -1 - ret -restore .handle - -align 4 -proc SetFormat stdcall, str:dword, format:dword - - cmp word [format], PCM_1_8_8 - ja .fail - - mov edx, [str] - mov [edx+STREAM.flags], SND_STOP - - test [edx+STREAM.format], PCM_RING - jnz .fail - -; mov eax,[edx+STREAM.out_base] -; mov [edx+STREAM.out_wp], eax -; mov [edx+STREAM.out_rp], eax -; mov [edx+STREAM.out_count], 0 - - movzx eax, word [format] - mov word [edx+STREAM.format], ax - - xor ebx, ebx - cmp eax, 19 - jb @f - mov ebx, 0x80808080 -@@: - mov [edx+STREAM.r_silence], ebx - - shl eax, 2 - lea eax, [eax+eax*2] ;eax*=12 - - mov edi, [resampler_params+eax] - mov ecx, [resampler_params+eax+4] - mov ebx, [resampler_params+eax+8] - - mov [edx+STREAM.r_size],edi - mov [edx+STREAM.r_dt], ecx - mov [edx+STREAM.resample], ebx - - mov edi, [edx+STREAM.in_base] - mov ecx, 128/4 - mov eax, [edx+STREAM.r_silence] - cld - rep stosd - xor eax, eax - ret -.fail: - or eax, -1 - ret -endp - -; for static buffers only -; use waveout for streams - -align 4 -proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword - - mov edx, [str] - test [edx+STREAM.format], PCM_OUT - jnz .fail - - mov esi, [src] - mov edi, [offs] - add edi, [edx+STREAM.in_base] - add edi, 128 - - cmp edi, [edx+STREAM.in_top] - jae .fail - - mov ecx, [size] - lea ebx, [ecx+edi] - sub ebx, [edx+STREAM.in_top] - jb @F - sub ecx, ebx -@@: - shr ecx, 2 - cld - rep movsd - xor eax,eax - ret -.fail: - or eax, -1 - ret -endp - -; for stream buffers only - -align 4 -proc wave_out stdcall, str:dword,src:dword,size:dword - locals - state_saved dd ? - fpu_state rb 528 - endl - - mov edx, [str] - mov eax, [edx+STREAM.format] - test eax, PCM_OUT - jz .fail - - cmp ax, PCM_ALL - je .fail - - mov esi,[src] - test esi, esi - jz .fail - - cmp esi, OS_BASE - jae .fail - - mov [state_saved], 0 - -.main_loop: - mov edx, [str] - - mov ebx, [size] - test ebx, ebx - jz .done - - cmp [edx+STREAM.flags], SND_STOP - jne .fill - - mov edi, [edx+STREAM.in_base] - mov ecx, 128/4 - mov eax, [edx+STREAM.r_silence] - cld - rep stosd - - mov ecx, [edx+STREAM.in_size] - sub ecx, 128 - mov [edx+STREAM.in_wp], edi - mov [edx+STREAM.in_rp], edi - mov [edx+STREAM.in_count], 0 - mov [edx+STREAM.in_free], ecx - - mov eax,[edx+STREAM.out_base] - mov [edx+STREAM.out_wp], eax - mov [edx+STREAM.out_rp], eax - mov [edx+STREAM.out_count], 0 -.fill: - cli - - mov ecx, [edx+STREAM.in_free] - test ecx, ecx - jz .wait - - cmp ecx, ebx - jbe @F - - mov ecx, ebx -@@: - sub [size], ecx - add [edx+STREAM.in_count], ecx - sub [edx+STREAM.in_free], ecx - - shr ecx, 2 - mov edi, [edx+STREAM.in_wp] - mov esi, [src] - cld - rep movsd - - mov [src], esi - cmp edi, [edx+STREAM.in_top] - jb @F - sub edi, [edx+STREAM.in_size] -@@: - mov [edx+STREAM.in_wp], edi - - cmp [edx+STREAM.out_count], 32768 - jae .skip - - cmp [state_saved], 0 - jne @F - lea eax, [fpu_state+15] - and eax, -16 - call FpuSave - mov [state_saved], 1 -@@: - stdcall refill, edx - -.skip: - sti - mov edx, [str] - mov [edx+STREAM.flags], SND_PLAY - cmp [eng_state], SND_PLAY - je .main_loop - - stdcall dev_play, [hSound] - mov [eng_state], SND_PLAY - jmp .main_loop -.wait: - sti - mov edx, [str] - mov eax, [edx+STREAM.notify_event] - mov ebx, [edx+STREAM.notify_id] - call WaitEvent ;eax ebx - jmp .main_loop -.done: - cmp [state_saved], 1 - jne @F - - lea eax, [fpu_state+15] - and eax, -16 - call FpuRestore -@@: - xor eax, eax - ret -.fail: - or eax, -1 - ret -endp - -; both static and stream -; reset all but not clear buffers - - -; flags reserved -; RESET_INPUT equ 1 ;reserved reset and clear input buffer -; RESET_OUTPUT equ 2 ;reserved reset and clear output buffer -; RESET_ALL equ 3 - - -align 4 -proc ResetBuffer stdcall, str:dword, flags:dword - - mov edx, [str] - mov [edx+STREAM.flags], SND_STOP - - mov edi, [edx+STREAM.in_base] - mov ecx, 128/4 - mov eax, [edx+STREAM.r_silence] - cld - rep stosd - - mov [edx+STREAM.in_wp], edi - mov [edx+STREAM.in_rp], edi - - test [edx+STREAM.flags], PCM_STATIC - jnz .static - mov [edx+STREAM.in_count], 0 - jmp @F -.static: - mov eax, [edx+STREAM.in_size] - mov [edx+STREAM.in_count], eax -@@: - - mov eax, [edx+STREAM.in_size] - sub eax, 128 - mov [edx+STREAM.in_free], eax - - xor eax, eax - mov ebx,[edx+STREAM.out_base] - mov [edx+STREAM.out_wp], ebx - mov [edx+STREAM.out_rp], ebx - mov [edx+STREAM.out_count], eax - ret -.fail: - or eax, -1 - ret -endp - -; for static buffers only - -align 4 -proc SetBufferPos stdcall, str:dword, pos:dword - - mov edx, [str] - test [edx+STREAM.format], PCM_STATIC - jz .fail - - mov [edx+STREAM.flags], SND_STOP - - mov eax, [pos] - add eax, [edx+STREAM.in_base] - mov ebx, [edx+STREAM.in_top] - add eax, 128 - - cmp eax, ebx - jae .fail - - mov [edx+STREAM.in_rp], eax - sub ebx, eax - mov [edx+STREAM.in_count], ebx - xor eax, eax - ret -.fail: - or eax, -1 - ret -endp - -align 4 -proc GetBufferPos stdcall, str:dword - - mov edx, [str] - test [edx+STREAM.format], PCM_STATIC - jz .fail - - mov ebx, [edx+STREAM.in_rp] - sub ebx, [edx+STREAM.in_base] - sub ebx, 128 - xor eax, eax - ret -.fail: - xor ebx,ebx - or eax, -1 - ret -endp - -; both - -align 4 -proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword - - mov edx, [str] - stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan] - ret -endp - - -proc minw stdcall, arg1:dword, arg2:dword - mov ax, word [arg1] - cmp ax, word [arg2] - jle @f - mov eax, [arg2] -@@: - ret -endp - -proc maxw stdcall, arg1:dword, arg2:dword - mov ax, word [arg1] - cmp ax, word [arg2] - jge @f - mov eax, [arg2] -@@: - ret -endp - - -proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword - locals - _600 dd ? - _32767 dd ? - state rb 108 - endl - - mov [_600], 0x44160000 ;600.0 - mov [_32767], 32767 - - lea ebx, [state] - fnsave [ebx] - - stdcall minw, [l_vol], [vol_max] - stdcall maxw, eax, [vol_min] - mov [l_vol], eax - mov [edx+STREAM.l_vol], eax - stdcall minw, [r_vol], [vol_max+4] - stdcall maxw, eax, [vol_min+4] - mov [r_vol], eax - mov [edx+STREAM.r_vol], eax - - stdcall minw, [pan], [pan_max] - stdcall maxw, eax, [vol_min] - mov [edx+STREAM.pan], eax - - cmp word [edx+STREAM.pan], 0 - jl @f - - mov ebx, [l_vol] - sub ebx, eax - stdcall minw, ebx, [vol_max] - stdcall maxw, eax, [vol_min] - mov [l_vol], eax - jmp .calc_amp -@@: - mov ebx, [r_vol] - add ebx, [pan] - stdcall minw, ebx, [vol_max+4] - stdcall maxw, eax, [vol_min+4] - mov [r_vol], eax -.calc_amp: - emms - fild word [l_vol] - - call .calc - - fistp word [edx+STREAM.l_amp] - fstp dword [edx+STREAM.l_amp_f] - fstp st0 - - fild word [r_vol] - - call .calc - - fistp word [edx+STREAM.r_amp] - fstp dword [edx+STREAM.r_amp_f] - fstp st0 - - fnclex - lea ebx, [state] - frstor [ebx] - - xor eax, eax - inc eax - ret -.calc: - fdiv dword [_600] - fld st0 - frndint - fxch st1 - fsub st, st1 - f2xm1 - fld1 - faddp st1, st0 - fscale - fld st0 - fimul dword [_32767] - ret 0 -endp - - -align 4 -proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword - - mov edx, [str] - mov eax, [p_lvol] - movsx ecx, word [edx+STREAM.l_vol] - mov [eax], ecx - - mov eax, [p_rvol] - movsx ecx, word [edx+STREAM.r_vol] - mov [eax], ecx - xor eax, eax - ret -endp - -align 4 -proc SetBufferPan stdcall, str:dword,pan:dword - - mov edx, [str] - stdcall set_vol_param,[edx+STREAM.l_vol],\ - [edx+STREAM.r_vol],[pan] - ret -endp - -; for static and ring buffers only - -align 4 -proc play_buffer stdcall, str:dword, flags:dword - - mov ebx, [str] - mov eax, [ebx+STREAM.format] - test eax, PCM_OUT - jnz .fail - - cmp ax, PCM_ALL - je .fail - - mov [ebx+STREAM.flags], SND_PLAY - cmp [eng_state], SND_PLAY - je .done - - stdcall dev_play, [hSound] - mov [eng_state], SND_PLAY -.done: - test [flags], PLAY_SYNC - jz @F - - mov edx, [str] -.wait: - mov eax, [edx+STREAM.notify_event] - mov ebx, [edx+STREAM.notify_id] - call WaitEvent ;eax ebx - - mov edx, [str] - cmp [edx+STREAM.flags], SND_STOP - jne .wait -@@: - xor eax, eax - ret -.fail: - or eax, -1 - ret -endp - -; for static and ring buffers only - -align 4 -proc stop_buffer stdcall, str:dword - - mov edx, [str] - test [edx+STREAM.format], PCM_STATIC+PCM_RING - jz .fail - - mov [edx+STREAM.flags], SND_STOP - -; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 - - mov eax, [edx+STREAM.notify_event] - mov ebx, [edx+STREAM.notify_id] - call ClearEvent ;eax ebx - - xor eax, eax - ret -.fail: - or eax, -1 - ret -endp - -; param -; eax= mix_list - -align 4 -do_mix_list: - - xor edx, edx - mov esi, str.fd-FD_OFFSET - mov ebx, [esi+STREAM.str_fd] -@@: - cmp ebx, esi - je .done - - cmp [ebx+STREAM.magic], 'WAVE' - jne .next - - cmp [ebx+STREAM.size], STREAM.sizeof - jne .next - - cmp [ebx+STREAM.flags], SND_PLAY; - jne .next - - mov ecx, [ebx+STREAM.out_count] - test ecx, ecx - jnz .l1 - - test [ebx+STREAM.format], PCM_RING - jnz .next - mov [ebx+STREAM.flags], SND_STOP - jmp .next -.l1: - cmp ecx, 512 - jae .add_buff - - mov edi, [ebx+STREAM.out_rp] - add edi, ecx - sub ecx, 512 - neg ecx - push eax - xor eax, eax - cld - rep stosb - pop eax - - mov [ebx+STREAM.out_count], 512 - -.add_buff: - mov ecx, [ebx+STREAM.out_rp] - mov [eax],ecx - -if USE_SSE2_MIXER - mov edi, dword [ebx+STREAM.l_amp_f] - mov [eax+4], edi - mov edi, dword [ebx+STREAM.r_amp_f] - mov [eax+8], edi -else - mov edi, dword [ebx+STREAM.l_amp] - mov [eax+4], edi -end if - add [ebx+STREAM.out_rp], 512 - sub [ebx+STREAM.out_count], 512 - - add eax, 12 - inc edx -.next: - mov ebx, [ebx+STREAM.str_fd] - jmp @B -.done: - mov eax, edx - ret - -align 4 -prepare_playlist: - - xor edx, edx - mov [play_count], edx - mov esi, str.fd-FD_OFFSET - mov edi, [esi+STREAM.str_fd] -@@: - cmp edi, esi - je .done - - cmp [edi+STREAM.magic], 'WAVE' - jne .next - - cmp [edi+STREAM.size], STREAM.sizeof - jne .next - - cmp [edi+STREAM.flags], SND_PLAY; - jne .next - - mov [play_list+edx], edi - inc [play_count] - add edx, 4 -.next: - mov edi, [edi+STREAM.str_fd] - jmp @B -.done: - ret - -align 4 -proc set_handler stdcall, hsrv:dword, handler_proc:dword - locals - handler dd ? - io_code dd ? - input dd ? - inp_size dd ? - output dd ? - out_size dd ? - val dd ? - endl - - mov eax, [hsrv] - lea ecx, [handler_proc] - xor ebx, ebx - - mov [handler], eax - mov [io_code], DEV_CALLBACK - mov [input], ecx - mov [inp_size], 4 - mov [output], ebx - mov [out_size], 0 - - lea eax, [handler] - stdcall ServiceHandler, eax - ret -endp - -align 4 -proc dev_play stdcall, hsrv:dword - locals - handle dd ? - io_code dd ? - input dd ? - inp_size dd ? - output dd ? - out_size dd ? - val dd ? - endl - - mov eax, [hsrv] - xor ebx, ebx - - mov [handle], eax - mov [io_code], DEV_PLAY - mov [input], ebx - mov [inp_size], ebx - mov [output], ebx - mov [out_size], ebx - - lea eax, [handle] - stdcall ServiceHandler, eax - ret -endp - -if 0 -align 4 -dword2str: - mov esi, hex_buff - mov ecx, -8 -@@: - rol eax, 4 - mov ebx, eax - and ebx, 0x0F - mov bl, [ebx+hexletters] - mov [8+esi+ecx], bl - inc ecx - jnz @B - ret - -hexletters db '0123456789ABCDEF' -hex_buff db 8 dup(0),13,10,0 - -end if - -include 'mixer.asm' -include 'mix_mmx.inc' -include 'mix_sse2.inc' - -;if USE_SSE -; include 'mix_sse.inc' -;end if - -align 16 -resampler_params: - ;r_size r_dt resampler_func - dd 0,0,0 ; 0 PCM_ALL - dd 16384, 0, copy_stream ; 1 PCM_2_16_48 - dd 8192, 0, m16_stereo ; 2 PCM_1_16_48 - - dd 16384, 30109, resample_2 ; 3 PCM_2_16_44 - dd 8192, 30109, resample_1 ; 4 PCM_1_16_44 - - dd 16384, 21846, resample_2 ; 5 PCM_2_16_32 - dd 8192, 21846, resample_1 ; 6 PCM_1_16_32 - - dd 16384, 16384, resample_2 ; 7 PCM_2_16_24 - dd 8192, 16384, resample_1 ; 8 PCM_1_16_24 - - dd 8192, 15052, resample_2 ; 9 PCM_2_16_22 - dd 4096, 15052, resample_1 ;10 PCM_1_16_22 - - dd 8192, 10923, resample_2 ;11 PCM_2_16_16 - dd 4096, 10923, resample_1 ;12 PCM_1_16_16 - - dd 8192, 8192, resample_2 ;13 PCM_2_16_12 - dd 4096, 8192, resample_1 ;14 PCM_1_16_12 - - dd 4096, 7527, resample_2 ;15 PCM_2_16_11 - dd 2048, 7527, resample_1 ;16 PCM_1_16_11 - - dd 4096, 5462, resample_2 ;17 PCM_2_16_8 - dd 2048, 5462, resample_1 ;18 PCM_1_16_8 - - dd 16384, 0, s8_stereo ;19 PCM_2_8_48 - dd 8192, 0, m8_stereo ;20 PCM_1_8_48 - - dd 8192, 30109, resample_28 ;21 PCM_2_8_44 - dd 4096, 30109, resample_18 ;22 PCM_1_8_44 - - dd 8192, 21846, resample_28 ;23 PCM_2_8_32 - dd 4096, 21846, resample_18 ;24 PCM_1_8_32 - - dd 8192, 16384, resample_28 ;25 PCM_2_8_24 - dd 4096, 16384, resample_18 ;26 PCM_1_8_24 - - dd 4096, 15052, resample_28 ;27 PCM_2_8_22 - dd 2048, 15052, resample_18 ;28 PCM_1_8_22 - - dd 4096, 10923, resample_28 ;29 PCM_2_8_16 - dd 2048, 10923, resample_18 ;30 PCM_1_8_16 - - dd 4096, 8192, resample_28 ;31 PCM_2_8_12 - dd 2048, 8192, resample_18 ;32 PCM_1_8_12 - - dd 2048, 7527, resample_28 ;33 PCM_2_8_11 - dd 1024, 7527, resample_18 ;34 PCM_1_8_11 - - dd 2048, 5462, resample_28 ;35 PCM_2_8_8 - dd 1024, 5462, resample_18 ;36 PCM_1_8_8 - -m7 dw 0x8000,0x8000,0x8000,0x8000 -mm80 dq 0x8080808080808080 -mm_mask dq 0xFF00FF00FF00FF00 - -vol_max dd 0x00000000,0x00000000 -vol_min dd 0x0000D8F0,0x0000D8F0 -pan_max dd 0x00002710,0x00002710 - -;stream_map dd 0xFFFF ; 16 -version dd (5 shl 16) or SOUND_VERSION - -szInfinity db 'INFINITY',0 -szSound db 'SOUND',0 - -if DEBUG -msgFail db 'Sound service not loaded',13,10,0 -msgPlay db 'Play buffer',13,10,0 -msgStop db 'Stop',13,10,0 -msgUser db 'User callback',13,10,0 -msgMem db 'Not enough memory',13,10,0 -msgDestroy db 'Destroy sound buffer', 13,10,0 -msgWaveout db 'Play waveout', 13,10,0 -msgSetVolume db 'Set volume',13,10,0 -end if - -section '.data' data readable writable align 16 - -play_list rd 16 -mix_input rd 16 -play_count rd 1 -hSound rd 1 -eng_state rd 1 -mix_buff rd 1 -mix_buff_map rd 1 -str.fd rd 1 -str.bk rd 1 - -mix_2_core rd 1 -mix_3_core rd 1 -mix_4_core rd 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Serge 2006-2008 +; email: infinity_sound@mail.ru + +format MS COFF + +DEBUG equ 1 + + +include 'proc32.inc' +include 'main.inc' +include 'imports.inc' + + +CURRENT_API equ 0x0101 ;1.01 +COMPATIBLE_API equ 0x0100 ;1.00 + +API_VERSION equ (COMPATIBLE_API shl 16) or CURRENT_API +SOUND_VERSION equ CURRENT_API + + +FORCE_MMX equ 0 ;set to 1 to force use mmx or +FORCE_MMX_128 equ 0 ;integer sse2 extensions + ;and reduce driver size + +;USE_SSE equ 0 + +USE_SSE2_MIXER equ 0 ;floating point mixer. Disabled by default + +OS_BASE equ 0x80000000 + +CAPS_SSE2 equ 26 +PG_SW equ 0x003 + +public START +public service_proc +public version + +RT_INP_EMPTY equ 0xFF000001 +RT_OUT_EMPTY equ 0xFF000002 +RT_INP_FULL equ 0xFF000003 +RT_OUT_FULL equ 0xFF000004 + +EVENT_WATCHED equ 0x10000000 +EVENT_SIGNALED equ 0x20000000 +MANUAL_RESET equ 0x40000000 +MANUAL_DESTROY equ 0x80000000 + +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_GET_POS equ 9 + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .exit + + stdcall GetService, szSound + test eax, eax + jz .fail + mov [hSound], eax + + stdcall KernelAlloc, 16*512 + test eax, eax + jz .out_of_mem + mov [mix_buff], eax + + mov eax, str.fd-FD_OFFSET + mov [str.fd], eax + mov [str.bk], eax + +if FORCE_MMX + if FORCE_MMX_128 + display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 + stop + end if + mov [mix_2_core], mmx_mix_2 + mov [mix_3_core], mmx_mix_3 + mov [mix_4_core], mmx_mix_4 +end if + +if FORCE_MMX_128 + if FORCE_MMX + display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10 + stop + end if + mov [mix_2_core], mmx128_mix_2 + mov [mix_3_core], mmx128_mix_3 + mov [mix_4_core], mmx128_mix_4 +end if + +if 0 + +if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect + mov eax, 1 + cpuid + bt edx, CAPS_SSE2 + jc .mmx128 + ;old 64-bit mmx + mov [mix_2_core], mmx_mix_2 + mov [mix_3_core], mmx_mix_3 + mov [mix_4_core], mmx_mix_4 + jmp @F +.mmx128: ;128-bit integer sse2 extensions + mov [mix_2_core], mmx128_mix_2 + mov [mix_3_core], mmx128_mix_3 + mov [mix_4_core], mmx128_mix_4 +@@: +end if + +end if + stdcall set_handler, [hSound], new_mix + mov [eng_state], SND_STOP + stdcall RegService, szInfinity, service_proc + ret +.fail: + if DEBUG + mov esi, msgFail + call SysMsgBoardStr + end if +.exit: + xor eax, eax + ret + +.out_of_mem: + if DEBUG + mov esi, msgMem + call SysMsgBoardStr + end if + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + + + +align 4 + +srv_calls dd service_proc.srv_getversion ; 0 + dd service_proc.snd_create_buff ; 1 + dd service_proc.snd_destroy_buff ; 2 + dd service_proc.snd_setformat ; 3 + dd service_proc.snd_getformat ; 4 + dd service_proc.snd_reset ; 5 + dd service_proc.snd_setpos ; 6 + dd service_proc.snd_getpos ; 7 + dd service_proc.snd_setbuff ; 8 + dd service_proc.snd_out ; 9 + dd service_proc.snd_play ; 10 + dd service_proc.snd_stop ; 11 + dd service_proc.snd_setvolume ; 12 + dd service_proc.snd_getvolume ; 13 + dd service_proc.snd_setpan ; 14 + dd service_proc.snd_getpan ; 15 + dd service_proc.snd_getbuffsize ; 16 + dd service_proc.snd_getfreespace ; 17 + dd service_proc.snd_settimebase ; 18 + dd service_proc.snd_gettimestamp ; 19 +srv_calls_end: + +proc service_proc stdcall, ioctl:dword + + mov edi, [ioctl] + mov eax, [edi+io_code] + + cmp eax, (srv_calls_end-srv_calls)/4 + ja .fail + + cmp eax, SND_DESTROY_BUFF + jb @F + +; cmp [edi+inp_size], 4 +; jb .fali + + mov ebx, [edi+input] + mov edx, [ebx] + + cmp [edx+STREAM.magic], 'WAVE' + jne .fail + + cmp [edx+STREAM.size], STREAM.sizeof + jne .fail + +@@: + jmp [srv_calls+eax*4] + + +.fail: + mov eax, -1 + ret + +align 4 +.srv_getversion: + mov eax, [edi+output] + cmp [edi+out_size], 4 + jne .fail + mov eax, [eax] + mov [eax], dword API_VERSION + xor eax, eax + ret + +align 4 +.snd_create_buff: + mov ebx, [edi+input] + stdcall CreateBuffer, [ebx], [ebx+4] + mov edi, [ioctl] + mov ecx, [edi+output] + mov ecx, [ecx] + mov [ecx], ebx + ret + +align 4 +.snd_destroy_buff: + mov eax, edx + call DestroyBuffer + ret + +align 4 +.snd_setformat: + stdcall SetFormat, edx, [ebx+4] + ret + +align 4 +.snd_getformat: + movzx eax, word [edx+STREAM.format] + mov ecx, [edi+output] + mov ecx, [ecx] + mov [ecx], eax + xor eax, eax + ret + +align 4 +.snd_reset: + stdcall ResetBuffer, edx, [ebx+4] + ret + +align 4 +.snd_setpos: + stdcall SetBufferPos, edx, [ebx+4] + ret + +align 4 +.snd_getpos: + stdcall GetBufferPos, edx + mov edi, [ioctl] + mov ecx, [edi+output] + mov ecx, [ecx] + mov [ecx], ebx + ret + +align 4 +.snd_setbuff: + mov eax, [ebx+4] + stdcall set_buffer, edx, eax, [ebx+8], [ebx+12] + ret + +align 4 +.snd_out: + mov eax, [ebx+4] + stdcall wave_out, edx, eax, [ebx+8] + ret + +align 4 +.snd_play: + stdcall play_buffer, edx, [ebx+4] + ret + +align 4 +.snd_stop: + stdcall stop_buffer, edx + ret + +align 4 +.snd_setvolume: + stdcall SetBufferVol, edx, [ebx+4], [ebx+8] + ret + +align 4 +.snd_getvolume: + mov eax, [edi+output] + mov ecx, [eax] + mov eax, [eax+4] + stdcall GetBufferVol, edx, ecx, eax + ret +align 4 +.snd_setpan: + stdcall SetBufferPan, edx, [ebx+4] + ret + +align 4 +.snd_getpan: + mov eax, [edx+STREAM.pan] + mov ebx, [edi+output] + mov ebx, [ebx] + mov [ebx], eax + xor eax, eax + ret + +align 4 +.snd_getbuffsize: + mov eax, [edx+STREAM.in_size] + mov ecx, [edi+output] + mov ecx, [ecx] + mov [ecx], eax + xor eax, eax + ret + +align 4 +.snd_getfreespace: + test [edx+STREAM.format], PCM_OUT + jz .fail + + mov ebx, [edx+STREAM.in_free] + mov ecx, [edi+output] + mov [ecx], ebx + xor eax, eax + ret +align 4 +.snd_settimebase: + cmp [edi+inp_size], 12 + jne .fail + + mov eax, [ebx] + mov ebx, [ebx+4] + mov dword [edx+STREAM.time_base], eax + mov dword [edx+STREAM.time_base+4], ebx + xor eax, eax + ret + +.snd_gettimestamp: + cmp [edi+out_size], 8 + jne .fail + + pushfd + cli + + xor ebx, ebx + push 48 + push ebx ; local storage + + cmp [edx+STREAM.flags], SND_STOP + je @F + + mov eax, esp + + push edx + push edi + + push 4 ;.out_size + push eax ;.output + push ebx ;.inp_size + push ebx ;.input + push DEV_GET_POS ;.code + push dword [hSound] ;.handle + mov eax, esp + + stdcall ServiceHandler, eax + add esp, 6*4 + + pop edi + pop edx + + test eax, eax + jz @F + + mov dword [esp], 0 ; clear offset +@@: + mov edi, [edi+output] + + emms + fild qword [edx+STREAM.time_stamp] + fiadd dword [esp] ; primary buffer offset + fidiv dword [esp+4] ; total_samples / frequency + fadd qword [edx+STREAM.time_base] + fstp qword [edi] + add esp, 8 + + popfd + + xor eax, eax + ret +endp + + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +align 4 +proc CreateBuffer stdcall, format:dword, size:dword + locals + str dd ? + ring_size dd ? + ring_pages dd ? + endl + + mov eax, [format] + cmp ax, PCM_1_8_8 + ja .fail + + test eax, PCM_OUT + jnz .test_out + test eax, PCM_RING + jnz .test_ring +;staic + test eax, PCM_STATIC + jz .test_out ;use PCM_OUT as default format + jmp .test_ok +.test_out: + test eax, PCM_RING+PCM_STATIC + jnz .fail + or [format], PCM_OUT ;force set + jmp .test_ok +.test_ring: + test eax, PCM_OUT+PCM_STATIC + jnz .fail +.test_ok: + + call GetPid + mov ebx, eax + mov eax, STREAM.sizeof + + call CreateObject + test eax, eax + jz .fail + mov [str], eax + + mov ebx, [format] + mov [eax+STREAM.format], ebx + + xor ecx, ecx + movzx ebx, bx + cmp ebx, 19 + jb @f + mov ecx, 0x80808080 +@@: + mov [eax+STREAM.r_silence], ecx + + shl ebx, 2 + lea ebx, [ebx+ebx*2] ;ebx*=12 + + mov ecx, [resampler_params+ebx] + mov edx, [resampler_params+ebx+4] + mov esi, [resampler_params+ebx+8] + + mov [eax+STREAM.r_size], ecx + mov [eax+STREAM.r_dt], edx + mov [eax+STREAM.resample], esi + xor ecx, ecx + mov [eax+STREAM.l_vol], ecx + mov [eax+STREAM.r_vol], ecx + mov dword [eax+STREAM.l_amp], 0x7FFF7FFF + mov [eax+STREAM.pan], ecx + + test [format], PCM_STATIC + jnz .static + +; ring and waveout + + mov ebx, 0x10000 + test [format], PCM_RING + jz .waveout + + mov ebx, [eax+STREAM.r_size] + add ebx, 4095 + and ebx, -4096 + add ebx, ebx +.waveout: + mov [ring_size], ebx + mov eax, ebx + shr ebx, 12 + mov [ring_pages], ebx + + stdcall CreateRingBuffer, eax, PG_SW + + mov edi, [str] + mov ecx, [ring_size] + mov [edi+STREAM.in_base], eax + mov [edi+STREAM.in_size], ecx + add eax, 128 + mov [edi+STREAM.in_wp], eax + mov [edi+STREAM.in_rp], eax + mov [edi+STREAM.in_count], 0 + + mov [edi+STREAM.in_free], ecx + add eax, ecx + mov [edi+STREAM.in_top], eax + + jmp .out_buff +.static: + mov ecx, [size] + add ecx, 128 ;resampler required + mov [eax+STREAM.in_size], ecx + stdcall KernelAlloc, ecx + + mov edi, [str] + mov [edi+STREAM.in_base], eax + add eax, 128 + mov [edi+STREAM.in_wp], eax + mov [edi+STREAM.in_rp], eax + mov ebx, [size] + mov [edi+STREAM.in_count], ebx + mov [edi+STREAM.in_free], ebx + add eax, ebx + mov [edi+STREAM.in_top], eax + +.out_buff: + stdcall AllocKernelSpace, dword 128*1024 + + mov edi, [str] + xor ebx, ebx + + mov [edi+STREAM.out_base], eax + mov [edi+STREAM.out_wp], eax + mov [edi+STREAM.out_rp], eax + mov [edi+STREAM.out_count], ebx + add eax, 64*1024 + mov [edi+STREAM.out_top], eax + + mov dword [edi+STREAM.time_base], ebx + mov dword [edi+STREAM.time_base+4], ebx + + mov dword [edi+STREAM.time_stamp], ebx + mov dword [edi+STREAM.time_stamp+4], ebx + mov dword [edi+STREAM.last_ts], ebx + + stdcall AllocPages, dword 64/4 + mov edi, [str] + mov ebx, [edi+STREAM.out_base] + mov ecx, 16 + or eax, PG_SW + push eax + push ebx + call CommitPages ;eax, ebx, ecx + mov ecx, 16 + pop ebx + pop eax + add ebx, 64*1024 + call CommitPages ;double mapped + + mov edi, [str] + mov ecx, [edi+STREAM.in_top] + mov edi, [edi+STREAM.in_base] + sub ecx, edi + xor eax, eax + shr ecx, 2 + cld + rep stosd + + mov edi, [str] + mov edi, [edi+STREAM.out_base] + mov ecx, (64*1024)/4 + rep stosd + + xor esi, esi + mov ecx, MANUAL_DESTROY + call CreateEvent + + mov ebx, [str] + mov [ebx+STREAM.notify_event], eax + mov [ebx+STREAM.notify_id], edx + + mov [ebx+STREAM.magic], 'WAVE' + mov [ebx+STREAM.destroy], DestroyBuffer.destroy + mov [ebx+STREAM.size], STREAM.sizeof + mov [ebx+STREAM.flags], SND_STOP + + pushf + cli + mov eax, str.fd-FD_OFFSET + mov edx, [eax+STREAM.str_fd] + mov [ebx+STREAM.str_fd], edx + mov [ebx+STREAM.str_bk], eax + mov [eax+STREAM.str_fd], ebx + mov [edx+STREAM.str_bk], ebx + popf + + xor eax, eax + ret +.fail: + xor ebx, ebx + or eax, -1 + ret +endp + +;param +; eax= buffer handle + +align 4 +DestroyBuffer: + .handle equ esp ;local + + mov [eax+STREAM.flags], SND_STOP +.destroy: + push eax + + pushfd + cli + mov ebx, [eax+STREAM.str_fd] + mov ecx, [eax+STREAM.str_bk] + mov [ebx+STREAM.str_bk], ecx + mov [ecx+STREAM.str_fd], ebx + popf + + stdcall KernelFree, [eax+STREAM.in_base] + mov eax, [.handle] + stdcall KernelFree, [eax+STREAM.out_base] + + pop eax ;restore stack + call DestroyObject ;eax= stream + xor eax, eax + ret +.fail: + or eax, -1 + ret +restore .handle + +align 4 +proc SetFormat stdcall, str:dword, format:dword + + cmp word [format], PCM_1_8_8 + ja .fail + + mov edx, [str] + mov [edx+STREAM.flags], SND_STOP + + test [edx+STREAM.format], PCM_RING + jnz .fail + +; mov eax,[edx+STREAM.out_base] +; mov [edx+STREAM.out_wp], eax +; mov [edx+STREAM.out_rp], eax +; mov [edx+STREAM.out_count], 0 + + movzx eax, word [format] + mov word [edx+STREAM.format], ax + + xor ebx, ebx + cmp eax, 19 + jb @f + mov ebx, 0x80808080 +@@: + mov [edx+STREAM.r_silence], ebx + + shl eax, 2 + lea eax, [eax+eax*2] ;eax*=12 + + mov edi, [resampler_params+eax] + mov ecx, [resampler_params+eax+4] + mov ebx, [resampler_params+eax+8] + + mov [edx+STREAM.r_size], edi + mov [edx+STREAM.r_dt], ecx + mov [edx+STREAM.resample], ebx + + mov edi, [edx+STREAM.in_base] + mov ecx, 128/4 + mov eax, [edx+STREAM.r_silence] + cld + rep stosd + xor eax, eax + ret +.fail: + or eax, -1 + ret +endp + +; for static buffers only +; use waveout for streams + +align 4 +proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword + + mov edx, [str] + test [edx+STREAM.format], PCM_OUT + jnz .fail + + mov esi, [src] + mov edi, [offs] + add edi, [edx+STREAM.in_base] + add edi, 128 + + cmp edi, [edx+STREAM.in_top] + jae .fail + + mov ecx, [size] + lea ebx, [ecx+edi] + sub ebx, [edx+STREAM.in_top] + jb @F + sub ecx, ebx +@@: + shr ecx, 2 + cld + rep movsd + xor eax, eax + ret +.fail: + or eax, -1 + ret +endp + +; for stream buffers only + +align 4 +proc wave_out stdcall, str:dword,src:dword,size:dword + locals + state_saved dd ? + fpu_state rb 528 + endl + + mov edx, [str] + mov eax, [edx+STREAM.format] + test eax, PCM_OUT + jz .fail + + cmp ax, PCM_ALL + je .fail + + mov esi, [src] + test esi, esi + jz .fail + + cmp esi, OS_BASE + jae .fail + + mov [state_saved], 0 + +.main_loop: + mov edx, [str] + + mov ebx, [size] + test ebx, ebx + jz .done + + cmp [edx+STREAM.flags], SND_STOP + jne .fill + + mov edi, [edx+STREAM.in_base] + mov ecx, 128/4 + mov eax, [edx+STREAM.r_silence] + cld + rep stosd + + mov ecx, [edx+STREAM.in_size] + sub ecx, 128 + mov [edx+STREAM.in_wp], edi + mov [edx+STREAM.in_rp], edi + mov [edx+STREAM.in_count], 0 + mov [edx+STREAM.in_free], ecx + + mov eax, [edx+STREAM.out_base] + mov [edx+STREAM.out_wp], eax + mov [edx+STREAM.out_rp], eax + mov [edx+STREAM.out_count], 0 +.fill: + cli + + mov ecx, [edx+STREAM.in_free] + test ecx, ecx + jz .wait + + cmp ecx, ebx + jbe @F + + mov ecx, ebx +@@: + sub [size], ecx + add [edx+STREAM.in_count], ecx + sub [edx+STREAM.in_free], ecx + + shr ecx, 2 + mov edi, [edx+STREAM.in_wp] + mov esi, [src] + cld + rep movsd + + mov [src], esi + cmp edi, [edx+STREAM.in_top] + jb @F + sub edi, [edx+STREAM.in_size] +@@: + mov [edx+STREAM.in_wp], edi + + cmp [edx+STREAM.out_count], 32768 + jae .skip + + cmp [state_saved], 0 + jne @F + lea eax, [fpu_state+15] + and eax, -16 + call FpuSave + mov [state_saved], 1 +@@: + stdcall refill, edx + +.skip: + sti + mov edx, [str] + mov [edx+STREAM.flags], SND_PLAY + cmp [eng_state], SND_PLAY + je .main_loop + + stdcall dev_play, [hSound] + mov [eng_state], SND_PLAY + jmp .main_loop +.wait: + sti + mov edx, [str] + mov eax, [edx+STREAM.notify_event] + mov ebx, [edx+STREAM.notify_id] + call WaitEvent ;eax ebx + jmp .main_loop +.done: + cmp [state_saved], 1 + jne @F + + lea eax, [fpu_state+15] + and eax, -16 + call FpuRestore +@@: + xor eax, eax + ret +.fail: + or eax, -1 + ret +endp + +; both static and stream +; reset all but not clear buffers + + +; flags reserved +; RESET_INPUT equ 1 ;reserved reset and clear input buffer +; RESET_OUTPUT equ 2 ;reserved reset and clear output buffer +; RESET_ALL equ 3 + + +align 4 +proc ResetBuffer stdcall, str:dword, flags:dword + + mov edx, [str] + mov [edx+STREAM.flags], SND_STOP + + mov edi, [edx+STREAM.in_base] + mov ecx, 128/4 + mov eax, [edx+STREAM.r_silence] + cld + rep stosd + + mov [edx+STREAM.in_wp], edi + mov [edx+STREAM.in_rp], edi + + test [edx+STREAM.flags], PCM_STATIC + jnz .static + mov [edx+STREAM.in_count], 0 + jmp @F +.static: + mov eax, [edx+STREAM.in_size] + mov [edx+STREAM.in_count], eax +@@: + + mov eax, [edx+STREAM.in_size] + sub eax, 128 + mov [edx+STREAM.in_free], eax + + xor eax, eax + mov ebx, [edx+STREAM.out_base] + mov [edx+STREAM.out_wp], ebx + mov [edx+STREAM.out_rp], ebx + mov [edx+STREAM.out_count], eax + ret +.fail: + or eax, -1 + ret +endp + +; for static buffers only + +align 4 +proc SetBufferPos stdcall, str:dword, pos:dword + + mov edx, [str] + test [edx+STREAM.format], PCM_STATIC + jz .fail + + mov [edx+STREAM.flags], SND_STOP + + mov eax, [pos] + add eax, [edx+STREAM.in_base] + mov ebx, [edx+STREAM.in_top] + add eax, 128 + + cmp eax, ebx + jae .fail + + mov [edx+STREAM.in_rp], eax + sub ebx, eax + mov [edx+STREAM.in_count], ebx + xor eax, eax + ret +.fail: + or eax, -1 + ret +endp + +align 4 +proc GetBufferPos stdcall, str:dword + + mov edx, [str] + test [edx+STREAM.format], PCM_STATIC + jz .fail + + mov ebx, [edx+STREAM.in_rp] + sub ebx, [edx+STREAM.in_base] + sub ebx, 128 + xor eax, eax + ret +.fail: + xor ebx, ebx + or eax, -1 + ret +endp + +; both + +align 4 +proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword + + mov edx, [str] + stdcall set_vol_param, [l_vol], [r_vol], [edx+STREAM.pan] + ret +endp + + +proc minw stdcall, arg1:dword, arg2:dword + mov ax, word [arg1] + cmp ax, word [arg2] + jle @f + mov eax, [arg2] +@@: + ret +endp + +proc maxw stdcall, arg1:dword, arg2:dword + mov ax, word [arg1] + cmp ax, word [arg2] + jge @f + mov eax, [arg2] +@@: + ret +endp + + +proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword + locals + _600 dd ? + _32767 dd ? + state rb 108 + endl + + mov [_600], 0x44160000 ;600.0 + mov [_32767], 32767 + + lea ebx, [state] + fnsave [ebx] + + stdcall minw, [l_vol], [vol_max] + stdcall maxw, eax, [vol_min] + mov [l_vol], eax + mov [edx+STREAM.l_vol], eax + stdcall minw, [r_vol], [vol_max+4] + stdcall maxw, eax, [vol_min+4] + mov [r_vol], eax + mov [edx+STREAM.r_vol], eax + + stdcall minw, [pan], [pan_max] + stdcall maxw, eax, [vol_min] + mov [edx+STREAM.pan], eax + + cmp word [edx+STREAM.pan], 0 + jl @f + + mov ebx, [l_vol] + sub ebx, eax + stdcall minw, ebx, [vol_max] + stdcall maxw, eax, [vol_min] + mov [l_vol], eax + jmp .calc_amp +@@: + mov ebx, [r_vol] + add ebx, [pan] + stdcall minw, ebx, [vol_max+4] + stdcall maxw, eax, [vol_min+4] + mov [r_vol], eax +.calc_amp: + emms + fild word [l_vol] + + call .calc + + fistp word [edx+STREAM.l_amp] + fstp dword [edx+STREAM.l_amp_f] + fstp st0 + + fild word [r_vol] + + call .calc + + fistp word [edx+STREAM.r_amp] + fstp dword [edx+STREAM.r_amp_f] + fstp st0 + + fnclex + lea ebx, [state] + frstor [ebx] + + xor eax, eax + inc eax + ret +.calc: + fdiv dword [_600] + fld st0 + frndint + fxch st1 + fsub st, st1 + f2xm1 + fld1 + faddp st1, st0 + fscale + fld st0 + fimul dword [_32767] + ret 0 +endp + + +align 4 +proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword + + mov edx, [str] + mov eax, [p_lvol] + movsx ecx, word [edx+STREAM.l_vol] + mov [eax], ecx + + mov eax, [p_rvol] + movsx ecx, word [edx+STREAM.r_vol] + mov [eax], ecx + xor eax, eax + ret +endp + +align 4 +proc SetBufferPan stdcall, str:dword,pan:dword + + mov edx, [str] + stdcall set_vol_param, [edx+STREAM.l_vol], \ + [edx+STREAM.r_vol],[pan] + ret +endp + +; for static and ring buffers only + +align 4 +proc play_buffer stdcall, str:dword, flags:dword + + mov ebx, [str] + mov eax, [ebx+STREAM.format] + test eax, PCM_OUT + jnz .fail + + cmp ax, PCM_ALL + je .fail + + mov [ebx+STREAM.flags], SND_PLAY + cmp [eng_state], SND_PLAY + je .done + + stdcall dev_play, [hSound] + mov [eng_state], SND_PLAY +.done: + test [flags], PLAY_SYNC + jz @F + + mov edx, [str] +.wait: + mov eax, [edx+STREAM.notify_event] + mov ebx, [edx+STREAM.notify_id] + call WaitEvent ;eax ebx + + mov edx, [str] + cmp [edx+STREAM.flags], SND_STOP + jne .wait +@@: + xor eax, eax + ret +.fail: + or eax, -1 + ret +endp + +; for static and ring buffers only + +align 4 +proc stop_buffer stdcall, str:dword + + mov edx, [str] + test [edx+STREAM.format], PCM_STATIC+PCM_RING + jz .fail + + mov [edx+STREAM.flags], SND_STOP + +; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0 + + mov eax, [edx+STREAM.notify_event] + mov ebx, [edx+STREAM.notify_id] + call ClearEvent ;eax ebx + + xor eax, eax + ret +.fail: + or eax, -1 + ret +endp + +; param +; eax= mix_list + +align 4 +do_mix_list: + + xor edx, edx + mov esi, str.fd-FD_OFFSET + mov ebx, [esi+STREAM.str_fd] +@@: + cmp ebx, esi + je .done + + cmp [ebx+STREAM.magic], 'WAVE' + jne .next + + cmp [ebx+STREAM.size], STREAM.sizeof + jne .next + + cmp [ebx+STREAM.flags], SND_PLAY; + jne .next + + mov ecx, [ebx+STREAM.out_count] + test ecx, ecx + jnz .l1 + + test [ebx+STREAM.format], PCM_RING + jnz .next + mov [ebx+STREAM.flags], SND_STOP + jmp .next +.l1: + cmp ecx, 512 + jae .add_buff + + mov edi, [ebx+STREAM.out_rp] + add edi, ecx + sub ecx, 512 + neg ecx + push eax + xor eax, eax + cld + rep stosb + pop eax + + mov [ebx+STREAM.out_count], 512 + +.add_buff: + mov ecx, [ebx+STREAM.out_rp] + mov [eax], ecx + +if USE_SSE2_MIXER + mov edi, dword [ebx+STREAM.l_amp_f] + mov [eax+4], edi + mov edi, dword [ebx+STREAM.r_amp_f] + mov [eax+8], edi +else + mov edi, dword [ebx+STREAM.l_amp] + mov [eax+4], edi +end if + add [ebx+STREAM.out_rp], 512 + sub [ebx+STREAM.out_count], 512 + + add eax, 12 + inc edx +.next: + mov ebx, [ebx+STREAM.str_fd] + jmp @B +.done: + mov eax, edx + ret + +align 4 +prepare_playlist: + + xor edx, edx + mov [play_count], edx + mov esi, str.fd-FD_OFFSET + mov edi, [esi+STREAM.str_fd] +@@: + cmp edi, esi + je .done + + cmp [edi+STREAM.magic], 'WAVE' + jne .next + + cmp [edi+STREAM.size], STREAM.sizeof + jne .next + + cmp [edi+STREAM.flags], SND_PLAY; + jne .next + + mov [play_list+edx], edi + inc [play_count] + add edx, 4 +.next: + mov edi, [edi+STREAM.str_fd] + jmp @B +.done: + ret + +align 4 +proc set_handler stdcall, hsrv:dword, handler_proc:dword + locals + handler dd ? + io_code dd ? + input dd ? + inp_size dd ? + output dd ? + out_size dd ? + val dd ? + endl + + mov eax, [hsrv] + lea ecx, [handler_proc] + xor ebx, ebx + + mov [handler], eax + mov [io_code], DEV_CALLBACK + mov [input], ecx + mov [inp_size], 4 + mov [output], ebx + mov [out_size], 0 + + lea eax, [handler] + stdcall ServiceHandler, eax + ret +endp + +align 4 +proc dev_play stdcall, hsrv:dword + locals + handle dd ? + io_code dd ? + input dd ? + inp_size dd ? + output dd ? + out_size dd ? + val dd ? + endl + + mov eax, [hsrv] + xor ebx, ebx + + mov [handle], eax + mov [io_code], DEV_PLAY + mov [input], ebx + mov [inp_size], ebx + mov [output], ebx + mov [out_size], ebx + + lea eax, [handle] + stdcall ServiceHandler, eax + ret +endp + +if 0 +align 4 +dword2str: + mov esi, hex_buff + mov ecx, -8 +@@: + rol eax, 4 + mov ebx, eax + and ebx, 0x0F + mov bl, [ebx+hexletters] + mov [8+esi+ecx], bl + inc ecx + jnz @B + ret + +hexletters db '0123456789ABCDEF' +hex_buff db 8 dup(0),13,10,0 + +end if + +include 'mixer.asm' +include 'mix_mmx.inc' +include 'mix_sse2.inc' + +;if USE_SSE +; include 'mix_sse.inc' +;end if + +align 16 +resampler_params: + ;r_size r_dt resampler_func + dd 0,0,0 ; 0 PCM_ALL + dd 16384, 0, copy_stream ; 1 PCM_2_16_48 + dd 8192, 0, m16_stereo ; 2 PCM_1_16_48 + + dd 16384, 30109, resample_2 ; 3 PCM_2_16_44 + dd 8192, 30109, resample_1 ; 4 PCM_1_16_44 + + dd 16384, 21846, resample_2 ; 5 PCM_2_16_32 + dd 8192, 21846, resample_1 ; 6 PCM_1_16_32 + + dd 16384, 16384, resample_2 ; 7 PCM_2_16_24 + dd 8192, 16384, resample_1 ; 8 PCM_1_16_24 + + dd 8192, 15052, resample_2 ; 9 PCM_2_16_22 + dd 4096, 15052, resample_1 ;10 PCM_1_16_22 + + dd 8192, 10923, resample_2 ;11 PCM_2_16_16 + dd 4096, 10923, resample_1 ;12 PCM_1_16_16 + + dd 8192, 8192, resample_2 ;13 PCM_2_16_12 + dd 4096, 8192, resample_1 ;14 PCM_1_16_12 + + dd 4096, 7527, resample_2 ;15 PCM_2_16_11 + dd 2048, 7527, resample_1 ;16 PCM_1_16_11 + + dd 4096, 5462, resample_2 ;17 PCM_2_16_8 + dd 2048, 5462, resample_1 ;18 PCM_1_16_8 + + dd 16384, 0, s8_stereo ;19 PCM_2_8_48 + dd 8192, 0, m8_stereo ;20 PCM_1_8_48 + + dd 8192, 30109, resample_28 ;21 PCM_2_8_44 + dd 4096, 30109, resample_18 ;22 PCM_1_8_44 + + dd 8192, 21846, resample_28 ;23 PCM_2_8_32 + dd 4096, 21846, resample_18 ;24 PCM_1_8_32 + + dd 8192, 16384, resample_28 ;25 PCM_2_8_24 + dd 4096, 16384, resample_18 ;26 PCM_1_8_24 + + dd 4096, 15052, resample_28 ;27 PCM_2_8_22 + dd 2048, 15052, resample_18 ;28 PCM_1_8_22 + + dd 4096, 10923, resample_28 ;29 PCM_2_8_16 + dd 2048, 10923, resample_18 ;30 PCM_1_8_16 + + dd 4096, 8192, resample_28 ;31 PCM_2_8_12 + dd 2048, 8192, resample_18 ;32 PCM_1_8_12 + + dd 2048, 7527, resample_28 ;33 PCM_2_8_11 + dd 1024, 7527, resample_18 ;34 PCM_1_8_11 + + dd 2048, 5462, resample_28 ;35 PCM_2_8_8 + dd 1024, 5462, resample_18 ;36 PCM_1_8_8 + +m7 dw 0x8000,0x8000,0x8000,0x8000 +mm80 dq 0x8080808080808080 +mm_mask dq 0xFF00FF00FF00FF00 + +vol_max dd 0x00000000,0x00000000 +vol_min dd 0x0000D8F0,0x0000D8F0 +pan_max dd 0x00002710,0x00002710 + +;stream_map dd 0xFFFF ; 16 +version dd (5 shl 16) or SOUND_VERSION + +szInfinity db 'INFINITY',0 +szSound db 'SOUND',0 + +if DEBUG +msgFail db 'Sound service not loaded',13,10,0 +msgPlay db 'Play buffer',13,10,0 +msgStop db 'Stop',13,10,0 +msgUser db 'User callback',13,10,0 +msgMem db 'Not enough memory',13,10,0 +msgDestroy db 'Destroy sound buffer', 13,10,0 +msgWaveout db 'Play waveout', 13,10,0 +msgSetVolume db 'Set volume',13,10,0 +end if + +section '.data' data readable writable align 16 + +play_list rd 16 +mix_input rd 16 +play_count rd 1 +hSound rd 1 +eng_state rd 1 +mix_buff rd 1 +mix_buff_map rd 1 +str.fd rd 1 +str.bk rd 1 + +mix_2_core rd 1 +mix_3_core rd 1 +mix_4_core rd 1 diff --git a/kernel/trunk/drivers/main.inc b/kernel/trunk/drivers/main.inc index 75a0c09b0..2f31d5dc9 100644 --- a/kernel/trunk/drivers/main.inc +++ b/kernel/trunk/drivers/main.inc @@ -1,173 +1,173 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Serge 2006-2008 -; email: infinity_sound@mail.ru - - -PLAY_SYNC equ 0x80000000 - -PCM_ALL equ 0 - -PCM_OUT equ 0x08000000 -PCM_RING equ 0x10000000 -PCM_STATIC equ 0x20000000 -PCM_FLOAT equ 0x40000000 ;reserved -PCM_FILTER equ 0x80000000 ;reserved - -PCM_2_16_48 equ 1 -PCM_1_16_48 equ 2 - -PCM_2_16_44 equ 3 -PCM_1_16_44 equ 4 - -PCM_2_16_32 equ 5 -PCM_1_16_32 equ 6 - -PCM_2_16_24 equ 7 -PCM_1_16_24 equ 8 - -PCM_2_16_22 equ 9 -PCM_1_16_22 equ 10 - -PCM_2_16_16 equ 11 -PCM_1_16_16 equ 12 - -PCM_2_16_12 equ 13 -PCM_1_16_12 equ 14 - -PCM_2_16_11 equ 15 -PCM_1_16_11 equ 16 - -PCM_2_16_8 equ 17 -PCM_1_16_8 equ 18 - -PCM_2_8_48 equ 19 -PCM_1_8_48 equ 20 - -PCM_2_8_44 equ 21 -PCM_1_8_44 equ 22 - -PCM_2_8_32 equ 23 -PCM_1_8_32 equ 24 - -PCM_2_8_24 equ 25 -PCM_1_8_24 equ 26 - -PCM_2_8_22 equ 27 -PCM_1_8_22 equ 28 - -PCM_2_8_16 equ 29 -PCM_1_8_16 equ 30 - -PCM_2_8_12 equ 31 -PCM_1_8_12 equ 32 - -PCM_2_8_11 equ 33 -PCM_1_8_11 equ 34 - -PCM_2_8_8 equ 35 -PCM_1_8_8 equ 36 - -SRV_GETVERSION equ 0 -SND_CREATE_BUFF equ 1 -SND_DESTROY_BUFF equ 2 -SND_SETFORMAT equ 3 -SND_GETFORMAT equ 4 -SND_RESET equ 5 -SND_SETPOS equ 6 -SND_GETPOS equ 7 -SND_SETBUFF equ 8 -SND_OUT equ 9 -SND_PLAY equ 10 -SND_STOP equ 11 -SND_SETVOLUME equ 12 -SND_GETVOLUME equ 13 -SND_SETPAN equ 14 -SND_GETPAN equ 15 -SND_GETBUFFSIZE equ 16 -SND_GETFREESPACE equ 17 -SND_SETTIMEBASE equ 18 -SND_GETTIMESTAMP equ 19 - -struc STREAM -{ - .magic dd ? ;'WAVE' - .destroy dd ? ;internal destructor - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id - - .size dd ? - .str_fd dd ? - .str_bk dd ? - .device dd ? - .format dd ? - .flags dd ? - - .out_base dd ? - .out_wp dd ? - .out_rp dd ? - .out_count dd ? - .out_top dd ? ;16*4 - - .in_base dd ? - .in_size dd ? - .in_wp dd ? - .in_rp dd ? - .in_count dd ? - .in_free dd ? - .in_top dd ? - -align 8 - - .time_base dq ? - .time_stamp dq ? - .last_ts dd ? - - .notify_event dd ? - .notify_id dd ? - - .r_size dd ? - .r_dt dd ? - .r_silence dd ? - .resample dd ? - .l_vol dd ? - .r_vol dd ? - .l_amp dw ? - .r_amp dw ? - .pan dd ? - .l_amp_f dd ? ;float point left - .r_amp_f dd ? ;float point right - - .sizeof: -} - -FD_OFFSET equ 24 - -virtual at 0 - STREAM STREAM -end virtual - -struc WAVE_HEADER -{ .riff_id dd ? - .riff_size dd ? - .riff_format dd ? - - .fmt_id dd ? - .fmt_size dd ? - .format_tag dw ? - .channels dw ? - .freq dd ? - .bytes_sec dd ? - .block_align dw ? - .bits_sample dw ? - - .data_id dd ? - .data_size dd ? -} - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; Serge 2006-2008 +; email: infinity_sound@mail.ru + + +PLAY_SYNC equ 0x80000000 + +PCM_ALL equ 0 + +PCM_OUT equ 0x08000000 +PCM_RING equ 0x10000000 +PCM_STATIC equ 0x20000000 +PCM_FLOAT equ 0x40000000 ;reserved +PCM_FILTER equ 0x80000000 ;reserved + +PCM_2_16_48 equ 1 +PCM_1_16_48 equ 2 + +PCM_2_16_44 equ 3 +PCM_1_16_44 equ 4 + +PCM_2_16_32 equ 5 +PCM_1_16_32 equ 6 + +PCM_2_16_24 equ 7 +PCM_1_16_24 equ 8 + +PCM_2_16_22 equ 9 +PCM_1_16_22 equ 10 + +PCM_2_16_16 equ 11 +PCM_1_16_16 equ 12 + +PCM_2_16_12 equ 13 +PCM_1_16_12 equ 14 + +PCM_2_16_11 equ 15 +PCM_1_16_11 equ 16 + +PCM_2_16_8 equ 17 +PCM_1_16_8 equ 18 + +PCM_2_8_48 equ 19 +PCM_1_8_48 equ 20 + +PCM_2_8_44 equ 21 +PCM_1_8_44 equ 22 + +PCM_2_8_32 equ 23 +PCM_1_8_32 equ 24 + +PCM_2_8_24 equ 25 +PCM_1_8_24 equ 26 + +PCM_2_8_22 equ 27 +PCM_1_8_22 equ 28 + +PCM_2_8_16 equ 29 +PCM_1_8_16 equ 30 + +PCM_2_8_12 equ 31 +PCM_1_8_12 equ 32 + +PCM_2_8_11 equ 33 +PCM_1_8_11 equ 34 + +PCM_2_8_8 equ 35 +PCM_1_8_8 equ 36 + +SRV_GETVERSION equ 0 +SND_CREATE_BUFF equ 1 +SND_DESTROY_BUFF equ 2 +SND_SETFORMAT equ 3 +SND_GETFORMAT equ 4 +SND_RESET equ 5 +SND_SETPOS equ 6 +SND_GETPOS equ 7 +SND_SETBUFF equ 8 +SND_OUT equ 9 +SND_PLAY equ 10 +SND_STOP equ 11 +SND_SETVOLUME equ 12 +SND_GETVOLUME equ 13 +SND_SETPAN equ 14 +SND_GETPAN equ 15 +SND_GETBUFFSIZE equ 16 +SND_GETFREESPACE equ 17 +SND_SETTIMEBASE equ 18 +SND_GETTIMESTAMP equ 19 + +struc STREAM +{ + .magic dd ? ;'WAVE' + .destroy dd ? ;internal destructor + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id + + .size dd ? + .str_fd dd ? + .str_bk dd ? + .device dd ? + .format dd ? + .flags dd ? + + .out_base dd ? + .out_wp dd ? + .out_rp dd ? + .out_count dd ? + .out_top dd ? ;16*4 + + .in_base dd ? + .in_size dd ? + .in_wp dd ? + .in_rp dd ? + .in_count dd ? + .in_free dd ? + .in_top dd ? + +align 8 + + .time_base dq ? + .time_stamp dq ? + .last_ts dd ? + + .notify_event dd ? + .notify_id dd ? + + .r_size dd ? + .r_dt dd ? + .r_silence dd ? + .resample dd ? + .l_vol dd ? + .r_vol dd ? + .l_amp dw ? + .r_amp dw ? + .pan dd ? + .l_amp_f dd ? ;float point left + .r_amp_f dd ? ;float point right + + .sizeof: +} + +FD_OFFSET equ 24 + +virtual at 0 + STREAM STREAM +end virtual + +struc WAVE_HEADER +{ .riff_id dd ? + .riff_size dd ? + .riff_format dd ? + + .fmt_id dd ? + .fmt_size dd ? + .format_tag dw ? + .channels dw ? + .freq dd ? + .bytes_sec dd ? + .block_align dw ? + .bits_sample dw ? + + .data_id dd ? + .data_size dd ? +} + diff --git a/kernel/trunk/drivers/mix_mmx.inc b/kernel/trunk/drivers/mix_mmx.inc index 5778cc823..1aa6e14e7 100644 --- a/kernel/trunk/drivers/mix_mmx.inc +++ b/kernel/trunk/drivers/mix_mmx.inc @@ -1,247 +1,247 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; params -; edi= output -; eax= input stream 1 -; ebx= input stream 2 - -if used mmx_mix_2 - -align 4 -mmx_mix_2: - movq mm0, [eax] - movq mm1, [eax+8] - movq mm2, [eax+16] - movq mm3, [eax+24] - movq mm4, [eax+32] - movq mm5, [eax+40] - movq mm6, [eax+48] - movq mm7, [eax+56] - - paddsw mm0, [ebx] - movq [edi], mm0 - paddsw mm1,[ebx+8] - movq [edi+8], mm1 - paddsw mm2, [ebx+16] - movq [edi+16], mm2 - paddsw mm3, [ebx+24] - movq [edi+24], mm3 - paddsw mm4, [ebx+32] - movq [edi+32], mm4 - paddsw mm5, [ebx+40] - movq [edi+40], mm5 - paddsw mm6, [ebx+48] - movq [edi+48], mm6 - paddsw mm7, [ebx+56] - movq [edi+56], mm7 - - movq mm0, [eax+64] - movq mm1, [eax+72] - movq mm2, [eax+80] - movq mm3, [eax+88] - movq mm4, [eax+96] - movq mm5, [eax+104] - movq mm6, [eax+112] - movq mm7, [eax+120] - - paddsw mm0, [ebx+64] - movq [edi+64], mm0 - paddsw mm1, [ebx+72] - movq [edi+72], mm1 - paddsw mm2, [ebx+80] - movq [edi+80], mm2 - paddsw mm3, [ebx+88] - movq [edi+88], mm3 - paddsw mm4, [ebx+96] - movq [edi+96], mm4 - paddsw mm5, [ecx+104] - movq [edx+104], mm5 - paddsw mm6, [ebx+112] - movq [edi+112], mm6 - paddsw mm7, [ebx+120] - movq [edi+120], mm7 - ret - -align 4 -mmx_mix_3: - movq mm0, [eax] - movq mm1, [eax+8] - movq mm2, [eax+16] - movq mm3, [eax+24] - movq mm4, [eax+32] - movq mm5, [eax+40] - movq mm6, [eax+48] - movq mm7, [eax+56] - - paddsw mm0, [ebx] - paddsw mm1, [ebx+8] - paddsw mm2, [ebx+16] - paddsw mm3, [ebx+24] - paddsw mm4, [ebx+32] - paddsw mm5, [ebx+40] - paddsw mm6, [ebx+48] - paddsw mm7, [ebx+56] - paddsw mm0, [ecx] - movq [edi], mm0 - paddsw mm1,[ecx+8] - movq [edi+8], mm1 - paddsw mm2, [ecx+16] - movq [edi+16], mm2 - paddsw mm3, [ecx+24] - movq [edi+24], mm3 - paddsw mm4, [ecx+32] - movq [edi+32], mm4 - paddsw mm5, [ecx+40] - movq [edi+40], mm5 - paddsw mm6, [ecx+48] - movq [edi+48], mm6 - paddsw mm7, [ecx+56] - movq [edi+56], mm7 - - movq mm0, [eax+64] - movq mm1, [eax+72] - movq mm2, [eax+80] - movq mm3, [eax+88] - movq mm4, [eax+96] - movq mm5, [eax+104] - movq mm6, [eax+112] - movq mm7, [eax+120] - paddsw mm0, [ebx+64] - paddsw mm1, [ebx+72] - paddsw mm2, [ebx+80] - paddsw mm3, [ebx+88] - paddsw mm4, [ebx+96] - paddsw mm5, [ebx+104] - paddsw mm6, [ebx+112] - paddsw mm7, [ebx+120] - paddsw mm0, [ecx+64] - movq [edi+64], mm0 - paddsw mm1, [ecx+72] - movq [edi+72], mm1 - paddsw mm2, [ecx+80] - movq [edi+80], mm2 - paddsw mm3, [ecx+88] - movq [edi+88], mm3 - paddsw mm4, [ecx+96] - movq [edi+96], mm4 - paddsw mm5, [ecx+104] - movq [edi+104], mm5 - paddsw mm6, [ecx+112] - movq [edi+112], mm6 - paddsw mm7, [ecx+120] - movq [edi+120], mm7 - ret - -align 4 -mmx_mix_4: - - movq mm0, [eax] - movq mm2, [eax+8] - movq mm4, [eax+16] - movq mm6, [eax+24] - movq mm1, [ebx] - movq mm3, [ebx+8] - movq mm5, [ebx+16] - movq mm7, [ebx+24] - paddsw mm0, [ecx] - paddsw mm2, [ecx+8] - paddsw mm4, [ecx+16] - paddsw mm6, [ecx+24] - paddsw mm1, [edx] - paddsw mm3, [edx+8] - paddsw mm5, [edx+16] - paddsw mm7, [edx+24] - - paddsw mm0, mm1 - movq [edi], mm0 - paddsw mm2, mm3 - movq [edi+8], mm2 - paddsw mm4, mm5 - movq [edi+16], mm4 - paddsw mm5, mm6 - movq [edi+24], mm6 - - movq mm0, [eax+32] - movq mm2, [eax+40] - movq mm4, [eax+48] - movq mm6, [eax+56] - movq mm1, [ebx+32] - movq mm3, [ebx+40] - movq mm5, [ebx+48] - movq mm7, [ebx+56] - paddsw mm0, [ecx+32] - paddsw mm2, [ecx+40] - paddsw mm4, [ecx+48] - paddsw mm6, [ecx+56] - paddsw mm1, [edx+32] - paddsw mm3, [edx+40] - paddsw mm5, [edx+48] - paddsw mm7, [edx+56] - - paddsw mm0, mm1 - movq [edi+32], mm0 - paddsw mm2, mm2 - movq [edi+40], mm2 - paddsw mm4, mm5 - movq [edi+48], mm4 - paddsw mm6, mm7 - movq [edi+56], mm6 - - movq mm0, [eax+64] - movq mm2, [eax+72] - movq mm4, [eax+80] - movq mm6, [eax+88] - movq mm1, [ebx+64] - movq mm3, [ebx+72] - movq mm5, [ebx+80] - movq mm7, [ebx+88] - paddsw mm0, [ecx+64] - paddsw mm2, [ecx+72] - paddsw mm4, [ecx+80] - paddsw mm6, [ecx+88] - paddsw mm1, [edx+64] - paddsw mm3, [edx+72] - paddsw mm5, [edx+80] - paddsw mm7, [edx+88] - - paddsw mm0, mm1 - movq [edi+64], mm0 - paddsw mm2, mm3 - movq [edi+72], mm2 - paddsw mm4, mm5 - movq [edi+80], mm4 - paddsw mm6, mm5 - movq [edi+88], mm7 - - movq mm0, [eax+96] - movq mm2, [eax+104] - movq mm4, [eax+112] - movq mm6, [eax+120] - movq mm1, [ebx+96] - movq mm3, [ebx+104] - movq mm5, [ebx+112] - movq mm7, [ebx+120] - paddsw mm0, [ecx+96] - paddsw mm2, [ecx+104] - paddsw mm4, [ecx+112] - paddsw mm6, [ecx+120] - paddsw mm1, [edx+96] - paddsw mm3, [edx+104] - paddsw mm5, [edx+112] - paddsw mm7, [edx+120] - paddsw mm0, mm1 - movq [eax+96], mm0 - paddsw mm2, mm3 - movq [edi+104], mm2 - paddsw mm4, mm5 - movq [edi+112], mm4 - paddsw mm6, mm7 - movq [edi+120], mm6 - ret - -end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; params +; edi= output +; eax= input stream 1 +; ebx= input stream 2 + +if used mmx_mix_2 + +align 4 +mmx_mix_2: + movq mm0, [eax] + movq mm1, [eax+8] + movq mm2, [eax+16] + movq mm3, [eax+24] + movq mm4, [eax+32] + movq mm5, [eax+40] + movq mm6, [eax+48] + movq mm7, [eax+56] + + paddsw mm0, [ebx] + movq [edi], mm0 + paddsw mm1, [ebx+8] + movq [edi+8], mm1 + paddsw mm2, [ebx+16] + movq [edi+16], mm2 + paddsw mm3, [ebx+24] + movq [edi+24], mm3 + paddsw mm4, [ebx+32] + movq [edi+32], mm4 + paddsw mm5, [ebx+40] + movq [edi+40], mm5 + paddsw mm6, [ebx+48] + movq [edi+48], mm6 + paddsw mm7, [ebx+56] + movq [edi+56], mm7 + + movq mm0, [eax+64] + movq mm1, [eax+72] + movq mm2, [eax+80] + movq mm3, [eax+88] + movq mm4, [eax+96] + movq mm5, [eax+104] + movq mm6, [eax+112] + movq mm7, [eax+120] + + paddsw mm0, [ebx+64] + movq [edi+64], mm0 + paddsw mm1, [ebx+72] + movq [edi+72], mm1 + paddsw mm2, [ebx+80] + movq [edi+80], mm2 + paddsw mm3, [ebx+88] + movq [edi+88], mm3 + paddsw mm4, [ebx+96] + movq [edi+96], mm4 + paddsw mm5, [ecx+104] + movq [edx+104], mm5 + paddsw mm6, [ebx+112] + movq [edi+112], mm6 + paddsw mm7, [ebx+120] + movq [edi+120], mm7 + ret + +align 4 +mmx_mix_3: + movq mm0, [eax] + movq mm1, [eax+8] + movq mm2, [eax+16] + movq mm3, [eax+24] + movq mm4, [eax+32] + movq mm5, [eax+40] + movq mm6, [eax+48] + movq mm7, [eax+56] + + paddsw mm0, [ebx] + paddsw mm1, [ebx+8] + paddsw mm2, [ebx+16] + paddsw mm3, [ebx+24] + paddsw mm4, [ebx+32] + paddsw mm5, [ebx+40] + paddsw mm6, [ebx+48] + paddsw mm7, [ebx+56] + paddsw mm0, [ecx] + movq [edi], mm0 + paddsw mm1, [ecx+8] + movq [edi+8], mm1 + paddsw mm2, [ecx+16] + movq [edi+16], mm2 + paddsw mm3, [ecx+24] + movq [edi+24], mm3 + paddsw mm4, [ecx+32] + movq [edi+32], mm4 + paddsw mm5, [ecx+40] + movq [edi+40], mm5 + paddsw mm6, [ecx+48] + movq [edi+48], mm6 + paddsw mm7, [ecx+56] + movq [edi+56], mm7 + + movq mm0, [eax+64] + movq mm1, [eax+72] + movq mm2, [eax+80] + movq mm3, [eax+88] + movq mm4, [eax+96] + movq mm5, [eax+104] + movq mm6, [eax+112] + movq mm7, [eax+120] + paddsw mm0, [ebx+64] + paddsw mm1, [ebx+72] + paddsw mm2, [ebx+80] + paddsw mm3, [ebx+88] + paddsw mm4, [ebx+96] + paddsw mm5, [ebx+104] + paddsw mm6, [ebx+112] + paddsw mm7, [ebx+120] + paddsw mm0, [ecx+64] + movq [edi+64], mm0 + paddsw mm1, [ecx+72] + movq [edi+72], mm1 + paddsw mm2, [ecx+80] + movq [edi+80], mm2 + paddsw mm3, [ecx+88] + movq [edi+88], mm3 + paddsw mm4, [ecx+96] + movq [edi+96], mm4 + paddsw mm5, [ecx+104] + movq [edi+104], mm5 + paddsw mm6, [ecx+112] + movq [edi+112], mm6 + paddsw mm7, [ecx+120] + movq [edi+120], mm7 + ret + +align 4 +mmx_mix_4: + + movq mm0, [eax] + movq mm2, [eax+8] + movq mm4, [eax+16] + movq mm6, [eax+24] + movq mm1, [ebx] + movq mm3, [ebx+8] + movq mm5, [ebx+16] + movq mm7, [ebx+24] + paddsw mm0, [ecx] + paddsw mm2, [ecx+8] + paddsw mm4, [ecx+16] + paddsw mm6, [ecx+24] + paddsw mm1, [edx] + paddsw mm3, [edx+8] + paddsw mm5, [edx+16] + paddsw mm7, [edx+24] + + paddsw mm0, mm1 + movq [edi], mm0 + paddsw mm2, mm3 + movq [edi+8], mm2 + paddsw mm4, mm5 + movq [edi+16], mm4 + paddsw mm5, mm6 + movq [edi+24], mm6 + + movq mm0, [eax+32] + movq mm2, [eax+40] + movq mm4, [eax+48] + movq mm6, [eax+56] + movq mm1, [ebx+32] + movq mm3, [ebx+40] + movq mm5, [ebx+48] + movq mm7, [ebx+56] + paddsw mm0, [ecx+32] + paddsw mm2, [ecx+40] + paddsw mm4, [ecx+48] + paddsw mm6, [ecx+56] + paddsw mm1, [edx+32] + paddsw mm3, [edx+40] + paddsw mm5, [edx+48] + paddsw mm7, [edx+56] + + paddsw mm0, mm1 + movq [edi+32], mm0 + paddsw mm2, mm2 + movq [edi+40], mm2 + paddsw mm4, mm5 + movq [edi+48], mm4 + paddsw mm6, mm7 + movq [edi+56], mm6 + + movq mm0, [eax+64] + movq mm2, [eax+72] + movq mm4, [eax+80] + movq mm6, [eax+88] + movq mm1, [ebx+64] + movq mm3, [ebx+72] + movq mm5, [ebx+80] + movq mm7, [ebx+88] + paddsw mm0, [ecx+64] + paddsw mm2, [ecx+72] + paddsw mm4, [ecx+80] + paddsw mm6, [ecx+88] + paddsw mm1, [edx+64] + paddsw mm3, [edx+72] + paddsw mm5, [edx+80] + paddsw mm7, [edx+88] + + paddsw mm0, mm1 + movq [edi+64], mm0 + paddsw mm2, mm3 + movq [edi+72], mm2 + paddsw mm4, mm5 + movq [edi+80], mm4 + paddsw mm6, mm5 + movq [edi+88], mm7 + + movq mm0, [eax+96] + movq mm2, [eax+104] + movq mm4, [eax+112] + movq mm6, [eax+120] + movq mm1, [ebx+96] + movq mm3, [ebx+104] + movq mm5, [ebx+112] + movq mm7, [ebx+120] + paddsw mm0, [ecx+96] + paddsw mm2, [ecx+104] + paddsw mm4, [ecx+112] + paddsw mm6, [ecx+120] + paddsw mm1, [edx+96] + paddsw mm3, [edx+104] + paddsw mm5, [edx+112] + paddsw mm7, [edx+120] + paddsw mm0, mm1 + movq [eax+96], mm0 + paddsw mm2, mm3 + movq [edi+104], mm2 + paddsw mm4, mm5 + movq [edi+112], mm4 + paddsw mm6, mm7 + movq [edi+120], mm6 + ret + +end if diff --git a/kernel/trunk/drivers/mix_sse2.inc b/kernel/trunk/drivers/mix_sse2.inc index aa450a61f..c4340a4b8 100644 --- a/kernel/trunk/drivers/mix_sse2.inc +++ b/kernel/trunk/drivers/mix_sse2.inc @@ -1,145 +1,145 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -if used mmx128_mix_2 - -align 4 -mmx128_mix_2: - prefetcht1 [eax+128] - prefetcht1 [ebx+128] - - movaps xmm0, [eax] - movaps xmm1, [eax+16] - movaps xmm2, [eax+32] - movaps xmm3, [eax+48] - movaps xmm4, [eax+64] - movaps xmm5, [eax+80] - movaps xmm6, [eax+96] - movaps xmm7, [eax+112] - - paddsw xmm0, [ebx] - movaps [edi], xmm0 - paddsw xmm1,[ebx+16] - movaps [edi+16], xmm1 - paddsw xmm2, [ebx+32] - movaps [edi+32], xmm2 - paddsw xmm3, [ebx+48] - movaps [edi+48], xmm3 - paddsw xmm4, [ebx+64] - movaps [edi+64], xmm4 - paddsw xmm5, [ebx+80] - movaps [edi+80], xmm5 - paddsw xmm6, [ebx+96] - movaps [edi+96], xmm6 - paddsw xmm7, [ebx+112] - movaps [edi+112], xmm7 - ret - -align 4 -mmx128_mix_3: - prefetcht1 [eax+128] - prefetcht1 [ebx+128] - prefetcht1 [ecx+128] - - movaps xmm0, [eax] - movaps xmm1, [eax+16] - movaps xmm2, [eax+32] - movaps xmm3, [eax+48] - movaps xmm4, [eax+64] - movaps xmm5, [eax+80] - movaps xmm6, [eax+96] - movaps xmm7, [eax+112] - - paddsw xmm0, [ebx] - paddsw xmm1, [ebx+16] - paddsw xmm2, [ebx+32] - paddsw xmm3, [ebx+48] - paddsw xmm4, [ebx+64] - paddsw xmm5, [ebx+80] - paddsw xmm6, [ebx+96] - paddsw xmm7, [ebx+112] - - paddsw xmm0, [ecx] - movaps [edi], xmm0 - paddsw xmm1, [ecx+16] - movaps [edi+16], xmm1 - paddsw xmm2, [ecx+32] - movaps [edi+32], xmm2 - paddsw xmm3, [ecx+48] - movaps [edi+48], xmm3 - paddsw xmm4, [ecx+64] - movaps [edi+64], xmm4 - paddsw xmm5, [ecx+80] - movaps [edi+80], xmm5 - paddsw xmm6, [ecx+96] - movaps [edi+96], xmm6 - paddsw xmm7, [ecx+112] - movaps [edi+112], xmm7 - ret - -align 4 -mmx128_mix_4: - prefetcht1 [eax+128] - prefetcht1 [ebx+128] - prefetcht1 [ecx+128] - prefetcht1 [edx+128] - - movaps xmm0, [eax] - movaps xmm2, [eax+16] - movaps xmm4, [eax+32] - movaps xmm6, [eax+48] - movaps xmm1, [ebx] - movaps xmm3, [ebx+16] - movaps xmm5, [ebx+32] - movaps xmm7, [ebx+48] - - paddsw xmm0, [ecx] - paddsw xmm2, [ecx+16] - paddsw xmm4, [ecx+32] - paddsw xmm6, [ecx+48] - paddsw xmm1, [edx] - paddsw xmm3, [edx+16] - paddsw xmm5, [edx+32] - paddsw xmm7, [edx+48] - - paddsw xmm0, xmm1 - movaps [edi], xmm0 - paddsw xmm2, xmm3 - movaps [edi+16], xmm2 - paddsw xmm4, xmm5 - movaps [edi+32], xmm4 - paddsw xmm6, xmm7 - movaps [edi+48], xmm6 - - movaps xmm0, [eax+64] - movaps xmm2, [eax+80] - movaps xmm4, [eax+96] - movaps xmm6, [eax+112] - - movaps xmm1, [ebx+64] - movaps xmm3, [ebx+80] - movaps xmm5, [ebx+96] - movaps xmm7, [ebx+112] - paddsw xmm0, [ecx+64] - paddsw xmm2, [ecx+80] - paddsw xmm4, [ecx+96] - paddsw xmm6, [ecx+112] - - paddsw xmm1, [edx+64] - paddsw xmm3, [edx+80] - paddsw xmm5, [edx+96] - paddsw xmm7, [edx+112] - paddsw xmm0, xmm1 - movaps [edi+64], xmm0 - paddsw xmm2, xmm3 - movaps [edi+80], xmm2 - paddsw xmm4, xmm5 - movaps [edi+96], xmm4 - paddsw xmm6, xmm7 - movaps [edi+112], xmm6 - ret -end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +if used mmx128_mix_2 + +align 4 +mmx128_mix_2: + prefetcht1 [eax+128] + prefetcht1 [ebx+128] + + movaps xmm0, [eax] + movaps xmm1, [eax+16] + movaps xmm2, [eax+32] + movaps xmm3, [eax+48] + movaps xmm4, [eax+64] + movaps xmm5, [eax+80] + movaps xmm6, [eax+96] + movaps xmm7, [eax+112] + + paddsw xmm0, [ebx] + movaps [edi], xmm0 + paddsw xmm1, [ebx+16] + movaps [edi+16], xmm1 + paddsw xmm2, [ebx+32] + movaps [edi+32], xmm2 + paddsw xmm3, [ebx+48] + movaps [edi+48], xmm3 + paddsw xmm4, [ebx+64] + movaps [edi+64], xmm4 + paddsw xmm5, [ebx+80] + movaps [edi+80], xmm5 + paddsw xmm6, [ebx+96] + movaps [edi+96], xmm6 + paddsw xmm7, [ebx+112] + movaps [edi+112], xmm7 + ret + +align 4 +mmx128_mix_3: + prefetcht1 [eax+128] + prefetcht1 [ebx+128] + prefetcht1 [ecx+128] + + movaps xmm0, [eax] + movaps xmm1, [eax+16] + movaps xmm2, [eax+32] + movaps xmm3, [eax+48] + movaps xmm4, [eax+64] + movaps xmm5, [eax+80] + movaps xmm6, [eax+96] + movaps xmm7, [eax+112] + + paddsw xmm0, [ebx] + paddsw xmm1, [ebx+16] + paddsw xmm2, [ebx+32] + paddsw xmm3, [ebx+48] + paddsw xmm4, [ebx+64] + paddsw xmm5, [ebx+80] + paddsw xmm6, [ebx+96] + paddsw xmm7, [ebx+112] + + paddsw xmm0, [ecx] + movaps [edi], xmm0 + paddsw xmm1, [ecx+16] + movaps [edi+16], xmm1 + paddsw xmm2, [ecx+32] + movaps [edi+32], xmm2 + paddsw xmm3, [ecx+48] + movaps [edi+48], xmm3 + paddsw xmm4, [ecx+64] + movaps [edi+64], xmm4 + paddsw xmm5, [ecx+80] + movaps [edi+80], xmm5 + paddsw xmm6, [ecx+96] + movaps [edi+96], xmm6 + paddsw xmm7, [ecx+112] + movaps [edi+112], xmm7 + ret + +align 4 +mmx128_mix_4: + prefetcht1 [eax+128] + prefetcht1 [ebx+128] + prefetcht1 [ecx+128] + prefetcht1 [edx+128] + + movaps xmm0, [eax] + movaps xmm2, [eax+16] + movaps xmm4, [eax+32] + movaps xmm6, [eax+48] + movaps xmm1, [ebx] + movaps xmm3, [ebx+16] + movaps xmm5, [ebx+32] + movaps xmm7, [ebx+48] + + paddsw xmm0, [ecx] + paddsw xmm2, [ecx+16] + paddsw xmm4, [ecx+32] + paddsw xmm6, [ecx+48] + paddsw xmm1, [edx] + paddsw xmm3, [edx+16] + paddsw xmm5, [edx+32] + paddsw xmm7, [edx+48] + + paddsw xmm0, xmm1 + movaps [edi], xmm0 + paddsw xmm2, xmm3 + movaps [edi+16], xmm2 + paddsw xmm4, xmm5 + movaps [edi+32], xmm4 + paddsw xmm6, xmm7 + movaps [edi+48], xmm6 + + movaps xmm0, [eax+64] + movaps xmm2, [eax+80] + movaps xmm4, [eax+96] + movaps xmm6, [eax+112] + + movaps xmm1, [ebx+64] + movaps xmm3, [ebx+80] + movaps xmm5, [ebx+96] + movaps xmm7, [ebx+112] + paddsw xmm0, [ecx+64] + paddsw xmm2, [ecx+80] + paddsw xmm4, [ecx+96] + paddsw xmm6, [ecx+112] + + paddsw xmm1, [edx+64] + paddsw xmm3, [edx+80] + paddsw xmm5, [edx+96] + paddsw xmm7, [edx+112] + paddsw xmm0, xmm1 + movaps [edi+64], xmm0 + paddsw xmm2, xmm3 + movaps [edi+80], xmm2 + paddsw xmm4, xmm5 + movaps [edi+96], xmm4 + paddsw xmm6, xmm7 + movaps [edi+112], xmm6 + ret +end if diff --git a/kernel/trunk/drivers/mixer.asm b/kernel/trunk/drivers/mixer.asm index 8feb37703..e6b608247 100644 --- a/kernel/trunk/drivers/mixer.asm +++ b/kernel/trunk/drivers/mixer.asm @@ -1,1266 +1,1266 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; (C) copyright Serge 2006 -; email: infinity_sound@mail.ru - - -align 4 - -mix_list rd 32*3 - -align 4 -proc new_mix stdcall, output:dword - locals - main_count rd 1 - fpu_state rb 528 ;512+16 - endl - - mov [main_count], 32 - call prepare_playlist - cmp [play_count], 0 - je .clear - - lea eax, [fpu_state+16] - and eax, -16 ;must be 16b aligned - call FpuSave - - call update_streams -.mix: - lea eax, [mix_list] - call do_mix_list - test eax, eax - je .done - -if USE_SSE2_MIXER - - cmp eax, 1 - ja @F - ;use fast path - mov edi, [output] - lea edx, [mix_list] - call mix_fast - jmp .next -@@: - cmp eax, 2 - ja @F - - mov edi, [output] - lea edx, [mix_list] - call mix_fast_2_stream - jmp .next -@@: - -end if - - lea ebx, [mix_list] - stdcall mix_all, [output], ebx, eax -.next: - add [output], 512 - dec [main_count] - jnz .mix -.exit: - lea eax, [fpu_state+16] - and eax, -16 - call FpuRestore - ret -.done: - mov ecx, [main_count] - shl ecx, 7 ;ecx*= 512/4 - - mov edi, [output] - xor eax, eax - cld - rep stosd - jmp .exit -.clear: - mov edi, [output] - mov ecx, 4096 - xor eax, eax - cld - rep stosd - ret -endp - -align 4 -proc update_streams - locals - stream_index dd ? - event rd 6 - endl - - mov [stream_index], 0 -.l1: - mov edx, [stream_index] - mov esi, [play_list+edx*4] - - add dword [esi+STREAM.time_stamp], 4096 - adc dword [esi+STREAM.time_stamp+4], 0 - mov dword [esi+STREAM.last_ts], 0 - - mov eax, [esi+STREAM.out_rp] - cmp eax, [esi+STREAM.out_top] - jb @f - sub eax, 64*1024 -@@: - mov [esi+STREAM.out_rp], eax - - cmp [esi+STREAM.out_count], 16384 - ja .skip - - test [esi+STREAM.format], PCM_RING - jnz .ring - - stdcall refill, esi -.skip: - inc [stream_index] - dec [play_count] - jnz .l1 - ret -.ring: - stdcall refill_ring, esi - jmp .skip -endp - -align 4 -proc refill stdcall, str:dword - locals - r_size rd 1 - endl - - mov ebx, [str] - mov edi, [ebx+STREAM.out_wp] - cmp edi, [ebx+STREAM.out_top] - jb @F - sub edi, 0x10000 - mov [ebx+STREAM.out_wp], edi -@@: - mov eax, [ebx+STREAM.in_count] - test eax, eax - jz .done - - mov ecx, [ebx+STREAM.r_size] - cmp eax, ecx - jle @F - - mov eax, ecx -@@: - mov ecx, eax - cmp word [ebx+STREAM.format], PCM_1_16_8 - ja @F - - shr eax, 1 ;two channles -@@: - test [ebx+STREAM.format], 1 ;even formats mono - jz @F - - shr eax, 1 ;eax= samples -@@: - shl eax, 15 ;eax*=32768 =r_end - - mov [r_size], ecx - - mov esi, [ebx+STREAM.in_rp] - mov edi, [ebx+STREAM.out_wp] - - stdcall [ebx+STREAM.resample], edi, esi, \ - [ebx+STREAM.r_dt], ecx, eax - - mov ebx, [str] - - add [ebx+STREAM.out_count], eax; - add [ebx+STREAM.out_wp], eax; - - mov eax, [ebx+STREAM.in_rp] - mov ecx, [r_size] - add eax, ecx - add [ebx+STREAM.in_free], ecx - sub [ebx+STREAM.in_count], ecx - - cmp eax, [ebx+STREAM.in_top] - jb @f - - sub eax, [ebx+STREAM.in_size] -@@: - mov [ebx+STREAM.in_rp], eax - -.done: - mov eax, [ebx+STREAM.notify_event] - test eax, eax - jz .exit - - mov ebx, [ebx+STREAM.notify_id] - mov edx, EVENT_WATCHED - xor esi, esi - call RaiseEvent ;eax, ebx, edx, esi -.exit: - ret -endp - -align 4 -proc refill_ring stdcall, str:dword - locals - event rd 6 - endl - - mov ebx, [str] - mov edi, [ebx+STREAM.out_wp] - cmp edi, [ebx+STREAM.out_top] - jb @F - sub edi, 0x10000 - mov [ebx+STREAM.out_wp], edi -@@: - mov ecx, [ebx+STREAM.r_size] - mov eax, ecx - cmp word [ebx+STREAM.format], PCM_1_16_8 - ja @F - - shr eax, 1 ;two channles -@@: - test [ebx+STREAM.format], 1 ;even formats mono - jz @F - - shr eax, 1 ;eax= samples -@@: - shl eax, 15 ;eax*=32768 =r_end - - mov esi, [ebx+STREAM.in_rp] - mov edi, [ebx+STREAM.out_wp] - - stdcall [ebx+STREAM.resample], edi, esi, \ - [ebx+STREAM.r_dt], ecx, eax - - mov ebx, [str] - - add [ebx+STREAM.out_count], eax; - add [ebx+STREAM.out_wp], eax; - - mov eax, [ebx+STREAM.in_rp] - mov ecx, [ebx+STREAM.r_size] - add eax, ecx - add [ebx+STREAM.in_free], ecx - sub [ebx+STREAM.in_count], ecx - - cmp eax, [ebx+STREAM.in_top] - jb @f - - sub eax, [ebx+STREAM.in_size] -@@: - mov [ebx+STREAM.in_rp], eax - - sub eax, [ebx+STREAM.in_base] - sub eax, 128 - lea esi, [event] - - mov dword [esi], RT_INP_EMPTY - mov dword [esi+4], 0 - mov dword [esi+8], ebx - mov dword [esi+12], eax - - mov eax, [ebx+STREAM.notify_event] - test eax, eax - jz .exit - - mov ebx, [ebx+STREAM.notify_id] - xor edx, edx - call RaiseEvent ;eax, ebx, edx, esi -.exit: - ret -endp - -if USE_SSE2_MIXER - -align 4 -proc mix_all stdcall, dest:dword, list:dword, count:dword - - mov edi, [dest] - mov ebx, 32 -.mix: - mov edx, [list] - mov ecx, [count] - - mov eax, [edx] - - movdqa xmm1, [eax] - movss xmm2, [edx+4] - movss xmm3, [edx+8] - - punpcklwd xmm0, xmm1 - punpckhwd xmm1, xmm1 - - shufps xmm2, xmm3, 0 - shufps xmm2, xmm2, 0x88 - - psrad xmm0, 16 - psrad xmm1, 16 - cvtdq2ps xmm0, xmm0 - cvtdq2ps xmm1, xmm1 - mulps xmm0, xmm2 - mulps xmm1, xmm2 - -.mix_loop: - add dword [edx], 16 - add edx, 12 - dec ecx - jz @F - - mov eax, [edx] - - movdqa xmm3, [eax] - movss xmm4, [edx+4] - movss xmm5, [edx+8] - - punpcklwd xmm2, xmm3 - punpckhwd xmm3, xmm3 - - shufps xmm4, xmm5, 0 - shufps xmm4, xmm4, 0x88 - - psrad xmm2, 16 - psrad xmm3, 16 - - cvtdq2ps xmm2, xmm2 - cvtdq2ps xmm3, xmm3 - - mulps xmm2, xmm4 - mulps xmm3, xmm4 - addps xmm0, xmm2 - addps xmm1, xmm3 - - jmp .mix_loop -@@: - cvtps2dq xmm0, xmm0 - cvtps2dq xmm1, xmm1 - packssdw xmm0, xmm0 - packssdw xmm1, xmm1 - punpcklqdq xmm0, xmm1 - movntdq [edi], xmm0 - - add edi, 16 - dec ebx - jnz .mix - - ret -endp - -; param -; edi = dest -; edx = mix_list - -align 4 -mix_fast: - - mov ebx, 32 - mov eax, [edx] - - movss xmm2, [edx+4] ; vol Lf - movss xmm3, [edx+8] ; vol Rf - shufps xmm2, xmm3, 0 ; Rf Rf Lf Lf - shufps xmm2, xmm2, 0x88 ; volume level Rf Lf Rf Lf -.mix: - movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w - add eax, 16 - punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w - punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w - - psrad xmm0, 16 ; R1d L1d R0d L0d - psrad xmm1, 16 ; R3d L3d R2d L2d - - cvtdq2ps xmm0, xmm0 ; time to use all power - cvtdq2ps xmm1, xmm1 ; of the dark side - - mulps xmm0, xmm2 ; R1f' L1f' R0f' L0f' - mulps xmm1, xmm2 ; R3f' L3f' R2f' L2f' - - cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' - cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' - packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' - packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' - punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' - movntdq [edi], xmm0 - - add edi, 16 - dec ebx - jnz .mix - - ret - -align 4 -mix_fast_2_stream: - - mov ebx, 32 - mov eax, [edx] - - movss xmm4, [edx+4] ; vol Lf - movss xmm5, [edx+8] ; vol Rf - mov ecx, [edx+12] - - movss xmm6, [edx+16] ; vol Lf - movss xmm7, [edx+20] ; vol Rf - - shufps xmm4, xmm5, 0 ; Rf Rf Lf Lf - shufps xmm4, xmm4, 0x88 ; volume level Rf Lf Rf Lf - - shufps xmm6, xmm7, 0 ; Rf Rf Lf Lf - shufps xmm6, xmm6, 0x88 ; volume level Rf Lf Rf Lf - -.mix: - movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w - movdqa xmm3, [ecx] ; R3w L3w R2w L2w R1w L1w R0w L0w - - add eax, 16 - add ecx, 16 - - punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w - punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w - - psrad xmm0, 16 ; R1d L1d R0d L0d - psrad xmm1, 16 ; R3d L3d R2d L2d - - cvtdq2ps xmm0, xmm0 ; time to use all power - cvtdq2ps xmm1, xmm1 ; of the dark side - - mulps xmm0, xmm4 ; R1f' L1f' R0f' L0f' - mulps xmm1, xmm4 ; R3f' L3f' R2f' L2f' - - punpcklwd xmm2, xmm3 ; R1w R1w L1w L1W R0w R0w L0w L0w - punpckhwd xmm3, xmm3 ; R3w R3w L3w L3w R2w R2w L2w L2w - - psrad xmm2, 16 ; R1d L1d R0d L0d - psrad xmm3, 16 ; R3d L3d R2d L2d - - cvtdq2ps xmm2, xmm2 ; time to use all power - cvtdq2ps xmm3, xmm3 ; of the dark side - - mulps xmm2, xmm6 ; R1f' L1f' R0f' L0f' - mulps xmm3, xmm6 ; R3f' L3f' R2f' L2f' - - addps xmm0, xmm2 - addps xmm1, xmm3 - - cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' - cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' - packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' - packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' - punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' - movntdq [edi], xmm0 - - add edi, 16 - dec ebx - jnz .mix - - ret - -else ; fixed point mmx version - -align 4 -proc mix_all stdcall, dest:dword, list:dword, count:dword - - mov edi, [dest] - mov ebx, 64 -.mix: - mov edx, [list] - mov ecx, [count] - - mov eax, [edx] - - movq mm0, [eax] - - movd mm1, [edx+4] - punpckldq mm1,mm1 - pmulhw mm0, mm1 - psllw mm0, 1 - -.mix_loop: - add dword [edx], 8 - add edx, 12 - dec ecx - jz @F - - mov eax, [edx] - movq mm1, [eax] - movd mm2, [edx+4] - punpckldq mm2,mm2 - pmulhw mm1, mm2 - psllw mm1, 1 - paddsw mm0, mm1 - jmp .mix_loop -@@: - movq [edi], mm0 - add edi, 8 - dec ebx - jnz .mix - - ret -endp - -end if - - -align 4 -proc resample_1 stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - -; dest equ esp+8 -; src equ esp+12 -; r_dt equ esp+16 -; r_size equ esp+20 -; r_end equ esp+24 - - mov edi, [dest] - mov edx, [src] - sub edx, 32*2 - mov eax, 16 - -align 4 -.l1: - mov ecx, eax - mov esi, eax - and ecx, 0x7FFF - shr esi, 15 - lea esi, [edx+esi*2] - - movsx ebp, word [esi] - movsx esi, word [esi+2] - mov ebx, 32768 - imul esi, ecx - sub ebx, ecx - imul ebx, ebp - lea ecx, [ebx+esi+16384] - sar ecx, 15 - cmp ecx, 32767 ; 00007fffH - jle @f - mov ecx, 32767 ; 00007fffH - jmp .write -@@: - cmp ecx, -32768 ; ffff8000H - jge .write - mov ecx, -32768 ; ffff8000H -.write: - mov ebx, ecx - shl ebx, 16 - mov bx, cx - mov [edi], ebx - add edi, 4 - - add eax, [esp+16] - cmp eax, [esp+24] - jb .l1 - - mov ebp, esp - - sub edi, [dest] - mov eax, edi - ret -endp - -align 4 -proc resample_18 stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - - - mov edi, [dest] - mov edx, [src] - sub edx, 32 - - mov esi, 16 - -align 4 -.l1: - mov ecx, esi - mov eax, esi - and ecx, 0x7FFF - shr eax, 15 - lea eax, [edx+eax] - - mov bx, word [eax] - sub bh, 0x80 - sub bl, 0x80 - movsx eax, bh - shl eax,8 - movsx ebp, bl - shl ebp,8 - mov ebx, 32768 - imul eax, ecx - sub ebx, ecx - imul ebx, ebp - lea ecx, [ebx+eax+16384] - sar ecx, 15 - cmp ecx, 32767 ; 00007fffH - jle @f - mov ecx, 32767 ; 00007fffH - jmp .write -@@: - cmp ecx, -32768 ; ffff8000H - jge .write - mov ecx, -32768 ; ffff8000H -.write: - mov ebx, ecx - shl ebx, 16 - mov bx, cx - mov [edi], ebx - add edi, 4 - - add esi, [esp+16] - cmp esi, [esp+24] - jb .l1 - - mov ebp, esp - sub edi, [dest] - mov eax, edi - ret -endp - -align 4 -proc copy_stream stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - - mov ecx, [r_size] - mov eax, ecx - shr ecx, 2 - mov esi, [src] - mov edi, [dest] - cld - rep movsd - ret -endp - -align 4 -proc resample_2 stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - - mov edx, [src] - sub edx, 32*4 - mov edi, [dest] - mov ebx, [r_dt] - mov eax, 16 - emms - -align 4 -.l1: - mov ecx, eax - mov esi, eax - and ecx, 0x7FFF - shr esi, 15 - lea esi, [edx+esi*4] - - movq mm0, [esi] - movq mm1, mm0 - - movd mm2, ecx - punpcklwd mm2, mm2 - movq mm3, qword [m7] ;0x8000 - - psubw mm3, mm2 ; ;0x8000 - iconst - punpckldq mm3, mm2 - - pmulhw mm0, mm3 - pmullw mm1, mm3 - - movq mm4, mm1 - punpcklwd mm1, mm0 - punpckhwd mm4, mm0 - paddd mm1, mm4 - psrad mm1, 15 - packssdw mm1, mm1 - movd [edi], mm1 - add edi, 4 - - add eax, ebx - cmp eax, [r_end] - jb .l1 - emms - - sub edi, [dest] - mov eax, edi - ret -endp - -align 4 -proc resample_28 stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - - mov edx, [src] - sub edx, 32*2 - mov edi, [dest] - mov ebx, [r_dt] - mov eax, 16 - emms - movq mm7,[mm80] - movq mm6,[mm_mask] - -align 4 -.l1: - mov ecx, eax - mov esi, eax - and ecx, 0x7FFF - shr esi, 15 - lea esi, [edx+esi*2] - - movq mm0, [esi] - psubb mm0,mm7 - punpcklbw mm0,mm0 - pand mm0,mm6 - - movq mm1, mm0 - - movd mm2, ecx - punpcklwd mm2, mm2 - movq mm3, qword [m7] ; // 0x8000 - - psubw mm3, mm2 ; // 0x8000 - iconst - punpckldq mm3, mm2 - - pmulhw mm0, mm3 - pmullw mm1, mm3 - - movq mm4, mm1 - punpcklwd mm1, mm0 - punpckhwd mm4, mm0 - paddd mm1, mm4 - psrad mm1, 15 - packssdw mm1, mm1 - movd [edi], mm1 - add edi, 4 - - add eax, ebx - cmp eax, [r_end] - jb .l1 - emms - - - sub edi, [dest] - mov eax, edi - ret -endp - - -proc m16_stereo stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - - mov esi, [src] - mov edi, [dest] - mov ecx, [r_size] - shr ecx,8 -@@: - call m16_s_mmx - add edi, 128 - add esi, 64 - call m16_s_mmx - add edi, 128 - add esi, 64 - call m16_s_mmx - add edi, 128 - add esi, 64 - call m16_s_mmx - add edi, 128 - add esi, 64 - dec ecx - jnz @b - - mov eax, [r_size] - add eax, eax - ret -endp - -align 4 -proc s8_stereo stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - - mov esi, [src] - mov edi, [dest] - mov ecx, [r_size] - shr ecx, 7 - - movq mm7, [mm80] - movq mm6, [mm_mask] -@@: - call s8_s_mmx - add edi, 64 - add esi, 32 - call s8_s_mmx - add edi, 64 - add esi, 32 - call s8_s_mmx - add edi, 64 - add esi, 32 - call s8_s_mmx - add edi, 64 - add esi, 32 - dec ecx - jnz @b - - mov eax, [r_size] - add eax, eax - ret -endp - -proc m8_stereo stdcall, dest:dword,src:dword,\ - r_dt:dword, r_size:dword,r_end:dword - - mov esi, [src] - mov edi, [dest] - mov ecx, [r_size] - shr ecx, 6 - - movq mm7, [mm80] - movq mm6, [mm_mask] -@@: - call m8_s_mmx - add edi, 64 - add esi, 16 - call m8_s_mmx - add edi, 64 - add esi, 16 - call m8_s_mmx - add edi, 64 - add esi, 16 - call m8_s_mmx - add edi, 64 - add esi, 16 - dec ecx - jnz @b - - mov eax, [r_size] - add eax, eax - add eax, eax - ret -endp - -align 4 -proc alloc_mix_buff - - bsf eax, [mix_buff_map] - jnz .find - xor eax, eax - ret -.find: - btr [mix_buff_map], eax - shl eax, 9 - add eax, [mix_buff] - ret -endp - -align 4 -proc m16_s_mmx - - movq mm0, [esi] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi], mm0 - movq [edi+8], mm1 - - movq mm0, [esi+8] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi+16], mm0 - movq [edi+24], mm1 - - movq mm0, [esi+16] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi+32], mm0 - movq [edi+40], mm1 - - movq mm0, [esi+24] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi+48], mm0 - movq [edi+56], mm1 - - movq mm0, [esi+32] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi+64], mm0 - movq [edi+72], mm1 - - movq mm0, [esi+40] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi+80], mm0 - movq [edi+88], mm1 - - - movq mm0, [esi+48] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi+96], mm0 - movq [edi+104], mm1 - - movq mm0, [esi+56] - movq mm1, mm0 - punpcklwd mm0, mm0 - punpckhwd mm1, mm1 - movq [edi+112], mm0 - movq [edi+120], mm1 - - ret -endp - -align 4 -proc s8_s_mmx - - movq mm0, [esi] - psubb mm0, mm7 - movq mm1, mm0 - punpcklbw mm0, mm0 - pand mm0, mm6 - punpckhbw mm1, mm1 - pand mm1, mm6 - movq [edi], mm0 - movq [edi+8], mm1 - - movq mm0, [esi+8] - psubb mm0, mm7 - movq mm1, mm0 - punpcklbw mm0, mm0 - pand mm0, mm6 - punpckhbw mm1, mm1 - pand mm1, mm6 - movq [edi+16], mm0 - movq [edi+24], mm1 - - movq mm0, [esi+16] - psubb mm0, mm7 - movq mm1, mm0 - punpcklbw mm0, mm0 - pand mm0, mm6 - punpckhbw mm1, mm1 - pand mm1, mm6 - movq [edi+32], mm0 - movq [edi+40], mm1 - - movq mm0, [esi+24] - psubb mm0, mm7 - movq mm1, mm0 - punpcklbw mm0, mm0 - pand mm0, mm6 - punpckhbw mm1, mm1 - pand mm1, mm6 - movq [edi+48], mm0 - movq [edi+56], mm1 - - ret - -endp - -align 4 -proc m8_s_mmx - - movq mm0, [esi] - psubb mm0, mm7 - movq mm1, mm0 - punpcklbw mm0, mm0 - pand mm0, mm6 - punpckhbw mm1, mm1 - pand mm1, mm6 - movq mm2, mm0 - punpcklwd mm0, mm0 - punpckhwd mm2, mm2 - - movq mm3, mm1 - punpcklwd mm1, mm1 - punpckhwd mm3, mm3 - - movq [edi], mm0 - movq [edi+8], mm2 - movq [edi+16], mm1 - movq [edi+24], mm3 - - movq mm0, [esi+8] - psubb mm0, mm7 - movq mm1, mm0 - punpcklbw mm0, mm0 - pand mm0, mm6 - punpckhbw mm1, mm1 - pand mm1, mm6 - movq mm2, mm0 - punpcklwd mm0, mm0 - punpckhwd mm2, mm2 - - movq mm3, mm1 - punpcklwd mm1, mm1 - punpckhwd mm3, mm3 - - movq [edi+32], mm0 - movq [edi+40], mm2 - movq [edi+48], mm1 - movq [edi+56], mm3 - - ret -endp - -align 4 -proc mix_2_1 stdcall, output:dword, str0:dword, str1:dword - - mov edi, [output] - mov eax, [str0] - mov ebx, [str1] - mov esi, 128 - call [mix_2_core] ;edi, eax, ebx - - add edi, esi - add eax, esi - add ebx, esi - call [mix_2_core] ;edi, eax, ebx - - add edi, esi - add eax, esi - add ebx, esi - call [mix_2_core] ;edi, eax, ebx - - add edi, esi - add eax, esi - add ebx, esi - call [mix_2_core] ;edi, eax, ebx - ret -endp - -align 4 -proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword - - mov edi, [output] - mov eax, [str0] - mov ebx, [str1] - mov ecx, [str2] - mov esi, 128 - call [mix_3_core] - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - call [mix_3_core] - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - call [mix_3_core] - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - call [mix_3_core] - ret -endp - -align 4 -proc mix_4_1 stdcall, str0:dword, str1:dword,\ - str2:dword, str3:dword - - local output:DWORD - - call alloc_mix_buff - and eax, eax - jz .err - - mov [output], eax - - mov edi, eax - mov eax, [str0] - mov ebx, [str1] - mov ecx, [str2] - mov edx, [str3] - mov esi, 128 - call [mix_4_core] ;edi, eax, ebx, ecx, edx - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - add edx, esi - call [mix_4_core] ;edi, eax, ebx, ecx, edx - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - add edx, esi - call [mix_4_core] ;edi, eax, ebx, ecx, edx - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - add edx, esi - call [mix_4_core] ;edi, eax, ebx, ecx, edx - mov eax, [output] - ret -.err: - xor eax, eax - ret -endp - - -align 4 -proc final_mix stdcall, output:dword, str0:dword, str1:dword,\ - str2:dword, str3:dword - - mov edi, [output] - - mov eax, [str0] - mov ebx, [str1] - mov ecx, [str2] - mov edx, [str3] - mov esi, 128 - call [mix_4_core] ;edi, eax, ebx, ecx, edx - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - add edx, esi - call [mix_4_core] ;edi, eax, ebx, ecx, edx - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - add edx, esi - call [mix_4_core] ;edi, eax, ebx, ecx, edx - - add edi, esi - add eax, esi - add ebx, esi - add ecx, esi - add edx, esi - call [mix_4_core] ;edi, eax, ebx, ecx, edx - ret -endp - -align 4 -proc copy_mem stdcall, output:dword, input:dword - - mov edi, [output] - mov esi, [input] - mov ecx, 0x80 -.l1: - mov eax, [esi] - mov [edi], eax - add esi, 4 - add edi, 4 - loop .l1 - - ret -endp - -proc memcpy -@@: - mov eax, [esi] - mov [edi], eax - add esi, 4 - add edi, 4 - dec ecx - jnz @B - ret -endp - -if 0 - -align 4 -proc new_mix stdcall, output:dword - locals - mixCounter dd ? - mixIndex dd ? - streamIndex dd ? - inputCount dd ? - main_count dd ? - blockCount dd ? - mix_out dd ? - endl - - call prepare_playlist - - cmp [play_count], 0 - je .exit - call FpuSave - mov [main_count], 32; -.l00: - mov [mix_buff_map], 0x0000FFFF; - xor eax, eax - mov [mixCounter], eax - mov [mixIndex],eax - mov [streamIndex], eax; - mov ebx, [play_count] - mov [inputCount], ebx -.l0: - mov ecx, 4 -.l1: - mov ebx, [streamIndex] - mov esi, [play_list+ebx*4] - mov eax, [esi+STREAM.work_read] - add [esi+STREAM.work_read], 512 - - mov ebx, [mixIndex] - mov [mix_input+ebx*4], eax - inc [mixCounter] - inc [mixIndex] - inc [streamIndex] - dec [inputCount] - jz .m2 - - dec ecx - jnz .l1 - - cmp [mixCounter], 4 - jnz .m2 - - stdcall mix_4_1, [mix_input],[mix_input+4],[mix_input+8],[mix_input+12] - sub [mixIndex],4 - mov ebx, [mixIndex] - mov [mix_input+ebx*4], eax - inc [mixIndex] - mov [mixCounter], 0 - - cmp [inputCount], 0 - jnz .l0 -.m2: - cmp [mixIndex], 1 - jne @f - stdcall copy_mem, [output], [mix_input] - jmp .m3 -@@: - cmp [mixIndex], 2 - jne @f - stdcall mix_2_1, [output], [mix_input], [mix_input+4] - jmp .m3 -@@: - cmp [mixIndex], 3 - jne @f - stdcall mix_3_1, [output],[mix_input],[mix_input+4],[mix_input+8] - jmp .m3 -@@: - stdcall final_mix, [output],[mix_input],[mix_input+4],[mix_input+8], [mix_input+12] -.m3: - add [output],512 - - dec [main_count] - jnz .l00 - - call update_stream - emms - call FpuRestore - ret -.exit: - mov edi, [output] - mov ecx, 0x1000 - xor eax, eax - cld - rep stosd - ret -endp - -end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; (C) copyright Serge 2006 +; email: infinity_sound@mail.ru + + +align 4 + +mix_list rd 32*3 + +align 4 +proc new_mix stdcall, output:dword + locals + main_count rd 1 + fpu_state rb 528 ;512+16 + endl + + mov [main_count], 32 + call prepare_playlist + cmp [play_count], 0 + je .clear + + lea eax, [fpu_state+16] + and eax, -16 ;must be 16b aligned + call FpuSave + + call update_streams +.mix: + lea eax, [mix_list] + call do_mix_list + test eax, eax + je .done + +if USE_SSE2_MIXER + + cmp eax, 1 + ja @F + ;use fast path + mov edi, [output] + lea edx, [mix_list] + call mix_fast + jmp .next +@@: + cmp eax, 2 + ja @F + + mov edi, [output] + lea edx, [mix_list] + call mix_fast_2_stream + jmp .next +@@: + +end if + + lea ebx, [mix_list] + stdcall mix_all, [output], ebx, eax +.next: + add [output], 512 + dec [main_count] + jnz .mix +.exit: + lea eax, [fpu_state+16] + and eax, -16 + call FpuRestore + ret +.done: + mov ecx, [main_count] + shl ecx, 7 ;ecx*= 512/4 + + mov edi, [output] + xor eax, eax + cld + rep stosd + jmp .exit +.clear: + mov edi, [output] + mov ecx, 4096 + xor eax, eax + cld + rep stosd + ret +endp + +align 4 +proc update_streams + locals + stream_index dd ? + event rd 6 + endl + + mov [stream_index], 0 +.l1: + mov edx, [stream_index] + mov esi, [play_list+edx*4] + + add dword [esi+STREAM.time_stamp], 4096 + adc dword [esi+STREAM.time_stamp+4], 0 + mov dword [esi+STREAM.last_ts], 0 + + mov eax, [esi+STREAM.out_rp] + cmp eax, [esi+STREAM.out_top] + jb @f + sub eax, 64*1024 +@@: + mov [esi+STREAM.out_rp], eax + + cmp [esi+STREAM.out_count], 16384 + ja .skip + + test [esi+STREAM.format], PCM_RING + jnz .ring + + stdcall refill, esi +.skip: + inc [stream_index] + dec [play_count] + jnz .l1 + ret +.ring: + stdcall refill_ring, esi + jmp .skip +endp + +align 4 +proc refill stdcall, str:dword + locals + r_size rd 1 + endl + + mov ebx, [str] + mov edi, [ebx+STREAM.out_wp] + cmp edi, [ebx+STREAM.out_top] + jb @F + sub edi, 0x10000 + mov [ebx+STREAM.out_wp], edi +@@: + mov eax, [ebx+STREAM.in_count] + test eax, eax + jz .done + + mov ecx, [ebx+STREAM.r_size] + cmp eax, ecx + jle @F + + mov eax, ecx +@@: + mov ecx, eax + cmp word [ebx+STREAM.format], PCM_1_16_8 + ja @F + + shr eax, 1 ;two channles +@@: + test [ebx+STREAM.format], 1 ;even formats mono + jz @F + + shr eax, 1 ;eax= samples +@@: + shl eax, 15 ;eax*=32768 =r_end + + mov [r_size], ecx + + mov esi, [ebx+STREAM.in_rp] + mov edi, [ebx+STREAM.out_wp] + + stdcall [ebx+STREAM.resample], edi, esi, \ + [ebx+STREAM.r_dt], ecx, eax + + mov ebx, [str] + + add [ebx+STREAM.out_count], eax; + add [ebx+STREAM.out_wp], eax; + + mov eax, [ebx+STREAM.in_rp] + mov ecx, [r_size] + add eax, ecx + add [ebx+STREAM.in_free], ecx + sub [ebx+STREAM.in_count], ecx + + cmp eax, [ebx+STREAM.in_top] + jb @f + + sub eax, [ebx+STREAM.in_size] +@@: + mov [ebx+STREAM.in_rp], eax + +.done: + mov eax, [ebx+STREAM.notify_event] + test eax, eax + jz .exit + + mov ebx, [ebx+STREAM.notify_id] + mov edx, EVENT_WATCHED + xor esi, esi + call RaiseEvent ;eax, ebx, edx, esi +.exit: + ret +endp + +align 4 +proc refill_ring stdcall, str:dword + locals + event rd 6 + endl + + mov ebx, [str] + mov edi, [ebx+STREAM.out_wp] + cmp edi, [ebx+STREAM.out_top] + jb @F + sub edi, 0x10000 + mov [ebx+STREAM.out_wp], edi +@@: + mov ecx, [ebx+STREAM.r_size] + mov eax, ecx + cmp word [ebx+STREAM.format], PCM_1_16_8 + ja @F + + shr eax, 1 ;two channles +@@: + test [ebx+STREAM.format], 1 ;even formats mono + jz @F + + shr eax, 1 ;eax= samples +@@: + shl eax, 15 ;eax*=32768 =r_end + + mov esi, [ebx+STREAM.in_rp] + mov edi, [ebx+STREAM.out_wp] + + stdcall [ebx+STREAM.resample], edi, esi, \ + [ebx+STREAM.r_dt], ecx, eax + + mov ebx, [str] + + add [ebx+STREAM.out_count], eax; + add [ebx+STREAM.out_wp], eax; + + mov eax, [ebx+STREAM.in_rp] + mov ecx, [ebx+STREAM.r_size] + add eax, ecx + add [ebx+STREAM.in_free], ecx + sub [ebx+STREAM.in_count], ecx + + cmp eax, [ebx+STREAM.in_top] + jb @f + + sub eax, [ebx+STREAM.in_size] +@@: + mov [ebx+STREAM.in_rp], eax + + sub eax, [ebx+STREAM.in_base] + sub eax, 128 + lea esi, [event] + + mov dword [esi], RT_INP_EMPTY + mov dword [esi+4], 0 + mov dword [esi+8], ebx + mov dword [esi+12], eax + + mov eax, [ebx+STREAM.notify_event] + test eax, eax + jz .exit + + mov ebx, [ebx+STREAM.notify_id] + xor edx, edx + call RaiseEvent ;eax, ebx, edx, esi +.exit: + ret +endp + +if USE_SSE2_MIXER + +align 4 +proc mix_all stdcall, dest:dword, list:dword, count:dword + + mov edi, [dest] + mov ebx, 32 +.mix: + mov edx, [list] + mov ecx, [count] + + mov eax, [edx] + + movdqa xmm1, [eax] + movss xmm2, [edx+4] + movss xmm3, [edx+8] + + punpcklwd xmm0, xmm1 + punpckhwd xmm1, xmm1 + + shufps xmm2, xmm3, 0 + shufps xmm2, xmm2, 0x88 + + psrad xmm0, 16 + psrad xmm1, 16 + cvtdq2ps xmm0, xmm0 + cvtdq2ps xmm1, xmm1 + mulps xmm0, xmm2 + mulps xmm1, xmm2 + +.mix_loop: + add dword [edx], 16 + add edx, 12 + dec ecx + jz @F + + mov eax, [edx] + + movdqa xmm3, [eax] + movss xmm4, [edx+4] + movss xmm5, [edx+8] + + punpcklwd xmm2, xmm3 + punpckhwd xmm3, xmm3 + + shufps xmm4, xmm5, 0 + shufps xmm4, xmm4, 0x88 + + psrad xmm2, 16 + psrad xmm3, 16 + + cvtdq2ps xmm2, xmm2 + cvtdq2ps xmm3, xmm3 + + mulps xmm2, xmm4 + mulps xmm3, xmm4 + addps xmm0, xmm2 + addps xmm1, xmm3 + + jmp .mix_loop +@@: + cvtps2dq xmm0, xmm0 + cvtps2dq xmm1, xmm1 + packssdw xmm0, xmm0 + packssdw xmm1, xmm1 + punpcklqdq xmm0, xmm1 + movntdq [edi], xmm0 + + add edi, 16 + dec ebx + jnz .mix + + ret +endp + +; param +; edi = dest +; edx = mix_list + +align 4 +mix_fast: + + mov ebx, 32 + mov eax, [edx] + + movss xmm2, [edx+4] ; vol Lf + movss xmm3, [edx+8] ; vol Rf + shufps xmm2, xmm3, 0 ; Rf Rf Lf Lf + shufps xmm2, xmm2, 0x88 ; volume level Rf Lf Rf Lf +.mix: + movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w + add eax, 16 + punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w + punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w + + psrad xmm0, 16 ; R1d L1d R0d L0d + psrad xmm1, 16 ; R3d L3d R2d L2d + + cvtdq2ps xmm0, xmm0 ; time to use all power + cvtdq2ps xmm1, xmm1 ; of the dark side + + mulps xmm0, xmm2 ; R1f' L1f' R0f' L0f' + mulps xmm1, xmm2 ; R3f' L3f' R2f' L2f' + + cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' + cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' + packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' + packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' + punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' + movntdq [edi], xmm0 + + add edi, 16 + dec ebx + jnz .mix + + ret + +align 4 +mix_fast_2_stream: + + mov ebx, 32 + mov eax, [edx] + + movss xmm4, [edx+4] ; vol Lf + movss xmm5, [edx+8] ; vol Rf + mov ecx, [edx+12] + + movss xmm6, [edx+16] ; vol Lf + movss xmm7, [edx+20] ; vol Rf + + shufps xmm4, xmm5, 0 ; Rf Rf Lf Lf + shufps xmm4, xmm4, 0x88 ; volume level Rf Lf Rf Lf + + shufps xmm6, xmm7, 0 ; Rf Rf Lf Lf + shufps xmm6, xmm6, 0x88 ; volume level Rf Lf Rf Lf + +.mix: + movdqa xmm1, [eax] ; R3w L3w R2w L2w R1w L1w R0w L0w + movdqa xmm3, [ecx] ; R3w L3w R2w L2w R1w L1w R0w L0w + + add eax, 16 + add ecx, 16 + + punpcklwd xmm0, xmm1 ; R1w R1w L1w L1W R0w R0w L0w L0w + punpckhwd xmm1, xmm1 ; R3w R3w L3w L3w R2w R2w L2w L2w + + psrad xmm0, 16 ; R1d L1d R0d L0d + psrad xmm1, 16 ; R3d L3d R2d L2d + + cvtdq2ps xmm0, xmm0 ; time to use all power + cvtdq2ps xmm1, xmm1 ; of the dark side + + mulps xmm0, xmm4 ; R1f' L1f' R0f' L0f' + mulps xmm1, xmm4 ; R3f' L3f' R2f' L2f' + + punpcklwd xmm2, xmm3 ; R1w R1w L1w L1W R0w R0w L0w L0w + punpckhwd xmm3, xmm3 ; R3w R3w L3w L3w R2w R2w L2w L2w + + psrad xmm2, 16 ; R1d L1d R0d L0d + psrad xmm3, 16 ; R3d L3d R2d L2d + + cvtdq2ps xmm2, xmm2 ; time to use all power + cvtdq2ps xmm3, xmm3 ; of the dark side + + mulps xmm2, xmm6 ; R1f' L1f' R0f' L0f' + mulps xmm3, xmm6 ; R3f' L3f' R2f' L2f' + + addps xmm0, xmm2 + addps xmm1, xmm3 + + cvtps2dq xmm0, xmm0 ; R1d' L1d' R0d' L0d' + cvtps2dq xmm1, xmm1 ; R3d' L3d' R2d' L2d' + packssdw xmm0, xmm0 ; R1w' L1w' R0w' L0w' R1w' L1w' R0w' L0w' + packssdw xmm1, xmm1 ; R3w' L3w' R2w' L2w' R3w' L3w' R2w' L2w' + punpcklqdq xmm0, xmm1 ; R3w' L3w' R2w' L2w' R1w' L1w' R0w' L0w' + movntdq [edi], xmm0 + + add edi, 16 + dec ebx + jnz .mix + + ret + +else ; fixed point mmx version + +align 4 +proc mix_all stdcall, dest:dword, list:dword, count:dword + + mov edi, [dest] + mov ebx, 64 +.mix: + mov edx, [list] + mov ecx, [count] + + mov eax, [edx] + + movq mm0, [eax] + + movd mm1, [edx+4] + punpckldq mm1, mm1 + pmulhw mm0, mm1 + psllw mm0, 1 + +.mix_loop: + add dword [edx], 8 + add edx, 12 + dec ecx + jz @F + + mov eax, [edx] + movq mm1, [eax] + movd mm2, [edx+4] + punpckldq mm2, mm2 + pmulhw mm1, mm2 + psllw mm1, 1 + paddsw mm0, mm1 + jmp .mix_loop +@@: + movq [edi], mm0 + add edi, 8 + dec ebx + jnz .mix + + ret +endp + +end if + + +align 4 +proc resample_1 stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + +; dest equ esp+8 +; src equ esp+12 +; r_dt equ esp+16 +; r_size equ esp+20 +; r_end equ esp+24 + + mov edi, [dest] + mov edx, [src] + sub edx, 32*2 + mov eax, 16 + +align 4 +.l1: + mov ecx, eax + mov esi, eax + and ecx, 0x7FFF + shr esi, 15 + lea esi, [edx+esi*2] + + movsx ebp, word [esi] + movsx esi, word [esi+2] + mov ebx, 32768 + imul esi, ecx + sub ebx, ecx + imul ebx, ebp + lea ecx, [ebx+esi+16384] + sar ecx, 15 + cmp ecx, 32767 ; 00007fffH + jle @f + mov ecx, 32767 ; 00007fffH + jmp .write +@@: + cmp ecx, -32768 ; ffff8000H + jge .write + mov ecx, -32768 ; ffff8000H +.write: + mov ebx, ecx + shl ebx, 16 + mov bx, cx + mov [edi], ebx + add edi, 4 + + add eax, [esp+16] + cmp eax, [esp+24] + jb .l1 + + mov ebp, esp + + sub edi, [dest] + mov eax, edi + ret +endp + +align 4 +proc resample_18 stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + + mov edi, [dest] + mov edx, [src] + sub edx, 32 + + mov esi, 16 + +align 4 +.l1: + mov ecx, esi + mov eax, esi + and ecx, 0x7FFF + shr eax, 15 + lea eax, [edx+eax] + + mov bx, word [eax] + sub bh, 0x80 + sub bl, 0x80 + movsx eax, bh + shl eax, 8 + movsx ebp, bl + shl ebp, 8 + mov ebx, 32768 + imul eax, ecx + sub ebx, ecx + imul ebx, ebp + lea ecx, [ebx+eax+16384] + sar ecx, 15 + cmp ecx, 32767 ; 00007fffH + jle @f + mov ecx, 32767 ; 00007fffH + jmp .write +@@: + cmp ecx, -32768 ; ffff8000H + jge .write + mov ecx, -32768 ; ffff8000H +.write: + mov ebx, ecx + shl ebx, 16 + mov bx, cx + mov [edi], ebx + add edi, 4 + + add esi, [esp+16] + cmp esi, [esp+24] + jb .l1 + + mov ebp, esp + sub edi, [dest] + mov eax, edi + ret +endp + +align 4 +proc copy_stream stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov ecx, [r_size] + mov eax, ecx + shr ecx, 2 + mov esi, [src] + mov edi, [dest] + cld + rep movsd + ret +endp + +align 4 +proc resample_2 stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov edx, [src] + sub edx, 32*4 + mov edi, [dest] + mov ebx, [r_dt] + mov eax, 16 + emms + +align 4 +.l1: + mov ecx, eax + mov esi, eax + and ecx, 0x7FFF + shr esi, 15 + lea esi, [edx+esi*4] + + movq mm0, [esi] + movq mm1, mm0 + + movd mm2, ecx + punpcklwd mm2, mm2 + movq mm3, qword [m7] ;0x8000 + + psubw mm3, mm2 ; ;0x8000 - iconst + punpckldq mm3, mm2 + + pmulhw mm0, mm3 + pmullw mm1, mm3 + + movq mm4, mm1 + punpcklwd mm1, mm0 + punpckhwd mm4, mm0 + paddd mm1, mm4 + psrad mm1, 15 + packssdw mm1, mm1 + movd [edi], mm1 + add edi, 4 + + add eax, ebx + cmp eax, [r_end] + jb .l1 + emms + + sub edi, [dest] + mov eax, edi + ret +endp + +align 4 +proc resample_28 stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov edx, [src] + sub edx, 32*2 + mov edi, [dest] + mov ebx, [r_dt] + mov eax, 16 + emms + movq mm7, [mm80] + movq mm6, [mm_mask] + +align 4 +.l1: + mov ecx, eax + mov esi, eax + and ecx, 0x7FFF + shr esi, 15 + lea esi, [edx+esi*2] + + movq mm0, [esi] + psubb mm0, mm7 + punpcklbw mm0, mm0 + pand mm0, mm6 + + movq mm1, mm0 + + movd mm2, ecx + punpcklwd mm2, mm2 + movq mm3, qword [m7] ; // 0x8000 + + psubw mm3, mm2 ; // 0x8000 - iconst + punpckldq mm3, mm2 + + pmulhw mm0, mm3 + pmullw mm1, mm3 + + movq mm4, mm1 + punpcklwd mm1, mm0 + punpckhwd mm4, mm0 + paddd mm1, mm4 + psrad mm1, 15 + packssdw mm1, mm1 + movd [edi], mm1 + add edi, 4 + + add eax, ebx + cmp eax, [r_end] + jb .l1 + emms + + + sub edi, [dest] + mov eax, edi + ret +endp + + +proc m16_stereo stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov esi, [src] + mov edi, [dest] + mov ecx, [r_size] + shr ecx, 8 +@@: + call m16_s_mmx + add edi, 128 + add esi, 64 + call m16_s_mmx + add edi, 128 + add esi, 64 + call m16_s_mmx + add edi, 128 + add esi, 64 + call m16_s_mmx + add edi, 128 + add esi, 64 + dec ecx + jnz @b + + mov eax, [r_size] + add eax, eax + ret +endp + +align 4 +proc s8_stereo stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov esi, [src] + mov edi, [dest] + mov ecx, [r_size] + shr ecx, 7 + + movq mm7, [mm80] + movq mm6, [mm_mask] +@@: + call s8_s_mmx + add edi, 64 + add esi, 32 + call s8_s_mmx + add edi, 64 + add esi, 32 + call s8_s_mmx + add edi, 64 + add esi, 32 + call s8_s_mmx + add edi, 64 + add esi, 32 + dec ecx + jnz @b + + mov eax, [r_size] + add eax, eax + ret +endp + +proc m8_stereo stdcall, dest:dword,src:dword,\ + r_dt:dword, r_size:dword,r_end:dword + + mov esi, [src] + mov edi, [dest] + mov ecx, [r_size] + shr ecx, 6 + + movq mm7, [mm80] + movq mm6, [mm_mask] +@@: + call m8_s_mmx + add edi, 64 + add esi, 16 + call m8_s_mmx + add edi, 64 + add esi, 16 + call m8_s_mmx + add edi, 64 + add esi, 16 + call m8_s_mmx + add edi, 64 + add esi, 16 + dec ecx + jnz @b + + mov eax, [r_size] + add eax, eax + add eax, eax + ret +endp + +align 4 +proc alloc_mix_buff + + bsf eax, [mix_buff_map] + jnz .find + xor eax, eax + ret +.find: + btr [mix_buff_map], eax + shl eax, 9 + add eax, [mix_buff] + ret +endp + +align 4 +proc m16_s_mmx + + movq mm0, [esi] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi], mm0 + movq [edi+8], mm1 + + movq mm0, [esi+8] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi+16], mm0 + movq [edi+24], mm1 + + movq mm0, [esi+16] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi+32], mm0 + movq [edi+40], mm1 + + movq mm0, [esi+24] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi+48], mm0 + movq [edi+56], mm1 + + movq mm0, [esi+32] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi+64], mm0 + movq [edi+72], mm1 + + movq mm0, [esi+40] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi+80], mm0 + movq [edi+88], mm1 + + + movq mm0, [esi+48] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi+96], mm0 + movq [edi+104], mm1 + + movq mm0, [esi+56] + movq mm1, mm0 + punpcklwd mm0, mm0 + punpckhwd mm1, mm1 + movq [edi+112], mm0 + movq [edi+120], mm1 + + ret +endp + +align 4 +proc s8_s_mmx + + movq mm0, [esi] + psubb mm0, mm7 + movq mm1, mm0 + punpcklbw mm0, mm0 + pand mm0, mm6 + punpckhbw mm1, mm1 + pand mm1, mm6 + movq [edi], mm0 + movq [edi+8], mm1 + + movq mm0, [esi+8] + psubb mm0, mm7 + movq mm1, mm0 + punpcklbw mm0, mm0 + pand mm0, mm6 + punpckhbw mm1, mm1 + pand mm1, mm6 + movq [edi+16], mm0 + movq [edi+24], mm1 + + movq mm0, [esi+16] + psubb mm0, mm7 + movq mm1, mm0 + punpcklbw mm0, mm0 + pand mm0, mm6 + punpckhbw mm1, mm1 + pand mm1, mm6 + movq [edi+32], mm0 + movq [edi+40], mm1 + + movq mm0, [esi+24] + psubb mm0, mm7 + movq mm1, mm0 + punpcklbw mm0, mm0 + pand mm0, mm6 + punpckhbw mm1, mm1 + pand mm1, mm6 + movq [edi+48], mm0 + movq [edi+56], mm1 + + ret + +endp + +align 4 +proc m8_s_mmx + + movq mm0, [esi] + psubb mm0, mm7 + movq mm1, mm0 + punpcklbw mm0, mm0 + pand mm0, mm6 + punpckhbw mm1, mm1 + pand mm1, mm6 + movq mm2, mm0 + punpcklwd mm0, mm0 + punpckhwd mm2, mm2 + + movq mm3, mm1 + punpcklwd mm1, mm1 + punpckhwd mm3, mm3 + + movq [edi], mm0 + movq [edi+8], mm2 + movq [edi+16], mm1 + movq [edi+24], mm3 + + movq mm0, [esi+8] + psubb mm0, mm7 + movq mm1, mm0 + punpcklbw mm0, mm0 + pand mm0, mm6 + punpckhbw mm1, mm1 + pand mm1, mm6 + movq mm2, mm0 + punpcklwd mm0, mm0 + punpckhwd mm2, mm2 + + movq mm3, mm1 + punpcklwd mm1, mm1 + punpckhwd mm3, mm3 + + movq [edi+32], mm0 + movq [edi+40], mm2 + movq [edi+48], mm1 + movq [edi+56], mm3 + + ret +endp + +align 4 +proc mix_2_1 stdcall, output:dword, str0:dword, str1:dword + + mov edi, [output] + mov eax, [str0] + mov ebx, [str1] + mov esi, 128 + call [mix_2_core] ;edi, eax, ebx + + add edi, esi + add eax, esi + add ebx, esi + call [mix_2_core] ;edi, eax, ebx + + add edi, esi + add eax, esi + add ebx, esi + call [mix_2_core] ;edi, eax, ebx + + add edi, esi + add eax, esi + add ebx, esi + call [mix_2_core] ;edi, eax, ebx + ret +endp + +align 4 +proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword + + mov edi, [output] + mov eax, [str0] + mov ebx, [str1] + mov ecx, [str2] + mov esi, 128 + call [mix_3_core] + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + call [mix_3_core] + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + call [mix_3_core] + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + call [mix_3_core] + ret +endp + +align 4 +proc mix_4_1 stdcall, str0:dword, str1:dword,\ + str2:dword, str3:dword + + local output:DWORD + + call alloc_mix_buff + and eax, eax + jz .err + + mov [output], eax + + mov edi, eax + mov eax, [str0] + mov ebx, [str1] + mov ecx, [str2] + mov edx, [str3] + mov esi, 128 + call [mix_4_core] ;edi, eax, ebx, ecx, edx + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + add edx, esi + call [mix_4_core] ;edi, eax, ebx, ecx, edx + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + add edx, esi + call [mix_4_core] ;edi, eax, ebx, ecx, edx + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + add edx, esi + call [mix_4_core] ;edi, eax, ebx, ecx, edx + mov eax, [output] + ret +.err: + xor eax, eax + ret +endp + + +align 4 +proc final_mix stdcall, output:dword, str0:dword, str1:dword,\ + str2:dword, str3:dword + + mov edi, [output] + + mov eax, [str0] + mov ebx, [str1] + mov ecx, [str2] + mov edx, [str3] + mov esi, 128 + call [mix_4_core] ;edi, eax, ebx, ecx, edx + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + add edx, esi + call [mix_4_core] ;edi, eax, ebx, ecx, edx + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + add edx, esi + call [mix_4_core] ;edi, eax, ebx, ecx, edx + + add edi, esi + add eax, esi + add ebx, esi + add ecx, esi + add edx, esi + call [mix_4_core] ;edi, eax, ebx, ecx, edx + ret +endp + +align 4 +proc copy_mem stdcall, output:dword, input:dword + + mov edi, [output] + mov esi, [input] + mov ecx, 0x80 +.l1: + mov eax, [esi] + mov [edi], eax + add esi, 4 + add edi, 4 + loop .l1 + + ret +endp + +proc memcpy +@@: + mov eax, [esi] + mov [edi], eax + add esi, 4 + add edi, 4 + dec ecx + jnz @B + ret +endp + +if 0 + +align 4 +proc new_mix stdcall, output:dword + locals + mixCounter dd ? + mixIndex dd ? + streamIndex dd ? + inputCount dd ? + main_count dd ? + blockCount dd ? + mix_out dd ? + endl + + call prepare_playlist + + cmp [play_count], 0 + je .exit + call FpuSave + mov [main_count], 32; +.l00: + mov [mix_buff_map], 0x0000FFFF; + xor eax, eax + mov [mixCounter], eax + mov [mixIndex], eax + mov [streamIndex], eax; + mov ebx, [play_count] + mov [inputCount], ebx +.l0: + mov ecx, 4 +.l1: + mov ebx, [streamIndex] + mov esi, [play_list+ebx*4] + mov eax, [esi+STREAM.work_read] + add [esi+STREAM.work_read], 512 + + mov ebx, [mixIndex] + mov [mix_input+ebx*4], eax + inc [mixCounter] + inc [mixIndex] + inc [streamIndex] + dec [inputCount] + jz .m2 + + dec ecx + jnz .l1 + + cmp [mixCounter], 4 + jnz .m2 + + stdcall mix_4_1, [mix_input], [mix_input+4], [mix_input+8], [mix_input+12] + sub [mixIndex], 4 + mov ebx, [mixIndex] + mov [mix_input+ebx*4], eax + inc [mixIndex] + mov [mixCounter], 0 + + cmp [inputCount], 0 + jnz .l0 +.m2: + cmp [mixIndex], 1 + jne @f + stdcall copy_mem, [output], [mix_input] + jmp .m3 +@@: + cmp [mixIndex], 2 + jne @f + stdcall mix_2_1, [output], [mix_input], [mix_input+4] + jmp .m3 +@@: + cmp [mixIndex], 3 + jne @f + stdcall mix_3_1, [output], [mix_input], [mix_input+4], [mix_input+8] + jmp .m3 +@@: + stdcall final_mix, [output], [mix_input], [mix_input+4], [mix_input+8], [mix_input+12] +.m3: + add [output], 512 + + dec [main_count] + jnz .l00 + + call update_stream + emms + call FpuRestore + ret +.exit: + mov edi, [output] + mov ecx, 0x1000 + xor eax, eax + cld + rep stosd + ret +endp + +end if diff --git a/kernel/trunk/drivers/proc32.inc b/kernel/trunk/drivers/proc32.inc index 23c56b03c..ae8de0a48 100644 --- a/kernel/trunk/drivers/proc32.inc +++ b/kernel/trunk/drivers/proc32.inc @@ -1,268 +1,268 @@ - -; Macroinstructions for defining and calling procedures - -macro stdcall proc,[arg] ; directly call STDCALL procedure - { common - if ~ arg eq - reverse - pushd arg - common - end if - call proc } - -macro invoke proc,[arg] ; indirectly call STDCALL procedure - { common - if ~ arg eq - reverse - pushd arg - common - end if - call [proc] } - -macro ccall proc,[arg] ; directly call CDECL procedure - { common - size@ccall = 0 - if ~ arg eq - reverse - pushd arg - size@ccall = size@ccall+4 - common - end if - call proc - if size@ccall - add esp,size@ccall - end if } - -macro cinvoke proc,[arg] ; indirectly call CDECL procedure - { common - size@ccall = 0 - if ~ arg eq - reverse - pushd arg - size@ccall = size@ccall+4 - common - end if - call [proc] - if size@ccall - add esp,size@ccall - end if } - -macro proc [args] ; define procedure - { common - match name params, args> - \{ define@proc name, \{ prologue name,flag,parmbytes,localbytes,reglist \} - macro locals - \{ virtual at ebp-localbytes+current - macro label . \\{ deflocal@proc .,:, \\} - struc db [val] \\{ \common deflocal@proc .,db,val \\} - struc dw [val] \\{ \common deflocal@proc .,dw,val \\} - struc dp [val] \\{ \common deflocal@proc .,dp,val \\} - struc dd [val] \\{ \common deflocal@proc .,dd,val \\} - struc dt [val] \\{ \common deflocal@proc .,dt,val \\} - struc dq [val] \\{ \common deflocal@proc .,dq,val \\} - struc rb cnt \\{ deflocal@proc .,rb cnt, \\} - struc rw cnt \\{ deflocal@proc .,rw cnt, \\} - struc rp cnt \\{ deflocal@proc .,rp cnt, \\} - struc rd cnt \\{ deflocal@proc .,rd cnt, \\} - struc rt cnt \\{ deflocal@proc .,rt cnt, \\} - struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} - macro endl - \{ purge label - restruc db,dw,dp,dd,dt,dq - restruc rb,rw,rp,rd,rt,rq - restruc byte,word,dword,pword,tword,qword - current = $-(ebp-localbytes) - end virtual \} - macro ret operand - \{ match any, operand \\{ retn operand \\} - match , operand \\{ match epilogue:reglist, epilogue@proc: - \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} - macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 - end if \} } - -macro defargs@proc [arg] - { common - if ~ arg eq - forward - local ..arg,current@arg - match argname:type, arg - \{ current@arg equ argname - label ..arg type - argname equ ..arg - if dqword eq type - dd ?,?,?,? - else if tbyte eq type - dd ?,?,? - else if qword eq type | pword eq type - dd ?,? - else - dd ? - end if \} - match =current@arg,current@arg - \{ current@arg equ arg - arg equ ..arg - ..arg dd ? \} - common - args@proc equ current@arg - forward - restore current@arg - common - end if } - -macro deflocal@proc name,def,[val] - { common - match vars, all@vars \{ all@vars equ all@vars, \} - all@vars equ all@vars name - forward - local ..var,..tmp - ..var def val - match =?, val \{ ..tmp equ \} - match any =dup (=?), val \{ ..tmp equ \} - match tmp : value, ..tmp : val - \{ tmp: end virtual - initlocal@proc ..var,def value - virtual at tmp\} - common - match first rest, ..var, \{ name equ first \} } - -macro initlocal@proc name,def - { virtual at name - def - size@initlocal = $ - name - end virtual - position@initlocal = 0 - while size@initlocal > position@initlocal - virtual at name - def - if size@initlocal - position@initlocal < 2 - current@initlocal = 1 - load byte@initlocal byte from name+position@initlocal - else if size@initlocal - position@initlocal < 4 - current@initlocal = 2 - load word@initlocal word from name+position@initlocal - else - current@initlocal = 4 - load dword@initlocal dword from name+position@initlocal - end if - end virtual - if current@initlocal = 1 - mov byte [name+position@initlocal],byte@initlocal - else if current@initlocal = 2 - mov word [name+position@initlocal],word@initlocal - else - mov dword [name+position@initlocal],dword@initlocal - end if - position@initlocal = position@initlocal + current@initlocal - end while } - -macro endp - { purge ret,locals,endl - finish@proc - purge finish@proc - restore regs@proc - match all,args@proc \{ restore all \} - restore args@proc - match all,all@vars \{ restore all \} } - -macro local [var] - { common - locals - forward done@local equ - match varname[count]:vartype, var - \{ match =BYTE, vartype \\{ varname rb count - restore done@local \\} - match =WORD, vartype \\{ varname rw count - restore done@local \\} - match =DWORD, vartype \\{ varname rd count - restore done@local \\} - match =PWORD, vartype \\{ varname rp count - restore done@local \\} - match =QWORD, vartype \\{ varname rq count - restore done@local \\} - match =TBYTE, vartype \\{ varname rt count - restore done@local \\} - match =DQWORD, vartype \\{ label varname dqword - rq count+count - restore done@local \\} - match , done@local \\{ virtual - varname vartype - end virtual - rb count*sizeof.\#vartype - restore done@local \\} \} - match :varname:vartype, done@local:var - \{ match =BYTE, vartype \\{ varname db ? - restore done@local \\} - match =WORD, vartype \\{ varname dw ? - restore done@local \\} - match =DWORD, vartype \\{ varname dd ? - restore done@local \\} - match =PWORD, vartype \\{ varname dp ? - restore done@local \\} - match =QWORD, vartype \\{ varname dq ? - restore done@local \\} - match =TBYTE, vartype \\{ varname dt ? - restore done@local \\} - match =DQWORD, vartype \\{ label varname dqword - dq ?,? - restore done@local \\} - match , done@local \\{ varname vartype - restore done@local \\} \} - match ,done@local - \{ var - restore done@local \} - common - endl } + +; Macroinstructions for defining and calling procedures + +macro stdcall proc,[arg] ; directly call STDCALL procedure + { common + if ~ arg eq + reverse + pushd arg + common + end if + call proc } + +macro invoke proc,[arg] ; indirectly call STDCALL procedure + { common + if ~ arg eq + reverse + pushd arg + common + end if + call [proc] } + +macro ccall proc,[arg] ; directly call CDECL procedure + { common + size@ccall = 0 + if ~ arg eq + reverse + pushd arg + size@ccall = size@ccall+4 + common + end if + call proc + if size@ccall + add esp, size@ccall + end if } + +macro cinvoke proc,[arg] ; indirectly call CDECL procedure + { common + size@ccall = 0 + if ~ arg eq + reverse + pushd arg + size@ccall = size@ccall+4 + common + end if + call [proc] + if size@ccall + add esp, size@ccall + end if } + +macro proc [args] ; define procedure + { common + match name params, args> + \{ define@proc name, \{ prologue name,flag,parmbytes,localbytes,reglist \} + macro locals + \{ virtual at ebp-localbytes+current + macro label . \\{ deflocal@proc .,:, \\} + struc db [val] \\{ \common deflocal@proc .,db,val \\} + struc dw [val] \\{ \common deflocal@proc .,dw,val \\} + struc dp [val] \\{ \common deflocal@proc .,dp,val \\} + struc dd [val] \\{ \common deflocal@proc .,dd,val \\} + struc dt [val] \\{ \common deflocal@proc .,dt,val \\} + struc dq [val] \\{ \common deflocal@proc .,dq,val \\} + struc rb cnt \\{ deflocal@proc .,rb cnt, \\} + struc rw cnt \\{ deflocal@proc .,rw cnt, \\} + struc rp cnt \\{ deflocal@proc .,rp cnt, \\} + struc rd cnt \\{ deflocal@proc .,rd cnt, \\} + struc rt cnt \\{ deflocal@proc .,rt cnt, \\} + struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} + macro endl + \{ purge label + restruc db,dw,dp,dd,dt,dq + restruc rb,rw,rp,rd,rt,rq + restruc byte,word,dword,pword,tword,qword + current = $-(ebp-localbytes) + end virtual \} + macro ret operand + \{ match any, operand \\{ retn operand \\} + match , operand \\{ match epilogue:reglist, epilogue@proc: + \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} + macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 + end if \} } + +macro defargs@proc [arg] + { common + if ~ arg eq + forward + local ..arg,current@arg + match argname:type, arg + \{ current@arg equ argname + label ..arg type + argname equ ..arg + if dqword eq type + dd ?,?,?,? + else if tbyte eq type + dd ?,?,? + else if qword eq type | pword eq type + dd ?,? + else + dd ? + end if \} + match =current@arg,current@arg + \{ current@arg equ arg + arg equ ..arg + ..arg dd ? \} + common + args@proc equ current@arg + forward + restore current@arg + common + end if } + +macro deflocal@proc name,def,[val] + { common + match vars, all@vars \{ all@vars equ all@vars, \} + all@vars equ all@vars name + forward + local ..var,..tmp + ..var def val + match =?, val \{ ..tmp equ \} + match any =dup (=?), val \{ ..tmp equ \} + match tmp : value, ..tmp : val + \{ tmp: end virtual + initlocal@proc ..var,def value + virtual at tmp\} + common + match first rest, ..var, \{ name equ first \} } + +macro initlocal@proc name,def + { virtual at name + def + size@initlocal = $ - name + end virtual + position@initlocal = 0 + while size@initlocal > position@initlocal + virtual at name + def + if size@initlocal - position@initlocal < 2 + current@initlocal = 1 + load byte@initlocal byte from name+position@initlocal + else if size@initlocal - position@initlocal < 4 + current@initlocal = 2 + load word@initlocal word from name+position@initlocal + else + current@initlocal = 4 + load dword@initlocal dword from name+position@initlocal + end if + end virtual + if current@initlocal = 1 + mov byte [name+position@initlocal], byte@initlocal + else if current@initlocal = 2 + mov word [name+position@initlocal], word@initlocal + else + mov dword [name+position@initlocal], dword@initlocal + end if + position@initlocal = position@initlocal + current@initlocal + end while } + +macro endp + { purge ret,locals,endl + finish@proc + purge finish@proc + restore regs@proc + match all,args@proc \{ restore all \} + restore args@proc + match all,all@vars \{ restore all \} } + +macro local [var] + { common + locals + forward done@local equ + match varname[count]:vartype, var + \{ match =BYTE, vartype \\{ varname rb count + restore done@local \\} + match =WORD, vartype \\{ varname rw count + restore done@local \\} + match =DWORD, vartype \\{ varname rd count + restore done@local \\} + match =PWORD, vartype \\{ varname rp count + restore done@local \\} + match =QWORD, vartype \\{ varname rq count + restore done@local \\} + match =TBYTE, vartype \\{ varname rt count + restore done@local \\} + match =DQWORD, vartype \\{ label varname dqword + rq count+count + restore done@local \\} + match , done@local \\{ virtual + varname vartype + end virtual + rb count*sizeof.\#vartype + restore done@local \\} \} + match :varname:vartype, done@local:var + \{ match =BYTE, vartype \\{ varname db ? + restore done@local \\} + match =WORD, vartype \\{ varname dw ? + restore done@local \\} + match =DWORD, vartype \\{ varname dd ? + restore done@local \\} + match =PWORD, vartype \\{ varname dp ? + restore done@local \\} + match =QWORD, vartype \\{ varname dq ? + restore done@local \\} + match =TBYTE, vartype \\{ varname dt ? + restore done@local \\} + match =DQWORD, vartype \\{ label varname dqword + dq ?,? + restore done@local \\} + match , done@local \\{ varname vartype + restore done@local \\} \} + match ,done@local + \{ var + restore done@local \} + common + endl } diff --git a/kernel/trunk/drivers/sb16/CONFIG.INC b/kernel/trunk/drivers/sb16/CONFIG.INC index 322fccfbc..dd870925f 100644 --- a/kernel/trunk/drivers/sb16/CONFIG.INC +++ b/kernel/trunk/drivers/sb16/CONFIG.INC @@ -1,50 +1,50 @@ -;flags------------------------------------------------------------ -DEBUG equ 1 ;show messages at debug board -use_cli_sti equ 1 ;driver become more stable (theoretically) - -;constants-------------------------------------------------------- -API_VERSION equ 0 ;debug - -OS_BASE equ 0x80000000 -new_app_base equ 0x0 -PROC_BASE equ (OS_BASE+0x080000) -SB16Buffer equ (OS_BASE+0x2A0000) -SB16_Status equ (OS_BASE+0x2B0000) -DMAPage equ ((SB16Buffer-OS_BASE) shr 16) - -SB16Buffer0 equ SB16Buffer -SB16Buffer1 equ (SB16Buffer+16384) -SB16Buffer2 equ (SB16Buffer+(2*16384)) -SB16Buffer3 equ (SB16Buffer+(3*16384)) - -sb_irq_num equ 5 ;default values for SB16, may be overrided by autodetect -sb_dma_num equ 5 ;default values for SB16, may be overrided by autodetect - -small_buffer equ 32768 -full_buffer equ 65536 -sb_buffer_size equ small_buffer ; FIX ring buffer overlapped events issue; full_buffer - -__supported_buffer_sizes fix - -if ~(sb_buffer_size in __supported_buffer_sizes) -display 13,10,'unsupported buffer size was selected, check config.inc',13,10 -stop -end if - -sb_out_rate equ 48000 -;time constant for cards older than SB16 -sb_tc equ (256-(1000000/(sb_out_rate*2))) - -SRV_GETVERSION equ 0 -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_SET_BUFF equ 4 -DEV_NOTIFY equ 5 -DEV_SET_MASTERVOL equ 6 -DEV_GET_MASTERVOL equ 7 -DEV_GET_INFO equ 8 - -DRV_ENTRY equ 1 -DRV_EXIT equ -1 - +;flags------------------------------------------------------------ +DEBUG equ 1 ;show messages at debug board +use_cli_sti equ 1 ;driver become more stable (theoretically) + +;constants-------------------------------------------------------- +API_VERSION equ 0 ;debug + +OS_BASE equ 0x80000000 +new_app_base equ 0x0 +PROC_BASE equ (OS_BASE+0x080000) +SB16Buffer equ (OS_BASE+0x2A0000) +SB16_Status equ (OS_BASE+0x2B0000) +DMAPage equ ((SB16Buffer-OS_BASE) shr 16) + +SB16Buffer0 equ SB16Buffer +SB16Buffer1 equ (SB16Buffer+16384) +SB16Buffer2 equ (SB16Buffer+(2*16384)) +SB16Buffer3 equ (SB16Buffer+(3*16384)) + +sb_irq_num equ 5 ;default values for SB16, may be overrided by autodetect +sb_dma_num equ 5 ;default values for SB16, may be overrided by autodetect + +small_buffer equ 32768 +full_buffer equ 65536 +sb_buffer_size equ small_buffer ; FIX ring buffer overlapped events issue; full_buffer + +__supported_buffer_sizes fix + +if ~(sb_buffer_size in __supported_buffer_sizes) +display 13,10,'unsupported buffer size was selected, check config.inc',13,10 +stop +end if + +sb_out_rate equ 48000 +;time constant for cards older than SB16 +sb_tc equ (256-(1000000/(sb_out_rate*2))) + +SRV_GETVERSION equ 0 +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_SET_BUFF equ 4 +DEV_NOTIFY equ 5 +DEV_SET_MASTERVOL equ 6 +DEV_GET_MASTERVOL equ 7 +DEV_GET_INFO equ 8 + +DRV_ENTRY equ 1 +DRV_EXIT equ -1 + diff --git a/kernel/trunk/drivers/sb16/SB16.INC b/kernel/trunk/drivers/sb16/SB16.INC index 40f03ba4e..3139c2249 100644 --- a/kernel/trunk/drivers/sb16/SB16.INC +++ b/kernel/trunk/drivers/sb16/SB16.INC @@ -1,297 +1,297 @@ -;-------------------------------- -; program dma -;-------------------------------- -sb_set_dma: - mov ebx,[sound_dma] - lea eax,[ebx+4] ;mask required channel - cmp bl,4 - ja .use_second_dma_controller - jb @f -.dma_setup_error: -if DEBUG - mov esi,msgErrDMAsetup - call SysMsgBoardStr -end if - mov dword[esp],START.stop - ret -@@: -if use_cli_sti - cli ;here to minimize time with disabled ints -end if - out 0xA,al ;mask required channel - - xor eax,eax - out 0xC,al ;clear byte pointer flip-flop register - - lea eax,[ebx+0x58] ;auto-init mode for channel (ebx) - out 0xB,al ;DMA channel 0-3 mode register - - movzx edx,byte[ebx+dma_table] ;page register - mov al,DMAPage - out dx,al - - lea edx,[ebx*2] ;DMA channel 0-3 base address - - mov al,0 ;LSB is 0 - out dx,al - -; mov al,0 ;MSB is 0 too - out dx,al - - inc edx ;DMA channel 0-3 byte count - - mov al,((sb_buffer_size-1) and 0xff) - out dx,al - - mov al,((sb_buffer_size-1) shr 8) ;it is the same - out dx,al - - mov eax,ebx ;unmask DMA channel - out 0xA,al - -if use_cli_sti - sti -end if - ret - -.use_second_dma_controller: - cmp bl,7 - ja .dma_setup_error - - sub bl,4 - sub al,4 -if use_cli_sti - cli ;here to minimize time with disabled ints -end if - out 0xD4,al ;mask required channel - - xor eax,eax - out 0xD8,al ;clear byte pointer flip-flop register - - lea eax,[ebx+0x58] ;auto-init mode for channel (ebx+4) - out 0xD6,al ;DMA channel 4-7 mode register - - movzx edx,byte[ebx+dma_table+4] ;page register - mov al,DMAPage - out dx,al - - lea edx,[ebx*4+0xC0] ;DMA channel 4-7 base address - - mov al,0 ;LSB is 0 ;for 16bit DMA this contains - out dx,al ;A1-A8 lines of address bus, A0 is zero - -; mov al,0 ;MSB is 0 too ;for 16bit DMA this contains - out dx,al ;A9-A16 lines of address bus - - inc edx - inc edx ;DMA channel 4-7 16bit word count - - mov al,(((sb_buffer_size/2)-1) and 0xff) - out dx,al - - mov al,(((sb_buffer_size/2)-1) shr 8) - out dx,al - - mov eax,ebx ;unmask DMA channel - out 0xD4,al - -if use_cli_sti - sti -end if - ret -;------------------------------------------------------------------------------- -; out byte to SB DSP's write port -;------------------------------------------------------------------------------- -macro sb_out data_to_out { -@@: - in al,dx - test al,al ;is DSP busy? - js @b ;it's busy - mov al,data_to_out ;it's free - out dx,al -} -;------------------------------------------------------------------------------- -; stop playing -;------------------------------------------------------------------------------- -proc sb_stop - mov edx,[sb_base_port] - add dl,0xC - sb_out 0xD3 ;turn the speaker off - sb_out 0xDA ;exit 8bit DMA - sb_out 0xD9 ;exit 16bit DMA - ret -endp -;------------------------------------------------------------------------------- -; start playing -;------------------------------------------------------------------------------- -proc sb_play - and [int_flip_flop],0 - mov edx,[sb_base_port] - add dl,0xC - sb_out 0xD1 ;turn speaker on -; sb_out 0x48 ;set DSP transfer size ;for older cards, not supported -; ;in this version -; mov ax,32767 ;(64k)/2-1 -;@@: ;out the low byte... -; in al,dx -; test al,al ;is DSP busy? -; js @b ;it's busy -; out dx,al - -; mov al,ah ;...then the high byte -;@@: -; in al,dx -; test al,al ;is DSP busy? -; js @b ;it's busy -; out dx,al - -; sb_out 0x1C ;auto-init 8bit playback - -; 0xBXh - 16 bit DMA mode -; |||| - sb_out 10110110b ;bCommand -; |||| -; |||+-reserved -; ||+--turn FIFO on (0 for off) -; |+---auto-init mode on (0 for off) -; +----A/D: 0-output, 1-input -; +------stereo on -; |+-----unsigned (1 for signed) -; || - sb_out 00110000b ;bMode -; || |||| -; ---------reserved -;wSize is a number of 16bit samples less 1. For auto-init mode each half -;buffer is (64k)/2 bytes long and, obviously, contains ((64k)/2)/2 samples - sb_out (((sb_buffer_size/2/2)-1) and 0xFF) ;wSize.LowByte - sb_out (((sb_buffer_size/2/2)-1) shr 8) ;wSize.HighByte - ret -endp -;------------------------------------------------------------------------------- -; reset DSP -;------------------------------------------------------------------------------- -proc sb_reset - and [int_flip_flop],0 - mov edx,[sb_base_port] - add dl,6 - mov al,1 ;start DSP reset - -if use_cli_sti - cli ;here to minimize time with disabled ints -end if - out dx,al - mov ecx,40 ;wait at least 3 microsec. -@@: - in al,dx - loop @b - - xor eax,eax ;stop DSP reset -if use_cli_sti - sti -end if - out dx,al - ret -endp - -;------------------------------------------------------------------------------- -; set the rate for playing, enable stereo -;------------------------------------------------------------------------------- -proc sb_setup - mov edx,[sb_base_port] - add dl,0xC - sb_out 40h ;set time constant, this is for old cards - sb_out sb_tc - - sb_out 41h ;set sound rate, this can only SB16 - sb_out (sb_out_rate shr 8) ;first high byte (MSB) - sb_out (sb_out_rate and 0xff) ;then low byte (LSB) - -; mov al,0xE ;for older cards, not supported in this version -; sub dl,(0xC-4) ;talk to SB's mixer -; out dx,al ;select this register of the mixer -; mov ecx,6 ;wait for the chip -;@@: -; in al,dx -; loop @b - -; inc edx ;now read the data port -; in al,dx -; or al,22h ;turn on stereo -; mov ah,al - -; mov al,0xE -; dec edx ;talk to SB's mixer -; out dx,al ;select this register of the mixer - -; mov ecx,6 ;wait for the chip -;@@: -; in al,dx -; loop @b - -; inc edx ;now send data to the data port -; mov al,ah -; out dx,al - -; dec edx -; mov ecx,35 ;wait for the chip -;@@: -; in al,dx -; loop @b - ret -endp - -;------------------------------------------------------------------------------- -; set master volume of SB mixer, note, not only SB16 but SBPro and older -; this is the first step to more full support for hardware -;------------------------------------------------------------------------------- -;in: eax in range [-10000;0] - master volume for _both_ channels -;note that x*3*17/2000 and x*3/2000*17 are not the same numbers, -;because we count in integers -proc sb_set_master_vol - mov [sb_master_vol],eax - add eax,10000 ;SB sound level rise from 0 to MAX_LEVEL - lea eax,[eax+eax*2] ;*3 - mov ebx,2000 ;divisor - xor edx,edx - cmp byte[sb_DSP_version_int],4 - jae @f ;SBPro's MAX_LEVEL is 15, but we *11 because - ;volume byte looks like that: 0xLR, where L - left - ;channel volume, R - right, 0<=R,L<=15 - div ebx - imul eax,17 - mov edx,[sb_base_port] - push eax ;here for optimisation - add dl,4 - mov al,0x22 ;write mixer register 0x22 - out dx,al - in al,dx ;wait for the chip ;6 - in al,dx ;wait for the chip ;5 - in al,dx ;wait for the chip ;4 - in al,dx ;wait for the chip ;3 - in al,dx ;wait for the chip ;2 - in al,dx ;wait for the chip ;1 - pop eax ;go! - inc edx - out dx,al - ret -@@: ;SB16's MAX_LEVEL is 255 - imul eax,17 - div ebx - mov edx,[sb_base_port] - push eax ;here for optimisation - add dl,4 - mov al,0x30 ;left speaker - out dx,al - pop eax ;<--+ - inc edx ; \/ - push eax ;here for optimisation - out dx,al ;write - dec edx - mov al,0x31 ;right speaker - out dx,al - pop eax - inc edx - out dx,al ;write - ret -endp -;------------------------------------------------------------------------------- +;-------------------------------- +; program dma +;-------------------------------- +sb_set_dma: + mov ebx, [sound_dma] + lea eax, [ebx+4];mask required channel + cmp bl, 4 + ja .use_second_dma_controller + jb @f +.dma_setup_error: +if DEBUG + mov esi, msgErrDMAsetup + call SysMsgBoardStr +end if + mov dword[esp], START.stop + ret +@@: +if use_cli_sti + cli ;here to minimize time with disabled ints +end if + out 0xA, al;mask required channel + + xor eax, eax + out 0xC, al;clear byte pointer flip-flop register + + lea eax, [ebx+0x58];auto-init mode for channel (ebx) + out 0xB, al;DMA channel 0-3 mode register + + movzx edx, byte[ebx+dma_table];page register + mov al, DMAPage + out dx, al + + lea edx, [ebx*2];DMA channel 0-3 base address + + mov al, 0;LSB is 0 + out dx, al + +; mov al,0 ;MSB is 0 too + out dx, al + + inc edx ;DMA channel 0-3 byte count + + mov al, ((sb_buffer_size-1) and 0xff) + out dx, al + + mov al, ((sb_buffer_size-1) shr 8);it is the same + out dx, al + + mov eax, ebx;unmask DMA channel + out 0xA, al + +if use_cli_sti + sti +end if + ret + +.use_second_dma_controller: + cmp bl, 7 + ja .dma_setup_error + + sub bl, 4 + sub al, 4 +if use_cli_sti + cli ;here to minimize time with disabled ints +end if + out 0xD4, al;mask required channel + + xor eax, eax + out 0xD8, al;clear byte pointer flip-flop register + + lea eax, [ebx+0x58];auto-init mode for channel (ebx+4) + out 0xD6, al;DMA channel 4-7 mode register + + movzx edx, byte[ebx+dma_table+4];page register + mov al, DMAPage + out dx, al + + lea edx, [ebx*4+0xC0];DMA channel 4-7 base address + + mov al, 0;LSB is 0 ;for 16bit DMA this contains + out dx, al;A1-A8 lines of address bus, A0 is zero + +; mov al,0 ;MSB is 0 too ;for 16bit DMA this contains + out dx, al;A9-A16 lines of address bus + + inc edx + inc edx ;DMA channel 4-7 16bit word count + + mov al, (((sb_buffer_size/2)-1) and 0xff) + out dx, al + + mov al, (((sb_buffer_size/2)-1) shr 8) + out dx, al + + mov eax, ebx;unmask DMA channel + out 0xD4, al + +if use_cli_sti + sti +end if + ret +;------------------------------------------------------------------------------- +; out byte to SB DSP's write port +;------------------------------------------------------------------------------- +macro sb_out data_to_out { +@@: + in al, dx + test al, al;is DSP busy? + js @b ;it's busy + mov al, data_to_out;it's free + out dx, al +} +;------------------------------------------------------------------------------- +; stop playing +;------------------------------------------------------------------------------- +proc sb_stop + mov edx, [sb_base_port] + add dl, 0xC + sb_out 0xD3 ;turn the speaker off + sb_out 0xDA ;exit 8bit DMA + sb_out 0xD9 ;exit 16bit DMA + ret +endp +;------------------------------------------------------------------------------- +; start playing +;------------------------------------------------------------------------------- +proc sb_play + and [int_flip_flop], 0 + mov edx, [sb_base_port] + add dl, 0xC + sb_out 0xD1 ;turn speaker on +; sb_out 0x48 ;set DSP transfer size ;for older cards, not supported +; ;in this version +; mov ax,32767 ;(64k)/2-1 +;@@: ;out the low byte... +; in al,dx +; test al,al ;is DSP busy? +; js @b ;it's busy +; out dx,al + +; mov al,ah ;...then the high byte +;@@: +; in al,dx +; test al,al ;is DSP busy? +; js @b ;it's busy +; out dx,al + +; sb_out 0x1C ;auto-init 8bit playback + +; 0xBXh - 16 bit DMA mode +; |||| + sb_out 10110110b ;bCommand +; |||| +; |||+-reserved +; ||+--turn FIFO on (0 for off) +; |+---auto-init mode on (0 for off) +; +----A/D: 0-output, 1-input +; +------stereo on +; |+-----unsigned (1 for signed) +; || + sb_out 00110000b ;bMode +; || |||| +; ---------reserved +;wSize is a number of 16bit samples less 1. For auto-init mode each half +;buffer is (64k)/2 bytes long and, obviously, contains ((64k)/2)/2 samples + sb_out (((sb_buffer_size/2/2)-1) and 0xFF) ;wSize.LowByte + sb_out (((sb_buffer_size/2/2)-1) shr 8) ;wSize.HighByte + ret +endp +;------------------------------------------------------------------------------- +; reset DSP +;------------------------------------------------------------------------------- +proc sb_reset + and [int_flip_flop], 0 + mov edx, [sb_base_port] + add dl, 6 + mov al, 1;start DSP reset + +if use_cli_sti + cli ;here to minimize time with disabled ints +end if + out dx, al + mov ecx, 40;wait at least 3 microsec. +@@: + in al, dx + loop @b + + xor eax, eax;stop DSP reset +if use_cli_sti + sti +end if + out dx, al + ret +endp + +;------------------------------------------------------------------------------- +; set the rate for playing, enable stereo +;------------------------------------------------------------------------------- +proc sb_setup + mov edx, [sb_base_port] + add dl, 0xC + sb_out 40h ;set time constant, this is for old cards + sb_out sb_tc + + sb_out 41h ;set sound rate, this can only SB16 + sb_out (sb_out_rate shr 8) ;first high byte (MSB) + sb_out (sb_out_rate and 0xff) ;then low byte (LSB) + +; mov al,0xE ;for older cards, not supported in this version +; sub dl,(0xC-4) ;talk to SB's mixer +; out dx,al ;select this register of the mixer +; mov ecx,6 ;wait for the chip +;@@: +; in al,dx +; loop @b + +; inc edx ;now read the data port +; in al,dx +; or al,22h ;turn on stereo +; mov ah,al + +; mov al,0xE +; dec edx ;talk to SB's mixer +; out dx,al ;select this register of the mixer + +; mov ecx,6 ;wait for the chip +;@@: +; in al,dx +; loop @b + +; inc edx ;now send data to the data port +; mov al,ah +; out dx,al + +; dec edx +; mov ecx,35 ;wait for the chip +;@@: +; in al,dx +; loop @b + ret +endp + +;------------------------------------------------------------------------------- +; set master volume of SB mixer, note, not only SB16 but SBPro and older +; this is the first step to more full support for hardware +;------------------------------------------------------------------------------- +;in: eax in range [-10000;0] - master volume for _both_ channels +;note that x*3*17/2000 and x*3/2000*17 are not the same numbers, +;because we count in integers +proc sb_set_master_vol + mov [sb_master_vol], eax + add eax, 10000;SB sound level rise from 0 to MAX_LEVEL + lea eax, [eax+eax*2];*3 + mov ebx, 2000;divisor + xor edx, edx + cmp byte[sb_DSP_version_int], 4 + jae @f ;SBPro's MAX_LEVEL is 15, but we *11 because + ;volume byte looks like that: 0xLR, where L - left + ;channel volume, R - right, 0<=R,L<=15 + div ebx + imul eax, 17 + mov edx, [sb_base_port] + push eax ;here for optimisation + add dl, 4 + mov al, 0x22;write mixer register 0x22 + out dx, al + in al, dx;wait for the chip ;6 + in al, dx;wait for the chip ;5 + in al, dx;wait for the chip ;4 + in al, dx;wait for the chip ;3 + in al, dx;wait for the chip ;2 + in al, dx;wait for the chip ;1 + pop eax ;go! + inc edx + out dx, al + ret +@@: ;SB16's MAX_LEVEL is 255 + imul eax, 17 + div ebx + mov edx, [sb_base_port] + push eax ;here for optimisation + add dl, 4 + mov al, 0x30;left speaker + out dx, al + pop eax ;<--+ + inc edx ; \/ + push eax ;here for optimisation + out dx, al;write + dec edx + mov al, 0x31;right speaker + out dx, al + pop eax + inc edx + out dx, al;write + ret +endp +;------------------------------------------------------------------------------- diff --git a/kernel/trunk/drivers/sb16/sb16.asm b/kernel/trunk/drivers/sb16/sb16.asm index 70af1896b..7fb78a130 100644 --- a/kernel/trunk/drivers/sb16/sb16.asm +++ b/kernel/trunk/drivers/sb16/sb16.asm @@ -1,395 +1,398 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -format MS COFF - -include 'CONFIG.INC' - -;structs---------------------------------------------------------- -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -;something-------------------------------------------------------- -public START -public service_proc -public version - -include '..\proc32.inc' -include '..\imports.inc' - -section '.flat' code readable align 16 - -include 'SB16.INC' - -;------------------------------------------------------------------------------- -proc START stdcall, state:dword - cmp [state], 1 - jne .stop -.entry: - -if DEBUG - mov esi, msgInit - call SysMsgBoardStr -end if - - call detect ;returns DSP version or zero if - test eax,eax ;SB card not found - jz .exit - -if DEBUG - movzx eax,al ;major version - mov esi,sb_DSP_description - dec eax - jz .sb_say_about_found_dsp - mov dword[esi],'2.x ' - dec eax - jz .sb_say_about_found_dsp - mov dword[esi],'Pro ' - dec eax - jz .sb_say_about_found_dsp - mov dword[esi],'16 ' -.sb_say_about_found_dsp: - mov esi,msgDSPFound - call SysMsgBoardStr -end if -; xor eax,eax -; mov ebx,[sb_base_port] -; lea ecx,[ebx+0xF] - xor ebx,ebx - mov ecx,[sb_base_port] - lea edx,[ebx+0xF] - - call ReservePortArea ;these ports must be my! -if DEBUG - dec eax - jnz @f - mov esi,msgErrRsrvPorts - call SysMsgBoardStr -@@: -end if - - call sb_setup ;clock it, etc - - stdcall AttachIntHandler, sb_irq_num, sb_irq, 0 - -if DEBUG - test eax,eax - jnz @f - - mov esi,msgErrAtchIRQ - call SysMsgBoardStr - - stdcall GetIntHandler, sb_irq_num - call SysMsgBoardNum - - jmp .stop -@@: - mov esi,msgSucAtchIRQ - call SysMsgBoardStr -end if - stdcall RegService, my_service, service_proc - ret -.stop: - call sb_reset -.exit: - -if DEBUG - mov esi,msgExit - call SysMsgBoardStr -end if - - xor eax, eax - ret -endp -;------------------------------------------------------------------------------- - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - mov edi,[ioctl] - mov eax,[edi+io_code] - cmp eax,SRV_GETVERSION - jne @F - - mov eax,[edi+output] - cmp [edi+out_size],4 - jne .fail - mov [eax],dword API_VERSION - xor eax,eax - ret -@@: - cmp eax,DEV_PLAY - jne @f -if DEBUG - mov esi,msgPlay - call SysMsgBoardStr -end if - call sb_stop ;to play smth new we must stop smth old - - call pre_fill_data ;fill first and second half of the buffer - call pre_fill_data ; - - call sb_set_dma ;is it really needed here? Paranoia. - call sb_play - xor eax,eax ;set maximum volume - call sb_set_master_vol - xor eax,eax - ret -;@@: ;all this commented stuff in service proc -; cmp eax,DEV_STOP ;is never used. Mixer do this virtually, -; jne @f ;e.g. instead of stopping driver it -;if DEBUG ;outputs silence -; mov esi,msgStop -; call SysMsgBoardStr -;end if -; call sb_stop -; xor eax,eax -; ret -@@: - cmp eax,DEV_CALLBACK - jne @f -if DEBUG - mov esi,msgCallback - call SysMsgBoardStr -end if - mov edi,[edi+input] - mov eax,[edi] - mov [callback],eax -if DEBUG - call SysMsgBoardNum -end if - xor eax,eax - ret -@@: - cmp eax,DEV_SET_MASTERVOL ;Serge asked me to unlock - jne @F ;DEV_SET(GET)_MASTERVOL, although mixer doesn't use it. - ;It doesn't use it _in current version_ - but in the future... - -if DEBUG - mov esi,msgSetVol - call SysMsgBoardStr -end if - mov eax,[edi+input] - mov eax,[eax] - call sb_set_master_vol - xor eax,eax - ret -@@: - cmp eax,DEV_GET_MASTERVOL - jne @F -if DEBUG - mov esi,msgGetVol - call SysMsgBoardStr -end if - mov eax,[edi+output] - mov edx,[sb_master_vol] - mov [eax],edx - xor eax,eax - ret - -.fail: - or eax, -1 - ret -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - -;------------------------------------------------------------------------------- -align 4 -proc sb_irq - mov edx,[sb_base_port] ;tell the DSP that we have processed IRQ - add dl,0xF ;0xF for 16 bit sound, 0xE for 8 bit sound - in al,dx ;for non-stop sound - -pre_fill_data: - mov eax,int_flip_flop - not dword[eax] - mov eax,[eax] - test eax,eax - jns .fill_second_half - -if sb_buffer_size eq small_buffer - stdcall [callback],SB16Buffer0 ;for 32k buffer -else if sb_buffer_size eq full_buffer - stdcall [callback],SB16Buffer0 ;for 64k buffer - stdcall [callback],SB16Buffer1 ;for 64k buffer -end if - xor eax, eax - not eax - ret - -.fill_second_half: -if sb_buffer_size eq small_buffer - stdcall [callback],SB16Buffer1 ;for 32k buffer -else if sb_buffer_size eq full_buffer - stdcall [callback],SB16Buffer2 ;for 64k buffer - stdcall [callback],SB16Buffer3 ;for 64k buffer -end if - xor eax, eax - not eax - ret -endp -;------------------------------------------------------------------------------- -align 4 -proc detect -.sb_detect_next_port: -if DEBUG - inc dword[port_second_digit_num] -end if - mov edx,sb_base_port - add byte[edx],10h - cmp byte[edx],80h - jbe .sb_try_to_detect_at_specified_port -;error - no SB card detected -.sb_not_found_err: - xor eax, eax - ret - -.sb_try_to_detect_at_specified_port: - call sb_reset - add dl,8 - mov ecx,100 -.sb_check_port: - in al,dx - test al,al ;is DSP port ready to be read? - jns .sb_port_not_ready - - sub dl,4 - in al,dx ;check for AAh response - add dl,4 - cmp al,0xAA - jne .sb_port_not_ready -.sb_card_found: - and dl,0xF0 - add dl,0xC - sb_out 0xE1 ;get DSP version - add dl,2 -@@: - in al,dx - test al,al ;is DSP port ready to be read? - jns @b - sub dl,4 - in al,dx ;get major version - ror eax,16 - add dl,4 -@@: - in al,dx - test al,al ;is DSP port ready to be read? - jns @b - sub dl,4 - in al,dx ;get minor version - xor edx,edx - mov dl,10 - div dl - ror eax,16 - xor ah,ah - mov [sb_DSP_version_int],eax ;for internal usage -if DEBUG - add [sb_DSP_version],eax -end if - ret - -.sb_port_not_ready: - loop .sb_check_port ;100 retries (~100 microsec.) - jmp .sb_detect_next_port -endp -;------------------------------------------------------------------------------- -if DEBUG -proc SysMsgBoardNum ;warning: destroys eax,ebx,ecx,esi - mov ebx,eax - mov ecx,8 - mov esi,(number_to_out+1) -.1: - mov eax,ebx - and eax,0xF - add al,'0' - cmp al,(10+'0') - jb @f - add al,('A'-'0'-10) -@@: - mov [esi+ecx],al - shr ebx,4 - loop .1 - dec esi - call SysMsgBoardStr - ret -endp -end if -;all initialized data place here -align 4 -version dd (5 shl 16) or (API_VERSION and 0xFFFF) - -sb_base_port: dd 200h ;don't ask me why - see the code&docs - -sound_dma dd sb_dma_num - -;note that 4th DMA channel doesn't exist, it is used for cascade -;plugging the first DMA controler to the second -dma_table db 0x87,0x83,0x81,0x82,0xFF,0x8B,0x89,0x8A - -my_service db 'SOUND',0 ;max 16 chars include zero - -if DEBUG -number_to_out db '0x00000000',13,10,0 - -msgInit db 'detecting hardware...',13,10,0 -msgExit db 'exiting... May be some problems found?',13,10,0 -msgPlay db 'start play',13,10,0 -;msgStop db 'stop play',13,10,0 -msgCallback db 'set_callback received from the mixer!',13,10 - db 'callback handler is: ',0 -msgErrAtchIRQ db 'failed to attach IRQ',(sb_irq_num+'0'),13,10 - db 'owner',39,'s handler: ',0 -msgSucAtchIRQ db 'succesfully attached IRQ',(sb_irq_num+'0') - db ' as hardcoded',13,10,0 -msgErrRsrvPorts db 'failed to reserve needed ports.',13,10 - db 'Driver may work unstable',13,10,0 -msgSetVol db 'DEV_SET_MASTERVOL call came',13,10,0 -msgGetVol db 'DEV_GET_MASTERVOL call came',13,10,0 -msgErrDMAsetup db 'failed to setup DMA - bad channel',13,10,0 -;------------------------------------------------------------------------------- -msgDSPFound db 'DSP found at port 2' -label port_second_digit_num dword at $ - db '00h',13,10,'DSP version ' -sb_DSP_version: db '0.00 - SB' -sb_DSP_description: db 32,32,32,32,13,10,0 -;------------------------------------------------------------------------------- -end if - -section '.data' data readable writable align 16 -;all uninitialized data place here - -;pTempBuf rd 1 - -callback rd 1 - -int_flip_flop rd 1 - -sb_master_vol rd 1 - -sb_DSP_version_int rd 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +format MS COFF + +include 'CONFIG.INC' + +;structs---------------------------------------------------------- +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +;something-------------------------------------------------------- +public START +public service_proc +public version + +include '..\proc32.inc' +include '..\imports.inc' + +section '.flat' code readable align 16 + +include 'SB16.INC' + +;------------------------------------------------------------------------------- +proc START stdcall, state:dword + cmp [state], 1 + jne .stop +.entry: + +if DEBUG + mov esi, msgInit + call SysMsgBoardStr +end if + + call detect ;returns DSP version or zero if + test eax, eax ;SB card not found + jz .exit + +if DEBUG + movzx eax, al ;major version + mov esi, sb_DSP_description + dec eax + jz .sb_say_about_found_dsp + mov dword[esi], '2.x ' + dec eax + jz .sb_say_about_found_dsp + mov dword[esi], 'Pro ' + dec eax + jz .sb_say_about_found_dsp + mov dword[esi], '16 ' +.sb_say_about_found_dsp: + mov esi, msgDSPFound + call SysMsgBoardStr +end if +; xor eax,eax +; mov ebx,[sb_base_port] +; lea ecx,[ebx+0xF] + xor ebx, ebx + mov ecx, [sb_base_port] + lea edx, [ebx+0xF] + + call ReservePortArea ;these ports must be my! +if DEBUG + dec eax + jnz @f + mov esi, msgErrRsrvPorts + call SysMsgBoardStr +@@: +end if + + call sb_setup ;clock it, etc + + stdcall AttachIntHandler, sb_irq_num, sb_irq, 0 + +if DEBUG + test eax, eax + jnz @f + + mov esi, msgErrAtchIRQ + call SysMsgBoardStr + + stdcall GetIntHandler, sb_irq_num + call SysMsgBoardNum + + jmp .stop +@@: + mov esi, msgSucAtchIRQ + call SysMsgBoardStr +end if + stdcall RegService, my_service, service_proc + ret +.stop: + call sb_reset +.exit: + +if DEBUG + mov esi, msgExit + call SysMsgBoardStr +end if + + xor eax, eax + ret +endp +;------------------------------------------------------------------------------- + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + mov edi, [ioctl] + mov eax, [edi+io_code] + cmp eax, SRV_GETVERSION + jne @F + + mov eax, [edi+output] + cmp [edi+out_size], 4 + jne .fail + mov [eax], dword API_VERSION + xor eax, eax + ret +@@: + cmp eax, DEV_PLAY + jne @f +if DEBUG + mov esi, msgPlay + call SysMsgBoardStr +end if + call sb_stop ;to play smth new we must stop smth old + + call pre_fill_data ;fill first and second half of the buffer + call pre_fill_data ; + + call sb_set_dma ;is it really needed here? Paranoia. + call sb_play + xor eax, eax ;set maximum volume + call sb_set_master_vol + xor eax, eax + ret +;@@: ;all this commented stuff in service proc +; cmp eax,DEV_STOP ;is never used. Mixer do this virtually, +; jne @f ;e.g. instead of stopping driver it +;if DEBUG ;outputs silence +; mov esi,msgStop +; call SysMsgBoardStr +;end if +; call sb_stop +; xor eax,eax +; ret +@@: + cmp eax, DEV_CALLBACK + jne @f +if DEBUG + mov esi, msgCallback + call SysMsgBoardStr +end if + mov edi, [edi+input] + mov eax, [edi] + mov [callback], eax +if DEBUG + call SysMsgBoardNum +end if + xor eax, eax + ret +@@: + cmp eax, DEV_SET_MASTERVOL;Serge asked me to unlock + jne @F ;DEV_SET(GET)_MASTERVOL, although mixer doesn't use it. + ;It doesn't use it _in current version_ - but in the future... + +if DEBUG + mov esi, msgSetVol + call SysMsgBoardStr +end if + mov eax, [edi+input] + mov eax, [eax] + call sb_set_master_vol + xor eax, eax + ret +@@: + cmp eax, DEV_GET_MASTERVOL + jne @F +if DEBUG + mov esi, msgGetVol + call SysMsgBoardStr +end if + mov eax, [edi+output] + mov edx, [sb_master_vol] + mov [eax], edx + xor eax, eax + ret + +.fail: + or eax, -1 + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +;------------------------------------------------------------------------------- +align 4 +proc sb_irq + mov edx, [sb_base_port];tell the DSP that we have processed IRQ + add dl, 0xF ;0xF for 16 bit sound, 0xE for 8 bit sound + in al, dx ;for non-stop sound + +pre_fill_data: + mov eax, int_flip_flop + not dword[eax] + mov eax, [eax] + test eax, eax + jns .fill_second_half + +if sb_buffer_size eq small_buffer + stdcall [callback], SB16Buffer0 ;for 32k buffer +else if sb_buffer_size eq full_buffer + stdcall [callback], SB16Buffer0 ;for 64k buffer + stdcall [callback], SB16Buffer1 ;for 64k buffer +end if + xor eax, eax + not eax + ret + +.fill_second_half: +if sb_buffer_size eq small_buffer + stdcall [callback], SB16Buffer1 ;for 32k buffer +else if sb_buffer_size eq full_buffer + stdcall [callback], SB16Buffer2 ;for 64k buffer + stdcall [callback], SB16Buffer3 ;for 64k buffer +end if + xor eax, eax + not eax + ret +endp +;------------------------------------------------------------------------------- +align 4 +proc detect +.sb_detect_next_port: +if DEBUG + inc dword[port_second_digit_num] +end if + mov edx, sb_base_port + add byte[edx], 10h + cmp byte[edx], 80h + jbe .sb_try_to_detect_at_specified_port +;error - no SB card detected +.sb_not_found_err: + xor eax, eax + ret + +.sb_try_to_detect_at_specified_port: + call sb_reset + add dl, 8 + mov ecx, 100 +.sb_check_port: + in al, dx + test al, al ;is DSP port ready to be read? + jns .sb_port_not_ready + + sub dl, 4 + in al, dx ;check for AAh response + add dl, 4 + cmp al, 0xAA + jne .sb_port_not_ready +.sb_card_found: + and dl, 0xF0 + add dl, 0xC + sb_out 0xE1 ;get DSP version + add dl, 2 +@@: + in al, dx + test al, al ;is DSP port ready to be read? + jns @b + sub dl, 4 + in al, dx ;get major version + ror eax, 16 + add dl, 4 +@@: + in al, dx + test al, al ;is DSP port ready to be read? + jns @b + sub dl, 4 + in al, dx ;get minor version + xor edx, edx + mov dl, 10 + div dl + ror eax, 16 + xor ah, ah + mov [sb_DSP_version_int], eax;for internal usage +if DEBUG + add [sb_DSP_version], eax +end if + ret + +.sb_port_not_ready: + loop .sb_check_port ;100 retries (~100 microsec.) + jmp .sb_detect_next_port +endp +;------------------------------------------------------------------------------- +if DEBUG +proc SysMsgBoardNum ;warning: destroys eax,ebx,ecx,esi + mov ebx, eax + mov ecx, 8 + mov esi, (number_to_out+1) +.1: + mov eax, ebx + and eax, 0xF + add al, '0' + cmp al, (10+'0') + jb @f + add al, ('A'-'0'-10) +@@: + mov [esi+ecx], al + shr ebx, 4 + loop .1 + dec esi + call SysMsgBoardStr + ret +endp +end if +;all initialized data place here +align 4 +version dd (5 shl 16) or (API_VERSION and 0xFFFF) + +sb_base_port: + dd 200h ;don't ask me why - see the code&docs + +sound_dma dd sb_dma_num + +;note that 4th DMA channel doesn't exist, it is used for cascade +;plugging the first DMA controler to the second +dma_table db 0x87,0x83,0x81,0x82,0xFF,0x8B,0x89,0x8A + +my_service db 'SOUND',0 ;max 16 chars include zero + +if DEBUG +number_to_out db '0x00000000',13,10,0 + +msgInit db 'detecting hardware...',13,10,0 +msgExit db 'exiting... May be some problems found?',13,10,0 +msgPlay db 'start play',13,10,0 +;msgStop db 'stop play',13,10,0 +msgCallback db 'set_callback received from the mixer!',13,10 + db 'callback handler is: ',0 +msgErrAtchIRQ db 'failed to attach IRQ',(sb_irq_num+'0'),13,10 + db 'owner',39,'s handler: ',0 +msgSucAtchIRQ db 'succesfully attached IRQ',(sb_irq_num+'0') + db ' as hardcoded',13,10,0 +msgErrRsrvPorts db 'failed to reserve needed ports.',13,10 + db 'Driver may work unstable',13,10,0 +msgSetVol db 'DEV_SET_MASTERVOL call came',13,10,0 +msgGetVol db 'DEV_GET_MASTERVOL call came',13,10,0 +msgErrDMAsetup db 'failed to setup DMA - bad channel',13,10,0 +;------------------------------------------------------------------------------- +msgDSPFound db 'DSP found at port 2' +label port_second_digit_num dword at $ + db '00h',13,10,'DSP version ' +sb_DSP_version: + db '0.00 - SB' +sb_DSP_description: + db 32,32,32,32,13,10,0 +;------------------------------------------------------------------------------- +end if + +section '.data' data readable writable align 16 +;all uninitialized data place here + +;pTempBuf rd 1 + +callback rd 1 + +int_flip_flop rd 1 + +sb_master_vol rd 1 + +sb_DSP_version_int rd 1 diff --git a/kernel/trunk/drivers/sceletone.asm b/kernel/trunk/drivers/sceletone.asm index 2b3f06f75..892986fe9 100644 --- a/kernel/trunk/drivers/sceletone.asm +++ b/kernel/trunk/drivers/sceletone.asm @@ -1,173 +1,173 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;driver sceletone - -format MS COFF - -DEBUG equ 1 - -API_VERSION equ 0 ;debug - -include 'proc32.inc' -include 'imports.inc' - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -public START -public service_proc -public version - -DRV_ENTRY equ 1 -DRV_EXIT equ -1 -STRIDE equ 4 ;size of row in devices table - -SRV_GETVERSION equ 0 - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .exit -.entry: - - if DEBUG - mov esi, msgInit - call SysMsgBoardStr - end if - - stdcall RegService, my_service, service_proc - ret -.fail: -.exit: - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - - mov ebx, [ioctl] - mov eax, [ebx+io_code] - cmp eax, SRV_GETVERSION - jne @F - - mov eax, [ebx+output] - cmp [ebx+out_size], 4 - jne .fail - mov [eax], dword API_VERSION - xor eax, eax - ret -@@: -.fail: - or eax, -1 - ret -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - -align 4 -proc detect - locals - last_bus dd ? - endl - - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err - - mov [last_bus], eax - -.next_bus: - and [devfn], 0 -.next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next - - mov edi, devices -@@: - mov ebx, [edi] - test ebx, ebx - jz .next - - cmp eax, ebx - je .found - - add edi, STRIDE - jmp @B -.next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret -.found: - xor eax, eax - inc eax - ret -.err: - xor eax, eax - ret -endp - -DEVICE_ID equ 1234; pci device id -VENDOR_ID equ 5678; device vendor id - - -;all initialized data place here - -align 4 -devices dd (DEVICE_ID shl 16)+VENDOR_ID - dd 0 ;terminator - -version dd (5 shl 16) or (API_VERSION and 0xFFFF) - -my_service db 'MY_SERVICE',0 ;max 16 chars include zero - -msgInit db 'detect hardware...',13,10,0 -msgPCI db 'PCI accsess not supported',13,10,0 -msgFail db 'device not found',13,10,0 - -section '.data' data readable writable align 16 - -;all uninitialized data place here - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;driver sceletone + +format MS COFF + +DEBUG equ 1 + +API_VERSION equ 0 ;debug + +include 'proc32.inc' +include 'imports.inc' + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +public START +public service_proc +public version + +DRV_ENTRY equ 1 +DRV_EXIT equ -1 +STRIDE equ 4 ;size of row in devices table + +SRV_GETVERSION equ 0 + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .exit +.entry: + + if DEBUG + mov esi, msgInit + call SysMsgBoardStr + end if + + stdcall RegService, my_service, service_proc + ret +.fail: +.exit: + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + + mov ebx, [ioctl] + mov eax, [ebx+io_code] + cmp eax, SRV_GETVERSION + jne @F + + mov eax, [ebx+output] + cmp [ebx+out_size], 4 + jne .fail + mov [eax], dword API_VERSION + xor eax, eax + ret +@@: +.fail: + or eax, -1 + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +align 4 +proc detect + locals + last_bus dd ? + endl + + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err + + mov [last_bus], eax + +.next_bus: + and [devfn], 0 +.next_dev: + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next + + mov edi, devices +@@: + mov ebx, [edi] + test ebx, ebx + jz .next + + cmp eax, ebx + je .found + + add edi, STRIDE + jmp @B +.next: + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret +.found: + xor eax, eax + inc eax + ret +.err: + xor eax, eax + ret +endp + +DEVICE_ID equ 1234; pci device id +VENDOR_ID equ 5678; device vendor id + + +;all initialized data place here + +align 4 +devices dd (DEVICE_ID shl 16)+VENDOR_ID + dd 0 ;terminator + +version dd (5 shl 16) or (API_VERSION and 0xFFFF) + +my_service db 'MY_SERVICE',0 ;max 16 chars include zero + +msgInit db 'detect hardware...',13,10,0 +msgPCI db 'PCI accsess not supported',13,10,0 +msgFail db 'device not found',13,10,0 + +section '.data' data readable writable align 16 + +;all uninitialized data place here + diff --git a/kernel/trunk/drivers/sis.asm b/kernel/trunk/drivers/sis.asm index b0a2e8bee..927610926 100644 --- a/kernel/trunk/drivers/sis.asm +++ b/kernel/trunk/drivers/sis.asm @@ -1,1307 +1,1307 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -format MS COFF - - -DEBUG equ 1 - -include 'proc32.inc' -include 'imports.inc' - -API_VERSION equ 0x01000100 -DEBUG_IRQ equ 0 - -USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices -IRQ_REMAP equ 0 -IRQ_LINE equ 0 - - -;irq 0,1,2,8,12,13 недоступны -; FEDCBA9876543210 -VALID_IRQ equ 1100111011111000b -ATTCH_IRQ equ 0000111010100000b - -if USE_COM_IRQ -ATTCH_IRQ equ 0000111010111000b -end if - -CPU_FREQ equ 2600d - -BIT0 EQU 0x00000001 -BIT1 EQU 0x00000002 -BIT2 EQU 0x00000004 -BIT3 EQU 0x00000008 -BIT4 EQU 0x00000010 -BIT5 EQU 0x00000020 -BIT6 EQU 0x00000040 -BIT7 EQU 0x00000080 -BIT8 EQU 0x00000100 -BIT9 EQU 0x00000200 -BIT10 EQU 0x00000400 -BIT11 EQU 0x00000800 -BIT12 EQU 0x00001000 -BIT13 EQU 0x00002000 -BIT14 EQU 0x00004000 -BIT15 EQU 0x00008000 -BIT16 EQU 0x00010000 -BIT17 EQU 0x00020000 -BIT18 EQU 0x00040000 -BIT19 EQU 0x00080000 -BIT20 EQU 0x00100000 -BIT21 EQU 0x00200000 -BIT22 EQU 0x00400000 -BIT23 EQU 0x00800000 -BIT24 EQU 0x00100000 -BIT25 EQU 0x02000000 -BIT26 EQU 0x04000000 -BIT27 EQU 0x08000000 -BIT28 EQU 0x10000000 -BIT29 EQU 0x20000000 -BIT30 EQU 0x40000000 -BIT31 EQU 0x80000000 - -VID_SIS equ 0x1039 -CTRL_SIS equ 0x7012 - -PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list -PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register -PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index -PCM_OUT_SR_REG equ 0x18 ; PCM out Status register -PCM_OUT_PIV_REG equ 0x1a ; PCM out prefetched index -PCM_OUT_CIV_REG equ 0x14 ; PCM out current index - -PCM_IN_CR_REG equ 0x0b ; PCM in Control Register -MC_IN_CR_REG equ 0x2b ; MIC in Control Register -RR equ BIT1 ; reset registers. Nukes all regs - -CODEC_MASTER_VOL_REG equ 0x02 -CODEC_AUX_VOL equ 0x04 ; -CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume -CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio -CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control -CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate -CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate -CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate - -GLOB_CTRL equ 0x2C ; Global Control -CTRL_STAT equ 0x30 ; Global Status -CTRL_CAS equ 0x34 ; Codec Access Semiphore - -CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit - -CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready - -CTRL_ST_RCS equ 0x00008000 ; Read Completion Status - -CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable -CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off -CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset -CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset -CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable - -CODEC_REG_POWERDOWN equ 0x26 -CODEC_REG_ST equ 0x26 - -SRV_GETVERSION equ 0 -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_SET_BUFF equ 4 -DEV_NOTIFY equ 5 -DEV_SET_MASTERVOL equ 6 -DEV_GET_MASTERVOL equ 7 -DEV_GET_INFO equ 8 - -struc AC_CNTRL ;AC controller base class -{ .bus dd ? - .devfn dd ? - - .vendor dd ? - .dev_id dd ? - .pci_cmd dd ? - .pci_stat dd ? - - .codec_io_base dd ? - .codec_mem_base dd ? - - .ctrl_io_base dd ? - .ctrl_mem_base dd ? - .cfg_reg dd ? - .int_line dd ? - - .vendor_ids dd ? ;vendor id string - .ctrl_ids dd ? ;hub id string - - .buffer dd ? - - .notify_pos dd ? - .notify_task dd ? - - .lvi_reg dd ? - .ctrl_setup dd ? - .user_callback dd ? - .codec_read16 dd ? - .codec_write16 dd ? - - .ctrl_read8 dd ? - .ctrl_read16 dd ? - .ctrl_read32 dd ? - - .ctrl_write8 dd ? - .ctrl_write16 dd ? - .ctrl_write32 dd ? -} - -struc CODEC ;Audio Chip base class -{ - .chip_id dd ? - .flags dd ? - .status dd ? - - .ac_vendor_ids dd ? ;ac vendor id string - .chip_ids dd ? ;chip model string - - .shadow_flag dd ? - dd ? - - .regs dw ? ; codec registers - .reg_master_vol dw ? ;0x02 - .reg_aux_out_vol dw ? ;0x04 - .reg_mone_vol dw ? ;0x06 - .reg_master_tone dw ? ;0x08 - .reg_beep_vol dw ? ;0x0A - .reg_phone_vol dw ? ;0x0C - .reg_mic_vol dw ? ;0x0E - .reg_line_in_vol dw ? ;0x10 - .reg_cd_vol dw ? ;0x12 - .reg_video_vol dw ? ;0x14 - .reg_aux_in_vol dw ? ;0x16 - .reg_pcm_out_vol dw ? ;0x18 - .reg_rec_select dw ? ;0x1A - .reg_rec_gain dw ? ;0x1C - .reg_rec_gain_mic dw ? ;0x1E - .reg_gen dw ? ;0x20 - .reg_3d_ctrl dw ? ;0X22 - .reg_page dw ? ;0X24 - .reg_powerdown dw ? ;0x26 - .reg_ext_audio dw ? ;0x28 - .reg_ext_st dw ? ;0x2a - .reg_pcm_front_rate dw ? ;0x2c - .reg_pcm_surr_rate dw ? ;0x2e - .reg_lfe_rate dw ? ;0x30 - .reg_pcm_in_rate dw ? ;0x32 - dw ? ;0x34 - .reg_cent_lfe_vol dw ? ;0x36 - .reg_surr_vol dw ? ;0x38 - .reg_spdif_ctrl dw ? ;0x3A - dw ? ;0x3C - dw ? ;0x3E - dw ? ;0x40 - dw ? ;0x42 - dw ? ;0x44 - dw ? ;0x46 - dw ? ;0x48 - dw ? ;0x4A - dw ? ;0x4C - dw ? ;0x4E - dw ? ;0x50 - dw ? ;0x52 - dw ? ;0x54 - dw ? ;0x56 - dw ? ;0x58 - dw ? ;0x5A - dw ? ;0x5C - dw ? ;0x5E - .reg_page_0 dw ? ;0x60 - .reg_page_1 dw ? ;0x62 - .reg_page_2 dw ? ;0x64 - .reg_page_3 dw ? ;0x66 - .reg_page_4 dw ? ;0x68 - .reg_page_5 dw ? ;0x6A - .reg_page_6 dw ? ;0x6C - .reg_page_7 dw ? ;0x6E - dw ? ;0x70 - dw ? ;0x72 - dw ? ;0x74 - dw ? ;0x76 - dw ? ;0x78 - dw ? ;0x7A - .reg_vendor_id_1 dw ? ;0x7C - .reg_vendor_id_2 dw ? ;0x7E - - - .reset dd ? ;virual - .set_master_vol dd ? -} - -struc CTRL_INFO -{ .pci_cmd dd ? - .irq dd ? - .glob_cntrl dd ? - .glob_sta dd ? - .codec_io_base dd ? - .ctrl_io_base dd ? - .codec_mem_base dd ? - .ctrl_mem_base dd ? - .codec_id dd ? -} - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -EVENT_NOTIFY equ 0x00000200 - -public START -public service_proc -public version - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .stop - - if DEBUG - mov esi, msgInit - call SysMsgBoardStr - end if - - call detect_controller - test eax, eax - jz .fail - - if DEBUG - mov esi,[ctrl.vendor_ids] - call SysMsgBoardStr - mov esi, [ctrl.ctrl_ids] - call SysMsgBoardStr - - end if - - call init_controller - test eax, eax - jz .fail - - call init_codec - test eax, eax - jz .fail - - call reset_controller - call setup_codec - - mov esi, msgPrimBuff - call SysMsgBoardStr - call create_primary_buff - mov esi, msgDone - call SysMsgBoardStr - - if IRQ_REMAP - pushf - cli - - mov ebx, [ctrl.int_line] - in al, 0xA1 - mov ah, al - in al, 0x21 - test ebx, ebx - jz .skip - bts ax, bx ;mask old line -.skip - bts ax, IRQ_LINE ;mask new ine - out 0x21, al - mov al, ah - out 0xA1, al - ;remap IRQ - stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE - - mov dx, 0x4d0 ;8259 ELCR1 - in al, dx - bts ax, IRQ_LINE - out dx, al ;set level-triggered mode - mov [ctrl.int_line], IRQ_LINE - popf - mov esi, msgRemap - call SysMsgBoardStr - end if - - mov eax, VALID_IRQ - mov ebx, [ctrl.int_line] - mov esi, msgInvIRQ - bt eax, ebx - jnc .fail_msg - mov eax, ATTCH_IRQ - mov esi, msgAttchIRQ - bt eax, ebx - jnc .fail_msg - - stdcall AttachIntHandler, ebx, ac97_irq, dword 0 -.reg: - stdcall RegService, sz_sound_srv, service_proc - ret -.fail: - if DEBUG - mov esi, msgFail - call SysMsgBoardStr - end if - xor eax, eax - ret -.fail_msg: - call SysMsgBoardStr - xor eax, eax - ret -.stop: - call stop - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - - mov edi, [ioctl] - mov eax, [edi+io_code] - - cmp eax, SRV_GETVERSION - jne @F - - mov eax, [edi+output] - cmp [edi+out_size], 4 - jne .fail - - mov [eax], dword API_VERSION - xor eax, eax - ret -@@: - cmp eax, DEV_PLAY - jne @F - if DEBUG - mov esi, msgPlay - call SysMsgBoardStr - end if - call play - ret -@@: - cmp eax, DEV_STOP - jne @F - if DEBUG - mov esi, msgStop - call SysMsgBoardStr - end if - call stop - ret -@@: - cmp eax, DEV_CALLBACK - jne @F - mov ebx, [edi+input] - stdcall set_callback, [ebx] - ret -@@: - cmp eax, DEV_SET_MASTERVOL - jne @F - mov eax, [edi+input] - mov eax, [eax] - call set_master_vol ;eax= vol - ret -@@: - cmp eax, DEV_GET_MASTERVOL - jne @F - mov ebx, [edi+output] - stdcall get_master_vol, ebx - ret -;@@: -; cmp eax, DEV_GET_INFO -; jne @F -; mov ebx, [edi+output] -; stdcall get_dev_info, ebx -; ret -@@: -.fail: - or eax, -1 - ret -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - -align 4 -proc ac97_irq - - if DEBUG_IRQ - mov esi, msgIRQ - call SysMsgBoardStr - end if - - mov edx, PCM_OUT_CR_REG - mov al, 0x10 - call [ctrl.ctrl_write8] - - mov ax, 0x1c - mov edx, PCM_OUT_SR_REG - call [ctrl.ctrl_write16] - - mov edx, PCM_OUT_CIV_REG - call [ctrl.ctrl_read8] - - and eax, 0x1F - cmp eax, [civ_val] - je .skip - - mov [civ_val], eax - dec eax - and eax, 0x1F - mov [ctrl.lvi_reg], eax - - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - mov ax, 0x11 - call [ctrl.ctrl_write8] - - mov eax, [civ_val] - add eax, 1 - and eax, 31 - mov ebx, dword [buff_list+eax*4] - - cmp [ctrl.user_callback], 0 - je @f - - stdcall [ctrl.user_callback], ebx -@@: - ret - -.skip: - mov edx, PCM_OUT_CR_REG - mov ax, 0x11 - call [ctrl.ctrl_write8] - ret -endp - -align 4 -proc create_primary_buff - - stdcall KernelAlloc, 0x10000 - mov [ctrl.buffer], eax - - mov edi, eax - mov ecx, 0x10000/4 - xor eax, eax - cld - rep stosd - - mov eax, [ctrl.buffer] - call GetPgAddr - - mov ebx, 0xC0004000 - mov ecx, 4 - mov edi, pcmout_bdl -@@: - mov [edi], eax - mov [edi+4], ebx - - mov [edi+32], eax - mov [edi+4+32], ebx - - mov [edi+64], eax - mov [edi+4+64], ebx - - mov [edi+96], eax - mov [edi+4+96], ebx - - mov [edi+128], eax - mov [edi+4+128], ebx - - mov [edi+160], eax - mov [edi+4+160], ebx - - mov [edi+192], eax - mov [edi+4+192], ebx - - mov [edi+224], eax - mov [edi+4+224], ebx - - add eax, 0x4000 - add edi, 8 - loop @B - - mov edi, buff_list - mov eax, [ctrl.buffer] - mov ecx, 4 -@@: - mov [edi], eax - mov [edi+16], eax - mov [edi+32], eax - mov [edi+48], eax - mov [edi+64], eax - mov [edi+80], eax - mov [edi+96], eax - mov [edi+112], eax - - add eax, 0x4000 - add edi, 4 - loop @B - - mov eax, pcmout_bdl - mov ebx, eax - call GetPgAddr ;eax - and ebx, 0xFFF - add eax, ebx - - mov edx, PCM_OUT_BDL - call [ctrl.ctrl_write32] - - mov eax, 16 - mov [ctrl.lvi_reg], eax - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - and eax, not 0x000000C0 - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - ret -endp - -align 4 -proc detect_controller - locals - last_bus dd ? - bus dd ? - devfn dd ? - endl - - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err - - mov [last_bus], eax - -.next_bus: - and [devfn], 0 -.next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next - - mov edi, devices -@@: - mov ebx, [edi] - test ebx, ebx - jz .next - - cmp eax, ebx - je .found - add edi, 12 - jmp @B -.next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret -.found: - mov ebx, [bus] - mov [ctrl.bus], ebx - - mov ecx, [devfn] - mov [ctrl.devfn], ecx - - mov edx, eax - and edx, 0xFFFF - mov [ctrl.vendor], edx - shr eax, 16 - mov [ctrl.dev_id], eax - - mov ebx, [edi+4] - mov [ctrl.ctrl_ids], ebx - mov [ctrl.vendor_ids], msg_SIS - - mov esi, [edi+8] - mov [ctrl.ctrl_setup], esi - ret -.err: - xor eax, eax - ret -endp - -align 4 -proc init_controller - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 - mov ebx, eax - and eax, 0xFFFF - mov [ctrl.pci_cmd], eax - shr ebx, 16 - mov [ctrl.pci_stat], ebx - - mov esi, msgPciCmd - call SysMsgBoardStr - call dword2str - call SysMsgBoardStr - - mov esi, msgPciStat - call SysMsgBoardStr - mov eax, [ctrl.pci_stat] - call dword2str - call SysMsgBoardStr - - mov esi, msgMixIsaIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 - - call dword2str - call SysMsgBoardStr - - and eax,0xFFFE - mov [ctrl.codec_io_base], eax - - mov esi, msgCtrlIsaIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 - - call dword2str - call SysMsgBoardStr - - and eax, 0xFFC0 - mov [ctrl.ctrl_io_base], eax - - mov esi, msgMixMMIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 - mov [ctrl.codec_mem_base], eax - - call dword2str - call SysMsgBoardStr - - mov esi, msgCtrlMMIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C - mov [ctrl.ctrl_mem_base], eax - - call dword2str - call SysMsgBoardStr -.default: - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C - and eax, 0xFF -@@: - mov [ctrl.int_line], eax - - stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 - and eax, 0xFF - mov [ctrl.cfg_reg], eax - - call [ctrl.ctrl_setup] - xor eax, eax - inc eax - ret -endp - -align 4 -proc set_SIS - mov [ctrl.codec_read16], codec_io_r16 ;virtual - mov [ctrl.codec_write16], codec_io_w16 ;virtual - - mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual - mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual - mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual - - mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual - mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual - mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual - ret -endp - -align 4 -proc reset_controller - - xor eax, eax - mov edx, PCM_IN_CR_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - call [ctrl.ctrl_write8] - - mov edx, MC_IN_CR_REG - call [ctrl.ctrl_write8] - - mov eax, RR - mov edx, PCM_IN_CR_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - call [ctrl.ctrl_write8] - - mov edx, MC_IN_CR_REG - call [ctrl.ctrl_write8] - ret -endp - -align 4 -proc init_codec - locals - counter dd ? - endl - - mov esi, msgControl - call SysMsgBoardStr - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - call dword2str - call SysMsgBoardStr - - mov esi, msgStatus - call SysMsgBoardStr - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - push eax - call dword2str - call SysMsgBoardStr - pop eax - cmp eax, 0xFFFFFFFF - je .err - - test eax, CTRL_ST_CREADY - jnz .done ;;;;;.ready - - call reset_codec - test eax, eax - jz .err - -.ready: - xor edx, edx ;ac_reg_0 - call [ctrl.codec_write16] - - xor eax, eax - mov edx, CODEC_REG_POWERDOWN - call [ctrl.codec_write16] - - mov [counter], 200 ; total 200*5 ms = 1s -.wait: - mov eax, 5000 ; wait 5 ms - call StallExec - - mov edx, CODEC_REG_POWERDOWN - call [ctrl.codec_read16] - and eax, 0x0F - cmp eax, 0x0F - je .done - - sub [counter] , 1 - jnz .wait -.err: - xor eax, eax ; timeout error - ret -.done: - mov eax, 2 ;force set 16-bit 2-channel PCM - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - mov eax, 5000 ; wait 5 ms - call StallExec - - call detect_codec - - xor eax, eax - inc eax - ret -endp - -align 4 -proc reset_codec - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - - test eax, 0x02 - jz .cold - - call warm_reset - jnc .ok -.cold: - call cold_reset - jnc .ok - - if DEBUG - mov esi, msgCFail - call SysMsgBoardStr - end if - xor eax, eax ; timeout error - ret -.ok: - xor eax, eax - inc eax - ret -endp - -align 4 -proc warm_reset - locals - counter dd ? - endl - - mov eax, 0x06 - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - if DEBUG - mov esi, msgWarm - call SysMsgBoardStr - end if - - mov [counter], 10 ; total 10*100 ms = 1s -.wait: - mov eax, 100000 ; wait 100 ms - call StallExec - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - test eax, CTRL_ST_CREADY - jnz .ok - - dec [counter] - jnz .wait - - if DEBUG - mov esi, msgWRFail - call SysMsgBoardStr - end if -.fail: - stc - ret -.ok: - clc - ret -endp - -align 4 -proc cold_reset - locals - counter dd ? - endl - - mov eax, 0x02 - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - if DEBUG - mov esi, msgCold - call SysMsgBoardStr - end if - - mov eax, 400000 ; wait 400 ms - call StallExec - - mov [counter], 16 ; total 20*100 ms = 2s -.wait: - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - test eax, CTRL_ST_CREADY - jnz .ok - - mov eax, 100000 ; wait 100 ms - call StallExec - - dec [counter] - jnz .wait - - if DEBUG - mov esi, msgCRFail - call SysMsgBoardStr - end if - -.fail: - stc - ret -.ok: - mov esi, msgControl - call SysMsgBoardStr - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - call dword2str - call SysMsgBoardStr - - mov esi, msgStatus - call SysMsgBoardStr - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - push eax - call dword2str - call SysMsgBoardStr - pop eax - - test eax, CTRL_ST_CREADY - jz .fail - clc - ret -endp - -align 4 -play: - xor eax, eax - mov [civ_val], eax - mov edx, PCM_OUT_CIV_REG - call [ctrl.ctrl_write8] - - mov eax, 16 - mov [ctrl.lvi_reg], eax - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - mov ax, 0x1D - call [ctrl.ctrl_write8] - xor eax, eax - ret - -align 4 -stop: - mov edx, PCM_OUT_CR_REG - mov ax, 0x0 - call [ctrl.ctrl_write8] - - mov ax, 0x1c - mov edx, PCM_OUT_SR_REG - call [ctrl.ctrl_write16] - xor eax, eax - ret - -align 4 -proc get_dev_info stdcall, p_info:dword - virtual at esi - CTRL_INFO CTRL_INFO - end virtual - - mov esi, [p_info] - mov eax, [ctrl.int_line] - mov ebx, [ctrl.codec_io_base] - mov ecx, [ctrl.ctrl_io_base] - mov edx, [ctrl.codec_mem_base] - mov edi, [ctrl.ctrl_mem_base] - - mov [CTRL_INFO.irq], eax - mov [CTRL_INFO.codec_io_base], ebx - mov [CTRL_INFO.ctrl_io_base], ecx - mov [CTRL_INFO.codec_mem_base], edx - mov [CTRL_INFO.ctrl_mem_base], edi - - mov eax, [codec.chip_id] - mov [CTRL_INFO.codec_id], eax - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - mov [CTRL_INFO.glob_cntrl], eax - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - mov [CTRL_INFO.glob_sta], eax - - mov ebx, [ctrl.pci_cmd] - mov [CTRL_INFO.pci_cmd], ebx - ret -endp - -align 4 -proc set_callback stdcall, handler:dword - mov eax, [handler] - mov [ctrl.user_callback], eax - ret -endp - -align 4 -proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax - - mov edx, [ac_reg] - - mov ebx, edx - shr ebx, 1 - bt [codec.shadow_flag], ebx - jc .use_shadow - - call [ctrl.codec_read16] ;change edx !!! - mov ecx, eax - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - test eax, CTRL_ST_RCS - jz .read_ok - - mov edx, CTRL_STAT - call [ctrl.ctrl_write32] - xor eax,eax - not eax ;timeout - ret -.read_ok: - mov edx, [ac_reg] - mov [codec.regs+edx], cx - bts [codec.shadow_flag], ebx - mov eax, ecx - ret -.use_shadow: - movzx eax, word [codec.regs+edx] - ret -endp - -align 4 -proc codec_write stdcall, ac_reg:dword - push eax - call check_semafore - and eax, eax - jz .err - pop eax - - mov esi, [ac_reg] - mov edx, esi - call [ctrl.codec_write16] - mov [codec.regs+esi], ax - shr esi, 1 - bts [codec.shadow_flag], esi - ret -.err: - pop eax - ret -endp - -align 4 -proc codec_check_ready - - mov edx, CTRL_ST - call [ctrl.ctrl_read32] - and eax, CTRL_ST_CREADY - jz .not_ready - - xor eax, wax - inc eax - ret -.not_ready: - xor eax, eax - ret -endp - -align 4 -proc check_semafore - local counter:DWORD - - mov [counter], 100 -.l1: - mov edx, CTRL_CAS - call [ctrl.ctrl_read8] - and eax, CAS_FLAG - jz .ok - - mov eax, 1 - call StallExec - sub [counter], 1 - jnz .l1 - xor eax, eax - ret -align 4 -.ok: - xor eax,eax - inc eax - ret -endp - -align 4 -proc StallExec - push ecx - push edx - push ebx - push eax - - mov ecx, CPU_FREQ - mul ecx - mov ebx, eax ;low - mov ecx, edx ;high - rdtsc - add ebx, eax - adc ecx, edx -@@: - rdtsc - sub eax, ebx - sbb edx, ecx - js @B - - pop eax - pop ebx - pop edx - pop ecx - ret -endp - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; CONTROLLER IO functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -align 4 -proc codec_io_r16 - add edx, [ctrl.codec_io_base] - in ax, dx - ret -endp - -align 4 -proc codec_io_w16 - add edx, [ctrl.codec_io_base] - out dx, ax - ret -endp - -align 4 -proc ctrl_io_r8 - add edx, [ctrl.ctrl_io_base] - in al, dx - ret -endp - -align 4 -proc ctrl_io_r16 - add edx, [ctrl.ctrl_io_base] - in ax, dx - ret -endp - -align 4 -proc ctrl_io_r32 - add edx, [ctrl.ctrl_io_base] - in eax, dx - ret -endp - -align 4 -proc ctrl_io_w8 - add edx, [ctrl.ctrl_io_base] - out dx, al - ret -endp - -align 4 -proc ctrl_io_w16 - add edx, [ctrl.ctrl_io_base] - out dx, ax - ret -endp - -align 4 -proc ctrl_io_w32 - add edx, [ctrl.ctrl_io_base] - out dx, eax - ret -endp - -align 4 -dword2str: - mov esi, hex_buff - mov ecx, -8 -@@: - rol eax, 4 - mov ebx, eax - and ebx, 0x0F - mov bl, [ebx+hexletters] - mov [8+esi+ecx], bl - inc ecx - jnz @B - ret - -hexletters db '0123456789ABCDEF' -hex_buff db 8 dup(0),13,10,0 - -include "codec.inc" - -align 4 -devices dd (CTRL_SIS shl 16)+VID_SIS,msg_AC, set_SIS - dd 0 - -version dd (5 shl 16) or (API_VERSION and 0xFFFF) - -msg_AC db '7012 AC97 controller',13,10, 0 -msg_SIS db 'Silicon Integrated Systems',13,10, 0 - -sz_sound_srv db 'SOUND',0 - -msgInit db 'detect hardware...',13,10,0 -msgFail db 'device not found',13,10,0 -msgAttchIRQ db 'IRQ line not supported', 13,10, 0 -msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 -msgPlay db 'start play', 13,10,0 -msgStop db 'stop play', 13,10,0 -;msgNotify db 'call notify',13,10,0 -msgIRQ db 'AC97 IRQ', 13,10,0 -msgInitCtrl db 'init controller',13,10,0 -;msgInitCodec db 'init codec',13,10,0 -msgPrimBuff db 'create primary buffer ...',0 -msgDone db 'done',13,10,0 -msgRemap db 'Remap IRQ',13,10,0 -;msgReg db 'set service handler',13,10,0 -msgOk db 'service installed',13,10,0 -msgCold db 'cold reset',13,10,0 -msgWarm db 'warm reset',13,10,0 -msgWRFail db 'warm reset failed',13,10,0 -msgCRFail db 'cold reset failed',13,10,0 -msgCFail db 'codec not ready',13,10,0 -msgResetOk db 'reset complete',13,10,0 -msgStatus db 'global status ',0 -msgControl db 'global control ',0 -msgPciCmd db 'PCI command ',0 -msgPciStat db 'PCI status ',0 -msgCtrlIsaIo db 'controller io base ',0 -msgMixIsaIo db 'codec io base ',0 -msgCtrlMMIo db 'controller mmio base ',0 -msgMixMMIo db 'codec mmio base ',0 -msgIrqMap db 'AC97 irq map as ',0 - -section '.data' data readable writable align 16 - -pcmout_bdl rq 32 -buff_list rd 32 - -codec CODEC -ctrl AC_CNTRL - -lpc_bus rd 1 -civ_val rd 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +format MS COFF + + +DEBUG equ 1 + +include 'proc32.inc' +include 'imports.inc' + +API_VERSION equ 0x01000100 +DEBUG_IRQ equ 0 + +USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices +IRQ_REMAP equ 0 +IRQ_LINE equ 0 + + +;irq 0,1,2,8,12,13 недоступны +; FEDCBA9876543210 +VALID_IRQ equ 1100111011111000b +ATTCH_IRQ equ 0000111010100000b + +if USE_COM_IRQ +ATTCH_IRQ equ 0000111010111000b +end if + +CPU_FREQ equ 2600d + +BIT0 EQU 0x00000001 +BIT1 EQU 0x00000002 +BIT2 EQU 0x00000004 +BIT3 EQU 0x00000008 +BIT4 EQU 0x00000010 +BIT5 EQU 0x00000020 +BIT6 EQU 0x00000040 +BIT7 EQU 0x00000080 +BIT8 EQU 0x00000100 +BIT9 EQU 0x00000200 +BIT10 EQU 0x00000400 +BIT11 EQU 0x00000800 +BIT12 EQU 0x00001000 +BIT13 EQU 0x00002000 +BIT14 EQU 0x00004000 +BIT15 EQU 0x00008000 +BIT16 EQU 0x00010000 +BIT17 EQU 0x00020000 +BIT18 EQU 0x00040000 +BIT19 EQU 0x00080000 +BIT20 EQU 0x00100000 +BIT21 EQU 0x00200000 +BIT22 EQU 0x00400000 +BIT23 EQU 0x00800000 +BIT24 EQU 0x00100000 +BIT25 EQU 0x02000000 +BIT26 EQU 0x04000000 +BIT27 EQU 0x08000000 +BIT28 EQU 0x10000000 +BIT29 EQU 0x20000000 +BIT30 EQU 0x40000000 +BIT31 EQU 0x80000000 + +VID_SIS equ 0x1039 +CTRL_SIS equ 0x7012 + +PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list +PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register +PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index +PCM_OUT_SR_REG equ 0x18 ; PCM out Status register +PCM_OUT_PIV_REG equ 0x1a ; PCM out prefetched index +PCM_OUT_CIV_REG equ 0x14 ; PCM out current index + +PCM_IN_CR_REG equ 0x0b ; PCM in Control Register +MC_IN_CR_REG equ 0x2b ; MIC in Control Register +RR equ BIT1 ; reset registers. Nukes all regs + +CODEC_MASTER_VOL_REG equ 0x02 +CODEC_AUX_VOL equ 0x04 ; +CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume +CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio +CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control +CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate +CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate +CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate + +GLOB_CTRL equ 0x2C ; Global Control +CTRL_STAT equ 0x30 ; Global Status +CTRL_CAS equ 0x34 ; Codec Access Semiphore + +CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit + +CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready + +CTRL_ST_RCS equ 0x00008000 ; Read Completion Status + +CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable +CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off +CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset +CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset +CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable + +CODEC_REG_POWERDOWN equ 0x26 +CODEC_REG_ST equ 0x26 + +SRV_GETVERSION equ 0 +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_SET_BUFF equ 4 +DEV_NOTIFY equ 5 +DEV_SET_MASTERVOL equ 6 +DEV_GET_MASTERVOL equ 7 +DEV_GET_INFO equ 8 + +struc AC_CNTRL ;AC controller base class +{ .bus dd ? + .devfn dd ? + + .vendor dd ? + .dev_id dd ? + .pci_cmd dd ? + .pci_stat dd ? + + .codec_io_base dd ? + .codec_mem_base dd ? + + .ctrl_io_base dd ? + .ctrl_mem_base dd ? + .cfg_reg dd ? + .int_line dd ? + + .vendor_ids dd ? ;vendor id string + .ctrl_ids dd ? ;hub id string + + .buffer dd ? + + .notify_pos dd ? + .notify_task dd ? + + .lvi_reg dd ? + .ctrl_setup dd ? + .user_callback dd ? + .codec_read16 dd ? + .codec_write16 dd ? + + .ctrl_read8 dd ? + .ctrl_read16 dd ? + .ctrl_read32 dd ? + + .ctrl_write8 dd ? + .ctrl_write16 dd ? + .ctrl_write32 dd ? +} + +struc CODEC ;Audio Chip base class +{ + .chip_id dd ? + .flags dd ? + .status dd ? + + .ac_vendor_ids dd ? ;ac vendor id string + .chip_ids dd ? ;chip model string + + .shadow_flag dd ? + dd ? + + .regs dw ? ; codec registers + .reg_master_vol dw ? ;0x02 + .reg_aux_out_vol dw ? ;0x04 + .reg_mone_vol dw ? ;0x06 + .reg_master_tone dw ? ;0x08 + .reg_beep_vol dw ? ;0x0A + .reg_phone_vol dw ? ;0x0C + .reg_mic_vol dw ? ;0x0E + .reg_line_in_vol dw ? ;0x10 + .reg_cd_vol dw ? ;0x12 + .reg_video_vol dw ? ;0x14 + .reg_aux_in_vol dw ? ;0x16 + .reg_pcm_out_vol dw ? ;0x18 + .reg_rec_select dw ? ;0x1A + .reg_rec_gain dw ? ;0x1C + .reg_rec_gain_mic dw ? ;0x1E + .reg_gen dw ? ;0x20 + .reg_3d_ctrl dw ? ;0X22 + .reg_page dw ? ;0X24 + .reg_powerdown dw ? ;0x26 + .reg_ext_audio dw ? ;0x28 + .reg_ext_st dw ? ;0x2a + .reg_pcm_front_rate dw ? ;0x2c + .reg_pcm_surr_rate dw ? ;0x2e + .reg_lfe_rate dw ? ;0x30 + .reg_pcm_in_rate dw ? ;0x32 + dw ? ;0x34 + .reg_cent_lfe_vol dw ? ;0x36 + .reg_surr_vol dw ? ;0x38 + .reg_spdif_ctrl dw ? ;0x3A + dw ? ;0x3C + dw ? ;0x3E + dw ? ;0x40 + dw ? ;0x42 + dw ? ;0x44 + dw ? ;0x46 + dw ? ;0x48 + dw ? ;0x4A + dw ? ;0x4C + dw ? ;0x4E + dw ? ;0x50 + dw ? ;0x52 + dw ? ;0x54 + dw ? ;0x56 + dw ? ;0x58 + dw ? ;0x5A + dw ? ;0x5C + dw ? ;0x5E + .reg_page_0 dw ? ;0x60 + .reg_page_1 dw ? ;0x62 + .reg_page_2 dw ? ;0x64 + .reg_page_3 dw ? ;0x66 + .reg_page_4 dw ? ;0x68 + .reg_page_5 dw ? ;0x6A + .reg_page_6 dw ? ;0x6C + .reg_page_7 dw ? ;0x6E + dw ? ;0x70 + dw ? ;0x72 + dw ? ;0x74 + dw ? ;0x76 + dw ? ;0x78 + dw ? ;0x7A + .reg_vendor_id_1 dw ? ;0x7C + .reg_vendor_id_2 dw ? ;0x7E + + + .reset dd ? ;virual + .set_master_vol dd ? +} + +struc CTRL_INFO +{ .pci_cmd dd ? + .irq dd ? + .glob_cntrl dd ? + .glob_sta dd ? + .codec_io_base dd ? + .ctrl_io_base dd ? + .codec_mem_base dd ? + .ctrl_mem_base dd ? + .codec_id dd ? +} + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +EVENT_NOTIFY equ 0x00000200 + +public START +public service_proc +public version + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .stop + + if DEBUG + mov esi, msgInit + call SysMsgBoardStr + end if + + call detect_controller + test eax, eax + jz .fail + + if DEBUG + mov esi, [ctrl.vendor_ids] + call SysMsgBoardStr + mov esi, [ctrl.ctrl_ids] + call SysMsgBoardStr + + end if + + call init_controller + test eax, eax + jz .fail + + call init_codec + test eax, eax + jz .fail + + call reset_controller + call setup_codec + + mov esi, msgPrimBuff + call SysMsgBoardStr + call create_primary_buff + mov esi, msgDone + call SysMsgBoardStr + + if IRQ_REMAP + pushf + cli + + mov ebx, [ctrl.int_line] + in al, 0xA1 + mov ah, al + in al, 0x21 + test ebx, ebx + jz .skip + bts ax, bx ;mask old line +.skip + bts ax, IRQ_LINE ;mask new ine + out 0x21, al + mov al, ah + out 0xA1, al + ;remap IRQ + stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE + + mov dx, 0x4d0 ;8259 ELCR1 + in al, dx + bts ax, IRQ_LINE + out dx, al ;set level-triggered mode + mov [ctrl.int_line], IRQ_LINE + popf + mov esi, msgRemap + call SysMsgBoardStr + end if + + mov eax, VALID_IRQ + mov ebx, [ctrl.int_line] + mov esi, msgInvIRQ + bt eax, ebx + jnc .fail_msg + mov eax, ATTCH_IRQ + mov esi, msgAttchIRQ + bt eax, ebx + jnc .fail_msg + + stdcall AttachIntHandler, ebx, ac97_irq, dword 0 +.reg: + stdcall RegService, sz_sound_srv, service_proc + ret +.fail: + if DEBUG + mov esi, msgFail + call SysMsgBoardStr + end if + xor eax, eax + ret +.fail_msg: + call SysMsgBoardStr + xor eax, eax + ret +.stop: + call stop + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + + mov edi, [ioctl] + mov eax, [edi+io_code] + + cmp eax, SRV_GETVERSION + jne @F + + mov eax, [edi+output] + cmp [edi+out_size], 4 + jne .fail + + mov [eax], dword API_VERSION + xor eax, eax + ret +@@: + cmp eax, DEV_PLAY + jne @F + if DEBUG + mov esi, msgPlay + call SysMsgBoardStr + end if + call play + ret +@@: + cmp eax, DEV_STOP + jne @F + if DEBUG + mov esi, msgStop + call SysMsgBoardStr + end if + call stop + ret +@@: + cmp eax, DEV_CALLBACK + jne @F + mov ebx, [edi+input] + stdcall set_callback, [ebx] + ret +@@: + cmp eax, DEV_SET_MASTERVOL + jne @F + mov eax, [edi+input] + mov eax, [eax] + call set_master_vol ;eax= vol + ret +@@: + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + stdcall get_master_vol, ebx + ret +;@@: +; cmp eax, DEV_GET_INFO +; jne @F +; mov ebx, [edi+output] +; stdcall get_dev_info, ebx +; ret +@@: +.fail: + or eax, -1 + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +align 4 +proc ac97_irq + + if DEBUG_IRQ + mov esi, msgIRQ + call SysMsgBoardStr + end if + + mov edx, PCM_OUT_CR_REG + mov al, 0x10 + call [ctrl.ctrl_write8] + + mov ax, 0x1c + mov edx, PCM_OUT_SR_REG + call [ctrl.ctrl_write16] + + mov edx, PCM_OUT_CIV_REG + call [ctrl.ctrl_read8] + + and eax, 0x1F + cmp eax, [civ_val] + je .skip + + mov [civ_val], eax + dec eax + and eax, 0x1F + mov [ctrl.lvi_reg], eax + + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + mov ax, 0x11 + call [ctrl.ctrl_write8] + + mov eax, [civ_val] + add eax, 1 + and eax, 31 + mov ebx, dword [buff_list+eax*4] + + cmp [ctrl.user_callback], 0 + je @f + + stdcall [ctrl.user_callback], ebx +@@: + ret + +.skip: + mov edx, PCM_OUT_CR_REG + mov ax, 0x11 + call [ctrl.ctrl_write8] + ret +endp + +align 4 +proc create_primary_buff + + stdcall KernelAlloc, 0x10000 + mov [ctrl.buffer], eax + + mov edi, eax + mov ecx, 0x10000/4 + xor eax, eax + cld + rep stosd + + mov eax, [ctrl.buffer] + call GetPgAddr + + mov ebx, 0xC0004000 + mov ecx, 4 + mov edi, pcmout_bdl +@@: + mov [edi], eax + mov [edi+4], ebx + + mov [edi+32], eax + mov [edi+4+32], ebx + + mov [edi+64], eax + mov [edi+4+64], ebx + + mov [edi+96], eax + mov [edi+4+96], ebx + + mov [edi+128], eax + mov [edi+4+128], ebx + + mov [edi+160], eax + mov [edi+4+160], ebx + + mov [edi+192], eax + mov [edi+4+192], ebx + + mov [edi+224], eax + mov [edi+4+224], ebx + + add eax, 0x4000 + add edi, 8 + loop @B + + mov edi, buff_list + mov eax, [ctrl.buffer] + mov ecx, 4 +@@: + mov [edi], eax + mov [edi+16], eax + mov [edi+32], eax + mov [edi+48], eax + mov [edi+64], eax + mov [edi+80], eax + mov [edi+96], eax + mov [edi+112], eax + + add eax, 0x4000 + add edi, 4 + loop @B + + mov eax, pcmout_bdl + mov ebx, eax + call GetPgAddr ;eax + and ebx, 0xFFF + add eax, ebx + + mov edx, PCM_OUT_BDL + call [ctrl.ctrl_write32] + + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + and eax, not 0x000000C0 + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + ret +endp + +align 4 +proc detect_controller + locals + last_bus dd ? + bus dd ? + devfn dd ? + endl + + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err + + mov [last_bus], eax + +.next_bus: + and [devfn], 0 +.next_dev: + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next + + mov edi, devices +@@: + mov ebx, [edi] + test ebx, ebx + jz .next + + cmp eax, ebx + je .found + add edi, 12 + jmp @B +.next: + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret +.found: + mov ebx, [bus] + mov [ctrl.bus], ebx + + mov ecx, [devfn] + mov [ctrl.devfn], ecx + + mov edx, eax + and edx, 0xFFFF + mov [ctrl.vendor], edx + shr eax, 16 + mov [ctrl.dev_id], eax + + mov ebx, [edi+4] + mov [ctrl.ctrl_ids], ebx + mov [ctrl.vendor_ids], msg_SIS + + mov esi, [edi+8] + mov [ctrl.ctrl_setup], esi + ret +.err: + xor eax, eax + ret +endp + +align 4 +proc init_controller + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 + mov ebx, eax + and eax, 0xFFFF + mov [ctrl.pci_cmd], eax + shr ebx, 16 + mov [ctrl.pci_stat], ebx + + mov esi, msgPciCmd + call SysMsgBoardStr + call dword2str + call SysMsgBoardStr + + mov esi, msgPciStat + call SysMsgBoardStr + mov eax, [ctrl.pci_stat] + call dword2str + call SysMsgBoardStr + + mov esi, msgMixIsaIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 + + call dword2str + call SysMsgBoardStr + + and eax, 0xFFFE + mov [ctrl.codec_io_base], eax + + mov esi, msgCtrlIsaIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 + + call dword2str + call SysMsgBoardStr + + and eax, 0xFFC0 + mov [ctrl.ctrl_io_base], eax + + mov esi, msgMixMMIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 + mov [ctrl.codec_mem_base], eax + + call dword2str + call SysMsgBoardStr + + mov esi, msgCtrlMMIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C + mov [ctrl.ctrl_mem_base], eax + + call dword2str + call SysMsgBoardStr +.default: + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C + and eax, 0xFF +@@: + mov [ctrl.int_line], eax + + stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 + and eax, 0xFF + mov [ctrl.cfg_reg], eax + + call [ctrl.ctrl_setup] + xor eax, eax + inc eax + ret +endp + +align 4 +proc set_SIS + mov [ctrl.codec_read16], codec_io_r16 ;virtual + mov [ctrl.codec_write16], codec_io_w16 ;virtual + + mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual + mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual + mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual + + mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual + mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual + mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual + ret +endp + +align 4 +proc reset_controller + + xor eax, eax + mov edx, PCM_IN_CR_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + call [ctrl.ctrl_write8] + + mov edx, MC_IN_CR_REG + call [ctrl.ctrl_write8] + + mov eax, RR + mov edx, PCM_IN_CR_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + call [ctrl.ctrl_write8] + + mov edx, MC_IN_CR_REG + call [ctrl.ctrl_write8] + ret +endp + +align 4 +proc init_codec + locals + counter dd ? + endl + + mov esi, msgControl + call SysMsgBoardStr + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + call dword2str + call SysMsgBoardStr + + mov esi, msgStatus + call SysMsgBoardStr + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + push eax + call dword2str + call SysMsgBoardStr + pop eax + cmp eax, 0xFFFFFFFF + je .err + + test eax, CTRL_ST_CREADY + jnz .done ;;;;;.ready + + call reset_codec + test eax, eax + jz .err + +.ready: + xor edx, edx ;ac_reg_0 + call [ctrl.codec_write16] + + xor eax, eax + mov edx, CODEC_REG_POWERDOWN + call [ctrl.codec_write16] + + mov [counter], 200 ; total 200*5 ms = 1s +.wait: + mov eax, 5000 ; wait 5 ms + call StallExec + + mov edx, CODEC_REG_POWERDOWN + call [ctrl.codec_read16] + and eax, 0x0F + cmp eax, 0x0F + je .done + + sub [counter] , 1 + jnz .wait +.err: + xor eax, eax ; timeout error + ret +.done: + mov eax, 2 ;force set 16-bit 2-channel PCM + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + mov eax, 5000 ; wait 5 ms + call StallExec + + call detect_codec + + xor eax, eax + inc eax + ret +endp + +align 4 +proc reset_codec + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + + test eax, 0x02 + jz .cold + + call warm_reset + jnc .ok +.cold: + call cold_reset + jnc .ok + + if DEBUG + mov esi, msgCFail + call SysMsgBoardStr + end if + xor eax, eax ; timeout error + ret +.ok: + xor eax, eax + inc eax + ret +endp + +align 4 +proc warm_reset + locals + counter dd ? + endl + + mov eax, 0x06 + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + if DEBUG + mov esi, msgWarm + call SysMsgBoardStr + end if + + mov [counter], 10 ; total 10*100 ms = 1s +.wait: + mov eax, 100000 ; wait 100 ms + call StallExec + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + test eax, CTRL_ST_CREADY + jnz .ok + + dec [counter] + jnz .wait + + if DEBUG + mov esi, msgWRFail + call SysMsgBoardStr + end if +.fail: + stc + ret +.ok: + clc + ret +endp + +align 4 +proc cold_reset + locals + counter dd ? + endl + + mov eax, 0x02 + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + if DEBUG + mov esi, msgCold + call SysMsgBoardStr + end if + + mov eax, 400000 ; wait 400 ms + call StallExec + + mov [counter], 16 ; total 20*100 ms = 2s +.wait: + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + test eax, CTRL_ST_CREADY + jnz .ok + + mov eax, 100000 ; wait 100 ms + call StallExec + + dec [counter] + jnz .wait + + if DEBUG + mov esi, msgCRFail + call SysMsgBoardStr + end if + +.fail: + stc + ret +.ok: + mov esi, msgControl + call SysMsgBoardStr + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + call dword2str + call SysMsgBoardStr + + mov esi, msgStatus + call SysMsgBoardStr + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + push eax + call dword2str + call SysMsgBoardStr + pop eax + + test eax, CTRL_ST_CREADY + jz .fail + clc + ret +endp + +align 4 +play: + xor eax, eax + mov [civ_val], eax + mov edx, PCM_OUT_CIV_REG + call [ctrl.ctrl_write8] + + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + mov ax, 0x1D + call [ctrl.ctrl_write8] + xor eax, eax + ret + +align 4 +stop: + mov edx, PCM_OUT_CR_REG + mov ax, 0x0 + call [ctrl.ctrl_write8] + + mov ax, 0x1c + mov edx, PCM_OUT_SR_REG + call [ctrl.ctrl_write16] + xor eax, eax + ret + +align 4 +proc get_dev_info stdcall, p_info:dword + virtual at esi + CTRL_INFO CTRL_INFO + end virtual + + mov esi, [p_info] + mov eax, [ctrl.int_line] + mov ebx, [ctrl.codec_io_base] + mov ecx, [ctrl.ctrl_io_base] + mov edx, [ctrl.codec_mem_base] + mov edi, [ctrl.ctrl_mem_base] + + mov [CTRL_INFO.irq], eax + mov [CTRL_INFO.codec_io_base], ebx + mov [CTRL_INFO.ctrl_io_base], ecx + mov [CTRL_INFO.codec_mem_base], edx + mov [CTRL_INFO.ctrl_mem_base], edi + + mov eax, [codec.chip_id] + mov [CTRL_INFO.codec_id], eax + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + mov [CTRL_INFO.glob_cntrl], eax + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + mov [CTRL_INFO.glob_sta], eax + + mov ebx, [ctrl.pci_cmd] + mov [CTRL_INFO.pci_cmd], ebx + ret +endp + +align 4 +proc set_callback stdcall, handler:dword + mov eax, [handler] + mov [ctrl.user_callback], eax + ret +endp + +align 4 +proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax + + mov edx, [ac_reg] + + mov ebx, edx + shr ebx, 1 + bt [codec.shadow_flag], ebx + jc .use_shadow + + call [ctrl.codec_read16] ;change edx !!! + mov ecx, eax + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + test eax, CTRL_ST_RCS + jz .read_ok + + mov edx, CTRL_STAT + call [ctrl.ctrl_write32] + xor eax, eax + not eax ;timeout + ret +.read_ok: + mov edx, [ac_reg] + mov [codec.regs+edx], cx + bts [codec.shadow_flag], ebx + mov eax, ecx + ret +.use_shadow: + movzx eax, word [codec.regs+edx] + ret +endp + +align 4 +proc codec_write stdcall, ac_reg:dword + push eax + call check_semafore + and eax, eax + jz .err + pop eax + + mov esi, [ac_reg] + mov edx, esi + call [ctrl.codec_write16] + mov [codec.regs+esi], ax + shr esi, 1 + bts [codec.shadow_flag], esi + ret +.err: + pop eax + ret +endp + +align 4 +proc codec_check_ready + + mov edx, CTRL_ST + call [ctrl.ctrl_read32] + and eax, CTRL_ST_CREADY + jz .not_ready + + xor eax, wax + inc eax + ret +.not_ready: + xor eax, eax + ret +endp + +align 4 +proc check_semafore + local counter:DWORD + + mov [counter], 100 +.l1: + mov edx, CTRL_CAS + call [ctrl.ctrl_read8] + and eax, CAS_FLAG + jz .ok + + mov eax, 1 + call StallExec + sub [counter], 1 + jnz .l1 + xor eax, eax + ret +align 4 +.ok: + xor eax, eax + inc eax + ret +endp + +align 4 +proc StallExec + push ecx + push edx + push ebx + push eax + + mov ecx, CPU_FREQ + mul ecx + mov ebx, eax ;low + mov ecx, edx ;high + rdtsc + add ebx, eax + adc ecx, edx +@@: + rdtsc + sub eax, ebx + sbb edx, ecx + js @B + + pop eax + pop ebx + pop edx + pop ecx + ret +endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; CONTROLLER IO functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +proc codec_io_r16 + add edx, [ctrl.codec_io_base] + in ax, dx + ret +endp + +align 4 +proc codec_io_w16 + add edx, [ctrl.codec_io_base] + out dx, ax + ret +endp + +align 4 +proc ctrl_io_r8 + add edx, [ctrl.ctrl_io_base] + in al, dx + ret +endp + +align 4 +proc ctrl_io_r16 + add edx, [ctrl.ctrl_io_base] + in ax, dx + ret +endp + +align 4 +proc ctrl_io_r32 + add edx, [ctrl.ctrl_io_base] + in eax, dx + ret +endp + +align 4 +proc ctrl_io_w8 + add edx, [ctrl.ctrl_io_base] + out dx, al + ret +endp + +align 4 +proc ctrl_io_w16 + add edx, [ctrl.ctrl_io_base] + out dx, ax + ret +endp + +align 4 +proc ctrl_io_w32 + add edx, [ctrl.ctrl_io_base] + out dx, eax + ret +endp + +align 4 +dword2str: + mov esi, hex_buff + mov ecx, -8 +@@: + rol eax, 4 + mov ebx, eax + and ebx, 0x0F + mov bl, [ebx+hexletters] + mov [8+esi+ecx], bl + inc ecx + jnz @B + ret + +hexletters db '0123456789ABCDEF' +hex_buff db 8 dup(0),13,10,0 + +include "codec.inc" + +align 4 +devices dd (CTRL_SIS shl 16)+VID_SIS,msg_AC, set_SIS + dd 0 + +version dd (5 shl 16) or (API_VERSION and 0xFFFF) + +msg_AC db '7012 AC97 controller',13,10, 0 +msg_SIS db 'Silicon Integrated Systems',13,10, 0 + +sz_sound_srv db 'SOUND',0 + +msgInit db 'detect hardware...',13,10,0 +msgFail db 'device not found',13,10,0 +msgAttchIRQ db 'IRQ line not supported', 13,10, 0 +msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 +msgPlay db 'start play', 13,10,0 +msgStop db 'stop play', 13,10,0 +;msgNotify db 'call notify',13,10,0 +msgIRQ db 'AC97 IRQ', 13,10,0 +msgInitCtrl db 'init controller',13,10,0 +;msgInitCodec db 'init codec',13,10,0 +msgPrimBuff db 'create primary buffer ...',0 +msgDone db 'done',13,10,0 +msgRemap db 'Remap IRQ',13,10,0 +;msgReg db 'set service handler',13,10,0 +msgOk db 'service installed',13,10,0 +msgCold db 'cold reset',13,10,0 +msgWarm db 'warm reset',13,10,0 +msgWRFail db 'warm reset failed',13,10,0 +msgCRFail db 'cold reset failed',13,10,0 +msgCFail db 'codec not ready',13,10,0 +msgResetOk db 'reset complete',13,10,0 +msgStatus db 'global status ',0 +msgControl db 'global control ',0 +msgPciCmd db 'PCI command ',0 +msgPciStat db 'PCI status ',0 +msgCtrlIsaIo db 'controller io base ',0 +msgMixIsaIo db 'codec io base ',0 +msgCtrlMMIo db 'controller mmio base ',0 +msgMixMMIo db 'codec mmio base ',0 +msgIrqMap db 'AC97 irq map as ',0 + +section '.data' data readable writable align 16 + +pcmout_bdl rq 32 +buff_list rd 32 + +codec CODEC +ctrl AC_CNTRL + +lpc_bus rd 1 +civ_val rd 1 diff --git a/kernel/trunk/drivers/sound.asm b/kernel/trunk/drivers/sound.asm index 08cdc688e..c7e703d73 100644 --- a/kernel/trunk/drivers/sound.asm +++ b/kernel/trunk/drivers/sound.asm @@ -1,1507 +1,1507 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -format MS COFF - -DEBUG equ 1 - -include 'proc32.inc' -include 'imports.inc' - -API_VERSION equ 0x01000100 - -DEBUG_IRQ equ 0 - -USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices -IRQ_REMAP equ 0 -IRQ_LINE equ 0 - - -;irq 0,1,2,8,12,13 недоступны -; FEDCBA9876543210 -VALID_IRQ equ 1100111011111000b -ATTCH_IRQ equ 0000111010100000b - -if USE_COM_IRQ -ATTCH_IRQ equ 0000111010111000b -end if - -CPU_FREQ equ 2600d - -BIT0 EQU 0x00000001 -BIT1 EQU 0x00000002 -BIT2 EQU 0x00000004 -BIT3 EQU 0x00000008 -BIT4 EQU 0x00000010 -BIT5 EQU 0x00000020 -BIT6 EQU 0x00000040 -BIT7 EQU 0x00000080 -BIT8 EQU 0x00000100 -BIT9 EQU 0x00000200 -BIT10 EQU 0x00000400 -BIT11 EQU 0x00000800 -BIT12 EQU 0x00001000 -BIT13 EQU 0x00002000 -BIT14 EQU 0x00004000 -BIT15 EQU 0x00008000 -BIT16 EQU 0x00010000 -BIT17 EQU 0x00020000 -BIT18 EQU 0x00040000 -BIT19 EQU 0x00080000 -BIT20 EQU 0x00100000 -BIT21 EQU 0x00200000 -BIT22 EQU 0x00400000 -BIT23 EQU 0x00800000 -BIT24 EQU 0x00100000 -BIT25 EQU 0x02000000 -BIT26 EQU 0x04000000 -BIT27 EQU 0x08000000 -BIT28 EQU 0x10000000 -BIT29 EQU 0x20000000 -BIT30 EQU 0x40000000 -BIT31 EQU 0x80000000 - -PCM_4 equ BIT20 -PCM_6 equ BIT21 - -VID_INTEL equ 0x8086 -VID_NVIDIA equ 0x10DE - -CTRL_ICH equ 0x2415 -CTRL_ICH0 equ 0x2425 -CTRL_ICH2 equ 0x2435 -CTRL_ICH3 equ 0x2445 -CTRL_ICH4 equ 0x24C5 -CTRL_ICH5 equ 0x24D5 -CTRL_ICH6 equ 0x266E -CTRL_ICH7 equ 0x27DE - -CTRL_NFORCE equ 0x01B1 -CTRL_NFORCE2 equ 0x006A -CTRL_NFORCE3 equ 0x00DA -CTRL_MCP04 equ 0x003A -CTRL_CK804 equ 0x0059 -CTRL_CK8 equ 0x008A -CTRL_CK8S equ 0x00EA -CTRL_MCP51 equ 0x026B - - -PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list -PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register -PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index -PCM_OUT_SR_REG equ 0x16 ; PCM out Status register -PCM_OUT_PIV_REG equ 0x1a -PCM_OUT_CIV_REG equ 0x14 ; PCM out current index - -PCM_IN_CR_REG equ 0x0b ; PCM in Control Register -MC_IN_CR_REG equ 0x2b ; MIC in Control Register -RR equ BIT1 ; reset registers. Nukes all regs - -CODEC_MASTER_VOL_REG equ 0x02 -CODEC_AUX_VOL equ 0x04 ; -CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume -CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio -CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control -CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate -CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate -CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate - -GLOB_CTRL equ 0x2C ; Global Control -CTRL_STAT equ 0x30 ; Global Status -CTRL_CAS equ 0x34 ; Codec Access Semiphore - -CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit - -CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready - -CTRL_ST_RCS equ 0x00008000 ; Read Completion Status - -CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable -CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off -CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset -CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset -CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable - -CODEC_REG_POWERDOWN equ 0x26 -CODEC_REG_ST equ 0x26 - -SRV_GETVERSION equ 0 -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_SET_BUFF equ 4 -DEV_NOTIFY equ 5 -DEV_SET_MASTERVOL equ 6 -DEV_GET_MASTERVOL equ 7 -DEV_GET_INFO equ 8 -DEV_GET_POS equ 9 - -struc AC_CNTRL ;AC controller base class -{ .bus dd ? - .devfn dd ? - - .vendor dd ? - .dev_id dd ? - .pci_cmd dd ? - .pci_stat dd ? - - .codec_io_base dd ? - .codec_mem_base dd ? - - .ctrl_io_base dd ? - .ctrl_mem_base dd ? - .cfg_reg dd ? - .int_line dd ? - - .vendor_ids dd ? ;vendor id string - .ctrl_ids dd ? ;hub id string - - .buffer dd ? - - .notify_pos dd ? - .notify_task dd ? - - .lvi_reg dd ? - .ctrl_setup dd ? - .user_callback dd ? - .codec_read16 dd ? - .codec_write16 dd ? - - .ctrl_read8 dd ? - .ctrl_read16 dd ? - .ctrl_read32 dd ? - - .ctrl_write8 dd ? - .ctrl_write16 dd ? - .ctrl_write32 dd ? -} - -struc CODEC ;Audio Chip base class -{ - .chip_id dd ? - .flags dd ? - .status dd ? - - .ac_vendor_ids dd ? ;ac vendor id string - .chip_ids dd ? ;chip model string - - .shadow_flag dd ? - dd ? - - .regs dw ? ; codec registers - .reg_master_vol dw ? ;0x02 - .reg_aux_out_vol dw ? ;0x04 - .reg_mone_vol dw ? ;0x06 - .reg_master_tone dw ? ;0x08 - .reg_beep_vol dw ? ;0x0A - .reg_phone_vol dw ? ;0x0C - .reg_mic_vol dw ? ;0x0E - .reg_line_in_vol dw ? ;0x10 - .reg_cd_vol dw ? ;0x12 - .reg_video_vol dw ? ;0x14 - .reg_aux_in_vol dw ? ;0x16 - .reg_pcm_out_vol dw ? ;0x18 - .reg_rec_select dw ? ;0x1A - .reg_rec_gain dw ? ;0x1C - .reg_rec_gain_mic dw ? ;0x1E - .reg_gen dw ? ;0x20 - .reg_3d_ctrl dw ? ;0X22 - .reg_page dw ? ;0X24 - .reg_powerdown dw ? ;0x26 - .reg_ext_audio dw ? ;0x28 - .reg_ext_st dw ? ;0x2a - .reg_pcm_front_rate dw ? ;0x2c - .reg_pcm_surr_rate dw ? ;0x2e - .reg_lfe_rate dw ? ;0x30 - .reg_pcm_in_rate dw ? ;0x32 - dw ? ;0x34 - .reg_cent_lfe_vol dw ? ;0x36 - .reg_surr_vol dw ? ;0x38 - .reg_spdif_ctrl dw ? ;0x3A - dw ? ;0x3C - dw ? ;0x3E - dw ? ;0x40 - dw ? ;0x42 - dw ? ;0x44 - dw ? ;0x46 - dw ? ;0x48 - dw ? ;0x4A - dw ? ;0x4C - dw ? ;0x4E - dw ? ;0x50 - dw ? ;0x52 - dw ? ;0x54 - dw ? ;0x56 - dw ? ;0x58 - dw ? ;0x5A - dw ? ;0x5C - dw ? ;0x5E - .reg_page_0 dw ? ;0x60 - .reg_page_1 dw ? ;0x62 - .reg_page_2 dw ? ;0x64 - .reg_page_3 dw ? ;0x66 - .reg_page_4 dw ? ;0x68 - .reg_page_5 dw ? ;0x6A - .reg_page_6 dw ? ;0x6C - .reg_page_7 dw ? ;0x6E - dw ? ;0x70 - dw ? ;0x72 - dw ? ;0x74 - dw ? ;0x76 - dw ? ;0x78 - dw ? ;0x7A - .reg_vendor_id_1 dw ? ;0x7C - .reg_vendor_id_2 dw ? ;0x7E - - - .reset dd ? ;virual - .set_master_vol dd ? -} - -struc CTRL_INFO -{ .pci_cmd dd ? - .irq dd ? - .glob_cntrl dd ? - .glob_sta dd ? - .codec_io_base dd ? - .ctrl_io_base dd ? - .codec_mem_base dd ? - .ctrl_mem_base dd ? - .codec_id dd ? -} - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -EVENT_NOTIFY equ 0x00000200 - -public START -public service_proc -public version - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .stop - - if DEBUG - mov esi, msgInit - call SysMsgBoardStr - end if - - call detect_controller - test eax, eax - jz .fail - - if DEBUG - mov esi,[ctrl.vendor_ids] - call SysMsgBoardStr - mov esi, [ctrl.ctrl_ids] - call SysMsgBoardStr - - end if - - call init_controller - test eax, eax - jz .fail - - call init_codec - test eax, eax - jz .fail - - call reset_controller - call setup_codec - - mov esi, msgPrimBuff - call SysMsgBoardStr - call create_primary_buff - mov esi, msgDone - call SysMsgBoardStr - - if IRQ_REMAP - pushf - cli - - mov ebx, [ctrl.int_line] - in al, 0xA1 - mov ah, al - in al, 0x21 - test ebx, ebx - jz .skip - bts ax, bx ;mask old line -.skip - bts ax, IRQ_LINE ;mask new ine - out 0x21, al - mov al, ah - out 0xA1, al - ;remap IRQ - stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE - - mov dx, 0x4d0 ;8259 ELCR1 - in al, dx - bts ax, IRQ_LINE - out dx, al ;set level-triggered mode - mov [ctrl.int_line], IRQ_LINE - popf - mov esi, msgRemap - call SysMsgBoardStr - end if - - mov ebx, [ctrl.int_line] - stdcall AttachIntHandler, ebx, ac97_irq, dword 0 -.reg: - stdcall RegService, sz_sound_srv, service_proc - ret -.fail: - if DEBUG - mov esi, msgFail - call SysMsgBoardStr - end if - xor eax, eax - ret -.fail_msg: - call SysMsgBoardStr - xor eax, eax - ret -.stop: - call stop - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - - mov edi, [ioctl] - mov eax, [edi+io_code] - - cmp eax, SRV_GETVERSION - jne @F - - mov eax, [edi+output] - cmp [edi+out_size], 4 - jne .fail - - mov [eax], dword API_VERSION - xor eax, eax - ret -@@: - cmp eax, DEV_PLAY - jne @F - if DEBUG - mov esi, msgPlay - call SysMsgBoardStr - end if - call play - ret -@@: - cmp eax, DEV_STOP - jne @F - if DEBUG - mov esi, msgStop - call SysMsgBoardStr - end if - call stop - ret -@@: - cmp eax, DEV_CALLBACK - jne @F - mov ebx, [edi+input] - stdcall set_callback, [ebx] - ret -@@: - cmp eax, DEV_SET_MASTERVOL - jne @F - mov eax, [edi+input] - mov eax, [eax] - call set_master_vol ;eax= vol - ret -@@: - cmp eax, DEV_GET_MASTERVOL - jne @F - mov ebx, [edi+output] - stdcall get_master_vol, ebx - ret - -@@: - cmp eax, DEV_GET_POS - jne @F - - mov ebx, 8192 - mov edx, 0x18 - xor eax, eax - call [ctrl.ctrl_read16] - sub ebx, eax - shr ebx, 1 - mov edx, [edi+output] - mov [edx], ebx - xor eax, eax - ret -;@@: -; cmp eax, DEV_GET_INFO -; jne @F -; mov ebx, [edi+output] -; stdcall get_dev_info, ebx -; ret -@@: -.fail: - or eax, -1 - ret -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - -align 4 -proc ac97_irq - - if DEBUG_IRQ - mov esi, msgIRQ - call SysMsgBoardStr - end if - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - - cmp eax, 0xffffffff - je .exit - - test eax, 0x40 - jnz .do_intr - - test eax, eax - jz .exit - - mov edx, CTRL_STAT - call [ctrl.ctrl_write32] -.exit: - xor eax, eax - ret - -.do_intr: - push eax - - mov edx, PCM_OUT_CR_REG - mov al, 0x10; 0x10 - call [ctrl.ctrl_write8] - - mov ax, 0x1c - mov edx, PCM_OUT_SR_REG - call [ctrl.ctrl_write16] - - mov edx, PCM_OUT_CIV_REG - call [ctrl.ctrl_read8] - - and eax, 0x1F - cmp eax, [civ_val] - je .skip - - mov [civ_val], eax - dec eax - and eax, 0x1F - mov [ctrl.lvi_reg], eax - - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - mov ax, 0x11 ;0x1D - call [ctrl.ctrl_write8] - - mov eax, [civ_val] - add eax, 1 - and eax, 31 - mov ebx, dword [buff_list+eax*4] - - cmp [ctrl.user_callback], 0 - je .done - - stdcall [ctrl.user_callback], ebx -.done: - pop eax - and eax, 0x40 - mov edx, CTRL_STAT - call [ctrl.ctrl_write32] - or eax, 1 - ret -.skip: - mov edx, PCM_OUT_CR_REG - mov ax, 0x11 ;0x1D - call [ctrl.ctrl_write8] - jmp .done -endp - -align 4 -proc create_primary_buff - - stdcall KernelAlloc, 0x10000 - mov [ctrl.buffer], eax - - mov edi, eax - mov ecx, 0x10000/4 - xor eax, eax - cld - rep stosd - - mov eax, [ctrl.buffer] - call GetPgAddr - - mov ebx, 0xC0002000 - mov ecx, 4 - mov edi, pcmout_bdl -@@: - mov [edi], eax - mov [edi+4], ebx - - mov [edi+32], eax - mov [edi+4+32], ebx - - mov [edi+64], eax - mov [edi+4+64], ebx - - mov [edi+96], eax - mov [edi+4+96], ebx - - mov [edi+128], eax - mov [edi+4+128], ebx - - mov [edi+160], eax - mov [edi+4+160], ebx - - mov [edi+192], eax - mov [edi+4+192], ebx - - mov [edi+224], eax - mov [edi+4+224], ebx - - add eax, 0x4000 - add edi, 8 - loop @B - - mov edi, buff_list - mov eax, [ctrl.buffer] - mov ecx, 4 -@@: - mov [edi], eax - mov [edi+16], eax - mov [edi+32], eax - mov [edi+48], eax - mov [edi+64], eax - mov [edi+80], eax - mov [edi+96], eax - mov [edi+112], eax - - add eax, 0x4000 - add edi, 4 - loop @B - - mov eax, pcmout_bdl - mov ebx, eax - call GetPgAddr ;eax - and ebx, 0xFFF - add eax, ebx - - mov edx, PCM_OUT_BDL - call [ctrl.ctrl_write32] - - mov eax, 16 - mov [ctrl.lvi_reg], eax - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - ret -endp - -align 4 -proc detect_controller - locals - last_bus dd ? - bus dd ? - devfn dd ? - endl - - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err - - mov [last_bus], eax - -.next_bus: - and [devfn], 0 -.next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next - - mov edi, devices -@@: - mov ebx, [edi] - test ebx, ebx - jz .next - - cmp eax, ebx - je .found - add edi, 12 - jmp @B -.next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret -.found: - mov ebx, [bus] - mov [ctrl.bus], ebx - - mov ecx, [devfn] - mov [ctrl.devfn], ecx - - mov edx, eax - and edx, 0xFFFF - mov [ctrl.vendor], edx - shr eax, 16 - mov [ctrl.dev_id], eax - - mov ebx, [edi+4] - mov [ctrl.ctrl_ids], ebx - mov esi, [edi+8] - mov [ctrl.ctrl_setup], esi - - cmp edx, VID_INTEL - jne @F - mov [ctrl.vendor_ids], msg_Intel - ret -@@: - cmp edx, VID_NVIDIA - jne @F - mov [ctrl.vendor_ids], msg_NVidia - ret -@@: -.err: - xor eax, eax - mov [ctrl.vendor_ids], eax ;something wrong ? - ret -endp - -align 4 -proc init_controller - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 - mov ebx, eax - and eax, 0xFFFF - mov [ctrl.pci_cmd], eax - shr ebx, 16 - mov [ctrl.pci_stat], ebx - - mov esi, msgPciCmd - call SysMsgBoardStr - call dword2str - call SysMsgBoardStr - - mov esi, msgPciStat - call SysMsgBoardStr - mov eax, [ctrl.pci_stat] - call dword2str - call SysMsgBoardStr - - mov esi, msgMixIsaIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 - - call dword2str - call SysMsgBoardStr - - and eax,0xFFFE - mov [ctrl.codec_io_base], eax - - mov esi, msgCtrlIsaIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 - - call dword2str - call SysMsgBoardStr - - and eax, 0xFFC0 - mov [ctrl.ctrl_io_base], eax - - mov esi, msgMixMMIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 - mov [ctrl.codec_mem_base], eax - - call dword2str - call SysMsgBoardStr - - mov esi, msgCtrlMMIo - call SysMsgBoardStr - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C - mov [ctrl.ctrl_mem_base], eax - - call dword2str - call SysMsgBoardStr - -if 0 - -;;patch for some ugly BIOS ICH-ICH5 compatible - cmp [ctrl.vendor], VID_INTEL - jne .default - - mov esi, msgIrqMap - call SysMsgBoardStr - stdcall PciRead8, 0, 0xF8, 0x61 - and eax, 0xFF - call dword2str - call SysMsgBoardStr - btr eax, 7 ;when bit 7 set remap disabled - jnc @F - xor eax, eax - jmp @F -end if - -.default: - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C - and eax, 0xFF -@@: - mov [ctrl.int_line], eax - - stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 - and eax, 0xFF - mov [ctrl.cfg_reg], eax - - mov [ctrl.user_callback], 0 - - call [ctrl.ctrl_setup] - xor eax, eax - inc eax - ret -endp - -align 4 -proc set_ICH - mov [ctrl.codec_read16], codec_io_r16 ;virtual - mov [ctrl.codec_write16], codec_io_w16 ;virtual - - mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual - mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual - mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual - - mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual - mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual - mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual - ret -endp - -PG_SW equ 0x003 -PG_NOCACHE equ 0x018 - -align 4 -proc set_ICH4 - - stdcall MapIoMem,[ctrl.codec_mem_base],0x1000,PG_SW+PG_NOCACHE - mov [ctrl.codec_mem_base], eax - - stdcall MapIoMem,[ctrl.ctrl_mem_base],0x1000,PG_SW+PG_NOCACHE - mov [ctrl.ctrl_mem_base], eax - - mov [ctrl.codec_read16], codec_mem_r16 ;virtual - mov [ctrl.codec_write16], codec_mem_w16 ;virtual - - mov [ctrl.ctrl_read8 ], ctrl_mem_r8 ;virtual - mov [ctrl.ctrl_read16], ctrl_mem_r16 ;virtual - mov [ctrl.ctrl_read32], ctrl_mem_r32 ;virtual - - mov [ctrl.ctrl_write8 ], ctrl_mem_w8 ;virtual - mov [ctrl.ctrl_write16], ctrl_mem_w16 ;virtual - mov [ctrl.ctrl_write32], ctrl_mem_w32 ;virtual - ret -endp - -align 4 -proc reset_controller - - xor eax, eax - mov edx, PCM_IN_CR_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - call [ctrl.ctrl_write8] - - mov edx, MC_IN_CR_REG - call [ctrl.ctrl_write8] - - mov eax, RR - mov edx, PCM_IN_CR_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - call [ctrl.ctrl_write8] - - mov edx, MC_IN_CR_REG - call [ctrl.ctrl_write8] - ret -endp - -align 4 -proc init_codec - locals - counter dd ? - endl - - mov esi, msgControl - call SysMsgBoardStr - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - call dword2str - call SysMsgBoardStr - - mov esi, msgStatus - call SysMsgBoardStr - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - push eax - call dword2str - call SysMsgBoardStr - pop eax - cmp eax, 0xFFFFFFFF - je .err - - test eax, CTRL_ST_CREADY - jnz .ready - - call reset_codec - test eax, eax - jz .err - -.ready: - xor edx, edx ;ac_reg_0 - call [ctrl.codec_write16] - - xor eax, eax - mov edx, CODEC_REG_POWERDOWN - call [ctrl.codec_write16] - - mov [counter], 200 ; total 200*5 ms = 1s -.wait: - mov eax, 5000 ; wait 5 ms - call StallExec - - mov edx, CODEC_REG_POWERDOWN - call [ctrl.codec_read16] - and eax, 0x0F - cmp eax, 0x0F - jz .done - - sub [counter] , 1 - jnz .wait -.err: - xor eax, eax ; timeout error - ret -.done: - mov eax, 2 ;force set 16-bit 2-channel PCM - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - mov eax, 5000 ; wait 5 ms - call StallExec - - call detect_codec - - xor eax, eax - inc eax - ret -endp - -align 4 -proc reset_codec - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - - test eax, 0x02 - jz .cold - - call warm_reset - jnc .ok -.cold: - call cold_reset - jnc .ok - - if DEBUG - mov esi, msgCFail - call SysMsgBoardStr - end if - xor eax, eax ; timeout error - ret -.ok: - if DEBUG - mov esi, msgResetOk - call SysMsgBoardStr - end if - - xor eax, eax - inc eax - ret -endp - -align 4 -proc warm_reset - locals - counter dd ? - endl - - mov eax, 0x06 - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - if DEBUG - mov esi, msgWarm - call SysMsgBoardStr - end if - - mov [counter], 10 ; total 10*100 ms = 1s -.wait: - mov eax, 100000 ; wait 100 ms - call StallExec - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - test eax, CTRL_ST_CREADY - jnz .ok - - dec [counter] - jnz .wait - - if DEBUG - mov esi, msgWRFail - call SysMsgBoardStr - end if -.fail: - stc - ret -.ok: - clc - ret -endp - -align 4 -proc cold_reset - locals - counter dd ? - endl - - mov eax, 0x02 - mov edx, GLOB_CTRL - call [ctrl.ctrl_write32] - - if DEBUG - mov esi, msgCold - call SysMsgBoardStr - end if - - mov eax, 400000 ; wait 400 ms - call StallExec - - mov [counter], 16 ; total 20*100 ms = 2s -.wait: - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - test eax, CTRL_ST_CREADY - jnz .ok - - mov eax, 100000 ; wait 100 ms - call StallExec - - dec [counter] - jnz .wait - - if DEBUG - mov esi, msgCRFail - call SysMsgBoardStr - end if - -.fail: - stc - ret -.ok: - mov esi, msgControl - call SysMsgBoardStr - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - call dword2str - call SysMsgBoardStr - - mov esi, msgStatus - call SysMsgBoardStr - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - push eax - call dword2str - call SysMsgBoardStr - pop eax - - test eax, CTRL_ST_CREADY - jz .fail - clc - ret -endp - -align 4 -play: - mov eax, 16 - mov [ctrl.lvi_reg], eax - mov edx, PCM_OUT_LVI_REG - call [ctrl.ctrl_write8] - - mov edx, PCM_OUT_CR_REG - mov ax, 0x1D - call [ctrl.ctrl_write8] - xor eax, eax - ret - -align 4 -stop: - mov edx, PCM_OUT_CR_REG - mov ax, 0x0 - call [ctrl.ctrl_write8] - - mov ax, 0x1c - mov edx, PCM_OUT_SR_REG - call [ctrl.ctrl_write16] - xor eax, eax - ret - -align 4 -proc get_dev_info stdcall, p_info:dword - virtual at esi - CTRL_INFO CTRL_INFO - end virtual - - mov esi, [p_info] - mov eax, [ctrl.int_line] - mov ebx, [ctrl.codec_io_base] - mov ecx, [ctrl.ctrl_io_base] - mov edx, [ctrl.codec_mem_base] - mov edi, [ctrl.ctrl_mem_base] - - mov [CTRL_INFO.irq], eax - mov [CTRL_INFO.codec_io_base], ebx - mov [CTRL_INFO.ctrl_io_base], ecx - mov [CTRL_INFO.codec_mem_base], edx - mov [CTRL_INFO.ctrl_mem_base], edi - - mov eax, [codec.chip_id] - mov [CTRL_INFO.codec_id], eax - - mov edx, GLOB_CTRL - call [ctrl.ctrl_read32] - mov [CTRL_INFO.glob_cntrl], eax - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - mov [CTRL_INFO.glob_sta], eax - - mov ebx, [ctrl.pci_cmd] - mov [CTRL_INFO.pci_cmd], ebx - ret -endp - -align 4 -proc set_callback stdcall, handler:dword - mov eax, [handler] - mov [ctrl.user_callback], eax - ret -endp - -align 4 -proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax - - mov edx, [ac_reg] - - mov ebx, edx - shr ebx, 1 - bt [codec.shadow_flag], ebx - jc .use_shadow - - call [ctrl.codec_read16] ;change edx !!! - mov ecx, eax - - mov edx, CTRL_STAT - call [ctrl.ctrl_read32] - test eax, CTRL_ST_RCS - jz .read_ok - - mov edx, CTRL_STAT - call [ctrl.ctrl_write32] - xor eax,eax - not eax ;timeout - ret -.read_ok: - mov edx, [ac_reg] - mov [codec.regs+edx], cx - bts [codec.shadow_flag], ebx - mov eax, ecx - ret -.use_shadow: - movzx eax, word [codec.regs+edx] - ret -endp - -align 4 -proc codec_write stdcall, ac_reg:dword - push eax - call check_semafore - and eax, eax - jz .err - pop eax - - mov esi, [ac_reg] - mov edx, esi - call [ctrl.codec_write16] - mov [codec.regs+esi], ax - shr esi, 1 - bts [codec.shadow_flag], esi - ret -.err: - pop eax - ret -endp - -align 4 -proc codec_check_ready - - mov edx, CTRL_ST - call [ctrl.ctrl_read32] - and eax, CTRL_ST_CREADY - jz .not_ready - - xor eax, wax - inc eax - ret -.not_ready: - xor eax, eax - ret -endp - -align 4 -proc check_semafore - local counter:DWORD - - mov [counter], 100 -.l1: - mov edx, CTRL_CAS - call [ctrl.ctrl_read8] - and eax, CAS_FLAG - jz .ok - - mov eax, 1 - call StallExec - sub [counter], 1 - jnz .l1 - xor eax, eax - ret -align 4 -.ok: - xor eax,eax - inc eax - ret -endp - -align 4 -proc StallExec - push ecx - push edx - push ebx - push eax - - mov ecx, CPU_FREQ - mul ecx - mov ebx, eax ;low - mov ecx, edx ;high - rdtsc - add ebx, eax - adc ecx,edx -@@: - rdtsc - sub eax, ebx - sbb edx, ecx - js @B - - pop eax - pop ebx - pop edx - pop ecx - ret -endp - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; CONTROLLER IO functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -align 4 -proc codec_io_r16 - add edx, [ctrl.codec_io_base] - in ax, dx - ret -endp - -align 4 -proc codec_io_w16 - add edx, [ctrl.codec_io_base] - out dx, ax - ret -endp - -align 4 -proc ctrl_io_r8 - add edx, [ctrl.ctrl_io_base] - in al, dx - ret -endp - -align 4 -proc ctrl_io_r16 - add edx, [ctrl.ctrl_io_base] - in ax, dx - ret -endp - -align 4 -proc ctrl_io_r32 - add edx, [ctrl.ctrl_io_base] - in eax, dx - ret -endp - -align 4 -proc ctrl_io_w8 - add edx, [ctrl.ctrl_io_base] - out dx, al - ret -endp - -align 4 -proc ctrl_io_w16 - add edx, [ctrl.ctrl_io_base] - out dx, ax - ret -endp - -align 4 -proc ctrl_io_w32 - add edx, [ctrl.ctrl_io_base] - out dx, eax - ret -endp - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; MEMORY MAPPED IO (os depended) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -align 4 -proc codec_mem_r16 - add edx, [ctrl.codec_mem_base] - mov ax, word [edx] - ret -endp - -align 4 -proc codec_mem_w16 - add edx, [ctrl.codec_mem_base] - mov word [edx], ax - ret -endp - -align 4 -proc ctrl_mem_r8 - add edx, [ctrl.ctrl_mem_base] - mov al, [edx] - ret -endp - -align 4 -proc ctrl_mem_r16 - add edx, [ctrl.ctrl_mem_base] - mov ax, [edx] - ret -endp - -align 4 -proc ctrl_mem_r32 - add edx, [ctrl.ctrl_mem_base] - mov eax, [edx] - ret -endp - -align 4 -proc ctrl_mem_w8 - add edx, [ctrl.ctrl_mem_base] - mov [edx], al - ret -endp - -align 4 -proc ctrl_mem_w16 - add edx, [ctrl.ctrl_mem_base] - mov [edx], ax - ret -endp - -align 4 -proc ctrl_mem_w32 - add edx, [ctrl.ctrl_mem_base] - mov [edx], eax - ret -endp - -align 4 -dword2str: - mov esi, hex_buff - mov ecx, -8 -@@: - rol eax, 4 - mov ebx, eax - and ebx, 0x0F - mov bl, [ebx+hexletters] - mov [8+esi+ecx], bl - inc ecx - jnz @B - ret - -hexletters db '0123456789ABCDEF' -hex_buff db 8 dup(0),13,10,0 - - -include "codec.inc" - -align 4 -devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH - dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH - dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH - dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH - dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4 - dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4 - dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4 - dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4 - - dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH - dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH - dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH - dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH - dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH - dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH - dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH - dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH - - dd 0 ;terminator - - -version dd (5 shl 16) or (API_VERSION and 0xFFFF) - -msg_ICH db '802801AA (ICH)', 13,10, 0 -msg_ICH0 db '802801AB (ICH0)', 13,10, 0 -msg_ICH2 db '802801BA (ICH2)', 13,10, 0 -msg_ICH3 db '802801CA (ICH3)', 13,10, 0 -msg_ICH4 db '802801DB (ICH4)', 13,10, 0 -msg_ICH5 db '802801EB (ICH5)', 13,10, 0 -msg_ICH6 db '802801FB (ICH6)', 13,10, 0 -msg_ICH7 db '802801GB (ICH7)', 13,10, 0 -msg_Intel db 'Intel ', 0 - -msg_NForce db 'NForce', 13,10, 0 -msg_NForce2 db 'NForce 2', 13,10, 0 -msg_NForce3 db 'NForce 3', 13,10, 0 -msg_MCP04 db 'NForce MCP04',13,10, 0 -msg_CK804 db 'NForce CK804',13,10, 0 -msg_CK8 db 'NForce CK8', 13,10, 0 -msg_CK8S db 'NForce CK8S', 13,10, 0 -msg_MCP51 db 'NForce MCP51',13,10, 0 - -msg_NVidia db 'NVidia', 0 - -szKernel db 'KERNEL', 0 -sz_sound_srv db 'SOUND',0 - -msgInit db 'detect hardware...',13,10,0 -msgFail db 'device not found',13,10,0 -msgAttchIRQ db 'IRQ line not supported', 13,10, 0 -msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 -msgPlay db 'start play', 13,10,0 -msgStop db 'stop play', 13,10,0 -;msgNotify db 'call notify',13,10,0 -msgIRQ db 'AC97 IRQ', 13,10,0 -msgInitCtrl db 'init controller',13,10,0 -;msgInitCodec db 'init codec',13,10,0 -msgPrimBuff db 'create primary buffer ...',0 -msgDone db 'done',13,10,0 -msgRemap db 'Remap IRQ',13,10,0 -;msgReg db 'set service handler',13,10,0 -msgOk db 'service installed',13,10,0 -msgCold db 'cold reset',13,10,0 -msgWarm db 'warm reset',13,10,0 -msgWRFail db 'warm reset failed',13,10,0 -msgCRFail db 'cold reset failed',13,10,0 -msgCFail db 'codec not ready',13,10,0 -msgResetOk db 'reset complete',13,10,0 -msgStatus db 'global status ',0 -msgControl db 'global control ',0 -msgPciCmd db 'PCI command ',0 -msgPciStat db 'PCI status ',0 -msgCtrlIsaIo db 'controller io base ',0 -msgMixIsaIo db 'codec io base ',0 -msgCtrlMMIo db 'controller mmio base ',0 -msgMixMMIo db 'codec mmio base ',0 -msgIrqMap db 'AC97 irq map as ',0 - -section '.data' data readable writable align 16 - -pcmout_bdl rq 32 -buff_list rd 32 - -codec CODEC -ctrl AC_CNTRL - -lpc_bus rd 1 -civ_val rd 1 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +format MS COFF + +DEBUG equ 1 + +include 'proc32.inc' +include 'imports.inc' + +API_VERSION equ 0x01000100 + +DEBUG_IRQ equ 0 + +USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices +IRQ_REMAP equ 0 +IRQ_LINE equ 0 + + +;irq 0,1,2,8,12,13 недоступны +; FEDCBA9876543210 +VALID_IRQ equ 1100111011111000b +ATTCH_IRQ equ 0000111010100000b + +if USE_COM_IRQ +ATTCH_IRQ equ 0000111010111000b +end if + +CPU_FREQ equ 2600d + +BIT0 EQU 0x00000001 +BIT1 EQU 0x00000002 +BIT2 EQU 0x00000004 +BIT3 EQU 0x00000008 +BIT4 EQU 0x00000010 +BIT5 EQU 0x00000020 +BIT6 EQU 0x00000040 +BIT7 EQU 0x00000080 +BIT8 EQU 0x00000100 +BIT9 EQU 0x00000200 +BIT10 EQU 0x00000400 +BIT11 EQU 0x00000800 +BIT12 EQU 0x00001000 +BIT13 EQU 0x00002000 +BIT14 EQU 0x00004000 +BIT15 EQU 0x00008000 +BIT16 EQU 0x00010000 +BIT17 EQU 0x00020000 +BIT18 EQU 0x00040000 +BIT19 EQU 0x00080000 +BIT20 EQU 0x00100000 +BIT21 EQU 0x00200000 +BIT22 EQU 0x00400000 +BIT23 EQU 0x00800000 +BIT24 EQU 0x00100000 +BIT25 EQU 0x02000000 +BIT26 EQU 0x04000000 +BIT27 EQU 0x08000000 +BIT28 EQU 0x10000000 +BIT29 EQU 0x20000000 +BIT30 EQU 0x40000000 +BIT31 EQU 0x80000000 + +PCM_4 equ BIT20 +PCM_6 equ BIT21 + +VID_INTEL equ 0x8086 +VID_NVIDIA equ 0x10DE + +CTRL_ICH equ 0x2415 +CTRL_ICH0 equ 0x2425 +CTRL_ICH2 equ 0x2435 +CTRL_ICH3 equ 0x2445 +CTRL_ICH4 equ 0x24C5 +CTRL_ICH5 equ 0x24D5 +CTRL_ICH6 equ 0x266E +CTRL_ICH7 equ 0x27DE + +CTRL_NFORCE equ 0x01B1 +CTRL_NFORCE2 equ 0x006A +CTRL_NFORCE3 equ 0x00DA +CTRL_MCP04 equ 0x003A +CTRL_CK804 equ 0x0059 +CTRL_CK8 equ 0x008A +CTRL_CK8S equ 0x00EA +CTRL_MCP51 equ 0x026B + + +PCM_OUT_BDL equ 0x10 ; PCM out buffer descriptors list +PCM_OUT_CR_REG equ 0x1b ; PCM out Control Register +PCM_OUT_LVI_REG equ 0x15 ; PCM last valid index +PCM_OUT_SR_REG equ 0x16 ; PCM out Status register +PCM_OUT_PIV_REG equ 0x1a +PCM_OUT_CIV_REG equ 0x14 ; PCM out current index + +PCM_IN_CR_REG equ 0x0b ; PCM in Control Register +MC_IN_CR_REG equ 0x2b ; MIC in Control Register +RR equ BIT1 ; reset registers. Nukes all regs + +CODEC_MASTER_VOL_REG equ 0x02 +CODEC_AUX_VOL equ 0x04 ; +CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume +CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio +CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control +CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate +CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate +CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate + +GLOB_CTRL equ 0x2C ; Global Control +CTRL_STAT equ 0x30 ; Global Status +CTRL_CAS equ 0x34 ; Codec Access Semiphore + +CAS_FLAG equ 0x01 ; Codec Access Semiphore Bit + +CTRL_ST_CREADY equ BIT8+BIT9+BIT28 ; Primary Codec Ready + +CTRL_ST_RCS equ 0x00008000 ; Read Completion Status + +CTRL_CNT_CRIE equ BIT4+BIT5+BIT6 ; Codecs Resume Interrupt Enable +CTRL_CNT_AC_OFF equ 0x00000008 ; ACLINK Off +CTRL_CNT_WARM equ 0x00000004 ; AC97 Warm Reset +CTRL_CNT_COLD equ 0x00000002 ; AC97 Cold Reset +CTRL_CNT_GIE equ 0x00000001 ; GPI Interrupt Enable + +CODEC_REG_POWERDOWN equ 0x26 +CODEC_REG_ST equ 0x26 + +SRV_GETVERSION equ 0 +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_SET_BUFF equ 4 +DEV_NOTIFY equ 5 +DEV_SET_MASTERVOL equ 6 +DEV_GET_MASTERVOL equ 7 +DEV_GET_INFO equ 8 +DEV_GET_POS equ 9 + +struc AC_CNTRL ;AC controller base class +{ .bus dd ? + .devfn dd ? + + .vendor dd ? + .dev_id dd ? + .pci_cmd dd ? + .pci_stat dd ? + + .codec_io_base dd ? + .codec_mem_base dd ? + + .ctrl_io_base dd ? + .ctrl_mem_base dd ? + .cfg_reg dd ? + .int_line dd ? + + .vendor_ids dd ? ;vendor id string + .ctrl_ids dd ? ;hub id string + + .buffer dd ? + + .notify_pos dd ? + .notify_task dd ? + + .lvi_reg dd ? + .ctrl_setup dd ? + .user_callback dd ? + .codec_read16 dd ? + .codec_write16 dd ? + + .ctrl_read8 dd ? + .ctrl_read16 dd ? + .ctrl_read32 dd ? + + .ctrl_write8 dd ? + .ctrl_write16 dd ? + .ctrl_write32 dd ? +} + +struc CODEC ;Audio Chip base class +{ + .chip_id dd ? + .flags dd ? + .status dd ? + + .ac_vendor_ids dd ? ;ac vendor id string + .chip_ids dd ? ;chip model string + + .shadow_flag dd ? + dd ? + + .regs dw ? ; codec registers + .reg_master_vol dw ? ;0x02 + .reg_aux_out_vol dw ? ;0x04 + .reg_mone_vol dw ? ;0x06 + .reg_master_tone dw ? ;0x08 + .reg_beep_vol dw ? ;0x0A + .reg_phone_vol dw ? ;0x0C + .reg_mic_vol dw ? ;0x0E + .reg_line_in_vol dw ? ;0x10 + .reg_cd_vol dw ? ;0x12 + .reg_video_vol dw ? ;0x14 + .reg_aux_in_vol dw ? ;0x16 + .reg_pcm_out_vol dw ? ;0x18 + .reg_rec_select dw ? ;0x1A + .reg_rec_gain dw ? ;0x1C + .reg_rec_gain_mic dw ? ;0x1E + .reg_gen dw ? ;0x20 + .reg_3d_ctrl dw ? ;0X22 + .reg_page dw ? ;0X24 + .reg_powerdown dw ? ;0x26 + .reg_ext_audio dw ? ;0x28 + .reg_ext_st dw ? ;0x2a + .reg_pcm_front_rate dw ? ;0x2c + .reg_pcm_surr_rate dw ? ;0x2e + .reg_lfe_rate dw ? ;0x30 + .reg_pcm_in_rate dw ? ;0x32 + dw ? ;0x34 + .reg_cent_lfe_vol dw ? ;0x36 + .reg_surr_vol dw ? ;0x38 + .reg_spdif_ctrl dw ? ;0x3A + dw ? ;0x3C + dw ? ;0x3E + dw ? ;0x40 + dw ? ;0x42 + dw ? ;0x44 + dw ? ;0x46 + dw ? ;0x48 + dw ? ;0x4A + dw ? ;0x4C + dw ? ;0x4E + dw ? ;0x50 + dw ? ;0x52 + dw ? ;0x54 + dw ? ;0x56 + dw ? ;0x58 + dw ? ;0x5A + dw ? ;0x5C + dw ? ;0x5E + .reg_page_0 dw ? ;0x60 + .reg_page_1 dw ? ;0x62 + .reg_page_2 dw ? ;0x64 + .reg_page_3 dw ? ;0x66 + .reg_page_4 dw ? ;0x68 + .reg_page_5 dw ? ;0x6A + .reg_page_6 dw ? ;0x6C + .reg_page_7 dw ? ;0x6E + dw ? ;0x70 + dw ? ;0x72 + dw ? ;0x74 + dw ? ;0x76 + dw ? ;0x78 + dw ? ;0x7A + .reg_vendor_id_1 dw ? ;0x7C + .reg_vendor_id_2 dw ? ;0x7E + + + .reset dd ? ;virual + .set_master_vol dd ? +} + +struc CTRL_INFO +{ .pci_cmd dd ? + .irq dd ? + .glob_cntrl dd ? + .glob_sta dd ? + .codec_io_base dd ? + .ctrl_io_base dd ? + .codec_mem_base dd ? + .ctrl_mem_base dd ? + .codec_id dd ? +} + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +EVENT_NOTIFY equ 0x00000200 + +public START +public service_proc +public version + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .stop + + if DEBUG + mov esi, msgInit + call SysMsgBoardStr + end if + + call detect_controller + test eax, eax + jz .fail + + if DEBUG + mov esi, [ctrl.vendor_ids] + call SysMsgBoardStr + mov esi, [ctrl.ctrl_ids] + call SysMsgBoardStr + + end if + + call init_controller + test eax, eax + jz .fail + + call init_codec + test eax, eax + jz .fail + + call reset_controller + call setup_codec + + mov esi, msgPrimBuff + call SysMsgBoardStr + call create_primary_buff + mov esi, msgDone + call SysMsgBoardStr + + if IRQ_REMAP + pushf + cli + + mov ebx, [ctrl.int_line] + in al, 0xA1 + mov ah, al + in al, 0x21 + test ebx, ebx + jz .skip + bts ax, bx ;mask old line +.skip + bts ax, IRQ_LINE ;mask new ine + out 0x21, al + mov al, ah + out 0xA1, al + ;remap IRQ + stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE + + mov dx, 0x4d0 ;8259 ELCR1 + in al, dx + bts ax, IRQ_LINE + out dx, al ;set level-triggered mode + mov [ctrl.int_line], IRQ_LINE + popf + mov esi, msgRemap + call SysMsgBoardStr + end if + + mov ebx, [ctrl.int_line] + stdcall AttachIntHandler, ebx, ac97_irq, dword 0 +.reg: + stdcall RegService, sz_sound_srv, service_proc + ret +.fail: + if DEBUG + mov esi, msgFail + call SysMsgBoardStr + end if + xor eax, eax + ret +.fail_msg: + call SysMsgBoardStr + xor eax, eax + ret +.stop: + call stop + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + + mov edi, [ioctl] + mov eax, [edi+io_code] + + cmp eax, SRV_GETVERSION + jne @F + + mov eax, [edi+output] + cmp [edi+out_size], 4 + jne .fail + + mov [eax], dword API_VERSION + xor eax, eax + ret +@@: + cmp eax, DEV_PLAY + jne @F + if DEBUG + mov esi, msgPlay + call SysMsgBoardStr + end if + call play + ret +@@: + cmp eax, DEV_STOP + jne @F + if DEBUG + mov esi, msgStop + call SysMsgBoardStr + end if + call stop + ret +@@: + cmp eax, DEV_CALLBACK + jne @F + mov ebx, [edi+input] + stdcall set_callback, [ebx] + ret +@@: + cmp eax, DEV_SET_MASTERVOL + jne @F + mov eax, [edi+input] + mov eax, [eax] + call set_master_vol ;eax= vol + ret +@@: + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + stdcall get_master_vol, ebx + ret + +@@: + cmp eax, DEV_GET_POS + jne @F + + mov ebx, 8192 + mov edx, 0x18 + xor eax, eax + call [ctrl.ctrl_read16] + sub ebx, eax + shr ebx, 1 + mov edx, [edi+output] + mov [edx], ebx + xor eax, eax + ret +;@@: +; cmp eax, DEV_GET_INFO +; jne @F +; mov ebx, [edi+output] +; stdcall get_dev_info, ebx +; ret +@@: +.fail: + or eax, -1 + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +align 4 +proc ac97_irq + + if DEBUG_IRQ + mov esi, msgIRQ + call SysMsgBoardStr + end if + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + + cmp eax, 0xffffffff + je .exit + + test eax, 0x40 + jnz .do_intr + + test eax, eax + jz .exit + + mov edx, CTRL_STAT + call [ctrl.ctrl_write32] +.exit: + xor eax, eax + ret + +.do_intr: + push eax + + mov edx, PCM_OUT_CR_REG + mov al, 0x10; 0x10 + call [ctrl.ctrl_write8] + + mov ax, 0x1c + mov edx, PCM_OUT_SR_REG + call [ctrl.ctrl_write16] + + mov edx, PCM_OUT_CIV_REG + call [ctrl.ctrl_read8] + + and eax, 0x1F + cmp eax, [civ_val] + je .skip + + mov [civ_val], eax + dec eax + and eax, 0x1F + mov [ctrl.lvi_reg], eax + + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + mov ax, 0x11 ;0x1D + call [ctrl.ctrl_write8] + + mov eax, [civ_val] + add eax, 1 + and eax, 31 + mov ebx, dword [buff_list+eax*4] + + cmp [ctrl.user_callback], 0 + je .done + + stdcall [ctrl.user_callback], ebx +.done: + pop eax + and eax, 0x40 + mov edx, CTRL_STAT + call [ctrl.ctrl_write32] + or eax, 1 + ret +.skip: + mov edx, PCM_OUT_CR_REG + mov ax, 0x11 ;0x1D + call [ctrl.ctrl_write8] + jmp .done +endp + +align 4 +proc create_primary_buff + + stdcall KernelAlloc, 0x10000 + mov [ctrl.buffer], eax + + mov edi, eax + mov ecx, 0x10000/4 + xor eax, eax + cld + rep stosd + + mov eax, [ctrl.buffer] + call GetPgAddr + + mov ebx, 0xC0002000 + mov ecx, 4 + mov edi, pcmout_bdl +@@: + mov [edi], eax + mov [edi+4], ebx + + mov [edi+32], eax + mov [edi+4+32], ebx + + mov [edi+64], eax + mov [edi+4+64], ebx + + mov [edi+96], eax + mov [edi+4+96], ebx + + mov [edi+128], eax + mov [edi+4+128], ebx + + mov [edi+160], eax + mov [edi+4+160], ebx + + mov [edi+192], eax + mov [edi+4+192], ebx + + mov [edi+224], eax + mov [edi+4+224], ebx + + add eax, 0x4000 + add edi, 8 + loop @B + + mov edi, buff_list + mov eax, [ctrl.buffer] + mov ecx, 4 +@@: + mov [edi], eax + mov [edi+16], eax + mov [edi+32], eax + mov [edi+48], eax + mov [edi+64], eax + mov [edi+80], eax + mov [edi+96], eax + mov [edi+112], eax + + add eax, 0x4000 + add edi, 4 + loop @B + + mov eax, pcmout_bdl + mov ebx, eax + call GetPgAddr ;eax + and ebx, 0xFFF + add eax, ebx + + mov edx, PCM_OUT_BDL + call [ctrl.ctrl_write32] + + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + ret +endp + +align 4 +proc detect_controller + locals + last_bus dd ? + bus dd ? + devfn dd ? + endl + + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err + + mov [last_bus], eax + +.next_bus: + and [devfn], 0 +.next_dev: + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next + + mov edi, devices +@@: + mov ebx, [edi] + test ebx, ebx + jz .next + + cmp eax, ebx + je .found + add edi, 12 + jmp @B +.next: + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret +.found: + mov ebx, [bus] + mov [ctrl.bus], ebx + + mov ecx, [devfn] + mov [ctrl.devfn], ecx + + mov edx, eax + and edx, 0xFFFF + mov [ctrl.vendor], edx + shr eax, 16 + mov [ctrl.dev_id], eax + + mov ebx, [edi+4] + mov [ctrl.ctrl_ids], ebx + mov esi, [edi+8] + mov [ctrl.ctrl_setup], esi + + cmp edx, VID_INTEL + jne @F + mov [ctrl.vendor_ids], msg_Intel + ret +@@: + cmp edx, VID_NVIDIA + jne @F + mov [ctrl.vendor_ids], msg_NVidia + ret +@@: +.err: + xor eax, eax + mov [ctrl.vendor_ids], eax ;something wrong ? + ret +endp + +align 4 +proc init_controller + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 + mov ebx, eax + and eax, 0xFFFF + mov [ctrl.pci_cmd], eax + shr ebx, 16 + mov [ctrl.pci_stat], ebx + + mov esi, msgPciCmd + call SysMsgBoardStr + call dword2str + call SysMsgBoardStr + + mov esi, msgPciStat + call SysMsgBoardStr + mov eax, [ctrl.pci_stat] + call dword2str + call SysMsgBoardStr + + mov esi, msgMixIsaIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 + + call dword2str + call SysMsgBoardStr + + and eax, 0xFFFE + mov [ctrl.codec_io_base], eax + + mov esi, msgCtrlIsaIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x14 + + call dword2str + call SysMsgBoardStr + + and eax, 0xFFC0 + mov [ctrl.ctrl_io_base], eax + + mov esi, msgMixMMIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x18 + mov [ctrl.codec_mem_base], eax + + call dword2str + call SysMsgBoardStr + + mov esi, msgCtrlMMIo + call SysMsgBoardStr + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x1C + mov [ctrl.ctrl_mem_base], eax + + call dword2str + call SysMsgBoardStr + +if 0 + +;;patch for some ugly BIOS ICH-ICH5 compatible + cmp [ctrl.vendor], VID_INTEL + jne .default + + mov esi, msgIrqMap + call SysMsgBoardStr + stdcall PciRead8, 0, 0xF8, 0x61 + and eax, 0xFF + call dword2str + call SysMsgBoardStr + btr eax, 7 ;when bit 7 set remap disabled + jnc @F + xor eax, eax + jmp @F +end if + +.default: + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C + and eax, 0xFF +@@: + mov [ctrl.int_line], eax + + stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword 0x41 + and eax, 0xFF + mov [ctrl.cfg_reg], eax + + mov [ctrl.user_callback], 0 + + call [ctrl.ctrl_setup] + xor eax, eax + inc eax + ret +endp + +align 4 +proc set_ICH + mov [ctrl.codec_read16], codec_io_r16 ;virtual + mov [ctrl.codec_write16], codec_io_w16 ;virtual + + mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual + mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual + mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual + + mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual + mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual + mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual + ret +endp + +PG_SW equ 0x003 +PG_NOCACHE equ 0x018 + +align 4 +proc set_ICH4 + + stdcall MapIoMem, [ctrl.codec_mem_base], 0x1000, PG_SW+PG_NOCACHE + mov [ctrl.codec_mem_base], eax + + stdcall MapIoMem, [ctrl.ctrl_mem_base], 0x1000, PG_SW+PG_NOCACHE + mov [ctrl.ctrl_mem_base], eax + + mov [ctrl.codec_read16], codec_mem_r16 ;virtual + mov [ctrl.codec_write16], codec_mem_w16 ;virtual + + mov [ctrl.ctrl_read8 ], ctrl_mem_r8 ;virtual + mov [ctrl.ctrl_read16], ctrl_mem_r16 ;virtual + mov [ctrl.ctrl_read32], ctrl_mem_r32 ;virtual + + mov [ctrl.ctrl_write8 ], ctrl_mem_w8 ;virtual + mov [ctrl.ctrl_write16], ctrl_mem_w16 ;virtual + mov [ctrl.ctrl_write32], ctrl_mem_w32 ;virtual + ret +endp + +align 4 +proc reset_controller + + xor eax, eax + mov edx, PCM_IN_CR_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + call [ctrl.ctrl_write8] + + mov edx, MC_IN_CR_REG + call [ctrl.ctrl_write8] + + mov eax, RR + mov edx, PCM_IN_CR_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + call [ctrl.ctrl_write8] + + mov edx, MC_IN_CR_REG + call [ctrl.ctrl_write8] + ret +endp + +align 4 +proc init_codec + locals + counter dd ? + endl + + mov esi, msgControl + call SysMsgBoardStr + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + call dword2str + call SysMsgBoardStr + + mov esi, msgStatus + call SysMsgBoardStr + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + push eax + call dword2str + call SysMsgBoardStr + pop eax + cmp eax, 0xFFFFFFFF + je .err + + test eax, CTRL_ST_CREADY + jnz .ready + + call reset_codec + test eax, eax + jz .err + +.ready: + xor edx, edx ;ac_reg_0 + call [ctrl.codec_write16] + + xor eax, eax + mov edx, CODEC_REG_POWERDOWN + call [ctrl.codec_write16] + + mov [counter], 200 ; total 200*5 ms = 1s +.wait: + mov eax, 5000 ; wait 5 ms + call StallExec + + mov edx, CODEC_REG_POWERDOWN + call [ctrl.codec_read16] + and eax, 0x0F + cmp eax, 0x0F + jz .done + + sub [counter] , 1 + jnz .wait +.err: + xor eax, eax ; timeout error + ret +.done: + mov eax, 2 ;force set 16-bit 2-channel PCM + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + mov eax, 5000 ; wait 5 ms + call StallExec + + call detect_codec + + xor eax, eax + inc eax + ret +endp + +align 4 +proc reset_codec + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + + test eax, 0x02 + jz .cold + + call warm_reset + jnc .ok +.cold: + call cold_reset + jnc .ok + + if DEBUG + mov esi, msgCFail + call SysMsgBoardStr + end if + xor eax, eax ; timeout error + ret +.ok: + if DEBUG + mov esi, msgResetOk + call SysMsgBoardStr + end if + + xor eax, eax + inc eax + ret +endp + +align 4 +proc warm_reset + locals + counter dd ? + endl + + mov eax, 0x06 + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + if DEBUG + mov esi, msgWarm + call SysMsgBoardStr + end if + + mov [counter], 10 ; total 10*100 ms = 1s +.wait: + mov eax, 100000 ; wait 100 ms + call StallExec + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + test eax, CTRL_ST_CREADY + jnz .ok + + dec [counter] + jnz .wait + + if DEBUG + mov esi, msgWRFail + call SysMsgBoardStr + end if +.fail: + stc + ret +.ok: + clc + ret +endp + +align 4 +proc cold_reset + locals + counter dd ? + endl + + mov eax, 0x02 + mov edx, GLOB_CTRL + call [ctrl.ctrl_write32] + + if DEBUG + mov esi, msgCold + call SysMsgBoardStr + end if + + mov eax, 400000 ; wait 400 ms + call StallExec + + mov [counter], 16 ; total 20*100 ms = 2s +.wait: + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + test eax, CTRL_ST_CREADY + jnz .ok + + mov eax, 100000 ; wait 100 ms + call StallExec + + dec [counter] + jnz .wait + + if DEBUG + mov esi, msgCRFail + call SysMsgBoardStr + end if + +.fail: + stc + ret +.ok: + mov esi, msgControl + call SysMsgBoardStr + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + call dword2str + call SysMsgBoardStr + + mov esi, msgStatus + call SysMsgBoardStr + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + push eax + call dword2str + call SysMsgBoardStr + pop eax + + test eax, CTRL_ST_CREADY + jz .fail + clc + ret +endp + +align 4 +play: + mov eax, 16 + mov [ctrl.lvi_reg], eax + mov edx, PCM_OUT_LVI_REG + call [ctrl.ctrl_write8] + + mov edx, PCM_OUT_CR_REG + mov ax, 0x1D + call [ctrl.ctrl_write8] + xor eax, eax + ret + +align 4 +stop: + mov edx, PCM_OUT_CR_REG + mov ax, 0x0 + call [ctrl.ctrl_write8] + + mov ax, 0x1c + mov edx, PCM_OUT_SR_REG + call [ctrl.ctrl_write16] + xor eax, eax + ret + +align 4 +proc get_dev_info stdcall, p_info:dword + virtual at esi + CTRL_INFO CTRL_INFO + end virtual + + mov esi, [p_info] + mov eax, [ctrl.int_line] + mov ebx, [ctrl.codec_io_base] + mov ecx, [ctrl.ctrl_io_base] + mov edx, [ctrl.codec_mem_base] + mov edi, [ctrl.ctrl_mem_base] + + mov [CTRL_INFO.irq], eax + mov [CTRL_INFO.codec_io_base], ebx + mov [CTRL_INFO.ctrl_io_base], ecx + mov [CTRL_INFO.codec_mem_base], edx + mov [CTRL_INFO.ctrl_mem_base], edi + + mov eax, [codec.chip_id] + mov [CTRL_INFO.codec_id], eax + + mov edx, GLOB_CTRL + call [ctrl.ctrl_read32] + mov [CTRL_INFO.glob_cntrl], eax + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + mov [CTRL_INFO.glob_sta], eax + + mov ebx, [ctrl.pci_cmd] + mov [CTRL_INFO.pci_cmd], ebx + ret +endp + +align 4 +proc set_callback stdcall, handler:dword + mov eax, [handler] + mov [ctrl.user_callback], eax + ret +endp + +align 4 +proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax + + mov edx, [ac_reg] + + mov ebx, edx + shr ebx, 1 + bt [codec.shadow_flag], ebx + jc .use_shadow + + call [ctrl.codec_read16] ;change edx !!! + mov ecx, eax + + mov edx, CTRL_STAT + call [ctrl.ctrl_read32] + test eax, CTRL_ST_RCS + jz .read_ok + + mov edx, CTRL_STAT + call [ctrl.ctrl_write32] + xor eax, eax + not eax ;timeout + ret +.read_ok: + mov edx, [ac_reg] + mov [codec.regs+edx], cx + bts [codec.shadow_flag], ebx + mov eax, ecx + ret +.use_shadow: + movzx eax, word [codec.regs+edx] + ret +endp + +align 4 +proc codec_write stdcall, ac_reg:dword + push eax + call check_semafore + and eax, eax + jz .err + pop eax + + mov esi, [ac_reg] + mov edx, esi + call [ctrl.codec_write16] + mov [codec.regs+esi], ax + shr esi, 1 + bts [codec.shadow_flag], esi + ret +.err: + pop eax + ret +endp + +align 4 +proc codec_check_ready + + mov edx, CTRL_ST + call [ctrl.ctrl_read32] + and eax, CTRL_ST_CREADY + jz .not_ready + + xor eax, wax + inc eax + ret +.not_ready: + xor eax, eax + ret +endp + +align 4 +proc check_semafore + local counter:DWORD + + mov [counter], 100 +.l1: + mov edx, CTRL_CAS + call [ctrl.ctrl_read8] + and eax, CAS_FLAG + jz .ok + + mov eax, 1 + call StallExec + sub [counter], 1 + jnz .l1 + xor eax, eax + ret +align 4 +.ok: + xor eax, eax + inc eax + ret +endp + +align 4 +proc StallExec + push ecx + push edx + push ebx + push eax + + mov ecx, CPU_FREQ + mul ecx + mov ebx, eax ;low + mov ecx, edx ;high + rdtsc + add ebx, eax + adc ecx, edx +@@: + rdtsc + sub eax, ebx + sbb edx, ecx + js @B + + pop eax + pop ebx + pop edx + pop ecx + ret +endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; CONTROLLER IO functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +proc codec_io_r16 + add edx, [ctrl.codec_io_base] + in ax, dx + ret +endp + +align 4 +proc codec_io_w16 + add edx, [ctrl.codec_io_base] + out dx, ax + ret +endp + +align 4 +proc ctrl_io_r8 + add edx, [ctrl.ctrl_io_base] + in al, dx + ret +endp + +align 4 +proc ctrl_io_r16 + add edx, [ctrl.ctrl_io_base] + in ax, dx + ret +endp + +align 4 +proc ctrl_io_r32 + add edx, [ctrl.ctrl_io_base] + in eax, dx + ret +endp + +align 4 +proc ctrl_io_w8 + add edx, [ctrl.ctrl_io_base] + out dx, al + ret +endp + +align 4 +proc ctrl_io_w16 + add edx, [ctrl.ctrl_io_base] + out dx, ax + ret +endp + +align 4 +proc ctrl_io_w32 + add edx, [ctrl.ctrl_io_base] + out dx, eax + ret +endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; MEMORY MAPPED IO (os depended) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +proc codec_mem_r16 + add edx, [ctrl.codec_mem_base] + mov ax, word [edx] + ret +endp + +align 4 +proc codec_mem_w16 + add edx, [ctrl.codec_mem_base] + mov word [edx], ax + ret +endp + +align 4 +proc ctrl_mem_r8 + add edx, [ctrl.ctrl_mem_base] + mov al, [edx] + ret +endp + +align 4 +proc ctrl_mem_r16 + add edx, [ctrl.ctrl_mem_base] + mov ax, [edx] + ret +endp + +align 4 +proc ctrl_mem_r32 + add edx, [ctrl.ctrl_mem_base] + mov eax, [edx] + ret +endp + +align 4 +proc ctrl_mem_w8 + add edx, [ctrl.ctrl_mem_base] + mov [edx], al + ret +endp + +align 4 +proc ctrl_mem_w16 + add edx, [ctrl.ctrl_mem_base] + mov [edx], ax + ret +endp + +align 4 +proc ctrl_mem_w32 + add edx, [ctrl.ctrl_mem_base] + mov [edx], eax + ret +endp + +align 4 +dword2str: + mov esi, hex_buff + mov ecx, -8 +@@: + rol eax, 4 + mov ebx, eax + and ebx, 0x0F + mov bl, [ebx+hexletters] + mov [8+esi+ecx], bl + inc ecx + jnz @B + ret + +hexletters db '0123456789ABCDEF' +hex_buff db 8 dup(0),13,10,0 + + +include "codec.inc" + +align 4 +devices dd (CTRL_ICH shl 16)+VID_INTEL,msg_ICH, set_ICH + dd (CTRL_ICH0 shl 16)+VID_INTEL,msg_ICH0,set_ICH + dd (CTRL_ICH2 shl 16)+VID_INTEL,msg_ICH2,set_ICH + dd (CTRL_ICH3 shl 16)+VID_INTEL,msg_ICH3,set_ICH + dd (CTRL_ICH4 shl 16)+VID_INTEL,msg_ICH4,set_ICH4 + dd (CTRL_ICH5 shl 16)+VID_INTEL,msg_ICH5,set_ICH4 + dd (CTRL_ICH6 shl 16)+VID_INTEL,msg_ICH6,set_ICH4 + dd (CTRL_ICH7 shl 16)+VID_INTEL,msg_ICH7,set_ICH4 + + dd (CTRL_NFORCE shl 16)+VID_NVIDIA,msg_NForce, set_ICH + dd (CTRL_NFORCE2 shl 16)+VID_NVIDIA,msg_NForce2,set_ICH + dd (CTRL_NFORCE3 shl 16)+VID_NVIDIA,msg_NForce3,set_ICH + dd (CTRL_MCP04 shl 16)+VID_NVIDIA,msg_MCP04,set_ICH + dd (CTRL_CK804 shl 16)+VID_NVIDIA,msg_CK804,set_ICH + dd (CTRL_CK8 shl 16)+VID_NVIDIA,msg_CK8,set_ICH + dd (CTRL_CK8S shl 16)+VID_NVIDIA,msg_CK8S,set_ICH + dd (CTRL_MCP51 shl 16)+VID_NVIDIA,msg_MCP51,set_ICH + + dd 0 ;terminator + + +version dd (5 shl 16) or (API_VERSION and 0xFFFF) + +msg_ICH db '802801AA (ICH)', 13,10, 0 +msg_ICH0 db '802801AB (ICH0)', 13,10, 0 +msg_ICH2 db '802801BA (ICH2)', 13,10, 0 +msg_ICH3 db '802801CA (ICH3)', 13,10, 0 +msg_ICH4 db '802801DB (ICH4)', 13,10, 0 +msg_ICH5 db '802801EB (ICH5)', 13,10, 0 +msg_ICH6 db '802801FB (ICH6)', 13,10, 0 +msg_ICH7 db '802801GB (ICH7)', 13,10, 0 +msg_Intel db 'Intel ', 0 + +msg_NForce db 'NForce', 13,10, 0 +msg_NForce2 db 'NForce 2', 13,10, 0 +msg_NForce3 db 'NForce 3', 13,10, 0 +msg_MCP04 db 'NForce MCP04',13,10, 0 +msg_CK804 db 'NForce CK804',13,10, 0 +msg_CK8 db 'NForce CK8', 13,10, 0 +msg_CK8S db 'NForce CK8S', 13,10, 0 +msg_MCP51 db 'NForce MCP51',13,10, 0 + +msg_NVidia db 'NVidia', 0 + +szKernel db 'KERNEL', 0 +sz_sound_srv db 'SOUND',0 + +msgInit db 'detect hardware...',13,10,0 +msgFail db 'device not found',13,10,0 +msgAttchIRQ db 'IRQ line not supported', 13,10, 0 +msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 +msgPlay db 'start play', 13,10,0 +msgStop db 'stop play', 13,10,0 +;msgNotify db 'call notify',13,10,0 +msgIRQ db 'AC97 IRQ', 13,10,0 +msgInitCtrl db 'init controller',13,10,0 +;msgInitCodec db 'init codec',13,10,0 +msgPrimBuff db 'create primary buffer ...',0 +msgDone db 'done',13,10,0 +msgRemap db 'Remap IRQ',13,10,0 +;msgReg db 'set service handler',13,10,0 +msgOk db 'service installed',13,10,0 +msgCold db 'cold reset',13,10,0 +msgWarm db 'warm reset',13,10,0 +msgWRFail db 'warm reset failed',13,10,0 +msgCRFail db 'cold reset failed',13,10,0 +msgCFail db 'codec not ready',13,10,0 +msgResetOk db 'reset complete',13,10,0 +msgStatus db 'global status ',0 +msgControl db 'global control ',0 +msgPciCmd db 'PCI command ',0 +msgPciStat db 'PCI status ',0 +msgCtrlIsaIo db 'controller io base ',0 +msgMixIsaIo db 'codec io base ',0 +msgCtrlMMIo db 'controller mmio base ',0 +msgMixMMIo db 'codec mmio base ',0 +msgIrqMap db 'AC97 irq map as ',0 + +section '.data' data readable writable align 16 + +pcmout_bdl rq 32 +buff_list rd 32 + +codec CODEC +ctrl AC_CNTRL + +lpc_bus rd 1 +civ_val rd 1 diff --git a/kernel/trunk/drivers/uart.asm b/kernel/trunk/drivers/uart.asm index a445a74a8..d170815d8 100644 --- a/kernel/trunk/drivers/uart.asm +++ b/kernel/trunk/drivers/uart.asm @@ -1,976 +1,976 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -format MS COFF - -DEBUG equ 1 - -include 'proc32.inc' -include 'imports.inc' - - - -API_VERSION equ 0 -UART_VERSION equ API_VERSION - -PG_SW equ 0x003 -page_tabs equ 0xFDC00000 ;hack - -OS_BASE equ 0x80000000 -SLOT_BASE equ (OS_BASE+0x0080000) -TASK_COUNT equ (OS_BASE+0x0003004) -CURRENT_TASK equ (OS_BASE+0x0003000) - - -struc APPOBJ ;common object header -{ - .magic dd ? ; - .destroy dd ? ;internal destructor - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id -}; - -virtual at 0 - APPOBJ APPOBJ -end virtual - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -DEBUG equ 1 - -DRV_ENTRY equ 1 -DRV_EXIT equ -1 - -THR_REG equ 0; x3f8 ;transtitter/reciever -IER_REG equ 1; x3f9 ;interrupt enable -IIR_REG equ 2; x3fA ;interrupt info -LCR_REG equ 3; x3FB ;line control -MCR_REG equ 4; x3FC ;modem control -LSR_REG equ 5; x3FD ;line status -MSR_REG equ 6; x3FE ;modem status - -LCR_5BIT equ 0x00 -LCR_6BIT equ 0x01 -LCR_7BIT equ 0x02 -LCR_8BIT equ 0x03 -LCR_STOP_1 equ 0x00 -LCR_STOP_2 equ 0x04 -LCR_PARITY equ 0x08 -LCR_EVEN equ 0x10 -LCR_STICK equ 0x20 -LCR_BREAK equ 0x40 -LCR_DLAB equ 0x80 - -LSR_DR equ 0x01 ;data ready -LSR_OE equ 0x02 ;overrun error -LSR_PE equ 0x04 ;parity error -LSR_FE equ 0x08 ;framing error -LSR_BI equ 0x10 ;break interrupt -LSR_THRE equ 0x20 ;transmitter holding empty -LSR_TEMT equ 0x40 ;transmitter empty -LSR_FER equ 0x80 ;FIFO error - -FCR_EFIFO equ 0x01 ;enable FIFO -FCR_CRB equ 0x02 ;clear reciever FIFO -FCR_CXMIT equ 0x04 ;clear transmitter FIFO -FCR_RDY equ 0x08 ;set RXRDY and TXRDY pins -FCR_FIFO_1 equ 0x00 ;1 byte trigger -FCR_FIFO_4 equ 0x40 ;4 bytes trigger -FCR_FIFO_8 equ 0x80 ;8 bytes trigger -FCR_FIFO_14 equ 0xC0 ;14 bytes trigger - -IIR_INTR equ 0x01 ;1= no interrupts - -IER_RDAI equ 0x01 ;reciever data interrupt -IER_THRI equ 0x02 ;transmitter empty interrupt -IER_LSI equ 0x04 ;line status interrupt -IER_MSI equ 0x08 ;modem status interrupt - -MCR_DTR equ 0x01 ;0-> DTR=1, 1-> DTR=0 -MCR_RTS equ 0x02 ;0-> RTS=1, 1-> RTS=0 -MCR_OUT_1 equ 0x04 ;0-> OUT1=1, 1-> OUT1=0 -MCR_OUT_2 equ 0x08 ;0-> OUT2=1, 1-> OUT2=0; enable intr -MCR_LOOP equ 0x10 ;lopback mode - -MSR_DCTS equ 0x01 ;delta clear to send -MSR_DDSR equ 0x02 ;delta data set redy -MSR_TERI equ 0x04 ;trailinh edge of ring -MSR_DDCD equ 0x08 ;delta carrier detect - - -RATE_50 equ 0 -RATE_75 equ 1 -RATE_110 equ 2 -RATE_134 equ 3 -RATE_150 equ 4 -RATE_300 equ 5 -RATE_600 equ 6 -RATE_1200 equ 7 -RATE_1800 equ 8 -RATE_2000 equ 9 -RATE_2400 equ 10 -RATE_3600 equ 11 -RATE_4800 equ 12 -RATE_7200 equ 13 -RATE_9600 equ 14 -RATE_19200 equ 15 -RATE_38400 equ 16 -RATE_57600 equ 17 -RATE_115200 equ 18 - -COM_1 equ 1 -COM_2 equ 2 -COM_3 equ 3 -COM_4 equ 4 -COM_MAX equ 2 ;only two port supported - -COM_1_BASE equ 0x3F8 -COM_2_BASE equ 0x2F8 - -COM_1_IRQ equ 4 -COM_2_IRQ equ 3 - -UART_CLOSED equ 0 -UART_TRANSMIT equ 1 -UART_STOP equ 2 - -struc UART -{ - .lock dd ? - .base dd ? - .lcr_reg dd ? - .mcr_reg dd ? - .rate dd ? - .mode dd ? - .state dd ? - - .rcvr_buff dd ? - .rcvr_rp dd ? - .rcvr_wp dd ? - .rcvr_count dd ? - .rcvr_top dd ? - - .xmit_buff dd ? - .xmit_rp dd ? - .xmit_wp dd ? - .xmit_count dd ? - .xmit_free dd ? - .xmit_top dd ? -} -virtual at 0 - UART UART -end virtual - -UART_SIZE equ 18*4 - -struc CONNECTION -{ - .magic dd ? ;'CNCT' - .destroy dd ? ;internal destructor - .fd dd ? ;next object in list - .bk dd ? ;prev object in list - .pid dd ? ;owner id - - .id dd ? ;reserved - .uart dd ? ;uart pointer -} - -virtual at 0 - CONNECTION CONNECTION -end virtual - -CONNECTION_SIZE equ 7*4 - -public START -public service_proc -public version - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .stop - - mov eax, UART_SIZE - call Kmalloc - test eax, eax - jz .fail - - mov [com1], eax - mov edi, eax - mov ecx, UART_SIZE/4 - xor eax, eax - cld - rep stosd - - mov eax, [com1] - mov [eax+UART.base], COM_1_BASE - - stdcall AllocKernelSpace, 32768 - - mov edi, [com1] - mov edx, eax - - mov [edi+UART.rcvr_buff], eax - add eax, 8192 - mov [edi+UART.rcvr_top], eax - add eax, 8192 - mov [edi+UART.xmit_buff], eax - add eax, 8192 - mov [edi+UART.xmit_top], eax - - call AllocPage - test eax, eax - jz .fail - - shr edx, 12 - or eax, PG_SW - mov [page_tabs+edx*4], eax - mov [page_tabs+edx*4+8], eax - - call AllocPage - test eax, eax - jz .fail - - or eax, PG_SW - mov [page_tabs+edx*4+4], eax - mov [page_tabs+edx*4+12], eax - - call AllocPage - test eax, eax - jz .fail - - or eax, PG_SW - mov [page_tabs+edx*4+16], eax - mov [page_tabs+edx*4+24], eax - - call AllocPage - test eax, eax - jz .fail - - or eax, PG_SW - mov [page_tabs+edx*4+20], eax - mov [page_tabs+edx*4+28], eax - - mov eax, [edi+UART.rcvr_buff] - invlpg [eax] - invlpg [eax+0x1000] - invlpg [eax+0x2000] - invlpg [eax+0x3000] - invlpg [eax+0x4000] - invlpg [eax+0x5000] - invlpg [eax+0x6000] - invlpg [eax+0x7000] - - mov eax, edi - call uart_reset.internal ;eax= uart - - stdcall AttachIntHandler, COM_1_IRQ, com_1_isr, dword 0 - stdcall RegService, sz_uart_srv, service_proc - ret -.fail: -.stop: - xor eax, eax - ret -endp - - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -SRV_GETVERSION equ 0 -PORT_OPEN equ 1 -PORT_CLOSE equ 2 -PORT_RESET equ 3 -PORT_SETMODE equ 4 -PORT_GETMODE equ 5 -PORT_SETMCR equ 6 -PORT_GETMCR equ 7 -PORT_READ equ 8 -PORT_WRITE equ 9 - -align 4 -proc service_proc stdcall, ioctl:dword - - mov ebx, [ioctl] - mov eax, [ebx+io_code] - cmp eax, PORT_WRITE - ja .fail - - cmp eax, SRV_GETVERSION - jne @F - - mov eax, [ebx+output] - cmp [ebx+out_size], 4 - jne .fail - mov [eax], dword UART_VERSION - xor eax, eax - ret -@@: - cmp eax, PORT_OPEN - jne @F - - cmp [ebx+out_size], 4 - jne .fail - - mov ebx, [ebx+input] - mov eax, [ebx] - call uart_open - mov ebx, [ioctl] - mov ebx, [ebx+output] - mov [ebx], ecx - ret -@@: - mov esi, [ebx+input] ;input buffer - mov edi, [ebx+output] - call [uart_func+eax*4] - ret -.fail: - or eax, -1 - ret - -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - - -; param -; esi= input buffer -; +0 connection -; -; retval -; eax= error code - -align 4 -uart_reset: - mov eax, [esi] - cmp [eax+APPOBJ.magic], 'CNCT' - jne .fail - - cmp [eax+APPOBJ.destroy], uart_close.destroy - jne .fail - - mov eax, [eax+CONNECTION.uart] - test eax, eax - jz .fail - -; set mode 2400 bod 8-bit -; disable DTR & RTS -; clear FIFO -; clear pending interrupts -; -; param -; eax= uart - -align 4 -.internal: - mov esi, eax - mov [eax+UART.state], UART_CLOSED - mov edx, [eax+UART.base] - add edx, MCR_REG - xor eax, eax - out dx, al ;clear DTR & RTS - - mov eax, esi - mov ebx, RATE_2400 - mov ecx, LCR_8BIT+LCR_STOP_1 - call uart_set_mode.internal - - mov edx, [esi+UART.base] - add edx, IIR_REG - mov eax,FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14 - out dx, al -.clear_RB: - mov edx, [esi+UART.base] - add edx, LSR_REG - in al, dx - test eax, LSR_DR - jz @F - - mov edx, [esi+UART.base] - in al, dx - jmp .clear_RB -@@: - mov edx, [esi+UART.base] - add edx, IER_REG - mov eax,IER_RDAI+IER_THRI+IER_LSI - out dx, al -.clear_IIR: - mov edx, [esi+UART.base] - add edx, IIR_REG - in al, dx - test al, IIR_INTR - jnz .done - - shr eax, 1 - and eax, 3 - jnz @F - - mov edx, [esi+UART.base] - add edx, MSR_REG - in al, dx - jmp .clear_IIR -@@: - cmp eax, 1 - je .clear_IIR - - cmp eax, 2 - jne @F - - mov edx, [esi+UART.base] - in al, dx - jmp .clear_IIR -@@: - mov edx, [esi+UART.base] - add edx, LSR_REG - in al, dx - jmp .clear_IIR -.done: - mov edi, [esi+UART.rcvr_buff] - mov ecx, 8192/4 - xor eax, eax - - mov [esi+UART.rcvr_rp], edi - mov [esi+UART.rcvr_wp], edi - mov [esi+UART.rcvr_count], eax - - cld - rep stosd - - mov edi, [esi+UART.xmit_buff] - mov ecx, 8192/4 - - mov [esi+UART.xmit_rp], edi - mov [esi+UART.xmit_wp], edi - mov [esi+UART.xmit_count], eax - mov [esi+UART.xmit_free], 8192 - - rep stosd - ret ;eax= 0 -.fail: - or eax, -1 - ret - -; param -; esi= input buffer -; +0 connection -; +4 rate -; +8 mode -; -; retval -; eax= error code - -align 4 -uart_set_mode: - mov eax, [esi] - cmp [eax+APPOBJ.magic], 'CNCT' - jne .fail - - cmp [eax+APPOBJ.destroy], uart_close.destroy - jne .fail - - mov eax, [eax+CONNECTION.uart] - test eax, eax - jz .fail - - mov ebx, [esi+4] - mov ecx, [esi+8] - -; param -; eax= uart -; ebx= baud rate -; ecx= mode - -align 4 -.internal: - cmp ebx, RATE_115200 - ja .fail - - cmp ecx, LCR_BREAK - jae .fail - - mov [eax+UART.rate], ebx - mov [eax+UART.mode], ecx - - mov esi, eax - mov bx, [divisor+ebx*2] - - mov edx, [esi+UART.base] - push edx - add edx, LCR_REG - in al, dx - or al, 0x80 - out dx, al - - pop edx - mov al, bl - out dx, al - - inc dx - mov al, bh - out dx, al - - add edx, LCR_REG-1 - mov eax, ecx - out dx, al - xor eax, eax - ret -.fail: - or eax, -1 - ret - -; param -; esi= input buffer -; +0 connection -; +4 modem control reg valie -; -; retval -; eax= error code - -align 4 -uart_set_mcr: - - mov eax, [esi] - cmp [eax+APPOBJ.magic], 'CNCT' - jne .fail - - cmp [eax+APPOBJ.destroy], uart_close.destroy - jne .fail - - mov eax, [eax+CONNECTION.uart] - test eax, eax - jz .fail - - mov ebx, [esi+4] - - mov [eax+UART.mcr_reg], ebx - mov edx, [eax+UART.base] - add edx, MCR_REG - mov al, bl - out dx, al - xor eax, eax - ret -.fail: - or eax, -1 - ret - -; param -; eax= port -; -; retval -; ecx= connection -; eax= error code - -align 4 -uart_open: - dec eax - cmp eax, COM_MAX - jae .fail - - mov esi, [com1+eax*4] ;uart - push esi -.do_wait: - cmp dword [esi+UART.lock],0 - je .get_lock - ; call change_task - jmp .do_wait -.get_lock: - mov eax, 1 - xchg eax, [esi+UART.lock] - test eax, eax - jnz .do_wait - - mov eax, esi ;uart - call uart_reset.internal - - mov ebx, [CURRENT_TASK] - shl ebx, 5 - mov ebx, [CURRENT_TASK+ebx+4] - mov eax, CONNECTION_SIZE - call CreateObject - pop esi ;uart - test eax, eax - jz .fail - - mov [eax+APPOBJ.magic], 'CNCT' - mov [eax+APPOBJ.destroy], uart_close.destroy - mov [eax+CONNECTION.uart], esi - mov ecx, eax - xor eax, eax - ret -.fail: - or eax, -1 - ret -restore .uart - -; param -; esi= input buffer - -align 4 -uart_close: - mov eax, [esi] - cmp [eax+APPOBJ.magic], 'CNCT' - jne .fail - - cmp [eax+APPOBJ.destroy], uart_close.destroy - jne .fail -.destroy: - push [eax+CONNECTION.uart] - call DestroyObject ;eax= object - pop eax ;eax= uart - test eax, eax - jz .fail - - mov [eax+UART.state], UART_CLOSED - mov [eax+UART.lock], 0 ;release port - xor eax, eax - ret -.fail: - or eax, -1 - ret - - -; param -; eax= uart -; ebx= baud rate - -align 4 -set_rate: - cmp ebx, RATE_115200 - ja .fail - - mov [eax+UART.rate], ebx - mov bx, [divisor+ebx*2] - - mov edx, [eax+UART.base] - add edx, LCR_REG - in al, dx - push eax - or al, 0x80 - out dx, al - - sub edx, LCR_REG - mov al, bl - out dx, al - - inc edx - mov al, bh - out dx, al - - pop eax - add edx, LCR_REG-1 - out dx, al -.fail: - ret - - -; param -; ebx= uart - -align 4 -transmit: - push esi - push edi - - mov edx, [ebx+UART.base] - - pushfd - cli - - mov esi, [ebx+UART.xmit_rp] - mov ecx, [ebx+UART.xmit_count] - test ecx, ecx - je .stop - - cmp ecx, 16 - jbe @F - mov ecx, 16 -@@: - sub [ebx+UART.xmit_count], ecx - add [ebx+UART.xmit_free], ecx - cld -@@: - lodsb - out dx, al - dec ecx - jnz @B - - cmp esi,[ebx+UART.xmit_top] - jb @F - sub esi, 8192 -@@: - mov [ebx+UART.xmit_rp], esi - - cmp [ebx+UART.xmit_count], 0 - je .stop - - mov [ebx+UART.state], UART_TRANSMIT - jmp @F -.stop: - mov [ebx+UART.state], UART_STOP -@@: - popfd - pop edi - pop esi - ret - - -; param -; esi= input buffer -; +0 connection -; +4 dst buffer -; +8 dst size -; edi= output buffer -; +0 bytes read - -; retval -; eax= error code - -align 4 -uart_read: - mov eax, [esi] - cmp [eax+APPOBJ.magic], 'CNCT' - jne .fail - - cmp [eax+APPOBJ.destroy], uart_close.destroy - jne .fail - - mov eax, [eax+CONNECTION.uart] - test eax, eax - jz .fail - - mov ebx, [esi+8] ;dst size - mov ecx, [eax+UART.rcvr_count] - cmp ecx, ebx - jbe @F - mov ecx, ebx -@@: - mov [edi], ecx ;bytes read - test ecx, ecx - jz .done - - push ecx - - mov edi, [esi+4] ;dst - mov esi, [eax+UART.rcvr_rp] - cld - rep movsb - pop ecx - - cmp esi, [eax+UART.rcvr_top] - jb @F - sub esi, 8192 -@@: - mov [eax+UART.rcvr_rp], esi - sub [eax+UART.rcvr_count], ecx -.done: - xor eax, eax - ret -.fail: - or eax, -1 - ret - -; param -; esi= input buffer -; +0 connection -; +4 src buffer -; +8 src size -; -; retval -; eax= error code - -align 4 -uart_write: - mov eax, [esi] - cmp [eax+APPOBJ.magic], 'CNCT' - jne .fail - - cmp [eax+APPOBJ.destroy], uart_close.destroy - jne .fail - - mov eax, [eax+CONNECTION.uart] - test eax, eax - jz .fail - - mov ebx, [esi+4] - mov edx, [esi+8] - -; param -; eax= uart -; ebx= src -; edx= count - -align 4 -.internal: - mov esi, ebx - mov edi, [eax+UART.xmit_wp] -.write: - test edx, edx - jz .fail -.wait: - cmp [eax+UART.xmit_free], 0 - jne .fill - - cmp [eax+UART.state], UART_TRANSMIT - je .wait - - mov ebx, eax - push edx - call transmit - pop edx - mov eax, ebx - jmp .write -.fill: - mov ecx, [eax+UART.xmit_free] - cmp ecx, edx - jbe @F - mov ecx, edx -@@: - push ecx - cld - rep movsb - pop ecx - sub [eax+UART.xmit_free], ecx - add [eax+UART.xmit_count], ecx - sub edx, ecx - jnz .wait -.done: - cmp edi, [eax+UART.xmit_top] - jb @F - sub edi, 8192 -@@: - mov [eax+UART.xmit_wp], edi - cmp [eax+UART.state], UART_TRANSMIT - je @F - mov ebx, eax - call transmit -@@: - xor eax, eax - ret -.fail: - or eax, -1 - ret - - -align 4 -com_2_isr: - mov ebx, [com2] - jmp com_1_isr.get_info -align 4 -com_1_isr: - mov ebx, [com1] -.get_info: - mov edx, [ebx+UART.base] - add edx, IIR_REG - in al, dx - - test al, IIR_INTR - jnz .done - - shr eax, 1 - and eax, 3 - - call [isr_action+eax*4] - jmp .get_info -.done: - ret - -align 4 -isr_line: - mov edx, [ebx+UART.base] - add edx, LSR_REG - in al, dx - ret - -align 4 -isr_recieve: - mov esi, [ebx+UART.base] - add esi, LSR_REG - mov edi, [ebx+UART.rcvr_wp] - xor ecx, ecx - cld -.read: - mov edx, esi - in al, dx - test eax, LSR_DR - jz .done - - mov edx, [ebx+UART.base] - in al, dx - stosb - inc ecx - jmp .read -.done: - cmp edi, [ebx+UART.rcvr_top] - jb @F - sub edi, 8192 -@@: - mov [ebx+UART.rcvr_wp], edi - add [ebx+UART.rcvr_count], ecx - ret - -align 4 -isr_modem: - mov edx, [ebx+UART.base] - add edx, MSR_REG - in al, dx - ret - - -align 4 -divisor dw 2304, 1536, 1047, 857, 768, 384 - dw 192, 96, 64, 58, 48, 32 - dw 24, 16, 12, 6, 3, 2, 1 - -align 4 -uart_func dd 0 ;SRV_GETVERSION - dd 0 ;PORT_OPEN - dd uart_close ;PORT_CLOSE - dd uart_reset ;PORT_RESET - dd uart_set_mode ;PORT_SETMODE - dd 0 ;PORT_GETMODE - dd uart_set_mcr ;PORT_SETMODEM - dd 0 ;PORT_GETMODEM - dd uart_read ;PORT_READ - dd uart_write ;PORT_WRITE - -isr_action dd isr_modem - dd transmit - dd isr_recieve - dd isr_line - -version dd (5 shl 16) or (UART_VERSION and 0xFFFF) - -sz_uart_srv db 'UART',0 - -align 4 - -com1 rd 1 -com2 rd 1 - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +format MS COFF + +DEBUG equ 1 + +include 'proc32.inc' +include 'imports.inc' + + + +API_VERSION equ 0 +UART_VERSION equ API_VERSION + +PG_SW equ 0x003 +page_tabs equ 0xFDC00000 ;hack + +OS_BASE equ 0x80000000 +SLOT_BASE equ (OS_BASE+0x0080000) +TASK_COUNT equ (OS_BASE+0x0003004) +CURRENT_TASK equ (OS_BASE+0x0003000) + + +struc APPOBJ ;common object header +{ + .magic dd ? ; + .destroy dd ? ;internal destructor + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id +}; + +virtual at 0 + APPOBJ APPOBJ +end virtual + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +DEBUG equ 1 + +DRV_ENTRY equ 1 +DRV_EXIT equ -1 + +THR_REG equ 0; x3f8 ;transtitter/reciever +IER_REG equ 1; x3f9 ;interrupt enable +IIR_REG equ 2; x3fA ;interrupt info +LCR_REG equ 3; x3FB ;line control +MCR_REG equ 4; x3FC ;modem control +LSR_REG equ 5; x3FD ;line status +MSR_REG equ 6; x3FE ;modem status + +LCR_5BIT equ 0x00 +LCR_6BIT equ 0x01 +LCR_7BIT equ 0x02 +LCR_8BIT equ 0x03 +LCR_STOP_1 equ 0x00 +LCR_STOP_2 equ 0x04 +LCR_PARITY equ 0x08 +LCR_EVEN equ 0x10 +LCR_STICK equ 0x20 +LCR_BREAK equ 0x40 +LCR_DLAB equ 0x80 + +LSR_DR equ 0x01 ;data ready +LSR_OE equ 0x02 ;overrun error +LSR_PE equ 0x04 ;parity error +LSR_FE equ 0x08 ;framing error +LSR_BI equ 0x10 ;break interrupt +LSR_THRE equ 0x20 ;transmitter holding empty +LSR_TEMT equ 0x40 ;transmitter empty +LSR_FER equ 0x80 ;FIFO error + +FCR_EFIFO equ 0x01 ;enable FIFO +FCR_CRB equ 0x02 ;clear reciever FIFO +FCR_CXMIT equ 0x04 ;clear transmitter FIFO +FCR_RDY equ 0x08 ;set RXRDY and TXRDY pins +FCR_FIFO_1 equ 0x00 ;1 byte trigger +FCR_FIFO_4 equ 0x40 ;4 bytes trigger +FCR_FIFO_8 equ 0x80 ;8 bytes trigger +FCR_FIFO_14 equ 0xC0 ;14 bytes trigger + +IIR_INTR equ 0x01 ;1= no interrupts + +IER_RDAI equ 0x01 ;reciever data interrupt +IER_THRI equ 0x02 ;transmitter empty interrupt +IER_LSI equ 0x04 ;line status interrupt +IER_MSI equ 0x08 ;modem status interrupt + +MCR_DTR equ 0x01 ;0-> DTR=1, 1-> DTR=0 +MCR_RTS equ 0x02 ;0-> RTS=1, 1-> RTS=0 +MCR_OUT_1 equ 0x04 ;0-> OUT1=1, 1-> OUT1=0 +MCR_OUT_2 equ 0x08 ;0-> OUT2=1, 1-> OUT2=0; enable intr +MCR_LOOP equ 0x10 ;lopback mode + +MSR_DCTS equ 0x01 ;delta clear to send +MSR_DDSR equ 0x02 ;delta data set redy +MSR_TERI equ 0x04 ;trailinh edge of ring +MSR_DDCD equ 0x08 ;delta carrier detect + + +RATE_50 equ 0 +RATE_75 equ 1 +RATE_110 equ 2 +RATE_134 equ 3 +RATE_150 equ 4 +RATE_300 equ 5 +RATE_600 equ 6 +RATE_1200 equ 7 +RATE_1800 equ 8 +RATE_2000 equ 9 +RATE_2400 equ 10 +RATE_3600 equ 11 +RATE_4800 equ 12 +RATE_7200 equ 13 +RATE_9600 equ 14 +RATE_19200 equ 15 +RATE_38400 equ 16 +RATE_57600 equ 17 +RATE_115200 equ 18 + +COM_1 equ 1 +COM_2 equ 2 +COM_3 equ 3 +COM_4 equ 4 +COM_MAX equ 2 ;only two port supported + +COM_1_BASE equ 0x3F8 +COM_2_BASE equ 0x2F8 + +COM_1_IRQ equ 4 +COM_2_IRQ equ 3 + +UART_CLOSED equ 0 +UART_TRANSMIT equ 1 +UART_STOP equ 2 + +struc UART +{ + .lock dd ? + .base dd ? + .lcr_reg dd ? + .mcr_reg dd ? + .rate dd ? + .mode dd ? + .state dd ? + + .rcvr_buff dd ? + .rcvr_rp dd ? + .rcvr_wp dd ? + .rcvr_count dd ? + .rcvr_top dd ? + + .xmit_buff dd ? + .xmit_rp dd ? + .xmit_wp dd ? + .xmit_count dd ? + .xmit_free dd ? + .xmit_top dd ? +} +virtual at 0 + UART UART +end virtual + +UART_SIZE equ 18*4 + +struc CONNECTION +{ + .magic dd ? ;'CNCT' + .destroy dd ? ;internal destructor + .fd dd ? ;next object in list + .bk dd ? ;prev object in list + .pid dd ? ;owner id + + .id dd ? ;reserved + .uart dd ? ;uart pointer +} + +virtual at 0 + CONNECTION CONNECTION +end virtual + +CONNECTION_SIZE equ 7*4 + +public START +public service_proc +public version + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .stop + + mov eax, UART_SIZE + call Kmalloc + test eax, eax + jz .fail + + mov [com1], eax + mov edi, eax + mov ecx, UART_SIZE/4 + xor eax, eax + cld + rep stosd + + mov eax, [com1] + mov [eax+UART.base], COM_1_BASE + + stdcall AllocKernelSpace, 32768 + + mov edi, [com1] + mov edx, eax + + mov [edi+UART.rcvr_buff], eax + add eax, 8192 + mov [edi+UART.rcvr_top], eax + add eax, 8192 + mov [edi+UART.xmit_buff], eax + add eax, 8192 + mov [edi+UART.xmit_top], eax + + call AllocPage + test eax, eax + jz .fail + + shr edx, 12 + or eax, PG_SW + mov [page_tabs+edx*4], eax + mov [page_tabs+edx*4+8], eax + + call AllocPage + test eax, eax + jz .fail + + or eax, PG_SW + mov [page_tabs+edx*4+4], eax + mov [page_tabs+edx*4+12], eax + + call AllocPage + test eax, eax + jz .fail + + or eax, PG_SW + mov [page_tabs+edx*4+16], eax + mov [page_tabs+edx*4+24], eax + + call AllocPage + test eax, eax + jz .fail + + or eax, PG_SW + mov [page_tabs+edx*4+20], eax + mov [page_tabs+edx*4+28], eax + + mov eax, [edi+UART.rcvr_buff] + invlpg [eax] + invlpg [eax+0x1000] + invlpg [eax+0x2000] + invlpg [eax+0x3000] + invlpg [eax+0x4000] + invlpg [eax+0x5000] + invlpg [eax+0x6000] + invlpg [eax+0x7000] + + mov eax, edi + call uart_reset.internal ;eax= uart + + stdcall AttachIntHandler, COM_1_IRQ, com_1_isr, dword 0 + stdcall RegService, sz_uart_srv, service_proc + ret +.fail: +.stop: + xor eax, eax + ret +endp + + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +SRV_GETVERSION equ 0 +PORT_OPEN equ 1 +PORT_CLOSE equ 2 +PORT_RESET equ 3 +PORT_SETMODE equ 4 +PORT_GETMODE equ 5 +PORT_SETMCR equ 6 +PORT_GETMCR equ 7 +PORT_READ equ 8 +PORT_WRITE equ 9 + +align 4 +proc service_proc stdcall, ioctl:dword + + mov ebx, [ioctl] + mov eax, [ebx+io_code] + cmp eax, PORT_WRITE + ja .fail + + cmp eax, SRV_GETVERSION + jne @F + + mov eax, [ebx+output] + cmp [ebx+out_size], 4 + jne .fail + mov [eax], dword UART_VERSION + xor eax, eax + ret +@@: + cmp eax, PORT_OPEN + jne @F + + cmp [ebx+out_size], 4 + jne .fail + + mov ebx, [ebx+input] + mov eax, [ebx] + call uart_open + mov ebx, [ioctl] + mov ebx, [ebx+output] + mov [ebx], ecx + ret +@@: + mov esi, [ebx+input] ;input buffer + mov edi, [ebx+output] + call [uart_func+eax*4] + ret +.fail: + or eax, -1 + ret + +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + + +; param +; esi= input buffer +; +0 connection +; +; retval +; eax= error code + +align 4 +uart_reset: + mov eax, [esi] + cmp [eax+APPOBJ.magic], 'CNCT' + jne .fail + + cmp [eax+APPOBJ.destroy], uart_close.destroy + jne .fail + + mov eax, [eax+CONNECTION.uart] + test eax, eax + jz .fail + +; set mode 2400 bod 8-bit +; disable DTR & RTS +; clear FIFO +; clear pending interrupts +; +; param +; eax= uart + +align 4 +.internal: + mov esi, eax + mov [eax+UART.state], UART_CLOSED + mov edx, [eax+UART.base] + add edx, MCR_REG + xor eax, eax + out dx, al ;clear DTR & RTS + + mov eax, esi + mov ebx, RATE_2400 + mov ecx, LCR_8BIT+LCR_STOP_1 + call uart_set_mode.internal + + mov edx, [esi+UART.base] + add edx, IIR_REG + mov eax, FCR_EFIFO+FCR_CRB+FCR_CXMIT+FCR_FIFO_14 + out dx, al +.clear_RB: + mov edx, [esi+UART.base] + add edx, LSR_REG + in al, dx + test eax, LSR_DR + jz @F + + mov edx, [esi+UART.base] + in al, dx + jmp .clear_RB +@@: + mov edx, [esi+UART.base] + add edx, IER_REG + mov eax, IER_RDAI+IER_THRI+IER_LSI + out dx, al +.clear_IIR: + mov edx, [esi+UART.base] + add edx, IIR_REG + in al, dx + test al, IIR_INTR + jnz .done + + shr eax, 1 + and eax, 3 + jnz @F + + mov edx, [esi+UART.base] + add edx, MSR_REG + in al, dx + jmp .clear_IIR +@@: + cmp eax, 1 + je .clear_IIR + + cmp eax, 2 + jne @F + + mov edx, [esi+UART.base] + in al, dx + jmp .clear_IIR +@@: + mov edx, [esi+UART.base] + add edx, LSR_REG + in al, dx + jmp .clear_IIR +.done: + mov edi, [esi+UART.rcvr_buff] + mov ecx, 8192/4 + xor eax, eax + + mov [esi+UART.rcvr_rp], edi + mov [esi+UART.rcvr_wp], edi + mov [esi+UART.rcvr_count], eax + + cld + rep stosd + + mov edi, [esi+UART.xmit_buff] + mov ecx, 8192/4 + + mov [esi+UART.xmit_rp], edi + mov [esi+UART.xmit_wp], edi + mov [esi+UART.xmit_count], eax + mov [esi+UART.xmit_free], 8192 + + rep stosd + ret ;eax= 0 +.fail: + or eax, -1 + ret + +; param +; esi= input buffer +; +0 connection +; +4 rate +; +8 mode +; +; retval +; eax= error code + +align 4 +uart_set_mode: + mov eax, [esi] + cmp [eax+APPOBJ.magic], 'CNCT' + jne .fail + + cmp [eax+APPOBJ.destroy], uart_close.destroy + jne .fail + + mov eax, [eax+CONNECTION.uart] + test eax, eax + jz .fail + + mov ebx, [esi+4] + mov ecx, [esi+8] + +; param +; eax= uart +; ebx= baud rate +; ecx= mode + +align 4 +.internal: + cmp ebx, RATE_115200 + ja .fail + + cmp ecx, LCR_BREAK + jae .fail + + mov [eax+UART.rate], ebx + mov [eax+UART.mode], ecx + + mov esi, eax + mov bx, [divisor+ebx*2] + + mov edx, [esi+UART.base] + push edx + add edx, LCR_REG + in al, dx + or al, 0x80 + out dx, al + + pop edx + mov al, bl + out dx, al + + inc dx + mov al, bh + out dx, al + + add edx, LCR_REG-1 + mov eax, ecx + out dx, al + xor eax, eax + ret +.fail: + or eax, -1 + ret + +; param +; esi= input buffer +; +0 connection +; +4 modem control reg valie +; +; retval +; eax= error code + +align 4 +uart_set_mcr: + + mov eax, [esi] + cmp [eax+APPOBJ.magic], 'CNCT' + jne .fail + + cmp [eax+APPOBJ.destroy], uart_close.destroy + jne .fail + + mov eax, [eax+CONNECTION.uart] + test eax, eax + jz .fail + + mov ebx, [esi+4] + + mov [eax+UART.mcr_reg], ebx + mov edx, [eax+UART.base] + add edx, MCR_REG + mov al, bl + out dx, al + xor eax, eax + ret +.fail: + or eax, -1 + ret + +; param +; eax= port +; +; retval +; ecx= connection +; eax= error code + +align 4 +uart_open: + dec eax + cmp eax, COM_MAX + jae .fail + + mov esi, [com1+eax*4] ;uart + push esi +.do_wait: + cmp dword [esi+UART.lock], 0 + je .get_lock + ; call change_task + jmp .do_wait +.get_lock: + mov eax, 1 + xchg eax, [esi+UART.lock] + test eax, eax + jnz .do_wait + + mov eax, esi ;uart + call uart_reset.internal + + mov ebx, [CURRENT_TASK] + shl ebx, 5 + mov ebx, [CURRENT_TASK+ebx+4] + mov eax, CONNECTION_SIZE + call CreateObject + pop esi ;uart + test eax, eax + jz .fail + + mov [eax+APPOBJ.magic], 'CNCT' + mov [eax+APPOBJ.destroy], uart_close.destroy + mov [eax+CONNECTION.uart], esi + mov ecx, eax + xor eax, eax + ret +.fail: + or eax, -1 + ret +restore .uart + +; param +; esi= input buffer + +align 4 +uart_close: + mov eax, [esi] + cmp [eax+APPOBJ.magic], 'CNCT' + jne .fail + + cmp [eax+APPOBJ.destroy], uart_close.destroy + jne .fail +.destroy: + push [eax+CONNECTION.uart] + call DestroyObject ;eax= object + pop eax ;eax= uart + test eax, eax + jz .fail + + mov [eax+UART.state], UART_CLOSED + mov [eax+UART.lock], 0;release port + xor eax, eax + ret +.fail: + or eax, -1 + ret + + +; param +; eax= uart +; ebx= baud rate + +align 4 +set_rate: + cmp ebx, RATE_115200 + ja .fail + + mov [eax+UART.rate], ebx + mov bx, [divisor+ebx*2] + + mov edx, [eax+UART.base] + add edx, LCR_REG + in al, dx + push eax + or al, 0x80 + out dx, al + + sub edx, LCR_REG + mov al, bl + out dx, al + + inc edx + mov al, bh + out dx, al + + pop eax + add edx, LCR_REG-1 + out dx, al +.fail: + ret + + +; param +; ebx= uart + +align 4 +transmit: + push esi + push edi + + mov edx, [ebx+UART.base] + + pushfd + cli + + mov esi, [ebx+UART.xmit_rp] + mov ecx, [ebx+UART.xmit_count] + test ecx, ecx + je .stop + + cmp ecx, 16 + jbe @F + mov ecx, 16 +@@: + sub [ebx+UART.xmit_count], ecx + add [ebx+UART.xmit_free], ecx + cld +@@: + lodsb + out dx, al + dec ecx + jnz @B + + cmp esi, [ebx+UART.xmit_top] + jb @F + sub esi, 8192 +@@: + mov [ebx+UART.xmit_rp], esi + + cmp [ebx+UART.xmit_count], 0 + je .stop + + mov [ebx+UART.state], UART_TRANSMIT + jmp @F +.stop: + mov [ebx+UART.state], UART_STOP +@@: + popfd + pop edi + pop esi + ret + + +; param +; esi= input buffer +; +0 connection +; +4 dst buffer +; +8 dst size +; edi= output buffer +; +0 bytes read + +; retval +; eax= error code + +align 4 +uart_read: + mov eax, [esi] + cmp [eax+APPOBJ.magic], 'CNCT' + jne .fail + + cmp [eax+APPOBJ.destroy], uart_close.destroy + jne .fail + + mov eax, [eax+CONNECTION.uart] + test eax, eax + jz .fail + + mov ebx, [esi+8] ;dst size + mov ecx, [eax+UART.rcvr_count] + cmp ecx, ebx + jbe @F + mov ecx, ebx +@@: + mov [edi], ecx ;bytes read + test ecx, ecx + jz .done + + push ecx + + mov edi, [esi+4] ;dst + mov esi, [eax+UART.rcvr_rp] + cld + rep movsb + pop ecx + + cmp esi, [eax+UART.rcvr_top] + jb @F + sub esi, 8192 +@@: + mov [eax+UART.rcvr_rp], esi + sub [eax+UART.rcvr_count], ecx +.done: + xor eax, eax + ret +.fail: + or eax, -1 + ret + +; param +; esi= input buffer +; +0 connection +; +4 src buffer +; +8 src size +; +; retval +; eax= error code + +align 4 +uart_write: + mov eax, [esi] + cmp [eax+APPOBJ.magic], 'CNCT' + jne .fail + + cmp [eax+APPOBJ.destroy], uart_close.destroy + jne .fail + + mov eax, [eax+CONNECTION.uart] + test eax, eax + jz .fail + + mov ebx, [esi+4] + mov edx, [esi+8] + +; param +; eax= uart +; ebx= src +; edx= count + +align 4 +.internal: + mov esi, ebx + mov edi, [eax+UART.xmit_wp] +.write: + test edx, edx + jz .fail +.wait: + cmp [eax+UART.xmit_free], 0 + jne .fill + + cmp [eax+UART.state], UART_TRANSMIT + je .wait + + mov ebx, eax + push edx + call transmit + pop edx + mov eax, ebx + jmp .write +.fill: + mov ecx, [eax+UART.xmit_free] + cmp ecx, edx + jbe @F + mov ecx, edx +@@: + push ecx + cld + rep movsb + pop ecx + sub [eax+UART.xmit_free], ecx + add [eax+UART.xmit_count], ecx + sub edx, ecx + jnz .wait +.done: + cmp edi, [eax+UART.xmit_top] + jb @F + sub edi, 8192 +@@: + mov [eax+UART.xmit_wp], edi + cmp [eax+UART.state], UART_TRANSMIT + je @F + mov ebx, eax + call transmit +@@: + xor eax, eax + ret +.fail: + or eax, -1 + ret + + +align 4 +com_2_isr: + mov ebx, [com2] + jmp com_1_isr.get_info +align 4 +com_1_isr: + mov ebx, [com1] +.get_info: + mov edx, [ebx+UART.base] + add edx, IIR_REG + in al, dx + + test al, IIR_INTR + jnz .done + + shr eax, 1 + and eax, 3 + + call [isr_action+eax*4] + jmp .get_info +.done: + ret + +align 4 +isr_line: + mov edx, [ebx+UART.base] + add edx, LSR_REG + in al, dx + ret + +align 4 +isr_recieve: + mov esi, [ebx+UART.base] + add esi, LSR_REG + mov edi, [ebx+UART.rcvr_wp] + xor ecx, ecx + cld +.read: + mov edx, esi + in al, dx + test eax, LSR_DR + jz .done + + mov edx, [ebx+UART.base] + in al, dx + stosb + inc ecx + jmp .read +.done: + cmp edi, [ebx+UART.rcvr_top] + jb @F + sub edi, 8192 +@@: + mov [ebx+UART.rcvr_wp], edi + add [ebx+UART.rcvr_count], ecx + ret + +align 4 +isr_modem: + mov edx, [ebx+UART.base] + add edx, MSR_REG + in al, dx + ret + + +align 4 +divisor dw 2304, 1536, 1047, 857, 768, 384 + dw 192, 96, 64, 58, 48, 32 + dw 24, 16, 12, 6, 3, 2, 1 + +align 4 +uart_func dd 0 ;SRV_GETVERSION + dd 0 ;PORT_OPEN + dd uart_close ;PORT_CLOSE + dd uart_reset ;PORT_RESET + dd uart_set_mode ;PORT_SETMODE + dd 0 ;PORT_GETMODE + dd uart_set_mcr ;PORT_SETMODEM + dd 0 ;PORT_GETMODEM + dd uart_read ;PORT_READ + dd uart_write ;PORT_WRITE + +isr_action dd isr_modem + dd transmit + dd isr_recieve + dd isr_line + +version dd (5 shl 16) or (UART_VERSION and 0xFFFF) + +sz_uart_srv db 'UART',0 + +align 4 + +com1 rd 1 +com2 rd 1 + diff --git a/kernel/trunk/drivers/usb/urb.inc b/kernel/trunk/drivers/usb/urb.inc index d3be5e75b..d0dce301d 100644 --- a/kernel/trunk/drivers/usb/urb.inc +++ b/kernel/trunk/drivers/usb/urb.inc @@ -1,115 +1,115 @@ - -struc URB -{ - .fd dd ? - .bk dd ? - .dev dd ? ; pointer to associated device - .pipe dd ? ; pipe information - .status dd ? ; non-ISO status - .transfer_flags dd ? ; URB_SHORT_NOT_OK | ... - .transfer_buffer dd ? ; associated data buffer - .transfer_dma dd ? ; dma addr for transfer_buffer - .transfer_buffer_length dd ? ; data buffer length - .actual_length dd ? ; actual transfer length - .setup_packet dd ? ; setup packet (control only) - .setup_dma dd ? ; dma addr for setup_packet - .start_frame dd ? ; start frame (ISO) - .number_of_packets dd ? ; number of ISO packets - .interval dd ? ; transfer interval - - .error_count dd ? ; number of ISO errors - .context dd ? ; context for completion - .complete dd ? ; (in) completion routine - .iso_frame_desc: -} - -virtual at 0 - URB URB -end virtual - - -struc REQ ;usb request -{ - .request_type db ? - .request db ? - .value dw ? - .index dw ? - .length dw ? -} - -virtual at 0 - REQ REQ -end virtual - -align 4 -proc usb_control_msg stdcall, dev:dword, pipe:dword, request:dword,\ - requesttype:dword, value:dword, index:dword,\ - data:dword, size:dword, timeout:dword - - locals - req REQ - endl - - lea eax, [req] - mov ecx, [request] - mov ebx, [requesttupe] - mov edx, [value] - mov esi, [index] - mov edi, [size] - - mov [eax+REQ.request_type], bl - mov [eax+REQ.request], cl - mov [eax+REQ.value], dx - mov [eax+REQ.index], si - mov [eax+REQ.length], di - - stdcall usb_internal_control_msg, [dev], [pipe],\ - eax, [data], [size], [timeout] - - ret -endp - - -; returns status (negative) or length (positive) -static int usb_internal_control_msg(struct usb_device *usb_dev, - unsigned int pipe, - struct usb_ctrlrequest *cmd, - void *data, int len, int timeout) -{ - struct urb *urb; - int retv; - int length; - - urb = usb_alloc_urb(0, GFP_NOIO); - if (!urb) - return -ENOMEM; - usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, - len, usb_api_blocking_completion, NULL); - - retv = usb_start_wait_urb(urb, timeout, &length); - if (retv < 0) - return retv; - else - return length; -} - - -void usb_fill_control_urb (struct urb *urb, - struct usb_device *dev, - unsigned int pipe, - unsigned char *setup_packet, - void *transfer_buffer, - int buffer_length, - usb_complete_t complete_fn, - void *context) -{ - - urb->dev = dev; - urb->pipe = pipe; - urb->setup_packet = setup_packet; - urb->transfer_buffer = transfer_buffer; - urb->transfer_buffer_length = buffer_length; - urb->complete = complete_fn; - urb->context = context; -} - + +struc URB +{ + .fd dd ? + .bk dd ? + .dev dd ? ; pointer to associated device + .pipe dd ? ; pipe information + .status dd ? ; non-ISO status + .transfer_flags dd ? ; URB_SHORT_NOT_OK | ... + .transfer_buffer dd ? ; associated data buffer + .transfer_dma dd ? ; dma addr for transfer_buffer + .transfer_buffer_length dd ? ; data buffer length + .actual_length dd ? ; actual transfer length + .setup_packet dd ? ; setup packet (control only) + .setup_dma dd ? ; dma addr for setup_packet + .start_frame dd ? ; start frame (ISO) + .number_of_packets dd ? ; number of ISO packets + .interval dd ? ; transfer interval + + .error_count dd ? ; number of ISO errors + .context dd ? ; context for completion + .complete dd ? ; (in) completion routine + .iso_frame_desc: +} + +virtual at 0 + URB URB +end virtual + + +struc REQ ;usb request +{ + .request_type db ? + .request db ? + .value dw ? + .index dw ? + .length dw ? +} + +virtual at 0 + REQ REQ +end virtual + +align 4 +proc usb_control_msg stdcall, dev:dword, pipe:dword, request:dword,\ + requesttype:dword, value:dword, index:dword,\ + data:dword, size:dword, timeout:dword + + locals + req REQ + endl + + lea eax, [req] + mov ecx, [request] + mov ebx, [requesttupe] + mov edx, [value] + mov esi, [index] + mov edi, [size] + + mov [eax+REQ.request_type], bl + mov [eax+REQ.request], cl + mov [eax+REQ.value], dx + mov [eax+REQ.index], si + mov [eax+REQ.length], di + + stdcall usb_internal_control_msg, [dev], [pipe], \ + eax, [data], [size], [timeout] + + ret +endp + + +; returns status (negative) or length (positive) +static int usb_internal_control_msg(struct usb_device *usb_dev, + unsigned int pipe, + struct usb_ctrlrequest *cmd, + void *data, int len, int timeout) +{ + struct urb *urb; + int retv; + int length; + + urb = usb_alloc_urb(0, GFP_NOIO); + if (!urb) + return -ENOMEM; + usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, + len, usb_api_blocking_completion, NULL); + + retv = usb_start_wait_urb(urb, timeout, &length); + if (retv < 0) + return retv; + else + return length; +} + + +;void usb_fill_control_urb (struct urb *urb, +; struct usb_device *dev, +; unsigned int pipe, +; unsigned char *setup_packet, +; void *transfer_buffer, +; int buffer_length, +; usb_complete_t complete_fn, +; void *context) +;{ +; +; urb->dev = dev; +; urb->pipe = pipe; +; urb->setup_packet = setup_packet; +; urb->transfer_buffer = transfer_buffer; +; urb->transfer_buffer_length = buffer_length; +; urb->complete = complete_fn; +; urb->context = context; +;} +; diff --git a/kernel/trunk/drivers/usb/usb.asm b/kernel/trunk/drivers/usb/usb.asm index 13cbd8133..90fc49ce3 100644 --- a/kernel/trunk/drivers/usb/usb.asm +++ b/kernel/trunk/drivers/usb/usb.asm @@ -1,435 +1,435 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;driver sceletone - -format MS COFF - -API_VERSION equ 0 ;debug - -include '../proc32.inc' -include '../imports.inc' -include 'urb.inc' - -struc UHCI -{ - .bus dd ? - .devfn dd ? - .io_base dd ? - .mm_base dd ? - .irq dd ? - .flags dd ? - .reset dd ? - .start dd ? - .stop dd ? - - .port_c_suspend dd ? - .resuming_ports dd ? - .rh_state dd ? - .rh_numports dd ? - .is_stopped dd ? - .dead dd ? - - .sizeof: -} - -virtual at 0 - UHCI UHCI -end virtual - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -struc TD ;transfer descriptor -{ - .link dd ? - .status dd ? - .token dd ? - .buffer dd ? - - .addr dd ? - .frame dd ? - .fd dd ? - .bk dd ? - .sizeof: -} - -virtual at 0 - TD TD -end virtual - -public START -public service_proc -public version - -DEBUG equ 1 - -DRV_ENTRY equ 1 -DRV_EXIT equ -1 -STRIDE equ 4 ;size of row in devices table - -SRV_GETVERSION equ 0 - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .exit -.entry: - - if DEBUG - mov esi, msgInit - call SysMsgBoardStr - end if - - call init - - stdcall RegService, my_service, service_proc - ret -.fail: -.exit: - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - - mov ebx, [ioctl] - mov eax, [ebx+io_code] - cmp eax, SRV_GETVERSION - jne @F - - mov eax, [ebx+output] - cmp [ebx+out_size], 4 - jne .fail - mov [eax], dword API_VERSION - xor eax, eax - ret -@@: -.fail: - or eax, -1 - ret -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - -align 4 -proc detect - locals - last_bus dd ? - bus dd ? - devfn dd ? - endl - - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err - - mov [last_bus], eax - -.next_bus: - and [devfn], 0 -.next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next - - mov edi, devices -@@: - mov ebx, [edi] - test ebx, ebx - jz .next - - cmp eax, ebx - je .found - - add edi, STRIDE - jmp @B -.next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret -.found: - mov eax, UHCI.sizeof - call Kmalloc - test eax, eax - jz .mem_fail - - mov ebx, [bus] - mov [eax+UHCI.bus], ebx - - mov ecx, [devfn] - mov [eax+UHCI.devfn], ecx - ret -.mem_fail: - if DEBUG - mov esi, msgMemFail - call SysMsgBoardStr - end if -.err: - xor eax, eax - ret -endp - -PCI_BASE equ 0x20 -USB_LEGKEY equ 0xC0 - -align 4 -proc init - locals - uhci dd ? - endl - - call detect - test eax, eax - jz .fail - - mov [uhci], eax - - stdcall PciRead32, [eax+UHCI.bus], [eax+UHCI.devfn], PCI_BASE - and eax, 0xFFC0 - mov esi, [uhci] - mov [esi+UHCI.io_base], eax - - stdcall uhci_reset, esi - - stdcall finish_reset, [uhci] - -.fail: - if DEBUG - mov esi, msgDevNotFound - call SysMsgBoardStr - end if - ret -endp - -UHCI_USBINTR equ 4 ; interrupt register - -UHCI_USBLEGSUP_RWC equ 0x8f00 ; the R/WC bits -UHCI_USBLEGSUP_RO equ 0x5040 ; R/O and reserved bits - -UHCI_USBCMD_RUN equ 0x0001 ; RUN/STOP bit -UHCI_USBCMD_HCRESET equ 0x0002 ; Host Controller reset -UHCI_USBCMD_EGSM equ 0x0008 ; Global Suspend Mode -UHCI_USBCMD_CONFIGURE equ 0x0040 ; Config Flag -UHCI_USBINTR_RESUME equ 0x0002 ; Resume interrupt enable - -PORTSC0 equ 0x10 -PORTSC1 equ 0x12 - - -UHCI_RH_RESET equ 0 -UHCI_RH_SUSPENDED equ 1 -UHCI_RH_AUTO_STOPPED equ 2 -UHCI_RH_RESUMING equ 3 - -; In this state the HC changes from running to halted -; so it can legally appear either way. -UHCI_RH_SUSPENDING equ 4 - -; In the following states it's an error if the HC is halted. -; These two must come last. -UHCI_RH_RUNNING equ 5 ; The normal state -UHCI_RH_RUNNING_NODEVS equ 6 ; Running with no devices - -UHCI_IS_STOPPED equ 9999 - -align 4 -proc uhci_reset stdcall, uhci:dword - mov esi, [uhci] - stdcall PciRead16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY - test eax, not (UHCI_USBLEGSUP_RO or UHCI_USBLEGSUP_RWC) - jnz .reset - - mov edx, [esi+UHCI.io_base] - in ax, dx - test ax, UHCI_USBCMD_RUN - jnz .reset - - test ax, UHCI_USBCMD_CONFIGURE - jz .reset - - test ax, UHCI_USBCMD_EGSM - jz .reset - - add edx, UHCI_USBINTR - in ax, dx - test ax, not UHCI_USBINTR_RESUME - jnz .reset - ret -.reset: - stdcall PciWrite16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY, UHCI_USBLEGSUP_RWC - - mov edx, [esi+UHCI.io_base] - mov ax, UHCI_USBCMD_HCRESET - out dx, ax - - xor eax, eax - out dx, ax - add edx, UHCI_USBINTR - out dx, ax - ret -endp - -proc finish_reset stdcall, uhci:dword - - mov esi, [uhci] - mov edx, [esi+UHCI.io_base] - add edx, PORTSC0 - xor eax, eax - out dx, ax - add edx, (PORTSC1-PORTSC0) - out dx, ax - - mov [esi+UHCI.port_c_suspend], eax - mov [esi+UHCI.resuming_ports], eax - mov [esi+UHCI.rh_state], UHCI_RH_RESET - mov [esi+UHCI.rh_numports], 2 - - mov [esi+UHCI.is_stopped], UHCI_IS_STOPPED - ; mov [ uhci_to_hcd(uhci)->state = HC_STATE_HALT; - ; uhci_to_hcd(uhci)->poll_rh = 0; - - mov [esi+UHCI.dead], eax ; Full reset resurrects the controller - - ret -endp - -proc insert_td stdcall, td:dword, frame:dword - - mov edi, [td] - mov eax, [frame] - and eax, -1024 - mov [edi+TD.frame], eax - - mov ebx, [framelist] - mov edx, [dma_framelist] - shl eax, 5 - - mov ecx, [eax+ebx] - test ecx, ecx - jz .empty - - mov ecx, [ecx+TD.bk] ;last TD - - mov edx, [ecx+TD.fd] - mov [edi+TD.fd], edx - mov [edi+TD.bk], ecx - mov [ecx+TD.fd], edi - mov [edx+TD.bk], edi - - mov eax, [ecx+TD.link] - mov [edi+TD.link], eax - mov ebx, [edi+TD.addr] - mov [ecx+TD.link], ebx - ret -.empty: - mov ecx, [eax+edx] - mov [edi+TD.link], ecx - mov [ebx+eax], edi - mov ecx, [edi+TD.addr] - mov [eax+edx], ecx - ret -endp - - -align 4 -proc usb_get_descriptor stdcall, dev:dword, type:dword, index:dword,\ - buf:dword, size:dword - - locals - count dd ? - endl - - mov esi, [buf] - mov ecx, [size] - xor eax, eax - cld - rep stosb - - mov [count], 3 -@@: - mov eax, [type] - shl eax, 8 - add eax, [index] - stdcall usb_control_msg, [dev],pipe,USB_REQ_GET_DESCRIPTOR,\ - USB_DIR_IN, eax,0,[buf], [size],\ - USB_CTRL_GET_TIMEOUT - test eax, eax - jz .next - cmp eax, -1 - je .next - jmp. ok -.next: - dec [count] - jnz @B - mov eax, -1 -.ok: - ret -endp - -DEVICE_ID equ 0x24D2 ; pci device id -VENDOR_ID equ 0x8086 ; device vendor id -QEMU_USB equ 0x7020 - -;all initialized data place here - -align 4 -devices dd (DEVICE_ID shl 16)+VENDOR_ID - dd (QEMU_USB shl 16)+VENDOR_ID - dd 0 ;terminator - -version dd (5 shl 16) or (API_VERSION and 0xFFFF) - -my_service db 'UHCI',0 ;max 16 chars include zero - -msgInit db 'detect hardware...',13,10,0 -msgPCI db 'PCI accsess not supported',13,10,0 -msgDevNotFound db 'device not found',13,10,0 -msgMemFail db 'Kmalloc failed', 10,10,0 -;msgFail db 'device not found',13,10,0 - -section '.data' data readable writable align 16 - -;all uninitialized data place here - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;driver sceletone + +format MS COFF + +API_VERSION equ 0 ;debug + +include '../proc32.inc' +include '../imports.inc' +include 'urb.inc' + +struc UHCI +{ + .bus dd ? + .devfn dd ? + .io_base dd ? + .mm_base dd ? + .irq dd ? + .flags dd ? + .reset dd ? + .start dd ? + .stop dd ? + + .port_c_suspend dd ? + .resuming_ports dd ? + .rh_state dd ? + .rh_numports dd ? + .is_stopped dd ? + .dead dd ? + + .sizeof: +} + +virtual at 0 + UHCI UHCI +end virtual + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +struc TD ;transfer descriptor +{ + .link dd ? + .status dd ? + .token dd ? + .buffer dd ? + + .addr dd ? + .frame dd ? + .fd dd ? + .bk dd ? + .sizeof: +} + +virtual at 0 + TD TD +end virtual + +public START +public service_proc +public version + +DEBUG equ 1 + +DRV_ENTRY equ 1 +DRV_EXIT equ -1 +STRIDE equ 4 ;size of row in devices table + +SRV_GETVERSION equ 0 + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .exit +.entry: + + if DEBUG + mov esi, msgInit + call SysMsgBoardStr + end if + + call init + + stdcall RegService, my_service, service_proc + ret +.fail: +.exit: + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + + mov ebx, [ioctl] + mov eax, [ebx+io_code] + cmp eax, SRV_GETVERSION + jne @F + + mov eax, [ebx+output] + cmp [ebx+out_size], 4 + jne .fail + mov [eax], dword API_VERSION + xor eax, eax + ret +@@: +.fail: + or eax, -1 + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + +align 4 +proc detect + locals + last_bus dd ? + bus dd ? + devfn dd ? + endl + + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err + + mov [last_bus], eax + +.next_bus: + and [devfn], 0 +.next_dev: + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next + + mov edi, devices +@@: + mov ebx, [edi] + test ebx, ebx + jz .next + + cmp eax, ebx + je .found + + add edi, STRIDE + jmp @B +.next: + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret +.found: + mov eax, UHCI.sizeof + call Kmalloc + test eax, eax + jz .mem_fail + + mov ebx, [bus] + mov [eax+UHCI.bus], ebx + + mov ecx, [devfn] + mov [eax+UHCI.devfn], ecx + ret +.mem_fail: + if DEBUG + mov esi, msgMemFail + call SysMsgBoardStr + end if +.err: + xor eax, eax + ret +endp + +PCI_BASE equ 0x20 +USB_LEGKEY equ 0xC0 + +align 4 +proc init + locals + uhci dd ? + endl + + call detect + test eax, eax + jz .fail + + mov [uhci], eax + + stdcall PciRead32, [eax+UHCI.bus], [eax+UHCI.devfn], PCI_BASE + and eax, 0xFFC0 + mov esi, [uhci] + mov [esi+UHCI.io_base], eax + + stdcall uhci_reset, esi + + stdcall finish_reset, [uhci] + +.fail: + if DEBUG + mov esi, msgDevNotFound + call SysMsgBoardStr + end if + ret +endp + +UHCI_USBINTR equ 4 ; interrupt register + +UHCI_USBLEGSUP_RWC equ 0x8f00 ; the R/WC bits +UHCI_USBLEGSUP_RO equ 0x5040 ; R/O and reserved bits + +UHCI_USBCMD_RUN equ 0x0001 ; RUN/STOP bit +UHCI_USBCMD_HCRESET equ 0x0002 ; Host Controller reset +UHCI_USBCMD_EGSM equ 0x0008 ; Global Suspend Mode +UHCI_USBCMD_CONFIGURE equ 0x0040 ; Config Flag +UHCI_USBINTR_RESUME equ 0x0002 ; Resume interrupt enable + +PORTSC0 equ 0x10 +PORTSC1 equ 0x12 + + +UHCI_RH_RESET equ 0 +UHCI_RH_SUSPENDED equ 1 +UHCI_RH_AUTO_STOPPED equ 2 +UHCI_RH_RESUMING equ 3 + +; In this state the HC changes from running to halted +; so it can legally appear either way. +UHCI_RH_SUSPENDING equ 4 + +; In the following states it's an error if the HC is halted. +; These two must come last. +UHCI_RH_RUNNING equ 5 ; The normal state +UHCI_RH_RUNNING_NODEVS equ 6 ; Running with no devices + +UHCI_IS_STOPPED equ 9999 + +align 4 +proc uhci_reset stdcall, uhci:dword + mov esi, [uhci] + stdcall PciRead16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY + test eax, not (UHCI_USBLEGSUP_RO or UHCI_USBLEGSUP_RWC) + jnz .reset + + mov edx, [esi+UHCI.io_base] + in ax, dx + test ax, UHCI_USBCMD_RUN + jnz .reset + + test ax, UHCI_USBCMD_CONFIGURE + jz .reset + + test ax, UHCI_USBCMD_EGSM + jz .reset + + add edx, UHCI_USBINTR + in ax, dx + test ax, not UHCI_USBINTR_RESUME + jnz .reset + ret +.reset: + stdcall PciWrite16, [esi+UHCI.bus], [esi+UHCI.devfn], USB_LEGKEY, UHCI_USBLEGSUP_RWC + + mov edx, [esi+UHCI.io_base] + mov ax, UHCI_USBCMD_HCRESET + out dx, ax + + xor eax, eax + out dx, ax + add edx, UHCI_USBINTR + out dx, ax + ret +endp + +proc finish_reset stdcall, uhci:dword + + mov esi, [uhci] + mov edx, [esi+UHCI.io_base] + add edx, PORTSC0 + xor eax, eax + out dx, ax + add edx, (PORTSC1-PORTSC0) + out dx, ax + + mov [esi+UHCI.port_c_suspend], eax + mov [esi+UHCI.resuming_ports], eax + mov [esi+UHCI.rh_state], UHCI_RH_RESET + mov [esi+UHCI.rh_numports], 2 + + mov [esi+UHCI.is_stopped], UHCI_IS_STOPPED + ; mov [ uhci_to_hcd(uhci)->state = HC_STATE_HALT; + ; uhci_to_hcd(uhci)->poll_rh = 0; + + mov [esi+UHCI.dead], eax ; Full reset resurrects the controller + + ret +endp + +proc insert_td stdcall, td:dword, frame:dword + + mov edi, [td] + mov eax, [frame] + and eax, -1024 + mov [edi+TD.frame], eax + + mov ebx, [framelist] + mov edx, [dma_framelist] + shl eax, 5 + + mov ecx, [eax+ebx] + test ecx, ecx + jz .empty + + mov ecx, [ecx+TD.bk] ;last TD + + mov edx, [ecx+TD.fd] + mov [edi+TD.fd], edx + mov [edi+TD.bk], ecx + mov [ecx+TD.fd], edi + mov [edx+TD.bk], edi + + mov eax, [ecx+TD.link] + mov [edi+TD.link], eax + mov ebx, [edi+TD.addr] + mov [ecx+TD.link], ebx + ret +.empty: + mov ecx, [eax+edx] + mov [edi+TD.link], ecx + mov [ebx+eax], edi + mov ecx, [edi+TD.addr] + mov [eax+edx], ecx + ret +endp + + +align 4 +proc usb_get_descriptor stdcall, dev:dword, type:dword, index:dword,\ + buf:dword, size:dword + + locals + count dd ? + endl + + mov esi, [buf] + mov ecx, [size] + xor eax, eax + cld + rep stosb + + mov [count], 3 +@@: + mov eax, [type] + shl eax, 8 + add eax, [index] + stdcall usb_control_msg, [dev], pipe, USB_REQ_GET_DESCRIPTOR, \ + USB_DIR_IN, eax,0,[buf], [size],\ + USB_CTRL_GET_TIMEOUT + test eax, eax + jz .next + cmp eax, -1 + je .next + jmp. ok +.next: + dec [count] + jnz @B + mov eax, -1 +.ok: + ret +endp + +DEVICE_ID equ 0x24D2 ; pci device id +VENDOR_ID equ 0x8086 ; device vendor id +QEMU_USB equ 0x7020 + +;all initialized data place here + +align 4 +devices dd (DEVICE_ID shl 16)+VENDOR_ID + dd (QEMU_USB shl 16)+VENDOR_ID + dd 0 ;terminator + +version dd (5 shl 16) or (API_VERSION and 0xFFFF) + +my_service db 'UHCI',0 ;max 16 chars include zero + +msgInit db 'detect hardware...',13,10,0 +msgPCI db 'PCI accsess not supported',13,10,0 +msgDevNotFound db 'device not found',13,10,0 +msgMemFail db 'Kmalloc failed', 10,10,0 +;msgFail db 'device not found',13,10,0 + +section '.data' data readable writable align 16 + +;all uninitialized data place here + diff --git a/kernel/trunk/drivers/vidintel.asm b/kernel/trunk/drivers/vidintel.asm index 70e898cdd..ab6fe5dc1 100644 --- a/kernel/trunk/drivers/vidintel.asm +++ b/kernel/trunk/drivers/vidintel.asm @@ -1,465 +1,465 @@ -; Stub of videodriver for Intel videocards. -; (c) CleverMouse - -; When the start procedure gots control, -; it tries to detect preferred resolution, -; sets the detected resolution assuming 32-bpp VESA mode and exits -; (without registering a service). -; Detection can be overloaded with compile-time settings -; use_predefined_mode/predefined_width/predefined_height. - -; set predefined resolution here -use_predefined_mode = 0;1 -predefined_width = 0;1366 -predefined_height = 0;768 - -; standard driver stuff -format MS COFF - -DEBUG = 1 - -include 'proc32.inc' -include 'imports.inc' - -public START -public version - -section '.flat' code readable align 16 -; the start procedure (see the description above) -START: -; 1. Detect device. Abort if not found. - push esi - call DetectDevice - test esi, esi - jz .return0 -; 2. Detect optimal mode unless the mode is given explicitly. Abort if failed. -if use_predefined_mode = 0 - call DetectMode -end if - cmp [width], 0 - jz .return0_cleanup -; 3. Set the detected mode. - call SetMode -; 4. Cleanup and return. -.return0_cleanup: - stdcall FreeKernelSpace, esi -.return0: - pop esi - xor eax, eax - ret 4 - -; check that there is Intel videocard -; if so, map MMIO registers and set internal variables -; esi points to MMIO block; NULL means no device -DetectDevice: -; 1. Sanity check: check that we are dealing with Intel videocard. -; Integrated video device for Intel is always at PCI:0:2:0. - xor esi, esi ; initialize return value to NULL -; 1a. Get PCI VendorID and DeviceID. - push esi - push 10h - push esi - call PciRead32 -; 1b. loword(eax) = ax = VendorID, hiword(eax) = DeviceID. -; Test whether we have Intel chipset. - cmp ax, 8086h - jnz .return -; 1c. Say hi including DeviceID. - shr eax, 10h - push edi - pusha - mov edi, pciid_text - call WriteWord - mov esi, hellomsg - call SysMsgBoardStr - popa -; 1d. Test whether we know this DeviceID. -; If this is the case, remember the position of the device in line of Intel cards; -; this knowledge will be useful later. -; Tested on devices with id: 8086:0046, partially 8086:2A02. - mov ecx, pciids_num - mov edi, pciids - repnz scasw - pop edi - jnz .return_unknown_pciid - sub ecx, pciids_num - 1 - neg ecx - mov [deviceType], ecx -; 1e. Continue saying hi with positive intonation. - pusha - mov esi, knownmsg - call SysMsgBoardStr - popa -; 2. Prepare MMIO region to control the card. -; 2a. Read MMIO physical address from PCI config space. - push 10h - cmp ecx, i9xx_start - jae @f - mov byte [esp], 14h -@@: - push 10h - push esi - call PciRead32 -; 2b. Mask out PCI region type, lower 4 bits. - and al, not 0xF -; 2c. Create virtual mapping of the physical memory. - push 1Bh - push 100000h - push eax - call MapIoMem -; 3. Return. - xchg esi, eax -.return: - ret -; 1f. If we do not know DeviceID, continue saying hi with negative intonation. -.return_unknown_pciid: - pusha - mov esi, unknownmsg - call SysMsgBoardStr - popa - ret - -; Convert word in ax to hexadecimal text in edi, advance edi. -WriteWord: -; 1. Convert high byte. - push eax - mov al, ah - call WriteByte - pop eax -; 2. Convert low byte. -; Fall through to WriteByte; ret from WriteByte is ret from WriteWord too. - -; Convert byte in al to hexadecimal text in edi, advance edi. -WriteByte: -; 1. Convert high nibble. - push eax - shr al, 4 - call WriteNibble - pop eax -; 2. Convert low nibble. - and al, 0xF -; Fall through to WriteNibble; ret from WriteNibble is ret from WriteByte too. - -; Convert nibble in al to hexadecimal text in edi, advance edi. -WriteNibble: -; Obvious, isn't it? - cmp al, 10 - sbb al, 69h - das - stosb - ret - -if use_predefined_mode = 0 -; detect resolution of the flat panel -DetectMode: - push esi edi -; 1. Get the location of block of GMBUS* registers. -; Starting with Ironlake, GMBUS* registers were moved. - add esi, 5100h - cmp [deviceType], ironlake_start - jb @f - add esi, 0xC0000 -@@: -; 2. Initialize GMBUS engine. - mov edi, edid - mov ecx, 0x10000 -@@: - test byte [esi+8+1], 80h - loopnz @b - jnz .fail - mov dword [esi], 3 - test byte [esi+8+1], 4 - jz .noreset - call ResetGMBus - jnz .fail -.noreset: -; 3. Send read command. - and dword [esi+20h], 0 - mov dword [esi+4], 4E8000A1h -; 4. Wait for data, writing to the buffer as data arrive. -.getdata: - mov ecx, 0x10000 -@@: - test byte [esi+8+1], 8 - loopz @b - test byte [esi+8+1], 4 - jz .dataok - call ResetGMBus - jmp .fail -.dataok: - mov eax, [esi+0Ch] - stosd - cmp edi, edid+80h - jb .getdata -; 5. Wait for bus idle. - mov ecx, 0x10000 -@@: - test byte [esi+8+1], 2 - loopnz @b -; 6. We got EDID; dump it if DEBUG. -if DEBUG - pusha - xor ecx, ecx - mov esi, edid - mov edi, edid_text -.dumploop: - lodsb - call WriteByte - mov al, ' ' - stosb - inc cl - test cl, 15 - jnz @f - mov byte [edi-1], 13 - mov al, 10 - stosb -@@: - test cl, cl - jns .dumploop - mov esi, edidmsg - call SysMsgBoardStr - popa -end if -; 7. Test whether EDID is good. -; 7a. Signature: 00 FF FF FF FF FF FF 00. - mov esi, edid - cmp dword [esi], 0xFFFFFF00 - jnz .fail - cmp dword [esi+4], 0x00FFFFFF - jnz .fail -; 7b. Checksum must be zero. - xor edx, edx - mov ecx, 80h -@@: - lodsb - add dl, al - loop @b - jnz .fail -; 8. Get width and height from EDID. - xor eax, eax - mov ah, [esi-80h+3Ah] - shr ah, 4 - mov al, [esi-80h+38h] - mov [width], eax - mov ah, [esi-80h+3Dh] - shr ah, 4 - mov al, [esi-80h+3Bh] - mov [height], eax -; 9. Return. -.fail: - pop edi esi - ret - -; reset bus, clear all errors -ResetGMBus: -; look into the PRM - mov dword [esi+4], 80000000h - mov dword [esi+4], 0 - mov ecx, 0x10000 -@@: - test byte [esi+8+1], 2 - loopnz @b - ret -end if - -; set resolution [width]*[height] -SetMode: -; 1. Program the registers of videocard. -; look into the PRM - cli -; or byte [esi+7000Ah], 0Ch ; PIPEACONF: disable Display+Cursor Planes -; or byte [esi+7100Ah], 0Ch ; PIPEBCONF: disable Display+Cursor Planes - xor eax, eax - xor edx, edx - cmp [deviceType], i965_start - jb @f - mov dl, 9Ch - 84h -@@: -; or byte [esi+71403h], 80h ; VGACNTRL: VGA Display Disable - and byte [esi+70080h], not 27h ; CURACNTR: disable cursor A - mov dword [esi+70084h], eax ; CURABASE: force write to CURA* regs - and byte [esi+700C0h], not 27h ; CURBCNTR: disable cursor B - mov dword [esi+700C4h], eax ; CURBBASE: force write to CURB* regs - and byte [esi+70183h], not 80h ; DSPACNTR: disable Primary A Plane - mov dword [esi+edx+70184h], eax ; DSPALINOFF/DSPASURF: force write to DSPA* regs - and byte [esi+71183h], not 80h ; DSPBCNTR: disable Primary B Plane - mov dword [esi+edx+71184h], eax ; DSPBLINOFF/DSPBSURF: force write to DSPB* regs -if 1 - cmp [deviceType], ironlake_start - jae .disable_pipes - mov edx, 10000h - or byte [esi+70024h], 2 ; PIPEASTAT: clear VBLANK status - or byte [esi+71024h], 2 ; PIPEBSTAT: clear VBLANK status -.wait_vblank_preironlake1: - mov ecx, 1000h - loop $ - test byte [esi+7000Bh], 80h ; PIPEACONF: pipe A active? - jz @f - test byte [esi+70024h], 2 ; PIPEASTAT: got VBLANK? - jz .wait_vblank_preironlake2 -@@: - test byte [esi+7100Bh], 80h ; PIPEBCONF: pipe B active? - jz .disable_pipes - test byte [esi+71024h], 2 ; PIPEBSTAT: got VBLANK? - jnz .disable_pipes -.wait_vblank_preironlake2: - dec edx - jnz .wait_vblank_preironlake1 - jmp .not_disabled -.disable_pipes: -end if - and byte [esi+7000Bh], not 80h ; PIPEACONF: disable pipe - and byte [esi+7100Bh], not 80h ; PIPEBCONF: disable pipe -if 1 - mov edx, 10000h -@@: - mov ecx, 1000h - loop $ - test byte [esi+7000Bh], 40h ; PIPEACONF: wait until pipe disabled - jz @f - dec edx - jnz @b -.not_disabled: - sti - jmp .return -@@: - test byte [esi+7100Bh], 40h ; PIPEBCONF: wait until pipe disabled - jz @f - mov ecx, 1000h - loop $ - dec edx - jnz @b - jmp .not_disabled -@@: -else -; alternative way of waiting for pipe stop, works too - mov edx, 1000h -.dis1: - push dword [esi+71000h] - push dword [esi+70000h] - mov ecx, 10000h - loop $ - pop eax - xor eax, [esi+70000h] - and eax, 1FFFh - pop eax - jnz .notdis1 - xor eax, [esi+71000h] - and eax, 1FFFh - jz .disabled -.notdis1: - dec edx - jnz .dis1 -.not_disabled: - sti - jmp .return -.disabled: -end if - lea eax, [esi+61183h] - cmp [deviceType], ironlake_start - jb @f - add eax, 0xE0000 - 0x60000 -@@: - lea edx, [esi+60000h] - test byte [eax], 40h - jz @f - add edx, 1000h -@@: - mov eax, [width] - dec eax - shl eax, 16 - mov ax, word [height] - dec eax - mov dword [edx+1Ch], eax ; PIPEASRC: set source image size - ror eax, 16 - mov dword [edx+10190h], eax ; for old cards - mov ecx, [width] - add ecx, 15 - and ecx, not 15 - shl ecx, 2 - mov dword [edx+10188h], ecx ; DSPASTRIDE: set scanline length - and byte [esi+61233h], not 80h ; PFIT_CONTROL: disable panel fitting - or byte [edx+1000Bh], 80h ; PIPEACONF: enable pipe -; and byte [edx+1000Ah], not 0Ch ; PIPEACONF: enable Display+Cursor Planes - or byte [edx+10183h], 80h ; DSPACNTR: enable Display Plane A - sti -; 2. Notify the kernel that resolution has changed. - call GetDisplay - mov edx, [width] - mov dword [eax+8], edx - mov edx, [height] - mov dword [eax+0Ch], edx - mov [eax+18h], ecx - mov eax, [width] - dec eax - dec edx - call SetScreen -.return: - ret - -align 4 -hellomsg db 'Intel videocard detected, PciId=8086:' -pciid_text db '0000' - db ', which is ', 0 -knownmsg db 'known',13,10,0 -unknownmsg db 'unknown',13,10,0 - -if DEBUG -edidmsg db 'EDID successfully read:',13,10 -edid_text rb 8*(16*3+1) - db 0 -end if - -version: - dd 0x50005 - -width dd predefined_width -height dd predefined_height - -pciids: - dw 0x3577 ; i830m - dw 0x2562 ; 845g - dw 0x3582 ; i855gm -i865_start = ($ - pciids) / 2 - dw 0x2572 ; i865g -i9xx_start = ($ - pciids) / 2 - dw 0x2582 ; i915g - dw 0x258a ; e7221g (i915g) - dw 0x2592 ; i915gm - dw 0x2772 ; i945g - dw 0x27a2 ; i945gm - dw 0x27ae ; i945gme -i965_start = ($ - pciids) / 2 - dw 0x2972 ; i946qz (i965g) - dw 0x2982 ; g35g (i965g) - dw 0x2992 ; i965q (i965g) - dw 0x29a2 ; i965g - dw 0x29b2 ; q35g - dw 0x29c2 ; g33g - dw 0x29d2 ; q33g - dw 0x2a02 ; i965gm - dw 0x2a12 ; i965gm - dw 0x2a42 ; gm45 - dw 0x2e02 ; g45 - dw 0x2e12 ; g45 - dw 0x2e22 ; g45 - dw 0x2e32 ; g45 - dw 0x2e42 ; g45 - dw 0x2e92 ; g45 - dw 0xa001 ; pineview - dw 0xa011 ; pineview -ironlake_start = ($ - pciids) / 2 - dw 0x0042 ; ironlake_d - dw 0x0046 ; ironlake_m - dw 0x0102 ; sandybridge_d - dw 0x0112 ; sandybridge_d - dw 0x0122 ; sandybridge_d - dw 0x0106 ; sandybridge_m - dw 0x0116 ; sandybridge_m - dw 0x0126 ; sandybridge_m - dw 0x010A ; sandybridge_d -pciids_num = ($ - pciids) / 2 - -align 4 -deviceType dd ? -edid rb 0x80 +; Stub of videodriver for Intel videocards. +; (c) CleverMouse + +; When the start procedure gots control, +; it tries to detect preferred resolution, +; sets the detected resolution assuming 32-bpp VESA mode and exits +; (without registering a service). +; Detection can be overloaded with compile-time settings +; use_predefined_mode/predefined_width/predefined_height. + +; set predefined resolution here +use_predefined_mode = 0;1 +predefined_width = 0;1366 +predefined_height = 0;768 + +; standard driver stuff +format MS COFF + +DEBUG = 1 + +include 'proc32.inc' +include 'imports.inc' + +public START +public version + +section '.flat' code readable align 16 +; the start procedure (see the description above) +START: +; 1. Detect device. Abort if not found. + push esi + call DetectDevice + test esi, esi + jz .return0 +; 2. Detect optimal mode unless the mode is given explicitly. Abort if failed. +if use_predefined_mode = 0 + call DetectMode +end if + cmp [width], 0 + jz .return0_cleanup +; 3. Set the detected mode. + call SetMode +; 4. Cleanup and return. +.return0_cleanup: + stdcall FreeKernelSpace, esi +.return0: + pop esi + xor eax, eax + ret 4 + +; check that there is Intel videocard +; if so, map MMIO registers and set internal variables +; esi points to MMIO block; NULL means no device +DetectDevice: +; 1. Sanity check: check that we are dealing with Intel videocard. +; Integrated video device for Intel is always at PCI:0:2:0. + xor esi, esi ; initialize return value to NULL +; 1a. Get PCI VendorID and DeviceID. + push esi + push 10h + push esi + call PciRead32 +; 1b. loword(eax) = ax = VendorID, hiword(eax) = DeviceID. +; Test whether we have Intel chipset. + cmp ax, 8086h + jnz .return +; 1c. Say hi including DeviceID. + shr eax, 10h + push edi + pusha + mov edi, pciid_text + call WriteWord + mov esi, hellomsg + call SysMsgBoardStr + popa +; 1d. Test whether we know this DeviceID. +; If this is the case, remember the position of the device in line of Intel cards; +; this knowledge will be useful later. +; Tested on devices with id: 8086:0046, partially 8086:2A02. + mov ecx, pciids_num + mov edi, pciids + repnz scasw + pop edi + jnz .return_unknown_pciid + sub ecx, pciids_num - 1 + neg ecx + mov [deviceType], ecx +; 1e. Continue saying hi with positive intonation. + pusha + mov esi, knownmsg + call SysMsgBoardStr + popa +; 2. Prepare MMIO region to control the card. +; 2a. Read MMIO physical address from PCI config space. + push 10h + cmp ecx, i9xx_start + jae @f + mov byte [esp], 14h +@@: + push 10h + push esi + call PciRead32 +; 2b. Mask out PCI region type, lower 4 bits. + and al, not 0xF +; 2c. Create virtual mapping of the physical memory. + push 1Bh + push 100000h + push eax + call MapIoMem +; 3. Return. + xchg esi, eax +.return: + ret +; 1f. If we do not know DeviceID, continue saying hi with negative intonation. +.return_unknown_pciid: + pusha + mov esi, unknownmsg + call SysMsgBoardStr + popa + ret + +; Convert word in ax to hexadecimal text in edi, advance edi. +WriteWord: +; 1. Convert high byte. + push eax + mov al, ah + call WriteByte + pop eax +; 2. Convert low byte. +; Fall through to WriteByte; ret from WriteByte is ret from WriteWord too. + +; Convert byte in al to hexadecimal text in edi, advance edi. +WriteByte: +; 1. Convert high nibble. + push eax + shr al, 4 + call WriteNibble + pop eax +; 2. Convert low nibble. + and al, 0xF +; Fall through to WriteNibble; ret from WriteNibble is ret from WriteByte too. + +; Convert nibble in al to hexadecimal text in edi, advance edi. +WriteNibble: +; Obvious, isn't it? + cmp al, 10 + sbb al, 69h + das + stosb + ret + +if use_predefined_mode = 0 +; detect resolution of the flat panel +DetectMode: + push esi edi +; 1. Get the location of block of GMBUS* registers. +; Starting with Ironlake, GMBUS* registers were moved. + add esi, 5100h + cmp [deviceType], ironlake_start + jb @f + add esi, 0xC0000 +@@: +; 2. Initialize GMBUS engine. + mov edi, edid + mov ecx, 0x10000 +@@: + test byte [esi+8+1], 80h + loopnz @b + jnz .fail + mov dword [esi], 3 + test byte [esi+8+1], 4 + jz .noreset + call ResetGMBus + jnz .fail +.noreset: +; 3. Send read command. + and dword [esi+20h], 0 + mov dword [esi+4], 4E8000A1h +; 4. Wait for data, writing to the buffer as data arrive. +.getdata: + mov ecx, 0x10000 +@@: + test byte [esi+8+1], 8 + loopz @b + test byte [esi+8+1], 4 + jz .dataok + call ResetGMBus + jmp .fail +.dataok: + mov eax, [esi+0Ch] + stosd + cmp edi, edid+80h + jb .getdata +; 5. Wait for bus idle. + mov ecx, 0x10000 +@@: + test byte [esi+8+1], 2 + loopnz @b +; 6. We got EDID; dump it if DEBUG. +if DEBUG + pusha + xor ecx, ecx + mov esi, edid + mov edi, edid_text +.dumploop: + lodsb + call WriteByte + mov al, ' ' + stosb + inc cl + test cl, 15 + jnz @f + mov byte [edi-1], 13 + mov al, 10 + stosb +@@: + test cl, cl + jns .dumploop + mov esi, edidmsg + call SysMsgBoardStr + popa +end if +; 7. Test whether EDID is good. +; 7a. Signature: 00 FF FF FF FF FF FF 00. + mov esi, edid + cmp dword [esi], 0xFFFFFF00 + jnz .fail + cmp dword [esi+4], 0x00FFFFFF + jnz .fail +; 7b. Checksum must be zero. + xor edx, edx + mov ecx, 80h +@@: + lodsb + add dl, al + loop @b + jnz .fail +; 8. Get width and height from EDID. + xor eax, eax + mov ah, [esi-80h+3Ah] + shr ah, 4 + mov al, [esi-80h+38h] + mov [width], eax + mov ah, [esi-80h+3Dh] + shr ah, 4 + mov al, [esi-80h+3Bh] + mov [height], eax +; 9. Return. +.fail: + pop edi esi + ret + +; reset bus, clear all errors +ResetGMBus: +; look into the PRM + mov dword [esi+4], 80000000h + mov dword [esi+4], 0 + mov ecx, 0x10000 +@@: + test byte [esi+8+1], 2 + loopnz @b + ret +end if + +; set resolution [width]*[height] +SetMode: +; 1. Program the registers of videocard. +; look into the PRM + cli +; or byte [esi+7000Ah], 0Ch ; PIPEACONF: disable Display+Cursor Planes +; or byte [esi+7100Ah], 0Ch ; PIPEBCONF: disable Display+Cursor Planes + xor eax, eax + xor edx, edx + cmp [deviceType], i965_start + jb @f + mov dl, 9Ch - 84h +@@: +; or byte [esi+71403h], 80h ; VGACNTRL: VGA Display Disable + and byte [esi+70080h], not 27h ; CURACNTR: disable cursor A + mov dword [esi+70084h], eax ; CURABASE: force write to CURA* regs + and byte [esi+700C0h], not 27h ; CURBCNTR: disable cursor B + mov dword [esi+700C4h], eax ; CURBBASE: force write to CURB* regs + and byte [esi+70183h], not 80h ; DSPACNTR: disable Primary A Plane + mov dword [esi+edx+70184h], eax ; DSPALINOFF/DSPASURF: force write to DSPA* regs + and byte [esi+71183h], not 80h ; DSPBCNTR: disable Primary B Plane + mov dword [esi+edx+71184h], eax ; DSPBLINOFF/DSPBSURF: force write to DSPB* regs +if 1 + cmp [deviceType], ironlake_start + jae .disable_pipes + mov edx, 10000h + or byte [esi+70024h], 2 ; PIPEASTAT: clear VBLANK status + or byte [esi+71024h], 2 ; PIPEBSTAT: clear VBLANK status +.wait_vblank_preironlake1: + mov ecx, 1000h + loop $ + test byte [esi+7000Bh], 80h ; PIPEACONF: pipe A active? + jz @f + test byte [esi+70024h], 2 ; PIPEASTAT: got VBLANK? + jz .wait_vblank_preironlake2 +@@: + test byte [esi+7100Bh], 80h ; PIPEBCONF: pipe B active? + jz .disable_pipes + test byte [esi+71024h], 2 ; PIPEBSTAT: got VBLANK? + jnz .disable_pipes +.wait_vblank_preironlake2: + dec edx + jnz .wait_vblank_preironlake1 + jmp .not_disabled +.disable_pipes: +end if + and byte [esi+7000Bh], not 80h ; PIPEACONF: disable pipe + and byte [esi+7100Bh], not 80h ; PIPEBCONF: disable pipe +if 1 + mov edx, 10000h +@@: + mov ecx, 1000h + loop $ + test byte [esi+7000Bh], 40h ; PIPEACONF: wait until pipe disabled + jz @f + dec edx + jnz @b +.not_disabled: + sti + jmp .return +@@: + test byte [esi+7100Bh], 40h ; PIPEBCONF: wait until pipe disabled + jz @f + mov ecx, 1000h + loop $ + dec edx + jnz @b + jmp .not_disabled +@@: +else +; alternative way of waiting for pipe stop, works too + mov edx, 1000h +.dis1: + push dword [esi+71000h] + push dword [esi+70000h] + mov ecx, 10000h + loop $ + pop eax + xor eax, [esi+70000h] + and eax, 1FFFh + pop eax + jnz .notdis1 + xor eax, [esi+71000h] + and eax, 1FFFh + jz .disabled +.notdis1: + dec edx + jnz .dis1 +.not_disabled: + sti + jmp .return +.disabled: +end if + lea eax, [esi+61183h] + cmp [deviceType], ironlake_start + jb @f + add eax, 0xE0000 - 0x60000 +@@: + lea edx, [esi+60000h] + test byte [eax], 40h + jz @f + add edx, 1000h +@@: + mov eax, [width] + dec eax + shl eax, 16 + mov ax, word [height] + dec eax + mov dword [edx+1Ch], eax ; PIPEASRC: set source image size + ror eax, 16 + mov dword [edx+10190h], eax ; for old cards + mov ecx, [width] + add ecx, 15 + and ecx, not 15 + shl ecx, 2 + mov dword [edx+10188h], ecx ; DSPASTRIDE: set scanline length + and byte [esi+61233h], not 80h ; PFIT_CONTROL: disable panel fitting + or byte [edx+1000Bh], 80h ; PIPEACONF: enable pipe +; and byte [edx+1000Ah], not 0Ch ; PIPEACONF: enable Display+Cursor Planes + or byte [edx+10183h], 80h ; DSPACNTR: enable Display Plane A + sti +; 2. Notify the kernel that resolution has changed. + call GetDisplay + mov edx, [width] + mov dword [eax+8], edx + mov edx, [height] + mov dword [eax+0Ch], edx + mov [eax+18h], ecx + mov eax, [width] + dec eax + dec edx + call SetScreen +.return: + ret + +align 4 +hellomsg db 'Intel videocard detected, PciId=8086:' +pciid_text db '0000' + db ', which is ', 0 +knownmsg db 'known',13,10,0 +unknownmsg db 'unknown',13,10,0 + +if DEBUG +edidmsg db 'EDID successfully read:',13,10 +edid_text rb 8*(16*3+1) + db 0 +end if + +version: + dd 0x50005 + +width dd predefined_width +height dd predefined_height + +pciids: + dw 0x3577 ; i830m + dw 0x2562 ; 845g + dw 0x3582 ; i855gm +i865_start = ($ - pciids) / 2 + dw 0x2572 ; i865g +i9xx_start = ($ - pciids) / 2 + dw 0x2582 ; i915g + dw 0x258a ; e7221g (i915g) + dw 0x2592 ; i915gm + dw 0x2772 ; i945g + dw 0x27a2 ; i945gm + dw 0x27ae ; i945gme +i965_start = ($ - pciids) / 2 + dw 0x2972 ; i946qz (i965g) + dw 0x2982 ; g35g (i965g) + dw 0x2992 ; i965q (i965g) + dw 0x29a2 ; i965g + dw 0x29b2 ; q35g + dw 0x29c2 ; g33g + dw 0x29d2 ; q33g + dw 0x2a02 ; i965gm + dw 0x2a12 ; i965gm + dw 0x2a42 ; gm45 + dw 0x2e02 ; g45 + dw 0x2e12 ; g45 + dw 0x2e22 ; g45 + dw 0x2e32 ; g45 + dw 0x2e42 ; g45 + dw 0x2e92 ; g45 + dw 0xa001 ; pineview + dw 0xa011 ; pineview +ironlake_start = ($ - pciids) / 2 + dw 0x0042 ; ironlake_d + dw 0x0046 ; ironlake_m + dw 0x0102 ; sandybridge_d + dw 0x0112 ; sandybridge_d + dw 0x0122 ; sandybridge_d + dw 0x0106 ; sandybridge_m + dw 0x0116 ; sandybridge_m + dw 0x0126 ; sandybridge_m + dw 0x010A ; sandybridge_d +pciids_num = ($ - pciids) / 2 + +align 4 +deviceType dd ? +edid rb 0x80 diff --git a/kernel/trunk/drivers/vt823x.asm b/kernel/trunk/drivers/vt823x.asm index 51de41738..607b9eacf 100644 --- a/kernel/trunk/drivers/vt823x.asm +++ b/kernel/trunk/drivers/vt823x.asm @@ -1,1281 +1,1281 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -format MS COFF - -DEBUG equ 1 - -include 'proc32.inc' -include 'imports.inc' - -API_VERSION equ 0x01000100 - -USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices -IRQ_REMAP equ 0 -IRQ_LINE equ 0 - - -;irq 0,1,2,8,12,13 ­Ґ¤®бвгЇ­л -; FEDCBA9876543210 -VALID_IRQ equ 1100111011111000b -ATTCH_IRQ equ 0000111010100000b - -if USE_COM_IRQ -ATTCH_IRQ equ 0000111010111000b -end if - -CPU_FREQ equ 2600d - -BIT0 EQU 0x00000001 -BIT1 EQU 0x00000002 -BIT5 EQU 0x00000020 -BIT10 EQU 0x00000400 - -VID_VIA equ 0x1106 - -CTRL_VT82C686 equ 0x3058 -CTRL_VT8233_5 equ 0x3059 - - -CODEC_MASTER_VOL_REG equ 0x02 -CODEC_AUX_VOL equ 0x04 ; -CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume -CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio -CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control -CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate -CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate -CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate - - -;VIA host controller registers set -;; common offsets -VIA_REG_OFFSET_STATUS equ 0x00 ;; byte - channel status - VIA_REG_STAT_ACTIVE equ 0x80 ;; RO - VIA_REG_STAT_PAUSED equ 0x40 ;; RO - VIA_REG_STAT_TRIGGER_QUEUED equ 0x08 ;; RO - VIA_REG_STAT_STOPPED equ 0x04 ;; RWC - VIA_REG_STAT_EOL equ 0x02 ;; RWC - VIA_REG_STAT_FLAG equ 0x01 ;; RWC -VIA_REG_OFFSET_CONTROL equ 0x01 ;; byte - channel control - VIA_REG_CTRL_START equ 0x80 ;; WO - VIA_REG_CTRL_TERMINATE equ 0x40 ;; WO - VIA_REG_CTRL_AUTOSTART equ 0x20 - VIA_REG_CTRL_PAUSE equ 0x08 ;; RW - VIA_REG_CTRL_INT_STOP equ 0x04 - VIA_REG_CTRL_INT_EOL equ 0x02 - VIA_REG_CTRL_INT_FLAG equ 0x01 - VIA_REG_CTRL_RESET equ 0x01 ;; RW - probably reset? undocumented - VIA_REG_CTRL_INT equ (VIA_REG_CTRL_INT_FLAG or \ - VIA_REG_CTRL_INT_EOL or \ - VIA_REG_CTRL_AUTOSTART) -VIA_REG_OFFSET_TYPE equ 0x02 ;; byte - channel type (686 only) - VIA_REG_TYPE_AUTOSTART equ 0x80 ;; RW - autostart at EOL - VIA_REG_TYPE_16BIT equ 0x20 ;; RW - VIA_REG_TYPE_STEREO equ 0x10 ;; RW - VIA_REG_TYPE_INT_LLINE equ 0x00 - VIA_REG_TYPE_INT_LSAMPLE equ 0x04 - VIA_REG_TYPE_INT_LESSONE equ 0x08 - VIA_REG_TYPE_INT_MASK equ 0x0c - VIA_REG_TYPE_INT_EOL equ 0x02 - VIA_REG_TYPE_INT_FLAG equ 0x01 -VIA_REG_OFFSET_TABLE_PTR equ 0x04 ;; dword - channel table pointer -VIA_REG_OFFSET_CURR_PTR equ 0x04 ;; dword - channel current pointer -VIA_REG_OFFSET_STOP_IDX equ 0x08 ;; dword - stop index, channel type, sample rate - VIA8233_REG_TYPE_16BIT equ 0x00200000 ;; RW - VIA8233_REG_TYPE_STEREO equ 0x00100000 ;; RW -VIA_REG_OFFSET_CURR_COUNT equ 0x0c ;; dword - channel current count (24 bit) -VIA_REG_OFFSET_CURR_INDEX equ 0x0f ;; byte - channel current index (for via8233 only) - - -VIADEV_PLAYBACK equ 0x00 -VIADEV_CAPTURE equ 0x10 -VIADEV_FM equ 0x20 - -;; AC'97 ;; -VIA_REG_AC97 equ 0x80 ; dword - VIA_REG_AC97_CODEC_ID_MASK equ 0xC0000000 ;(3<<30) - VIA_REG_AC97_CODEC_ID_SHIFT equ 30 - VIA_REG_AC97_CODEC_ID_PRIMARY equ 0x00 - VIA_REG_AC97_CODEC_ID_SECONDARY equ 0x01 - VIA_REG_AC97_SECONDARY_VALID equ 0x08000000 ;(1<<27) - VIA_REG_AC97_PRIMARY_VALID equ 0x02000000 ;(1<<25) - VIA_REG_AC97_BUSY equ 0x01000000 ;(1<<24) - VIA_REG_AC97_READ equ 0x00800000 ;(1<<23) - VIA_REG_AC97_CMD_SHIFT equ 16 - VIA_REG_AC97_CMD_MASK equ 0x7E - VIA_REG_AC97_DATA_SHIFT equ 0 - VIA_REG_AC97_DATA_MASK equ 0xFFFF - -VIA_REG_SGD_SHADOW equ 0x84 ; dword - -;; via8233-specific registers ;; -VIA_REG_OFS_PLAYBACK_VOLUME_L equ 0x02 ;; byte -VIA_REG_OFS_PLAYBACK_VOLUME_R equ 0x03 ;; byte -VIA_REG_OFS_MULTPLAY_FORMAT equ 0x02 ;; byte - format and channels - VIA_REG_MULTPLAY_FMT_8BIT equ 0x00 - VIA_REG_MULTPLAY_FMT_16BIT equ 0x80 - VIA_REG_MULTPLAY_FMT_CH_MASK equ 0x70 ;; # channels << 4 (valid = 1,2,4,6) -VIA_REG_OFS_CAPTURE_FIFO equ 0x02 ;; byte - bit 6 = fifo enable - VIA_REG_CAPTURE_FIFO_ENABLE equ 0x40 - -VIA_DXS_MAX_VOLUME equ 31 ;; max. volume (attenuation) of reg 0x32/33 - -VIA_TBL_BIT_FLAG equ 0x40000000 -VIA_TBL_BIT_EOL equ 0x80000000 - -;; pci space ;; -VIA_ACLINK_STAT equ 0x40 - ;... - VIA_ACLINK_C00_READY equ 0x01 ; primary codec ready -VIA_ACLINK_CTRL equ 0x41 - VIA_ACLINK_CTRL_ENABLE equ 0x80 ; 0: disable, 1: enable - VIA_ACLINK_CTRL_RESET equ 0x40 ; 0: assert, 1: de-assert - VIA_ACLINK_CTRL_SYNC equ 0x20 ; 0: release SYNC, 1: force SYNC hi - VIA_ACLINK_CTRL_SDO equ 0x10 ; 0: release SDO, 1: force SDO hi - VIA_ACLINK_CTRL_VRA equ 0x08 ; 0: disable VRA, 1: enable VRA - VIA_ACLINK_CTRL_PCM equ 0x04 ; 0: disable PCM, 1: enable PCM - VIA_ACLINK_CTRL_FM equ 0x02 ; via686 only - VIA_ACLINK_CTRL_SB equ 0x01 ; via686 only - VIA_ACLINK_CTRL_INIT equ (VIA_ACLINK_CTRL_ENABLE or \ - VIA_ACLINK_CTRL_RESET or \ - VIA_ACLINK_CTRL_PCM or \ - VIA_ACLINK_CTRL_VRA) -VIA_FUNC_ENABLE equ 0x42 - VIA_FUNC_MIDI_PNP equ 0x80 ; FIXME: it's 0x40 in the datasheet! - VIA_FUNC_MIDI_IRQMASK equ 0x40 ; FIXME: not documented! - VIA_FUNC_RX2C_WRITE equ 0x20 - VIA_FUNC_SB_FIFO_EMPTY equ 0x10 - VIA_FUNC_ENABLE_GAME equ 0x08 - VIA_FUNC_ENABLE_FM equ 0x04 - VIA_FUNC_ENABLE_MIDI equ 0x02 - VIA_FUNC_ENABLE_SB equ 0x01 -VIA_PNP_CONTROL equ 0x43 -VIA_FM_NMI_CTRL equ 0x48 -VIA8233_VOLCHG_CTRL equ 0x48 -VIA8233_SPDIF_CTRL equ 0x49 - VIA8233_SPDIF_DX3 equ 0x08 - VIA8233_SPDIF_SLOT_MASK equ 0x03 - VIA8233_SPDIF_SLOT_1011 equ 0x00 - VIA8233_SPDIF_SLOT_34 equ 0x01 - VIA8233_SPDIF_SLOT_78 equ 0x02 - VIA8233_SPDIF_SLOT_69 equ 0x03 -;] Asper - - -SRV_GETVERSION equ 0 -DEV_PLAY equ 1 -DEV_STOP equ 2 -DEV_CALLBACK equ 3 -DEV_SET_BUFF equ 4 -DEV_NOTIFY equ 5 -DEV_SET_MASTERVOL equ 6 -DEV_GET_MASTERVOL equ 7 -DEV_GET_INFO equ 8 - -struc AC_CNTRL ;AC controller base class -{ .bus dd ? - .devfn dd ? - - .vendor dd ? - .dev_id dd ? - .pci_cmd dd ? - .pci_stat dd ? - - .codec_io_base dd ? - .codec_mem_base dd ? - - .ctrl_io_base dd ? - .ctrl_mem_base dd ? - .cfg_reg dd ? - .int_line dd ? - - .vendor_ids dd ? ;vendor id string - .ctrl_ids dd ? ;hub id string - - .buffer dd ? - - .notify_pos dd ? - .notify_task dd ? - - .lvi_reg dd ? - .ctrl_setup dd ? - .user_callback dd ? - .codec_read16 dd ? - .codec_write16 dd ? - - .ctrl_read8 dd ? - .ctrl_read16 dd ? - .ctrl_read32 dd ? - - .ctrl_write8 dd ? - .ctrl_write16 dd ? - .ctrl_write32 dd ? -} - -struc CODEC ;Audio Chip base class -{ - .chip_id dd ? - .flags dd ? - .status dd ? - - .ac_vendor_ids dd ? ;ac vendor id string - .chip_ids dd ? ;chip model string - - .shadow_flag dd ? - dd ? - - .regs dw ? ; codec registers - .reg_master_vol dw ? ;0x02 - .reg_aux_out_vol dw ? ;0x04 - .reg_mone_vol dw ? ;0x06 - .reg_master_tone dw ? ;0x08 - .reg_beep_vol dw ? ;0x0A - .reg_phone_vol dw ? ;0x0C - .reg_mic_vol dw ? ;0x0E - .reg_line_in_vol dw ? ;0x10 - .reg_cd_vol dw ? ;0x12 - .reg_video_vol dw ? ;0x14 - .reg_aux_in_vol dw ? ;0x16 - .reg_pcm_out_vol dw ? ;0x18 - .reg_rec_select dw ? ;0x1A - .reg_rec_gain dw ? ;0x1C - .reg_rec_gain_mic dw ? ;0x1E - .reg_gen dw ? ;0x20 - .reg_3d_ctrl dw ? ;0X22 - .reg_page dw ? ;0X24 - .reg_powerdown dw ? ;0x26 - .reg_ext_audio dw ? ;0x28 - .reg_ext_st dw ? ;0x2a - .reg_pcm_front_rate dw ? ;0x2c - .reg_pcm_surr_rate dw ? ;0x2e - .reg_lfe_rate dw ? ;0x30 - .reg_pcm_in_rate dw ? ;0x32 - dw ? ;0x34 - .reg_cent_lfe_vol dw ? ;0x36 - .reg_surr_vol dw ? ;0x38 - .reg_spdif_ctrl dw ? ;0x3A - dw ? ;0x3C - dw ? ;0x3E - dw ? ;0x40 - dw ? ;0x42 - dw ? ;0x44 - dw ? ;0x46 - dw ? ;0x48 - dw ? ;0x4A - dw ? ;0x4C - dw ? ;0x4E - dw ? ;0x50 - dw ? ;0x52 - dw ? ;0x54 - dw ? ;0x56 - dw ? ;0x58 - dw ? ;0x5A - dw ? ;0x5C - dw ? ;0x5E - .reg_page_0 dw ? ;0x60 - .reg_page_1 dw ? ;0x62 - .reg_page_2 dw ? ;0x64 - .reg_page_3 dw ? ;0x66 - .reg_page_4 dw ? ;0x68 - .reg_page_5 dw ? ;0x6A - .reg_page_6 dw ? ;0x6C - .reg_page_7 dw ? ;0x6E - dw ? ;0x70 - dw ? ;0x72 - dw ? ;0x74 - dw ? ;0x76 - dw ? ;0x78 - dw ? ;0x7A - .reg_vendor_id_1 dw ? ;0x7C - .reg_vendor_id_2 dw ? ;0x7E - - - .reset dd ? ;virual - .set_master_vol dd ? -} - -struc CTRL_INFO -{ .pci_cmd dd ? - .irq dd ? - .glob_cntrl dd ? - .glob_sta dd ? - .codec_io_base dd ? - .ctrl_io_base dd ? - .codec_mem_base dd ? - .ctrl_mem_base dd ? - .codec_id dd ? -} - -struc IOCTL -{ .handle dd ? - .io_code dd ? - .input dd ? - .inp_size dd ? - .output dd ? - .out_size dd ? -} - -virtual at 0 - IOCTL IOCTL -end virtual - -EVENT_NOTIFY equ 0x00000200 - -public START -public service_proc -public version - -section '.flat' code readable align 16 - -proc START stdcall, state:dword - - cmp [state], 1 - jne .stop - - if DEBUG - mov esi, msgInit - call SysMsgBoardStr - end if - - call detect_controller - test eax, eax - jz .fail - - if DEBUG - mov esi,[ctrl.vendor_ids] - call SysMsgBoardStr - mov esi, [ctrl.ctrl_ids] - call SysMsgBoardStr - end if - - call init_controller - test eax, eax - jz .fail - - call init_codec - test eax, eax - jz .fail - - call setup_codec - - mov esi, msgPrimBuff - call SysMsgBoardStr - call create_primary_buff - mov esi, msgDone - call SysMsgBoardStr - - if IRQ_REMAP - pushf - cli - - mov ebx, [ctrl.int_line] - in al, 0xA1 - mov ah, al - in al, 0x21 - test ebx, ebx - jz .skip - bts ax, bx ;mask old line -.skip: - bts ax, IRQ_LINE ;mask new ine - out 0x21, al - mov al, ah - out 0xA1, al - - stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ - - mov dx, 0x4d0 ;8259 ELCR1 - in al, dx - bts ax, IRQ_LINE - out dx, al ;set level-triggered mode - mov [ctrl.int_line], IRQ_LINE - popf - mov esi, msgRemap - call SysMsgBoardStr - end if - - mov eax, VALID_IRQ - mov ebx, [ctrl.int_line] - mov esi, msgInvIRQ - bt eax, ebx - jnc .fail_msg - mov eax, ATTCH_IRQ - mov esi, msgAttchIRQ - bt eax, ebx - jnc .fail_msg - - stdcall AttachIntHandler, ebx, ac97_irq_VIA, dword 0 -.reg: - stdcall RegService, sz_sound_srv, service_proc - ret -.fail: - if DEBUG - mov esi, msgFail - call SysMsgBoardStr - end if - xor eax, eax - ret -.fail_msg: - call SysMsgBoardStr - xor eax, eax - ret -.stop: - call stop - xor eax, eax - ret -endp - -handle equ IOCTL.handle -io_code equ IOCTL.io_code -input equ IOCTL.input -inp_size equ IOCTL.inp_size -output equ IOCTL.output -out_size equ IOCTL.out_size - -align 4 -proc service_proc stdcall, ioctl:dword - - mov edi, [ioctl] - mov eax, [edi+io_code] - - cmp eax, SRV_GETVERSION - jne @F - mov eax, [edi+output] - cmp [edi+out_size], 4 - jne .fail - - mov [eax], dword API_VERSION - xor eax, eax - ret -@@: - cmp eax, DEV_PLAY - jne @F - if DEBUG - mov esi, msgPlay - call SysMsgBoardStr - end if - call play - ret -@@: - cmp eax, DEV_STOP - jne @F - if DEBUG - mov esi, msgStop - call SysMsgBoardStr - end if - call stop - ret -@@: - cmp eax, DEV_CALLBACK - jne @F - mov ebx, [edi+input] - stdcall set_callback, [ebx] - ret -@@: - cmp eax, DEV_SET_MASTERVOL - jne @F - mov eax, [edi+input] - mov eax, [eax] - call set_master_vol ;eax= vol - ret -@@: - cmp eax, DEV_GET_MASTERVOL - jne @F - mov ebx, [edi+output] - stdcall get_master_vol, ebx - ret -@@: - cmp eax, DEV_GET_INFO - jne @F - mov ebx, [edi+output] - stdcall get_dev_info, ebx - ret -@@: -.fail: - or eax, -1 - ret -endp - -restore handle -restore io_code -restore input -restore inp_size -restore output -restore out_size - - -align 4 -proc ac97_irq_VIA - locals - status db 0 - endl - - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS - call [ctrl.ctrl_read8] - test al, VIA_REG_STAT_ACTIVE - jz @f - - and al, VIA_REG_STAT_EOL or VIA_REG_STAT_FLAG or VIA_REG_STAT_STOPPED - mov byte [status], al - - mov ebx, dword [buff_list] - cmp [ctrl.user_callback], 0 - je @f - stdcall [ctrl.user_callback], ebx - @@: - mov al, byte [status] ;; ack ;; - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS - call [ctrl.ctrl_write8] - - ret -endp - - -align 4 -proc create_primary_buff - - stdcall KernelAlloc, 0x10000 - mov [ctrl.buffer], eax - - mov edi, eax - mov ecx, 0x10000/4 - xor eax, eax - cld - rep stosd - - mov eax, [ctrl.buffer] - call GetPgAddr - mov edi, pcmout_bdl - stosd - mov eax, 0x80004000 - stosd - - mov edi, buff_list - mov eax, [ctrl.buffer] - mov ecx, 4 -@@: - mov [edi], eax - mov [edi+16], eax - mov [edi+32], eax - mov [edi+48], eax - mov [edi+64], eax - mov [edi+80], eax - mov [edi+96], eax - mov [edi+112], eax - - ;add eax, 0x4000 - add edi, 4 - loop @B - - stdcall channel_reset, VIADEV_PLAYBACK - stdcall codec_check_ready - - mov eax, pcmout_bdl - mov ebx, eax - call GetPgAddr - and ebx, 0xFFF - add eax, ebx - - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR - call [ctrl.ctrl_write32] - - stdcall codec_check_ready - - mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_L - mov eax, 7;31 - call [ctrl.ctrl_write8] - - mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_R - mov eax, 7;31 - call [ctrl.ctrl_write8] - - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX - mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 - mov [ctrl.lvi_reg], 16;0xF;eax - call [ctrl.ctrl_write32] - - stdcall codec_check_ready - ret -endp - - -proc channel_reset channel:dword - mov esi, dword [channel] - mov edx, esi - add edx, VIA_REG_OFFSET_CONTROL - mov eax, VIA_REG_CTRL_PAUSE or VIA_REG_CTRL_TERMINATE or VIA_REG_CTRL_RESET - call [ctrl.ctrl_write8] - - mov edx, esi - add edx, VIA_REG_OFFSET_CONTROL - call [ctrl.ctrl_read8] - - mov eax, 50000 ; wait 50 ms - call StallExec - ; disable interrupts - mov edx, esi - add edx, VIA_REG_OFFSET_CONTROL - xor eax, eax - call [ctrl.ctrl_write8] - - ; clear interrupts - mov edx, esi - add edx, VIA_REG_OFFSET_STATUS - mov eax, 0x03 - call [ctrl.ctrl_write8] - - ;outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ - ; mov edx, esi ;; for via686 - ; add edx, VIA_REG_OFFSET_TYPE - ; mov eax, 0x03 - ; call [ctrl.ctrl_write8] - - ;; outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); - ;mov edx, esi - ;add edx, VIA_REG_OFFSET_CURR_PTR - ;xor eax, eax - ;call [ctrl.ctrl_write8] - - ret -endp - - -align 4 -proc detect_controller - locals - last_bus dd ? - bus dd ? - devfn dd ? - endl - - xor eax, eax - mov [bus], eax - inc eax - call PciApi - cmp eax, -1 - je .err - - mov [last_bus], eax - -.next_bus: - and [devfn], 0 -.next_dev: - stdcall PciRead32, [bus], [devfn], dword 0 - test eax, eax - jz .next - cmp eax, -1 - je .next - - mov edi, devices -@@: - mov ebx, [edi] - test ebx, ebx - jz .next - - cmp eax, ebx - je .found - add edi, 12 - jmp @B -.next: - inc [devfn] - cmp [devfn], 256 - jb .next_dev - mov eax, [bus] - inc eax - mov [bus], eax - cmp eax, [last_bus] - jna .next_bus - xor eax, eax - ret -.found: - mov ebx, [bus] - mov [ctrl.bus], ebx - - mov ecx, [devfn] - mov [ctrl.devfn], ecx - - mov edx, eax - and edx, 0xFFFF - mov [ctrl.vendor], edx - shr eax, 16 - mov [ctrl.dev_id], eax - - mov ebx, [edi+4] - mov [ctrl.ctrl_ids], ebx - mov esi, [edi+8] - mov [ctrl.ctrl_setup], esi - - cmp edx, VID_VIA - jne @F - mov [ctrl.vendor_ids], msg_VIA - ret -@@: - -.err: - xor eax, eax - mov [ctrl.vendor_ids], eax ;something wrong ? - ret -endp - -align 4 -proc init_controller - - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 - mov ebx, eax - and eax, 0xFFFF - mov [ctrl.pci_cmd], eax - shr ebx, 16 - mov [ctrl.pci_stat], ebx - - mov esi, msgPciCmd - call SysMsgBoardStr - call dword2str - call SysMsgBoardStr - - mov esi, msgPciStat - call SysMsgBoardStr - mov eax, [ctrl.pci_stat] - call dword2str - call SysMsgBoardStr - - mov esi, msgCtrlIsaIo - call SysMsgBoardStr - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 - call dword2str - call SysMsgBoardStr - - and eax, 0xFFC0 - mov [ctrl.ctrl_io_base], eax - -.default: - stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C - and eax, 0xFF -@@: - mov [ctrl.int_line], eax - - ;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE ;0x42 - ;mov byte [old_legacy], al - - ;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_PNP_CONTROL ;0x43 - ;mov byte [old_legacy_cfg], al - - ;mov al, VIA_FUNC_ENABLE_SB or VIA_FUNC_ENABLE_FM - ;xor al, 0xFF - ;and al, byte [old_legacy] - ;and eax, 0xFF - ;stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE, eax ;0x42 - ;mov byte [old_legacy], al - - call [ctrl.ctrl_setup] - xor eax, eax - inc eax - ret -endp - -align 4 -proc set_VIA - mov [ctrl.codec_read16], codec_io_r16 ;virtual - mov [ctrl.codec_write16], codec_io_w16 ;virtual - - mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual - mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual - mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual - - mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual - mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual - mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual - ret -endp - - -align 4 -proc init_codec - locals - counter dd ? - endl - - mov esi, msgControl - call SysMsgBoardStr - stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL - and eax, 0xFF - call dword2str - call SysMsgBoardStr - - mov esi, msgStatus - call SysMsgBoardStr - stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT - and eax, 0xFF - push eax - call dword2str - call SysMsgBoardStr - pop eax - - test eax, VIA_ACLINK_C00_READY - jz .ready - - call reset_codec - test eax, eax - jz .err - -.ready: - xor edx, edx ; ac_reg_0 - call [ctrl.codec_write16] - jmp .done - -.err: - xor eax, eax ; timeout error - ret - -.done: - call detect_codec - - xor eax, eax - inc eax - ret -endp - -align 4 -proc reset_codec - stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, \ - VIA_ACLINK_CTRL_ENABLE or VIA_ACLINK_CTRL_RESET or VIA_ACLINK_CTRL_SYNC - mov eax, 100000 ; wait 100 ms - call StallExec -.cold: - call cold_reset - jnc .ok - - if DEBUG - mov esi, msgCFail - call SysMsgBoardStr - end if - xor eax, eax ; timeout error - ret -.ok: - if DEBUG - mov esi, msgResetOk - call SysMsgBoardStr - end if - xor eax, eax - inc eax - ret -endp - - -align 4 -proc cold_reset - locals - counter dd ? - endl - - stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0 - - if DEBUG - mov esi, msgCold - call SysMsgBoardStr - end if - - mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms - call StallExec - - ;; ACLink on, deassert ACLink reset, VSR, SGD data out - ;; note - FM data out has trouble with non VRA codecs !! - stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT - - mov [counter], 16 ; total 20*100 ms = 2s -.wait: - stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT - test eax, VIA_ACLINK_C00_READY - jnz .ok - - mov eax, 100000 ; wait 100 ms - call StallExec - - dec [counter] - jnz .wait - - if DEBUG - mov esi, msgCRFail - call SysMsgBoardStr - end if - -.fail: - stc - ret -.ok: - mov esi, msgControl - call SysMsgBoardStr - stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL - call dword2str - call SysMsgBoardStr - - mov esi, msgStatus - call SysMsgBoardStr - stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT - and eax, 0xFF - push eax - call dword2str - call SysMsgBoardStr - pop eax - - test eax, VIA_ACLINK_C00_READY ;CTRL_ST_CREADY - jz .fail - clc - ret -endp - -align 4 -play: - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX - mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 - mov [ctrl.lvi_reg], 16 - call [ctrl.ctrl_write32] - - mov eax, VIA_REG_CTRL_INT - or eax, VIA_REG_CTRL_START - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL - call [ctrl.ctrl_write8] - - xor eax, eax - ret - -align 4 -stop: - mov eax, VIA_REG_CTRL_INT - or eax, VIA_REG_CTRL_TERMINATE - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL - call [ctrl.ctrl_write8] - - stdcall channel_reset, VIADEV_PLAYBACK - xor eax, eax - ret - -align 4 -proc get_dev_info stdcall, p_info:dword - virtual at esi - CTRL_INFO CTRL_INFO - end virtual - - mov esi, [p_info] - mov eax, [ctrl.int_line] - mov ecx, [ctrl.ctrl_io_base] - mov [CTRL_INFO.irq], eax - mov [CTRL_INFO.ctrl_io_base], ecx - - xor eax, eax - ;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR - ;call [ctrl.ctrl_read32] - mov [CTRL_INFO.codec_io_base], eax - ;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX - ;call [ctrl.ctrl_read32] - mov [CTRL_INFO.codec_mem_base], eax - ;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CURR_COUNT - ;call [ctrl.ctrl_read32] - mov [CTRL_INFO.ctrl_mem_base], eax - - mov eax, [codec.chip_id] - mov [CTRL_INFO.codec_id], eax - - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL - call [ctrl.ctrl_read8] - and eax, 0xFF - mov [CTRL_INFO.glob_cntrl], eax - - mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS - call [ctrl.ctrl_read8] - and eax, 0xFF - mov [CTRL_INFO.glob_sta], eax - - mov ebx, [ctrl.pci_cmd] - mov [CTRL_INFO.pci_cmd], ebx - ret -endp - -align 4 -proc set_callback stdcall, handler:dword - mov eax, [handler] - mov [ctrl.user_callback], eax - ret -endp - - -align 4 -proc codec_check_ready stdcall - locals - counter dd ? - endl - - mov [counter], 1000 ; total 1000*1 ms = 1s -.wait: - call [ctrl.codec_read16] - test eax, VIA_REG_AC97_BUSY - jz .ok - - mov eax, 1000 ; wait 1 ms - call StallExec - - sub [counter] , 1 - jnz .wait -.err: - mov eax, -1 - ret -.ok: - and eax, 0xFFFF - ret -endp - - -align 4 -proc codec_valid stdcall - stdcall codec_check_ready - ret -endp - -align 4 -proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax - locals - counter dd ? - endl - - ;Use only primary codec. - mov eax, [ac_reg] - and eax, 0x7F - shl eax, VIA_REG_AC97_CMD_SHIFT - or eax, VIA_REG_AC97_PRIMARY_VALID or VIA_REG_AC97_READ - - mov [counter], 3 ; total 3*20 ms = 60ms -.wait: - push eax - call [ctrl.codec_write16] - - mov eax, 20000 ; wait 20 ms - call StallExec - - stdcall codec_valid, - cmp eax, 0 - pop eax - jge .ok - - sub [counter] , 1 - jnz .wait - jmp .err - -.ok: - mov eax, 25000 ; wait 25 ms - call StallExec - - call [ctrl.codec_read16] ;change edx !!! - and eax, 0xFFFF - ret -.err: - if DEBUG - mov esi, msgCInvalid - call SysMsgBoardStr - end if - mov eax, -1 ; invalid codec error - ret -endp - -align 4 -proc codec_write stdcall, ac_reg:dword - ;Use only primary codec. - mov esi, [ac_reg] - mov edx, esi - shl edx, VIA_REG_AC97_CMD_SHIFT - - shl eax, VIA_REG_AC97_DATA_SHIFT - or edx, eax - - mov eax, VIA_REG_AC97_CODEC_ID_PRIMARY ;not VIA_REG_AC97_CODEC_ID_PRIMARY - shl eax, VIA_REG_AC97_CODEC_ID_SHIFT - or edx, eax - - mov eax, edx - mov edx, esi - call [ctrl.codec_write16] - mov [codec.regs+esi], ax - - stdcall codec_check_ready - cmp eax, 0 - jl .err -.ok: - ret -.err: - if DEBUG - mov esi, msgCFail - call SysMsgBoardStr - end if - ;mov eax, -1 ; codec not ready error - ret -endp - -align 4 -proc StallExec - push ecx - push edx - push ebx - push eax - - mov ecx, CPU_FREQ - mul ecx - mov ebx, eax ;low - mov ecx, edx ;high - rdtsc - add ebx, eax - adc ecx, edx -@@: - rdtsc - sub eax, ebx - sbb edx, ecx - js @B - - pop eax - pop ebx - pop edx - pop ecx - ret -endp - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; CONTROLLER IO functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -align 4 -proc codec_io_r16 ;r32 - mov edx, [ctrl.ctrl_io_base] - add edx, VIA_REG_AC97 - in eax, dx - ret -endp - -align 4 -proc codec_io_w16 ;w32 - mov edx, [ctrl.ctrl_io_base] - add edx, VIA_REG_AC97 - out dx, eax - ret -endp - -align 4 -proc ctrl_io_r8 - add edx, [ctrl.ctrl_io_base] - in al, dx - ret -endp - -align 4 -proc ctrl_io_r16 - add edx, [ctrl.ctrl_io_base] - in ax, dx - ret -endp - -align 4 -proc ctrl_io_r32 - add edx, [ctrl.ctrl_io_base] - in eax, dx - ret -endp - -align 4 -proc ctrl_io_w8 - add edx, [ctrl.ctrl_io_base] - out dx, al - ret -endp - -align 4 -proc ctrl_io_w16 - add edx, [ctrl.ctrl_io_base] - out dx, ax - ret -endp - -align 4 -proc ctrl_io_w32 - add edx, [ctrl.ctrl_io_base] - out dx, eax - ret -endp - - -align 4 -dword2str: - push eax ebx ecx - mov esi, hex_buff - mov ecx, -8 - @@: - rol eax, 4 - mov ebx, eax - and ebx, 0x0F - mov bl, [ebx+hexletters] - mov [8+esi+ecx], bl - inc ecx - jnz @B - pop ecx ebx eax - ret - -hexletters db '0123456789ABCDEF' -hex_buff db 8 dup(0),13,10,0 - - -include "codec.inc" - -align 4 -devices dd (CTRL_VT82C686 shl 16)+VID_VIA,msg_VT82C686,set_VIA - dd (CTRL_VT8233_5 shl 16)+VID_VIA,msg_VT8233,set_VIA - dd 0 ;terminator - - -version dd (5 shl 16) or (API_VERSION and 0xFFFF) - -msg_VT82C686 db 'VT82C686', 13,10, 0 -msg_VT8233 db 'VT8233', 13,10, 0 -msg_VIA db 'VIA' , 13,10, 0 - -szKernel db 'KERNEL', 0 -sz_sound_srv db 'SOUND',0 - -msgInit db 'detect hardware...',13,10,0 -msgFail db 'device not found',13,10,0 -msgAttchIRQ db 'IRQ line not supported', 13,10, 0 -msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 -msgPlay db 'start play', 13,10,0 -msgStop db 'stop play', 13,10,0 -;msgIRQ db 'AC97 IRQ', 13,10,0 -;msgInitCtrl db 'init controller',13,10,0 -;msgInitCodec db 'init codec',13,10,0 -msgPrimBuff db 'create primary buffer ...',0 -msgDone db 'done',13,10,0 -msgRemap db 'Remap IRQ',13,10,0 -;msgReg db 'set service handler',13,10,0 -;msgOk db 'service installed',13,10,0 -msgCold db 'cold reset',13,10,0 -;msgWarm db 'warm reset',13,10,0 -;msgWRFail db 'warm reset failed',13,10,0 -msgCRFail db 'cold reset failed',13,10,0 -msgCFail db 'codec not ready',13,10,0 -msgCInvalid db 'codec is not valid',13,10,0 ;Asper -msgResetOk db 'reset complete',13,10,0 -msgStatus db 'global status ',0 -msgControl db 'global control ',0 -msgPciCmd db 'PCI command ',0 -msgPciStat db 'PCI status ',0 -msgCtrlIsaIo db 'controller io base ',0 -;msgMixIsaIo db 'codec io base ',0 -;msgCtrlMMIo db 'controller mmio base ',0 -;msgMixMMIo db 'codec mmio base ',0 -;msgIrqMap db 'AC97 irq map as ',0 - - -section '.data' data readable writable align 16 - -pcmout_bdl rq 32 -buff_list rd 32 - -codec CODEC -ctrl AC_CNTRL - -chip_type rb 1 \ No newline at end of file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +format MS COFF + +DEBUG equ 1 + +include 'proc32.inc' +include 'imports.inc' + +API_VERSION equ 0x01000100 + +USE_COM_IRQ equ 0 ;make irq 3 and irq 4 available for PCI devices +IRQ_REMAP equ 0 +IRQ_LINE equ 0 + + +;irq 0,1,2,8,12,13 ­Ґ¤®бвгЇ­л +; FEDCBA9876543210 +VALID_IRQ equ 1100111011111000b +ATTCH_IRQ equ 0000111010100000b + +if USE_COM_IRQ +ATTCH_IRQ equ 0000111010111000b +end if + +CPU_FREQ equ 2600d + +BIT0 EQU 0x00000001 +BIT1 EQU 0x00000002 +BIT5 EQU 0x00000020 +BIT10 EQU 0x00000400 + +VID_VIA equ 0x1106 + +CTRL_VT82C686 equ 0x3058 +CTRL_VT8233_5 equ 0x3059 + + +CODEC_MASTER_VOL_REG equ 0x02 +CODEC_AUX_VOL equ 0x04 ; +CODEC_PCM_OUT_REG equ 0x18 ; PCM output volume +CODEC_EXT_AUDIO_REG equ 0x28 ; extended audio +CODEC_EXT_AUDIO_CTRL_REG equ 0x2a ; extended audio control +CODEC_PCM_FRONT_DACRATE_REG equ 0x2c ; PCM out sample rate +CODEC_PCM_SURND_DACRATE_REG equ 0x2e ; surround sound sample rate +CODEC_PCM_LFE_DACRATE_REG equ 0x30 ; LFE sample rate + + +;VIA host controller registers set +;; common offsets +VIA_REG_OFFSET_STATUS equ 0x00 ;; byte - channel status + VIA_REG_STAT_ACTIVE equ 0x80 ;; RO + VIA_REG_STAT_PAUSED equ 0x40 ;; RO + VIA_REG_STAT_TRIGGER_QUEUED equ 0x08 ;; RO + VIA_REG_STAT_STOPPED equ 0x04 ;; RWC + VIA_REG_STAT_EOL equ 0x02 ;; RWC + VIA_REG_STAT_FLAG equ 0x01 ;; RWC +VIA_REG_OFFSET_CONTROL equ 0x01 ;; byte - channel control + VIA_REG_CTRL_START equ 0x80 ;; WO + VIA_REG_CTRL_TERMINATE equ 0x40 ;; WO + VIA_REG_CTRL_AUTOSTART equ 0x20 + VIA_REG_CTRL_PAUSE equ 0x08 ;; RW + VIA_REG_CTRL_INT_STOP equ 0x04 + VIA_REG_CTRL_INT_EOL equ 0x02 + VIA_REG_CTRL_INT_FLAG equ 0x01 + VIA_REG_CTRL_RESET equ 0x01 ;; RW - probably reset? undocumented + VIA_REG_CTRL_INT equ (VIA_REG_CTRL_INT_FLAG or \ + VIA_REG_CTRL_INT_EOL or \ + VIA_REG_CTRL_AUTOSTART) +VIA_REG_OFFSET_TYPE equ 0x02 ;; byte - channel type (686 only) + VIA_REG_TYPE_AUTOSTART equ 0x80 ;; RW - autostart at EOL + VIA_REG_TYPE_16BIT equ 0x20 ;; RW + VIA_REG_TYPE_STEREO equ 0x10 ;; RW + VIA_REG_TYPE_INT_LLINE equ 0x00 + VIA_REG_TYPE_INT_LSAMPLE equ 0x04 + VIA_REG_TYPE_INT_LESSONE equ 0x08 + VIA_REG_TYPE_INT_MASK equ 0x0c + VIA_REG_TYPE_INT_EOL equ 0x02 + VIA_REG_TYPE_INT_FLAG equ 0x01 +VIA_REG_OFFSET_TABLE_PTR equ 0x04 ;; dword - channel table pointer +VIA_REG_OFFSET_CURR_PTR equ 0x04 ;; dword - channel current pointer +VIA_REG_OFFSET_STOP_IDX equ 0x08 ;; dword - stop index, channel type, sample rate + VIA8233_REG_TYPE_16BIT equ 0x00200000 ;; RW + VIA8233_REG_TYPE_STEREO equ 0x00100000 ;; RW +VIA_REG_OFFSET_CURR_COUNT equ 0x0c ;; dword - channel current count (24 bit) +VIA_REG_OFFSET_CURR_INDEX equ 0x0f ;; byte - channel current index (for via8233 only) + + +VIADEV_PLAYBACK equ 0x00 +VIADEV_CAPTURE equ 0x10 +VIADEV_FM equ 0x20 + +;; AC'97 ;; +VIA_REG_AC97 equ 0x80 ; dword + VIA_REG_AC97_CODEC_ID_MASK equ 0xC0000000 ;(3<<30) + VIA_REG_AC97_CODEC_ID_SHIFT equ 30 + VIA_REG_AC97_CODEC_ID_PRIMARY equ 0x00 + VIA_REG_AC97_CODEC_ID_SECONDARY equ 0x01 + VIA_REG_AC97_SECONDARY_VALID equ 0x08000000 ;(1<<27) + VIA_REG_AC97_PRIMARY_VALID equ 0x02000000 ;(1<<25) + VIA_REG_AC97_BUSY equ 0x01000000 ;(1<<24) + VIA_REG_AC97_READ equ 0x00800000 ;(1<<23) + VIA_REG_AC97_CMD_SHIFT equ 16 + VIA_REG_AC97_CMD_MASK equ 0x7E + VIA_REG_AC97_DATA_SHIFT equ 0 + VIA_REG_AC97_DATA_MASK equ 0xFFFF + +VIA_REG_SGD_SHADOW equ 0x84 ; dword + +;; via8233-specific registers ;; +VIA_REG_OFS_PLAYBACK_VOLUME_L equ 0x02 ;; byte +VIA_REG_OFS_PLAYBACK_VOLUME_R equ 0x03 ;; byte +VIA_REG_OFS_MULTPLAY_FORMAT equ 0x02 ;; byte - format and channels + VIA_REG_MULTPLAY_FMT_8BIT equ 0x00 + VIA_REG_MULTPLAY_FMT_16BIT equ 0x80 + VIA_REG_MULTPLAY_FMT_CH_MASK equ 0x70 ;; # channels << 4 (valid = 1,2,4,6) +VIA_REG_OFS_CAPTURE_FIFO equ 0x02 ;; byte - bit 6 = fifo enable + VIA_REG_CAPTURE_FIFO_ENABLE equ 0x40 + +VIA_DXS_MAX_VOLUME equ 31 ;; max. volume (attenuation) of reg 0x32/33 + +VIA_TBL_BIT_FLAG equ 0x40000000 +VIA_TBL_BIT_EOL equ 0x80000000 + +;; pci space ;; +VIA_ACLINK_STAT equ 0x40 + ;... + VIA_ACLINK_C00_READY equ 0x01 ; primary codec ready +VIA_ACLINK_CTRL equ 0x41 + VIA_ACLINK_CTRL_ENABLE equ 0x80 ; 0: disable, 1: enable + VIA_ACLINK_CTRL_RESET equ 0x40 ; 0: assert, 1: de-assert + VIA_ACLINK_CTRL_SYNC equ 0x20 ; 0: release SYNC, 1: force SYNC hi + VIA_ACLINK_CTRL_SDO equ 0x10 ; 0: release SDO, 1: force SDO hi + VIA_ACLINK_CTRL_VRA equ 0x08 ; 0: disable VRA, 1: enable VRA + VIA_ACLINK_CTRL_PCM equ 0x04 ; 0: disable PCM, 1: enable PCM + VIA_ACLINK_CTRL_FM equ 0x02 ; via686 only + VIA_ACLINK_CTRL_SB equ 0x01 ; via686 only + VIA_ACLINK_CTRL_INIT equ (VIA_ACLINK_CTRL_ENABLE or \ + VIA_ACLINK_CTRL_RESET or \ + VIA_ACLINK_CTRL_PCM or \ + VIA_ACLINK_CTRL_VRA) +VIA_FUNC_ENABLE equ 0x42 + VIA_FUNC_MIDI_PNP equ 0x80 ; FIXME: it's 0x40 in the datasheet! + VIA_FUNC_MIDI_IRQMASK equ 0x40 ; FIXME: not documented! + VIA_FUNC_RX2C_WRITE equ 0x20 + VIA_FUNC_SB_FIFO_EMPTY equ 0x10 + VIA_FUNC_ENABLE_GAME equ 0x08 + VIA_FUNC_ENABLE_FM equ 0x04 + VIA_FUNC_ENABLE_MIDI equ 0x02 + VIA_FUNC_ENABLE_SB equ 0x01 +VIA_PNP_CONTROL equ 0x43 +VIA_FM_NMI_CTRL equ 0x48 +VIA8233_VOLCHG_CTRL equ 0x48 +VIA8233_SPDIF_CTRL equ 0x49 + VIA8233_SPDIF_DX3 equ 0x08 + VIA8233_SPDIF_SLOT_MASK equ 0x03 + VIA8233_SPDIF_SLOT_1011 equ 0x00 + VIA8233_SPDIF_SLOT_34 equ 0x01 + VIA8233_SPDIF_SLOT_78 equ 0x02 + VIA8233_SPDIF_SLOT_69 equ 0x03 +;] Asper + + +SRV_GETVERSION equ 0 +DEV_PLAY equ 1 +DEV_STOP equ 2 +DEV_CALLBACK equ 3 +DEV_SET_BUFF equ 4 +DEV_NOTIFY equ 5 +DEV_SET_MASTERVOL equ 6 +DEV_GET_MASTERVOL equ 7 +DEV_GET_INFO equ 8 + +struc AC_CNTRL ;AC controller base class +{ .bus dd ? + .devfn dd ? + + .vendor dd ? + .dev_id dd ? + .pci_cmd dd ? + .pci_stat dd ? + + .codec_io_base dd ? + .codec_mem_base dd ? + + .ctrl_io_base dd ? + .ctrl_mem_base dd ? + .cfg_reg dd ? + .int_line dd ? + + .vendor_ids dd ? ;vendor id string + .ctrl_ids dd ? ;hub id string + + .buffer dd ? + + .notify_pos dd ? + .notify_task dd ? + + .lvi_reg dd ? + .ctrl_setup dd ? + .user_callback dd ? + .codec_read16 dd ? + .codec_write16 dd ? + + .ctrl_read8 dd ? + .ctrl_read16 dd ? + .ctrl_read32 dd ? + + .ctrl_write8 dd ? + .ctrl_write16 dd ? + .ctrl_write32 dd ? +} + +struc CODEC ;Audio Chip base class +{ + .chip_id dd ? + .flags dd ? + .status dd ? + + .ac_vendor_ids dd ? ;ac vendor id string + .chip_ids dd ? ;chip model string + + .shadow_flag dd ? + dd ? + + .regs dw ? ; codec registers + .reg_master_vol dw ? ;0x02 + .reg_aux_out_vol dw ? ;0x04 + .reg_mone_vol dw ? ;0x06 + .reg_master_tone dw ? ;0x08 + .reg_beep_vol dw ? ;0x0A + .reg_phone_vol dw ? ;0x0C + .reg_mic_vol dw ? ;0x0E + .reg_line_in_vol dw ? ;0x10 + .reg_cd_vol dw ? ;0x12 + .reg_video_vol dw ? ;0x14 + .reg_aux_in_vol dw ? ;0x16 + .reg_pcm_out_vol dw ? ;0x18 + .reg_rec_select dw ? ;0x1A + .reg_rec_gain dw ? ;0x1C + .reg_rec_gain_mic dw ? ;0x1E + .reg_gen dw ? ;0x20 + .reg_3d_ctrl dw ? ;0X22 + .reg_page dw ? ;0X24 + .reg_powerdown dw ? ;0x26 + .reg_ext_audio dw ? ;0x28 + .reg_ext_st dw ? ;0x2a + .reg_pcm_front_rate dw ? ;0x2c + .reg_pcm_surr_rate dw ? ;0x2e + .reg_lfe_rate dw ? ;0x30 + .reg_pcm_in_rate dw ? ;0x32 + dw ? ;0x34 + .reg_cent_lfe_vol dw ? ;0x36 + .reg_surr_vol dw ? ;0x38 + .reg_spdif_ctrl dw ? ;0x3A + dw ? ;0x3C + dw ? ;0x3E + dw ? ;0x40 + dw ? ;0x42 + dw ? ;0x44 + dw ? ;0x46 + dw ? ;0x48 + dw ? ;0x4A + dw ? ;0x4C + dw ? ;0x4E + dw ? ;0x50 + dw ? ;0x52 + dw ? ;0x54 + dw ? ;0x56 + dw ? ;0x58 + dw ? ;0x5A + dw ? ;0x5C + dw ? ;0x5E + .reg_page_0 dw ? ;0x60 + .reg_page_1 dw ? ;0x62 + .reg_page_2 dw ? ;0x64 + .reg_page_3 dw ? ;0x66 + .reg_page_4 dw ? ;0x68 + .reg_page_5 dw ? ;0x6A + .reg_page_6 dw ? ;0x6C + .reg_page_7 dw ? ;0x6E + dw ? ;0x70 + dw ? ;0x72 + dw ? ;0x74 + dw ? ;0x76 + dw ? ;0x78 + dw ? ;0x7A + .reg_vendor_id_1 dw ? ;0x7C + .reg_vendor_id_2 dw ? ;0x7E + + + .reset dd ? ;virual + .set_master_vol dd ? +} + +struc CTRL_INFO +{ .pci_cmd dd ? + .irq dd ? + .glob_cntrl dd ? + .glob_sta dd ? + .codec_io_base dd ? + .ctrl_io_base dd ? + .codec_mem_base dd ? + .ctrl_mem_base dd ? + .codec_id dd ? +} + +struc IOCTL +{ .handle dd ? + .io_code dd ? + .input dd ? + .inp_size dd ? + .output dd ? + .out_size dd ? +} + +virtual at 0 + IOCTL IOCTL +end virtual + +EVENT_NOTIFY equ 0x00000200 + +public START +public service_proc +public version + +section '.flat' code readable align 16 + +proc START stdcall, state:dword + + cmp [state], 1 + jne .stop + + if DEBUG + mov esi, msgInit + call SysMsgBoardStr + end if + + call detect_controller + test eax, eax + jz .fail + + if DEBUG + mov esi, [ctrl.vendor_ids] + call SysMsgBoardStr + mov esi, [ctrl.ctrl_ids] + call SysMsgBoardStr + end if + + call init_controller + test eax, eax + jz .fail + + call init_codec + test eax, eax + jz .fail + + call setup_codec + + mov esi, msgPrimBuff + call SysMsgBoardStr + call create_primary_buff + mov esi, msgDone + call SysMsgBoardStr + + if IRQ_REMAP + pushf + cli + + mov ebx, [ctrl.int_line] + in al, 0xA1 + mov ah, al + in al, 0x21 + test ebx, ebx + jz .skip + bts ax, bx ;mask old line +.skip: + bts ax, IRQ_LINE ;mask new ine + out 0x21, al + mov al, ah + out 0xA1, al + + stdcall PciWrite8, 0, 0xF8, 0x61, IRQ_LINE ;remap IRQ + + mov dx, 0x4d0 ;8259 ELCR1 + in al, dx + bts ax, IRQ_LINE + out dx, al ;set level-triggered mode + mov [ctrl.int_line], IRQ_LINE + popf + mov esi, msgRemap + call SysMsgBoardStr + end if + + mov eax, VALID_IRQ + mov ebx, [ctrl.int_line] + mov esi, msgInvIRQ + bt eax, ebx + jnc .fail_msg + mov eax, ATTCH_IRQ + mov esi, msgAttchIRQ + bt eax, ebx + jnc .fail_msg + + stdcall AttachIntHandler, ebx, ac97_irq_VIA, dword 0 +.reg: + stdcall RegService, sz_sound_srv, service_proc + ret +.fail: + if DEBUG + mov esi, msgFail + call SysMsgBoardStr + end if + xor eax, eax + ret +.fail_msg: + call SysMsgBoardStr + xor eax, eax + ret +.stop: + call stop + xor eax, eax + ret +endp + +handle equ IOCTL.handle +io_code equ IOCTL.io_code +input equ IOCTL.input +inp_size equ IOCTL.inp_size +output equ IOCTL.output +out_size equ IOCTL.out_size + +align 4 +proc service_proc stdcall, ioctl:dword + + mov edi, [ioctl] + mov eax, [edi+io_code] + + cmp eax, SRV_GETVERSION + jne @F + mov eax, [edi+output] + cmp [edi+out_size], 4 + jne .fail + + mov [eax], dword API_VERSION + xor eax, eax + ret +@@: + cmp eax, DEV_PLAY + jne @F + if DEBUG + mov esi, msgPlay + call SysMsgBoardStr + end if + call play + ret +@@: + cmp eax, DEV_STOP + jne @F + if DEBUG + mov esi, msgStop + call SysMsgBoardStr + end if + call stop + ret +@@: + cmp eax, DEV_CALLBACK + jne @F + mov ebx, [edi+input] + stdcall set_callback, [ebx] + ret +@@: + cmp eax, DEV_SET_MASTERVOL + jne @F + mov eax, [edi+input] + mov eax, [eax] + call set_master_vol ;eax= vol + ret +@@: + cmp eax, DEV_GET_MASTERVOL + jne @F + mov ebx, [edi+output] + stdcall get_master_vol, ebx + ret +@@: + cmp eax, DEV_GET_INFO + jne @F + mov ebx, [edi+output] + stdcall get_dev_info, ebx + ret +@@: +.fail: + or eax, -1 + ret +endp + +restore handle +restore io_code +restore input +restore inp_size +restore output +restore out_size + + +align 4 +proc ac97_irq_VIA + locals + status db 0 + endl + + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS + call [ctrl.ctrl_read8] + test al, VIA_REG_STAT_ACTIVE + jz @f + + and al, VIA_REG_STAT_EOL or VIA_REG_STAT_FLAG or VIA_REG_STAT_STOPPED + mov byte [status], al + + mov ebx, dword [buff_list] + cmp [ctrl.user_callback], 0 + je @f + stdcall [ctrl.user_callback], ebx + @@: + mov al, byte [status] ;; ack ;; + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS + call [ctrl.ctrl_write8] + + ret +endp + + +align 4 +proc create_primary_buff + + stdcall KernelAlloc, 0x10000 + mov [ctrl.buffer], eax + + mov edi, eax + mov ecx, 0x10000/4 + xor eax, eax + cld + rep stosd + + mov eax, [ctrl.buffer] + call GetPgAddr + mov edi, pcmout_bdl + stosd + mov eax, 0x80004000 + stosd + + mov edi, buff_list + mov eax, [ctrl.buffer] + mov ecx, 4 +@@: + mov [edi], eax + mov [edi+16], eax + mov [edi+32], eax + mov [edi+48], eax + mov [edi+64], eax + mov [edi+80], eax + mov [edi+96], eax + mov [edi+112], eax + + ;add eax, 0x4000 + add edi, 4 + loop @B + + stdcall channel_reset, VIADEV_PLAYBACK + stdcall codec_check_ready + + mov eax, pcmout_bdl + mov ebx, eax + call GetPgAddr + and ebx, 0xFFF + add eax, ebx + + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR + call [ctrl.ctrl_write32] + + stdcall codec_check_ready + + mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_L + mov eax, 7 ;31 + call [ctrl.ctrl_write8] + + mov edx, VIADEV_PLAYBACK +VIA_REG_OFS_PLAYBACK_VOLUME_R + mov eax, 7 ;31 + call [ctrl.ctrl_write8] + + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX + mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 + mov [ctrl.lvi_reg], 16 ;0xF;eax + call [ctrl.ctrl_write32] + + stdcall codec_check_ready + ret +endp + + +proc channel_reset channel:dword + mov esi, dword [channel] + mov edx, esi + add edx, VIA_REG_OFFSET_CONTROL + mov eax, VIA_REG_CTRL_PAUSE or VIA_REG_CTRL_TERMINATE or VIA_REG_CTRL_RESET + call [ctrl.ctrl_write8] + + mov edx, esi + add edx, VIA_REG_OFFSET_CONTROL + call [ctrl.ctrl_read8] + + mov eax, 50000 ; wait 50 ms + call StallExec + ; disable interrupts + mov edx, esi + add edx, VIA_REG_OFFSET_CONTROL + xor eax, eax + call [ctrl.ctrl_write8] + + ; clear interrupts + mov edx, esi + add edx, VIA_REG_OFFSET_STATUS + mov eax, 0x03 + call [ctrl.ctrl_write8] + + ;outb(0x00, VIADEV_REG(viadev, OFFSET_TYPE)); /* for via686 */ + ; mov edx, esi ;; for via686 + ; add edx, VIA_REG_OFFSET_TYPE + ; mov eax, 0x03 + ; call [ctrl.ctrl_write8] + + ;; outl(0, VIADEV_REG(viadev, OFFSET_CURR_PTR)); + ;mov edx, esi + ;add edx, VIA_REG_OFFSET_CURR_PTR + ;xor eax, eax + ;call [ctrl.ctrl_write8] + + ret +endp + + +align 4 +proc detect_controller + locals + last_bus dd ? + bus dd ? + devfn dd ? + endl + + xor eax, eax + mov [bus], eax + inc eax + call PciApi + cmp eax, -1 + je .err + + mov [last_bus], eax + +.next_bus: + and [devfn], 0 +.next_dev: + stdcall PciRead32, [bus], [devfn], dword 0 + test eax, eax + jz .next + cmp eax, -1 + je .next + + mov edi, devices +@@: + mov ebx, [edi] + test ebx, ebx + jz .next + + cmp eax, ebx + je .found + add edi, 12 + jmp @B +.next: + inc [devfn] + cmp [devfn], 256 + jb .next_dev + mov eax, [bus] + inc eax + mov [bus], eax + cmp eax, [last_bus] + jna .next_bus + xor eax, eax + ret +.found: + mov ebx, [bus] + mov [ctrl.bus], ebx + + mov ecx, [devfn] + mov [ctrl.devfn], ecx + + mov edx, eax + and edx, 0xFFFF + mov [ctrl.vendor], edx + shr eax, 16 + mov [ctrl.dev_id], eax + + mov ebx, [edi+4] + mov [ctrl.ctrl_ids], ebx + mov esi, [edi+8] + mov [ctrl.ctrl_setup], esi + + cmp edx, VID_VIA + jne @F + mov [ctrl.vendor_ids], msg_VIA + ret +@@: + +.err: + xor eax, eax + mov [ctrl.vendor_ids], eax ;something wrong ? + ret +endp + +align 4 +proc init_controller + + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 4 + mov ebx, eax + and eax, 0xFFFF + mov [ctrl.pci_cmd], eax + shr ebx, 16 + mov [ctrl.pci_stat], ebx + + mov esi, msgPciCmd + call SysMsgBoardStr + call dword2str + call SysMsgBoardStr + + mov esi, msgPciStat + call SysMsgBoardStr + mov eax, [ctrl.pci_stat] + call dword2str + call SysMsgBoardStr + + mov esi, msgCtrlIsaIo + call SysMsgBoardStr + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x10 + call dword2str + call SysMsgBoardStr + + and eax, 0xFFC0 + mov [ctrl.ctrl_io_base], eax + +.default: + stdcall PciRead32, [ctrl.bus], [ctrl.devfn], dword 0x3C + and eax, 0xFF +@@: + mov [ctrl.int_line], eax + + ;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE ;0x42 + ;mov byte [old_legacy], al + + ;stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_PNP_CONTROL ;0x43 + ;mov byte [old_legacy_cfg], al + + ;mov al, VIA_FUNC_ENABLE_SB or VIA_FUNC_ENABLE_FM + ;xor al, 0xFF + ;and al, byte [old_legacy] + ;and eax, 0xFF + ;stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_FUNC_ENABLE, eax ;0x42 + ;mov byte [old_legacy], al + + call [ctrl.ctrl_setup] + xor eax, eax + inc eax + ret +endp + +align 4 +proc set_VIA + mov [ctrl.codec_read16], codec_io_r16 ;virtual + mov [ctrl.codec_write16], codec_io_w16 ;virtual + + mov [ctrl.ctrl_read8 ], ctrl_io_r8 ;virtual + mov [ctrl.ctrl_read16], ctrl_io_r16 ;virtual + mov [ctrl.ctrl_read32], ctrl_io_r32 ;virtual + + mov [ctrl.ctrl_write8 ], ctrl_io_w8 ;virtual + mov [ctrl.ctrl_write16], ctrl_io_w16 ;virtual + mov [ctrl.ctrl_write32], ctrl_io_w32 ;virtual + ret +endp + + +align 4 +proc init_codec + locals + counter dd ? + endl + + mov esi, msgControl + call SysMsgBoardStr + stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL + and eax, 0xFF + call dword2str + call SysMsgBoardStr + + mov esi, msgStatus + call SysMsgBoardStr + stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT + and eax, 0xFF + push eax + call dword2str + call SysMsgBoardStr + pop eax + + test eax, VIA_ACLINK_C00_READY + jz .ready + + call reset_codec + test eax, eax + jz .err + +.ready: + xor edx, edx ; ac_reg_0 + call [ctrl.codec_write16] + jmp .done + +.err: + xor eax, eax ; timeout error + ret + +.done: + call detect_codec + + xor eax, eax + inc eax + ret +endp + +align 4 +proc reset_codec + stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, \ + VIA_ACLINK_CTRL_ENABLE or VIA_ACLINK_CTRL_RESET or VIA_ACLINK_CTRL_SYNC + mov eax, 100000 ; wait 100 ms + call StallExec +.cold: + call cold_reset + jnc .ok + + if DEBUG + mov esi, msgCFail + call SysMsgBoardStr + end if + xor eax, eax ; timeout error + ret +.ok: + if DEBUG + mov esi, msgResetOk + call SysMsgBoardStr + end if + xor eax, eax + inc eax + ret +endp + + +align 4 +proc cold_reset + locals + counter dd ? + endl + + stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword 0 + + if DEBUG + mov esi, msgCold + call SysMsgBoardStr + end if + + mov eax, 100000 ; wait 100 ms ;400000 ; wait 400 ms + call StallExec + + ;; ACLink on, deassert ACLink reset, VSR, SGD data out + ;; note - FM data out has trouble with non VRA codecs !! + stdcall PciWrite8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL, dword VIA_ACLINK_CTRL_INIT + + mov [counter], 16 ; total 20*100 ms = 2s +.wait: + stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT + test eax, VIA_ACLINK_C00_READY + jnz .ok + + mov eax, 100000 ; wait 100 ms + call StallExec + + dec [counter] + jnz .wait + + if DEBUG + mov esi, msgCRFail + call SysMsgBoardStr + end if + +.fail: + stc + ret +.ok: + mov esi, msgControl + call SysMsgBoardStr + stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_CTRL + call dword2str + call SysMsgBoardStr + + mov esi, msgStatus + call SysMsgBoardStr + stdcall PciRead8, [ctrl.bus], [ctrl.devfn], dword VIA_ACLINK_STAT + and eax, 0xFF + push eax + call dword2str + call SysMsgBoardStr + pop eax + + test eax, VIA_ACLINK_C00_READY ;CTRL_ST_CREADY + jz .fail + clc + ret +endp + +align 4 +play: + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX + mov eax, VIA8233_REG_TYPE_16BIT or VIA8233_REG_TYPE_STEREO or 0xfffff or 0xff000000 + mov [ctrl.lvi_reg], 16 + call [ctrl.ctrl_write32] + + mov eax, VIA_REG_CTRL_INT + or eax, VIA_REG_CTRL_START + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL + call [ctrl.ctrl_write8] + + xor eax, eax + ret + +align 4 +stop: + mov eax, VIA_REG_CTRL_INT + or eax, VIA_REG_CTRL_TERMINATE + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL + call [ctrl.ctrl_write8] + + stdcall channel_reset, VIADEV_PLAYBACK + xor eax, eax + ret + +align 4 +proc get_dev_info stdcall, p_info:dword + virtual at esi + CTRL_INFO CTRL_INFO + end virtual + + mov esi, [p_info] + mov eax, [ctrl.int_line] + mov ecx, [ctrl.ctrl_io_base] + mov [CTRL_INFO.irq], eax + mov [CTRL_INFO.ctrl_io_base], ecx + + xor eax, eax + ;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_TABLE_PTR + ;call [ctrl.ctrl_read32] + mov [CTRL_INFO.codec_io_base], eax + ;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STOP_IDX + ;call [ctrl.ctrl_read32] + mov [CTRL_INFO.codec_mem_base], eax + ;mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CURR_COUNT + ;call [ctrl.ctrl_read32] + mov [CTRL_INFO.ctrl_mem_base], eax + + mov eax, [codec.chip_id] + mov [CTRL_INFO.codec_id], eax + + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_CONTROL + call [ctrl.ctrl_read8] + and eax, 0xFF + mov [CTRL_INFO.glob_cntrl], eax + + mov edx, VIADEV_PLAYBACK +VIA_REG_OFFSET_STATUS + call [ctrl.ctrl_read8] + and eax, 0xFF + mov [CTRL_INFO.glob_sta], eax + + mov ebx, [ctrl.pci_cmd] + mov [CTRL_INFO.pci_cmd], ebx + ret +endp + +align 4 +proc set_callback stdcall, handler:dword + mov eax, [handler] + mov [ctrl.user_callback], eax + ret +endp + + +align 4 +proc codec_check_ready stdcall + locals + counter dd ? + endl + + mov [counter], 1000 ; total 1000*1 ms = 1s +.wait: + call [ctrl.codec_read16] + test eax, VIA_REG_AC97_BUSY + jz .ok + + mov eax, 1000 ; wait 1 ms + call StallExec + + sub [counter] , 1 + jnz .wait +.err: + mov eax, -1 + ret +.ok: + and eax, 0xFFFF + ret +endp + + +align 4 +proc codec_valid stdcall + stdcall codec_check_ready + ret +endp + +align 4 +proc codec_read stdcall, ac_reg:dword ; reg = edx, reval = eax + locals + counter dd ? + endl + + ;Use only primary codec. + mov eax, [ac_reg] + and eax, 0x7F + shl eax, VIA_REG_AC97_CMD_SHIFT + or eax, VIA_REG_AC97_PRIMARY_VALID or VIA_REG_AC97_READ + + mov [counter], 3 ; total 3*20 ms = 60ms +.wait: + push eax + call [ctrl.codec_write16] + + mov eax, 20000 ; wait 20 ms + call StallExec + + stdcall codec_valid + cmp eax, 0 + pop eax + jge .ok + + sub [counter] , 1 + jnz .wait + jmp .err + +.ok: + mov eax, 25000 ; wait 25 ms + call StallExec + + call [ctrl.codec_read16] ;change edx !!! + and eax, 0xFFFF + ret +.err: + if DEBUG + mov esi, msgCInvalid + call SysMsgBoardStr + end if + mov eax, -1 ; invalid codec error + ret +endp + +align 4 +proc codec_write stdcall, ac_reg:dword + ;Use only primary codec. + mov esi, [ac_reg] + mov edx, esi + shl edx, VIA_REG_AC97_CMD_SHIFT + + shl eax, VIA_REG_AC97_DATA_SHIFT + or edx, eax + + mov eax, VIA_REG_AC97_CODEC_ID_PRIMARY ;not VIA_REG_AC97_CODEC_ID_PRIMARY + shl eax, VIA_REG_AC97_CODEC_ID_SHIFT + or edx, eax + + mov eax, edx + mov edx, esi + call [ctrl.codec_write16] + mov [codec.regs+esi], ax + + stdcall codec_check_ready + cmp eax, 0 + jl .err +.ok: + ret +.err: + if DEBUG + mov esi, msgCFail + call SysMsgBoardStr + end if + ;mov eax, -1 ; codec not ready error + ret +endp + +align 4 +proc StallExec + push ecx + push edx + push ebx + push eax + + mov ecx, CPU_FREQ + mul ecx + mov ebx, eax ;low + mov ecx, edx ;high + rdtsc + add ebx, eax + adc ecx, edx +@@: + rdtsc + sub eax, ebx + sbb edx, ecx + js @B + + pop eax + pop ebx + pop edx + pop ecx + ret +endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; CONTROLLER IO functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +align 4 +proc codec_io_r16 ;r32 + mov edx, [ctrl.ctrl_io_base] + add edx, VIA_REG_AC97 + in eax, dx + ret +endp + +align 4 +proc codec_io_w16 ;w32 + mov edx, [ctrl.ctrl_io_base] + add edx, VIA_REG_AC97 + out dx, eax + ret +endp + +align 4 +proc ctrl_io_r8 + add edx, [ctrl.ctrl_io_base] + in al, dx + ret +endp + +align 4 +proc ctrl_io_r16 + add edx, [ctrl.ctrl_io_base] + in ax, dx + ret +endp + +align 4 +proc ctrl_io_r32 + add edx, [ctrl.ctrl_io_base] + in eax, dx + ret +endp + +align 4 +proc ctrl_io_w8 + add edx, [ctrl.ctrl_io_base] + out dx, al + ret +endp + +align 4 +proc ctrl_io_w16 + add edx, [ctrl.ctrl_io_base] + out dx, ax + ret +endp + +align 4 +proc ctrl_io_w32 + add edx, [ctrl.ctrl_io_base] + out dx, eax + ret +endp + + +align 4 +dword2str: + push eax ebx ecx + mov esi, hex_buff + mov ecx, -8 + @@: + rol eax, 4 + mov ebx, eax + and ebx, 0x0F + mov bl, [ebx+hexletters] + mov [8+esi+ecx], bl + inc ecx + jnz @B + pop ecx ebx eax + ret + +hexletters db '0123456789ABCDEF' +hex_buff db 8 dup(0),13,10,0 + + +include "codec.inc" + +align 4 +devices dd (CTRL_VT82C686 shl 16)+VID_VIA,msg_VT82C686,set_VIA + dd (CTRL_VT8233_5 shl 16)+VID_VIA,msg_VT8233,set_VIA + dd 0 ;terminator + + +version dd (5 shl 16) or (API_VERSION and 0xFFFF) + +msg_VT82C686 db 'VT82C686', 13,10, 0 +msg_VT8233 db 'VT8233', 13,10, 0 +msg_VIA db 'VIA' , 13,10, 0 + +szKernel db 'KERNEL', 0 +sz_sound_srv db 'SOUND',0 + +msgInit db 'detect hardware...',13,10,0 +msgFail db 'device not found',13,10,0 +msgAttchIRQ db 'IRQ line not supported', 13,10, 0 +msgInvIRQ db 'IRQ line not assigned or invalid', 13,10, 0 +msgPlay db 'start play', 13,10,0 +msgStop db 'stop play', 13,10,0 +;msgIRQ db 'AC97 IRQ', 13,10,0 +;msgInitCtrl db 'init controller',13,10,0 +;msgInitCodec db 'init codec',13,10,0 +msgPrimBuff db 'create primary buffer ...',0 +msgDone db 'done',13,10,0 +msgRemap db 'Remap IRQ',13,10,0 +;msgReg db 'set service handler',13,10,0 +;msgOk db 'service installed',13,10,0 +msgCold db 'cold reset',13,10,0 +;msgWarm db 'warm reset',13,10,0 +;msgWRFail db 'warm reset failed',13,10,0 +msgCRFail db 'cold reset failed',13,10,0 +msgCFail db 'codec not ready',13,10,0 +msgCInvalid db 'codec is not valid',13,10,0 ;Asper +msgResetOk db 'reset complete',13,10,0 +msgStatus db 'global status ',0 +msgControl db 'global control ',0 +msgPciCmd db 'PCI command ',0 +msgPciStat db 'PCI status ',0 +msgCtrlIsaIo db 'controller io base ',0 +;msgMixIsaIo db 'codec io base ',0 +;msgCtrlMMIo db 'controller mmio base ',0 +;msgMixMMIo db 'codec mmio base ',0 +;msgIrqMap db 'AC97 irq map as ',0 + + +section '.data' data readable writable align 16 + +pcmout_bdl rq 32 +buff_list rd 32 + +codec CODEC +ctrl AC_CNTRL + +chip_type rb 1 diff --git a/kernel/trunk/fdo.inc b/kernel/trunk/fdo.inc index 49414dd1c..ad50def6b 100644 --- a/kernel/trunk/fdo.inc +++ b/kernel/trunk/fdo.inc @@ -1,437 +1,444 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -_esp equ esp - -; -; Formatted Debug Output (FDO) -; Copyright (c) 2005-2006, mike.dld -; Created: 2005-01-29, Changed: 2006-11-10 -; -; For questions and bug reports, mail to mike.dld@gmail.com -; -; Available format specifiers are: %s, %d, %u, %x (with partial width support) -; - -; to be defined: -; __DEBUG__ equ 1 -; __DEBUG_LEVEL__ equ 5 - -macro debug_func name { - if used name - name@of@func equ name -} - -macro debug_beginf { - align 4 - name@of@func: -} - -debug_endf fix end if - -macro DEBUGS _sign,[_str] { - common - local tp - tp equ 0 - match _arg:_num,_str \{ - DEBUGS_N _sign,_num,_arg - tp equ 1 - \} - match =0 _arg,tp _str \{ - DEBUGS_N _sign,,_arg - \} -} - -macro DEBUGS_N _sign,_num,[_str] { - common - pushf - pushad - local ..str,..label,is_str - is_str = 0 - forward - if _str eqtype '' - is_str = 1 - end if - common - if is_str = 1 - jmp ..label - ..str db _str,0 - ..label: - mov edx,..str - else -esp equ esp+4*8+4 - mov edx,_str -esp equ _esp - end if - if ~_num eq - if _num eqtype eax - if _num in - mov esi,_num - else if ~_num eq esi - movzx esi,_num - end if - else if _num eqtype 0 - mov esi,_num - else - local tp - tp equ 0 - match [_arg],_num \{ - mov esi,dword[_arg] - tp equ 1 - \} - match =0 =dword[_arg],tp _num \{ - mov esi,dword[_arg] - tp equ 1 - \} - match =0 =word[_arg],tp _num \{ - movzx esi,word[_arg] - tp equ 1 - \} - match =0 =byte[_arg],tp _num \{ - movzx esi,byte[_arg] - tp equ 1 - \} - match =0,tp \{ - 'Error: specified string width is incorrect' - \} - end if - else - mov esi,0x7FFFFFFF - end if - call fdo_debug_outstr - popad - popf -} - -macro DEBUGD _sign,_dec { - local tp - tp equ 0 - match _arg:_num,_dec \{ - DEBUGD_N _sign,_num,_arg - tp equ 1 - \} - match =0 _arg,tp _dec \{ - DEBUGD_N _sign,,_arg - \} -} - -macro DEBUGD_N _sign,_num,_dec { - pushf - pushad - if (~_num eq) - if (_dec eqtype eax | _dec eqtype 0) - 'Error: precision allowed only for in-memory variables' - end if - if (~_num in <1,2,4>) - if _sign - 'Error: 1, 2 and 4 are only allowed for precision in %d' - else - 'Error: 1, 2 and 4 are only allowed for precision in %u' - end if - end if - end if - if _dec eqtype eax - if _dec in - mov eax,_dec - else if ~_dec eq eax - if _sign = 1 - movsx eax,_dec - else - movzx eax,_dec - end if - end if - else if _dec eqtype 0 - mov eax,_dec - else -; add esp,4*8+4 -esp equ esp+4*8+4 - if _num eq - mov eax,dword _dec - else if _num = 1 - if _sign = 1 - movsx eax,byte _dec - else - movzx eax,byte _dec - end if - else if _num = 2 - if _sign = 1 - movsx eax,word _dec - else - movzx eax,word _dec - end if - else - mov eax,dword _dec - end if -esp equ _esp -; sub esp,4*8+4 - end if - mov cl,_sign - call fdo_debug_outdec - popad - popf -} - -macro DEBUGH _sign,_hex { - local tp - tp equ 0 - match _arg:_num,_hex \{ - DEBUGH_N _sign,_num,_arg - tp equ 1 - \} - match =0 _arg,tp _hex \{ - DEBUGH_N _sign,,_arg - \} -} - -macro DEBUGH_N _sign,_num,_hex { - pushf - pushad - if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>) - 'Error: 1..8 are only allowed for precision in %x' - end if - if _hex eqtype eax - if _hex in - if ~_hex eq eax - mov eax,_hex - end if - mov edx,8 - else if _hex in - if ~_hex eq ax - movzx eax,_hex - end if - if (_num eq) - mov edx,4 - end if - else if _hex in - if ~_hex eq al - movzx eax,_hex - end if - if (_num eq) - mov edx,2 - end if - end if - else if _hex eqtype 0 - mov eax,_hex - else -; add esp,4*8+4 -esp equ esp+4*8+4 - mov eax,dword _hex -esp equ _esp -; sub esp,4*8+4 - end if - if ~_num eq - mov edx,_num - else - if ~_hex eqtype eax - mov edx,8 - end if - end if - call fdo_debug_outhex - popad - popf -} - -;----------------------------------------------------------------------------- - -debug_func fdo_debug_outchar -debug_beginf - pushad - movzx ebx,al - mov eax,1 - mov ecx,sys_msg_board - call ecx ; sys_msg_board - popad - ret -debug_endf - -debug_func fdo_debug_outstr -debug_beginf - mov eax,1 - .l1: dec esi - js .l2 - movzx ebx,byte[edx] - or bl,bl - jz .l2 - mov ecx,sys_msg_board - call ecx ; sys_msg_board - inc edx - jmp .l1 - .l2: ret -debug_endf - -debug_func fdo_debug_outdec -debug_beginf - or cl,cl - jz @f - or eax,eax - jns @f - neg eax - push eax - mov al,'-' - call fdo_debug_outchar - pop eax - @@: push 10 - pop ecx - push -'0' - .l1: xor edx,edx - div ecx - push edx - test eax,eax - jnz .l1 - .l2: pop eax - add al,'0' - jz .l3 - call fdo_debug_outchar - jmp .l2 - .l3: ret -debug_endf - -debug_func fdo_debug_outhex - __fdo_hexdigits db '0123456789ABCDEF' -debug_beginf - mov cl,dl - neg cl - add cl,8 - shl cl,2 - rol eax,cl - .l1: rol eax,4 - push eax - and eax,0x0000000F - mov al,[__fdo_hexdigits+eax] - call fdo_debug_outchar - pop eax - dec edx - jnz .l1 - ret -debug_endf - -;----------------------------------------------------------------------------- - -macro DEBUGF _level,_format,[_arg] { - common - if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__ - local ..f1,f2,a1,a2,c1,c2,c3,..lbl - _debug_str_ equ __debug_str_ # a1 - a1 = 0 - c2 = 0 - c3 = 0 - f2 = 0 - repeat ..lbl-..f1 - virtual at 0 - db _format,0,0 - load c1 word from %-1 - end virtual - if c1 = '%s' - virtual at 0 - db _format,0,0 - store word 0 at %-1 - load c1 from f2-c2 - end virtual - if c1 <> 0 - DEBUGS 0,_debug_str_+f2-c2 - end if - c2 = c2 + 1 - f2 = %+1 - DEBUGF_HELPER S,a1,0,_arg - else if c1 = '%x' - virtual at 0 - db _format,0,0 - store word 0 at %-1 - load c1 from f2-c2 - end virtual - if c1 <> 0 - DEBUGS 0,_debug_str_+f2-c2 - end if - c2 = c2 + 1 - f2 = %+1 - DEBUGF_HELPER H,a1,0,_arg - else if c1 = '%d' | c1 = '%u' - local c4 - if c1 = '%d' - c4 = 1 - else - c4 = 0 - end if - virtual at 0 - db _format,0,0 - store word 0 at %-1 - load c1 from f2-c2 - end virtual - if c1 <> 0 - DEBUGS 0,_debug_str_+f2-c2 - end if - c2 = c2 + 1 - f2 = %+1 - DEBUGF_HELPER D,a1,c4,_arg - else if c1 = '\n' - c3 = c3 + 1 - end if - end repeat - virtual at 0 - db _format,0,0 - load c1 from f2-c2 - end virtual - if (c1<>0)&(f2<>..lbl-..f1-1) - DEBUGS 0,_debug_str_+f2-c2 - end if - virtual at 0 - ..f1 db _format,0 - ..lbl: - __debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3 - end virtual - end if -} - -macro __include_debug_strings dummy,[_id,_fmt,_len] { - common - local c1,a1,a2 - forward - if defined _len & ~_len eq - _id: - a1 = 0 - a2 = 0 - repeat _len - virtual at 0 - db _fmt,0,0 - load c1 word from %+a2-1 - end virtual - if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u') - db 0 - a2 = a2 + 1 - else if (c1='\n') - dw $0A0D - a1 = a1 + 1 - a2 = a2 + 1 - else - db c1 and 0x0FF - end if - end repeat - db 0 - end if -} - -macro DEBUGF_HELPER _letter,_num,_sign,[_arg] { - common - local num - num = 0 - forward - if num = _num - DEBUG#_letter _sign,_arg - end if - num = num+1 - common - _num = _num+1 -} - -macro include_debug_strings { - if __DEBUG__ = 1 - match dbg_str,__debug_strings \{ - __include_debug_strings dbg_str - \} - end if -} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +_esp equ esp + +; +; Formatted Debug Output (FDO) +; Copyright (c) 2005-2006, mike.dld +; Created: 2005-01-29, Changed: 2006-11-10 +; +; For questions and bug reports, mail to mike.dld@gmail.com +; +; Available format specifiers are: %s, %d, %u, %x (with partial width support) +; + +; to be defined: +; __DEBUG__ equ 1 +; __DEBUG_LEVEL__ equ 5 + +macro debug_func name { + if used name + name@of@func equ name +} + +macro debug_beginf { + align 4 + name@of@func: +} + +debug_endf fix end if + +macro DEBUGS _sign,[_str] { + common + local tp + tp equ 0 + match _arg:_num,_str \{ + DEBUGS_N _sign,_num,_arg + tp equ 1 + \} + match =0 _arg,tp _str \{ + DEBUGS_N _sign,,_arg + \} +} + +macro DEBUGS_N _sign,_num,[_str] { + common + pushf + pushad + local ..str,..label,is_str + is_str = 0 + forward + if _str eqtype '' + is_str = 1 + end if + common + if is_str = 1 + jmp ..label + ..str db _str,0 + ..label: + mov edx, ..str + else +esp equ esp+4*8+4 + mov edx, _str +esp equ _esp + end if + if ~_num eq + if _num eqtype eax + if _num in + mov esi, _num + else if ~_num eq esi + movzx esi, _num + end if + else if _num eqtype 0 + mov esi, _num + else + local tp + tp equ 0 + match [_arg],_num \{ + mov esi, dword[_arg] + tp equ 1 + \} + match =0 =dword[_arg],tp _num \{ + mov esi, dword[_arg] + tp equ 1 + \} + match =0 =word[_arg],tp _num \{ + movzx esi, word[_arg] + tp equ 1 + \} + match =0 =byte[_arg],tp _num \{ + movzx esi, byte[_arg] + tp equ 1 + \} + match =0,tp \{ + 'Error: specified string width is incorrect' + \} + end if + else + mov esi, 0x7FFFFFFF + end if + call fdo_debug_outstr + popad + popf +} + +macro DEBUGD _sign,_dec { + local tp + tp equ 0 + match _arg:_num,_dec \{ + DEBUGD_N _sign,_num,_arg + tp equ 1 + \} + match =0 _arg,tp _dec \{ + DEBUGD_N _sign,,_arg + \} +} + +macro DEBUGD_N _sign,_num,_dec { + pushf + pushad + if (~_num eq) + if (_dec eqtype eax | _dec eqtype 0) + 'Error: precision allowed only for in-memory variables' + end if + if (~_num in <1,2,4>) + if _sign + 'Error: 1, 2 and 4 are only allowed for precision in %d' + else + 'Error: 1, 2 and 4 are only allowed for precision in %u' + end if + end if + end if + if _dec eqtype eax + if _dec in + mov eax, _dec + else if ~_dec eq eax + if _sign = 1 + movsx eax, _dec + else + movzx eax, _dec + end if + end if + else if _dec eqtype 0 + mov eax, _dec + else +; add esp,4*8+4 +esp equ esp+4*8+4 + if _num eq + mov eax, dword _dec + else if _num = 1 + if _sign = 1 + movsx eax, byte _dec + else + movzx eax, byte _dec + end if + else if _num = 2 + if _sign = 1 + movsx eax, word _dec + else + movzx eax, word _dec + end if + else + mov eax, dword _dec + end if +esp equ _esp +; sub esp,4*8+4 + end if + mov cl, _sign + call fdo_debug_outdec + popad + popf +} + +macro DEBUGH _sign,_hex { + local tp + tp equ 0 + match _arg:_num,_hex \{ + DEBUGH_N _sign,_num,_arg + tp equ 1 + \} + match =0 _arg,tp _hex \{ + DEBUGH_N _sign,,_arg + \} +} + +macro DEBUGH_N _sign,_num,_hex { + pushf + pushad + if (~_num eq) & (~_num in <1,2,3,4,5,6,7,8>) + 'Error: 1..8 are only allowed for precision in %x' + end if + if _hex eqtype eax + if _hex in + if ~_hex eq eax + mov eax, _hex + end if + mov edx, 8 + else if _hex in + if ~_hex eq ax + movzx eax, _hex + end if + if (_num eq) + mov edx, 4 + end if + else if _hex in + if ~_hex eq al + movzx eax, _hex + end if + if (_num eq) + mov edx, 2 + end if + end if + else if _hex eqtype 0 + mov eax, _hex + else +; add esp,4*8+4 +esp equ esp+4*8+4 + mov eax, dword _hex +esp equ _esp +; sub esp,4*8+4 + end if + if ~_num eq + mov edx, _num + else + if ~_hex eqtype eax + mov edx, 8 + end if + end if + call fdo_debug_outhex + popad + popf +} + +;----------------------------------------------------------------------------- + +debug_func fdo_debug_outchar +debug_beginf + pushad + movzx ebx, al + mov eax, 1 + mov ecx, sys_msg_board + call ecx ; sys_msg_board + popad + ret +debug_endf + +debug_func fdo_debug_outstr +debug_beginf + mov eax, 1 + .l1: + dec esi + js .l2 + movzx ebx, byte[edx] + or bl, bl + jz .l2 + mov ecx, sys_msg_board + call ecx ; sys_msg_board + inc edx + jmp .l1 + .l2: + ret +debug_endf + +debug_func fdo_debug_outdec +debug_beginf + or cl, cl + jz @f + or eax, eax + jns @f + neg eax + push eax + mov al, '-' + call fdo_debug_outchar + pop eax + @@: + push 10 + pop ecx + push -'0' + .l1: + xor edx, edx + div ecx + push edx + test eax, eax + jnz .l1 + .l2: + pop eax + add al, '0' + jz .l3 + call fdo_debug_outchar + jmp .l2 + .l3: + ret +debug_endf + +debug_func fdo_debug_outhex + __fdo_hexdigits db '0123456789ABCDEF' +debug_beginf + mov cl, dl + neg cl + add cl, 8 + shl cl, 2 + rol eax, cl + .l1: + rol eax, 4 + push eax + and eax, 0x0000000F + mov al, [__fdo_hexdigits+eax] + call fdo_debug_outchar + pop eax + dec edx + jnz .l1 + ret +debug_endf + +;----------------------------------------------------------------------------- + +macro DEBUGF _level,_format,[_arg] { + common + if __DEBUG__ = 1 & _level >= __DEBUG_LEVEL__ + local ..f1,f2,a1,a2,c1,c2,c3,..lbl + _debug_str_ equ __debug_str_ # a1 + a1 = 0 + c2 = 0 + c3 = 0 + f2 = 0 + repeat ..lbl-..f1 + virtual at 0 + db _format,0,0 + load c1 word from %-1 + end virtual + if c1 = '%s' + virtual at 0 + db _format,0,0 + store word 0 at %-1 + load c1 from f2-c2 + end virtual + if c1 <> 0 + DEBUGS 0,_debug_str_+f2-c2 + end if + c2 = c2 + 1 + f2 = %+1 + DEBUGF_HELPER S,a1,0,_arg + else if c1 = '%x' + virtual at 0 + db _format,0,0 + store word 0 at %-1 + load c1 from f2-c2 + end virtual + if c1 <> 0 + DEBUGS 0,_debug_str_+f2-c2 + end if + c2 = c2 + 1 + f2 = %+1 + DEBUGF_HELPER H,a1,0,_arg + else if c1 = '%d' | c1 = '%u' + local c4 + if c1 = '%d' + c4 = 1 + else + c4 = 0 + end if + virtual at 0 + db _format,0,0 + store word 0 at %-1 + load c1 from f2-c2 + end virtual + if c1 <> 0 + DEBUGS 0,_debug_str_+f2-c2 + end if + c2 = c2 + 1 + f2 = %+1 + DEBUGF_HELPER D,a1,c4,_arg + else if c1 = '\n' + c3 = c3 + 1 + end if + end repeat + virtual at 0 + db _format,0,0 + load c1 from f2-c2 + end virtual + if (c1<>0)&(f2<>..lbl-..f1-1) + DEBUGS 0,_debug_str_+f2-c2 + end if + virtual at 0 + ..f1 db _format,0 + ..lbl: + __debug_strings equ __debug_strings,_debug_str_,<_format>,..lbl-..f1-1-c2-c3 + end virtual + end if +} + +macro __include_debug_strings dummy,[_id,_fmt,_len] { + common + local c1,a1,a2 + forward + if defined _len & ~_len eq + _id: + a1 = 0 + a2 = 0 + repeat _len + virtual at 0 + db _fmt,0,0 + load c1 word from %+a2-1 + end virtual + if (c1='%s')|(c1='%x')|(c1='%d')|(c1='%u') + db 0 + a2 = a2 + 1 + else if (c1='\n') + dw $0A0D + a1 = a1 + 1 + a2 = a2 + 1 + else + db c1 and 0x0FF + end if + end repeat + db 0 + end if +} + +macro DEBUGF_HELPER _letter,_num,_sign,[_arg] { + common + local num + num = 0 + forward + if num = _num + DEBUG#_letter _sign,_arg + end if + num = num+1 + common + _num = _num+1 +} + +macro include_debug_strings { + if __DEBUG__ = 1 + match dbg_str,__debug_strings \{ + __include_debug_strings dbg_str + \} + end if +} diff --git a/kernel/trunk/fs/ext2.inc b/kernel/trunk/fs/ext2.inc index 0afc4e611..9c37d2b69 100644 --- a/kernel/trunk/fs/ext2.inc +++ b/kernel/trunk/fs/ext2.inc @@ -180,9 +180,9 @@ ext2_setup: mov esi, ebx mov edi, eax mov ecx, 512/4 - rep movsd ; copy sb to reserved mem + rep movsd ; copy sb to reserved mem mov ebx, eax - mov [ext2_data.sb],eax + mov [ext2_data.sb], eax mov eax, [ebx + EXT2_SB_STRUC.blocks_count] sub eax, [ebx + EXT2_SB_STRUC.first_data_block] @@ -238,7 +238,7 @@ ext2_setup: mov eax, EXT2_ROOT_INO call ext2_get_inode ; read root inode - jmp return_from_part_set + jmp return_from_part_set ;================================================================== ;in: eax = i_block @@ -276,8 +276,8 @@ ext2_get_inode_block: ;.get_triple_indirect_block: push eax edx ebx - mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4] - mov ebx, [ext2_data.ext2_temp_block] + mov eax, [ebx + EXT2_INODE_STRUC.i_block + 14*4] + mov ebx, [ext2_data.ext2_temp_block] call ext2_get_block xor edx, edx @@ -285,11 +285,11 @@ ext2_get_inode_block: div [ext2_data.count_pointer_in_block_square] ;eax - номер РІ полученном блоке edx - номер дальше - mov eax, [ebx + eax*4] - call ext2_get_block + mov eax, [ebx + eax*4] + call ext2_get_block - mov eax, edx - jmp @F + mov eax, edx + jmp @F .get_double_indirect_block: push eax edx ebx @@ -303,9 +303,9 @@ ext2_get_inode_block: xor edx, edx div [ext2_data.count_pointer_in_block] - mov eax, [ebx + eax*4] + mov eax, [ebx + eax*4] call ext2_get_block - mov ecx, [ebx + edx*4] + mov ecx, [ebx + edx*4] pop ebx edx eax ret @@ -330,11 +330,11 @@ ext2_get_inode_block: ; ebx = address of inode content ext2_get_inode: - pushad - mov edi, ebx ;сохраним адрес inode - dec eax - xor edx, edx - div [ext2_data.inodes_per_group] + pushad + mov edi, ebx ;сохраним адрес inode + dec eax + xor edx, edx + div [ext2_data.inodes_per_group] push edx ;locale num in group @@ -375,7 +375,7 @@ ext2_get_inode: mov esi, edx ;добавим "остаток" add esi, ebx ;Рє адресу ; mov ecx, [ext2_data.inode_size] - rep movsb ;копируем inode + rep movsb ;копируем inode popad ret @@ -387,56 +387,56 @@ ext2_get_inode: ext2_test_block_by_name: push eax ecx edx edi - mov edx, ebx - add edx, [ext2_data.block_size] ;запомним конец блока + mov edx, ebx + add edx, [ext2_data.block_size] ;запомним конец блока .start_rec: - cmp [ebx + EXT2_DIR_STRUC.inode], 0 - jz .next_rec + cmp [ebx + EXT2_DIR_STRUC.inode], 0 + jz .next_rec - push esi - movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] - mov edi, EXT2_filename - lea esi, [ebx + EXT2_DIR_STRUC.name] + push esi + movzx ecx, [ebx + EXT2_DIR_STRUC.name_len] + mov edi, EXT2_filename + lea esi, [ebx + EXT2_DIR_STRUC.name] - call utf8toansi_str - mov ecx, edi - sub ecx, EXT2_filename ;РєРѕР»-РІРѕ байт РІ получившейся строке + call utf8toansi_str + mov ecx, edi + sub ecx, EXT2_filename ;РєРѕР»-РІРѕ байт РІ получившейся строке - mov edi, EXT2_filename - mov esi, [esp] + mov edi, EXT2_filename + mov esi, [esp] @@: - jecxz .test_find - dec ecx + jecxz .test_find + dec ecx - lodsb - call char_toupper + lodsb + call char_toupper - mov ah, [edi] - inc edi - xchg al, ah - call char_toupper - cmp al, ah - je @B + mov ah, [edi] + inc edi + xchg al, ah + call char_toupper + cmp al, ah + je @B @@: ;РЅРµ подошло - pop esi + pop esi .next_rec: - movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] - add ebx, eax ;Рє след. записи - cmp ebx, edx ;проверим конец ли - jb .start_rec - jmp .ret + movzx eax, [ebx + EXT2_DIR_STRUC.rec_len] + add ebx, eax ;Рє след. записи + cmp ebx, edx ;проверим конец ли + jb .start_rec + jmp .ret .test_find: cmp byte [esi], 0 je .find ;нашли конец cmp byte [esi], '/' - jne @B + jne @B inc esi .find: - pop eax ;удаляем РёР· стека сохраненое значение + pop eax ;удаляем РёР· стека сохраненое значение .ret: - pop edi edx ecx eax + pop edi edx ecx eax ret ;---------------------------------------------------------------- @@ -480,7 +480,7 @@ ext2_HdReadFolder: xor eax, eax mov edi, edx mov ecx, 32/4 - rep stosd ; fill header zero + rep stosd ; fill header zero pop edi ; edi = число блоков для чтения push edx ebx @@ -510,31 +510,31 @@ ext2_HdReadFolder: mov ecx, [ecx] ; ecx = first wanted (flags ommited) .find_wanted_start: - jecxz .find_wanted_end + jecxz .find_wanted_end .find_wanted_cycle: - cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used - jz @F - inc [EXT2_files_in_folder] - dec ecx + cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used + jz @F + inc [EXT2_files_in_folder] + dec ecx @@: - movzx ebx, [eax+EXT2_DIR_STRUC.rec_len] + movzx ebx, [eax+EXT2_DIR_STRUC.rec_len] - cmp ebx, 12 ; минимальная длина записи - jb .end_error - test ebx, 0x3 ; длина записи должна делиться РЅР° 4 - jnz .end_error + cmp ebx, 12 ; минимальная длина записи + jb .end_error + test ebx, 0x3 ; длина записи должна делиться РЅР° 4 + jnz .end_error - add eax, ebx ; Рє следующей записи - cmp eax, [EXT2_end_block] ; проверяем "конец" - jb .find_wanted_start + add eax, ebx ; Рє следующей записи + cmp eax, [EXT2_end_block] ; проверяем "конец" + jb .find_wanted_start push .find_wanted_start - .end_block: ;вылетили РёР· цикла + .end_block: ;вылетили РёР· цикла mov ebx, [ext2_data.count_block_in_block] sub [EXT2_counter_blocks], ebx - jbe .end_dir + jbe .end_dir - inc esi ;получаем новый блок + inc esi ;получаем новый блок push ecx mov ecx, esi call ext2_get_inode_block @@ -545,99 +545,99 @@ ext2_HdReadFolder: mov eax, ebx add ebx, [ext2_data.block_size] mov [EXT2_end_block], ebx - ret ; опять РІ цикл + ret ; опять РІ цикл .wanted_end: - loop .find_wanted_cycle ; ecx = -1 + loop .find_wanted_cycle ; ecx = -1 .find_wanted_end: mov ecx, edi .wanted_start: ; ищем first_wanted+count - jecxz .wanted_end - cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used - jz .empty_rec - inc [EXT2_files_in_folder] - inc [EXT2_read_in_folder] + jecxz .wanted_end + cmp [eax + EXT2_DIR_STRUC.inode], 0 ; if (inode = 0) => not used + jz .empty_rec + inc [EXT2_files_in_folder] + inc [EXT2_read_in_folder] - mov edi, edx - push eax ecx - xor eax, eax - mov ecx, 40 / 4 - rep stosd - pop ecx eax + mov edi, edx + push eax ecx + xor eax, eax + mov ecx, 40 / 4 + rep stosd + pop ecx eax - push eax esi edx ;получим inode - mov eax, [eax + EXT2_DIR_STRUC.inode] - mov ebx, [ext2_data.ext2_temp_inode] - call ext2_get_inode + push eax esi edx ;получим inode + mov eax, [eax + EXT2_DIR_STRUC.inode] + mov ebx, [ext2_data.ext2_temp_inode] + call ext2_get_inode - lea edi, [edx + 8] + lea edi, [edx + 8] - mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; переведем время РІ ntfs формат - xor edx, edx - add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec + mov eax, [ebx + EXT2_INODE_STRUC.i_ctime] ; переведем время РІ ntfs формат + xor edx, edx + add eax, 3054539008 ;(369 * 365 + 89) * 24 * 3600 + adc edx, 2 + call ntfs_datetime_to_bdfe.sec - mov eax, [ebx + EXT2_INODE_STRUC.i_atime] - xor edx, edx - add eax, 3054539008 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec + mov eax, [ebx + EXT2_INODE_STRUC.i_atime] + xor edx, edx + add eax, 3054539008 + adc edx, 2 + call ntfs_datetime_to_bdfe.sec - mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] - xor edx, edx - add eax, 3054539008 - adc edx, 2 - call ntfs_datetime_to_bdfe.sec + mov eax, [ebx + EXT2_INODE_STRUC.i_mtime] + xor edx, edx + add eax, 3054539008 + adc edx, 2 + call ntfs_datetime_to_bdfe.sec - pop edx ; РїРѕРєР° достаем только буфер - test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; для папки размер - jnz @F ; РЅРµ возвращаем + pop edx ; РїРѕРєР° достаем только буфер + test [ebx + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR ; для папки размер + jnz @F ; РЅРµ возвращаем - mov eax, [ebx + EXT2_INODE_STRUC.i_size] ;low size - stosd - mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size - stosd - xor dword [edx], FS_FT_DIR + mov eax, [ebx + EXT2_INODE_STRUC.i_size] ;low size + stosd + mov eax, [ebx + EXT2_INODE_STRUC.i_dir_acl] ;high size + stosd + xor dword [edx], FS_FT_DIR @@: - xor dword [edx], FS_FT_DIR - pop esi eax + xor dword [edx], FS_FT_DIR + pop esi eax - or dword [edx+4], FS_FT_ASCII ; symbol type in name + or dword [edx+4], FS_FT_ASCII ; symbol type in name ;теперь скопируем РёРјСЏ, сконвертировав РёР· UTF-8 РІ CP866 - push eax ecx esi - movzx ecx, [eax + EXT2_DIR_STRUC.name_len] - lea edi, [edx + 40] - lea esi, [eax + EXT2_DIR_STRUC.name] - call utf8toansi_str - pop esi ecx eax - and byte [edi], 0 + push eax ecx esi + movzx ecx, [eax + EXT2_DIR_STRUC.name_len] + lea edi, [edx + 40] + lea esi, [eax + EXT2_DIR_STRUC.name] + call utf8toansi_str + pop esi ecx eax + and byte [edi], 0 - cmp byte [edx + 40], '.' - jne @F - or dword [edx], FS_FT_HIDDEN + cmp byte [edx + 40], '.' + jne @F + or dword [edx], FS_FT_HIDDEN @@: - add edx, 40 + 264 ; go to next record - dec ecx ; если запись пустая ecx РЅРµ надо уменьшать + add edx, 40 + 264 ; go to next record + dec ecx ; если запись пустая ecx РЅРµ надо уменьшать .empty_rec: - movzx ebx, [eax + EXT2_DIR_STRUC.rec_len] - cmp ebx, 12 ; минимальная длина записи - jb .end_error - test ebx, 0x3 ; длина записи должна делиться РЅР° 4 - jnz .end_error + movzx ebx, [eax + EXT2_DIR_STRUC.rec_len] + cmp ebx, 12 ; минимальная длина записи + jb .end_error + test ebx, 0x3 ; длина записи должна делиться РЅР° 4 + jnz .end_error - add eax, ebx - cmp eax, [EXT2_end_block] - jb .wanted_start + add eax, ebx + cmp eax, [EXT2_end_block] + jb .wanted_start push .wanted_start ; дошли РґРѕ конца очередного блока jmp .end_block .end_dir: - pop eax ; РјСѓСЃРѕСЂ (адрес возврата РІ цикл) + pop eax ; РјСѓСЃРѕСЂ (адрес возврата РІ цикл) .end_error: pop edx mov ebx, [EXT2_read_in_folder] @@ -648,17 +648,17 @@ ext2_HdReadFolder: mov [edx+8], ecx lea edi, [edx + 12] mov ecx, 20 / 4 - rep stosd + rep stosd ret ;====================== end ext2_HdReadFolder utf8toansi_str: -; convert UTF-8 string to ASCII-string (codepage 866) -; in: ecx=length source, esi->source, edi->buffer +; convert UTF-8 string to ASCII-string (codepage 866) +; in: ecx=length source, esi->source, edi->buffer ; destroys: eax,esi,edi jecxz .ret .start: lodsw - cmp al, 0x80 + cmp al, 0x80 jb .ascii xchg al, ah ; big-endian @@ -667,10 +667,10 @@ utf8toansi_str: cmp ax, 0xd191 jz .yo2 cmp ax, 0xd090 - jb .unk - cmp ax, 0xd180 - jb .rus1 - cmp ax, 0xd190 + jb .unk + cmp ax, 0xd180 + jb .rus1 + cmp ax, 0xd190 jb .rus2 .unk: mov al, '_' @@ -700,19 +700,19 @@ utf8toansi_str: .ret: ret -;---------------------------------------------------------------- -; -; ext2_HdRead - read hard disk -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to read, 0+ -; edx mem location to return data -; -; ret ebx = bytes read or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; +;---------------------------------------------------------------- +; +; ext2_HdRead - read hard disk +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to read, 0+ +; edx mem location to return data +; +; ret ebx = bytes read or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; ;-------------------------------------------------------------- ext2_HdRead: cmp byte [esi], 0 @@ -797,7 +797,7 @@ ext2_HdRead: add ebx, edx neg edx - add edx,[ext2_data.block_size] ;block_size - стартовый байт = сколько байт 1-РіРѕ блока + add edx, [ext2_data.block_size] ;block_size - стартовый байт = сколько байт 1-РіРѕ блока cmp ecx, edx jbe .only_one_block @@ -806,7 +806,7 @@ ext2_HdRead: mov ecx, edx mov esi, ebx - rep movsb ;РєСѓСЃРѕРє 1-РіРѕ блока + rep movsb ;РєСѓСЃРѕРє 1-РіРѕ блока jmp @F .zero_start: @@ -818,7 +818,7 @@ ext2_HdRead: div [ext2_data.block_size] ;РєРѕР»-РІРѕ байт РІ последнем блоке (остаток) РІ edx mov edi, eax ;РєРѕР»-РІРѕ целых блоков РІ edi @@: - test edi, edi + test edi, edi jz .finish_block inc [EXT2_counter_blocks] mov ecx, [EXT2_counter_blocks] @@ -848,7 +848,7 @@ ext2_HdRead: .only_one_block: mov esi, ebx - rep movsb ;РєСѓСЃРѕРє last блока + rep movsb ;РєСѓСЃРѕРє last блока .end_read: pop ebx cmp [EXT2_files_in_folder], 0 @@ -887,7 +887,7 @@ ext2_find_lfn: cmp eax, esi ;нашли РёРјСЏ? jz .next_block_folder - cmp byte [esi],0 + cmp byte [esi], 0 jz .get_inode_ret cmp [ebx + EXT2_DIR_STRUC.file_type], EXT2_FT_DIR @@ -934,7 +934,7 @@ ext2_HdGetFileInfo: xor eax, eax mov edi, edx mov ecx, 40/4 - rep stosd ; fill zero + rep stosd ; fill zero cmp byte [ebx], '.' jnz @F @@ -942,7 +942,7 @@ ext2_HdGetFileInfo: @@: test [ebp + EXT2_INODE_STRUC.i_mode], EXT2_S_IFDIR - jnz @F + jnz @F mov eax, [ebp + EXT2_INODE_STRUC.i_size] ;low size mov ebx, [ebp + EXT2_INODE_STRUC.i_dir_acl] ;high size mov dword [edx+32], eax @@ -982,14 +982,14 @@ ext2_HdCreateFolder: xor ebx, ebx mov eax, ERROR_UNSUPPORTED_FS ret -;---------------------------------------------------------------- -; -; ext2_HdCreateFolder - create new folder -; -; esi points to filename -; -; ret eax = 0 ok read or other = errormsg -; +;---------------------------------------------------------------- +; +; ext2_HdCreateFolder - create new folder +; +; esi points to filename +; +; ret eax = 0 ok read or other = errormsg +; ;-------------------------------------------------------------- cmp byte [esi], 0 jz .not_found @@ -1031,7 +1031,7 @@ ext2_HdCreateFolder: dec ecx ;выкинули '/' РёР· имени ролителя mov esi, ebx mov edi, EXT2_parent_name - rep movsb + rep movsb ; esi - pointer to last slash mov edx, esi @@ -1064,7 +1064,7 @@ ext2_HdCreateFolder: push ebp mov ecx, [ext2_data.sb] - cmp [ecx + EXT2_SB_STRUC.free_inodes_count],0 ; есть ли место для inode + cmp [ecx + EXT2_SB_STRUC.free_inodes_count], 0 ; есть ли место для inode jz .no_space mov eax, [ecx + EXT2_SB_STRUC.free_block_count] sub eax, [ecx + EXT2_SB_STRUC.r_block_count] @@ -1103,7 +1103,7 @@ ext2_HdCreateFolder: shr ecx, 5 ;делим РЅР° 32 mov ebp, ecx ; всего сохраним РІ ebp or eax, -1 ; ищем первый свободный inode (!= -1) - repne scasd + repne scasd jnz .test_last_dword ;нашли или нет mov eax, [esi-4] @@ -1152,7 +1152,7 @@ ext2_HdCreateFolder: mov ecx, [ext2_data.inode_size] shr ecx, 2 xor eax, eax - rep stosd + rep stosd mov edi, edx mov eax, EXT2_S_IFDIR or EXT2_777_MODE @@ -1226,8 +1226,8 @@ ext2_balloc: shr ecx, 5 ;делим РЅР° 32 mov ebp, ecx ;всего сохраним РІ ebp or eax, -1 ;ищем первый свободный inode (!= -1) - repe scasd - jz .test_last_dword ;нашли или нет + repe scasd + jz .test_last_dword ;нашли или нет mov eax, [edi-4] sub ebp, ecx diff --git a/kernel/trunk/fs/fat12.inc b/kernel/trunk/fs/fat12.inc index 52cec3ff3..20929530a 100644 --- a/kernel/trunk/fs/fat12.inc +++ b/kernel/trunk/fs/fat12.inc @@ -1,2272 +1,2272 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; FAT12.INC ;; -;; (C) 2005 Mario79, License: GPL ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -n_sector dd 0 ; temporary save for sector value -flp_status dd 0 -clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write -path_pointer_flp dd 0 -pointer_file_name_flp dd 0 -save_root_flag db 0 -save_flag db 0 -root_read db 0 ; 0-necessary to load root, 1-not to load root -flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat -flp_number db 0 ; 1- Floppy A, 2-Floppy B -old_track db 0 ; old value track -flp_label rb 15 ; Label and ID of inserted floppy disk - -reserve_flp: - - cli - cmp [flp_status],0 - je reserve_flp_ok - - sti - call change_task - jmp reserve_flp - - reserve_flp_ok: - - push eax - mov eax,[CURRENT_TASK] - shl eax,5 - mov eax,[eax+CURRENT_TASK+TASKDATA.pid] - mov [flp_status],eax - pop eax - sti - ret - - -floppy_fileread: -;---------------------------------------------------------------- -; -; fileread - sys floppy -; -; eax points to filename 11 chars - for root directory -; ebx first wanted block ; 1+ ; if 0 then set to 1 -; ecx number of blocks to read ; 1+ ; if 0 then set to 1 -; edx mem location to return data -; esi length of filename 12*X -; edi pointer to path /fd/1/...... - for all files in nested directories -; -; ret ebx = size or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; 10 = access denied -;-------------------------------------------------------------- - - mov [save_flag],0 - mov [path_pointer_flp],edi - test esi,esi ; return ramdisk root - jnz fr_noroot_1 - cmp ebx,224/16 - jbe fr_do_1 - mov eax,5 - xor ebx,ebx - mov [flp_status],ebx - ret - -fr_do_1: - push ebx ecx edx - call read_flp_root - pop edx ecx ebx - cmp [FDC_Status],0 - jne fdc_status_error_1 - mov edi,edx - dec ebx - shl ebx,9 - mov esi,FLOPPY_BUFF - add esi,ebx - shl ecx,9 - cld - rep movsb - xor eax,eax - xor ebx,ebx -; mov eax,0 ; ok read -; mov ebx,0 - mov [flp_status],eax - ret -fdc_status_error_1: - xor eax,eax - mov [flp_status],eax - mov eax,10 - or ebx,-1 - ret - -fr_noroot_1: - sub esp,32 - call expand_filename -frfloppy_1: - test ebx,ebx - jnz frfl5_1 - mov ebx,1 -frfl5_1: - test ecx,ecx - jnz frfl6_1 - mov ecx,1 -frfl6_1: - dec ebx - push eax - push eax ebx ecx edx esi edi - call read_flp_fat - cmp [FDC_Status],0 - jne fdc_status_error_3_1 - mov [FDD_Track],0 ; Цилиндр - mov [FDD_Head],1 ; Сторона - mov [FDD_Sector],2 ; Сектор - call SeekTrack - mov dh,14 -l.20_1: - call ReadSectWithRetr - cmp [FDC_Status],0 - jne fdc_status_error_3_1 - mov dl,16 - mov edi,FDD_BUFF - inc [FDD_Sector] -l.21_1: - mov esi,eax ;Name of file we want - mov ecx,11 - cld - rep cmpsb ;Found the file? - je fifound_1 ;Yes - add ecx,21 - add edi, ecx ;Advance to next entry - dec dl - test dl,dl - jnz l.21_1 - dec dh - test dh,dh - jnz l.20_1 -fdc_status_error_3: - mov eax,5 ; file not found ? - or ebx,-1 - add esp,32+28 - mov [flp_status],0 - ret -fdc_status_error_3_2: - cmp [FDC_Status],0 - je fdc_status_error_3 -fdc_status_error_3_1: - add esp,32+28 - jmp fdc_status_error_1 - -fifound_1: - mov eax,[path_pointer_flp] - cmp [eax+36],byte 0 - je fifound_2 - add edi,0xf - mov eax,[edi] - and eax,65535 - mov ebx,[path_pointer_flp] - add ebx,36 - call get_cluster_of_a_path_flp - jc fdc_status_error_3_2 - mov ebx,[ebx-11+28] ;file size - mov [esp+20],ebx - mov [esp+24],ebx - jmp fifound_3 -fifound_2: - mov ebx,[edi-11+28] ;file size - mov [esp+20],ebx - mov [esp+24],ebx - add edi,0xf - mov eax,[edi] -fifound_3: - and eax,65535 - mov [n_sector],eax ;eax=cluster -frnew_1: - add eax,31 ;bootsector+2*fat+filenames - cmp [esp+16],dword 0 ; wanted cluster ? - jne frfl7_1 - call read_chs_sector - cmp [FDC_Status],0 - jne fdc_status_error_5 - mov edi,[esp+8] - call give_back_application_data_1 - add [esp+8],dword 512 - dec dword [esp+12] ; last wanted cluster ? - cmp [esp+12],dword 0 - je frnoread_1 - jmp frfl8_1 -frfl7_1: - dec dword [esp+16] -frfl8_1: - mov edi,[n_sector] - shl edi,1 ;find next cluster from FAT - add edi,FLOPPY_FAT - mov eax,[edi] - and eax,4095 - mov edi,eax - mov [n_sector],edi - cmp edi,4095 ;eof - cluster - jz frnoread2_1 - cmp [esp+24],dword 512 ;eof - size - jb frnoread_1 - sub [esp+24],dword 512 - jmp frnew_1 - -read_chs_sector: - call calculate_chs - call ReadSectWithRetr - ret - -frnoread2_1: - cmp [esp+16],dword 0 ; eof without read ? - je frnoread_1 - mov [fdc_irq_func],fdc_null - pop edi esi edx ecx - add esp,4 - pop ebx ; ebx <- eax : size of file - add esp,36 - mov eax,6 ; end of file - mov [flp_status],0 - ret - -frnoread_1: - pop edi esi edx ecx - add esp,4 - pop ebx ; ebx <- eax : size of file - add esp,36 - xor eax,eax - mov [flp_status],eax - ret - -fdc_status_error_5: - pop edi esi edx ecx - add esp,4 - pop ebx ; ebx <- eax : size of file - add esp,36 - jmp fdc_status_error_1 - -read_flp_root: - pusha - call check_label - cmp [FDC_Status],0 - jne unnecessary_root_read - cmp [root_read],1 - je unnecessary_root_read - mov [FDD_Track],0 ; Цилиндр - mov [FDD_Head],1 ; Сторона - mov [FDD_Sector],2 ; Сектор - mov edi,FLOPPY_BUFF - call SeekTrack -read_flp_root_1: - call ReadSectWithRetr - cmp [FDC_Status],0 - jne unnecessary_root_read - push edi - call give_back_application_data_1 - pop edi - add edi,512 - inc [FDD_Sector] - cmp [FDD_Sector],16 - jne read_flp_root_1 - mov [root_read],1 -unnecessary_root_read: - popa - ret - - -read_flp_fat: - pusha - call check_label - cmp [FDC_Status],0 - jne unnecessary_flp_fat - cmp [flp_fat],1 - je unnecessary_flp_fat - mov [FDD_Track],0 ; Цилиндр - mov [FDD_Head],0 ; Сторона - mov [FDD_Sector],2 ; Сектор - mov edi,FLOPPY_BUFF - call SeekTrack -read_flp_fat_1: - call ReadSectWithRetr - cmp [FDC_Status],0 - jne unnecessary_flp_fat - push edi - call give_back_application_data_1 - pop edi - add edi,512 - inc [FDD_Sector] - cmp [FDD_Sector],19 - jne read_flp_fat_1 - mov [FDD_Sector],1 - mov [FDD_Head],1 - call ReadSectWithRetr - cmp [FDC_Status],0 - jne unnecessary_flp_fat - call give_back_application_data_1 - call calculatefatchain_flp - mov [root_read],0 - mov [flp_fat],1 -unnecessary_flp_fat: - popa - ret - -calculatefatchain_flp: - pushad - - mov esi,FLOPPY_BUFF - mov edi,FLOPPY_FAT - - fcnew_1: - mov eax,dword [esi] - mov ebx,dword [esi+4] - mov ecx,dword [esi+8] - mov edx,ecx - shr edx,4 ;8 ok - shr dx,4 ;7 ok - xor ch,ch - shld ecx,ebx,20 ;6 ok - shr cx,4 ;5 ok - shld ebx,eax,12 - and ebx,0x0fffffff ;4 ok - shr bx,4 ;3 ok - shl eax,4 - and eax,0x0fffffff ;2 ok - shr ax,4 ;1 ok - mov dword [edi],eax - add edi,4 - mov dword [edi],ebx - add edi,4 - mov dword [edi],ecx - add edi,4 - mov dword [edi],edx - add edi,4 - add esi,12 - - cmp edi,FLOPPY_FAT+2856*2 ;2849 clusters - jnz fcnew_1 - - popad - ret - -check_label: - pushad - mov [FDD_Track],0 ; Цилиндр - mov [FDD_Head],0 ; Сторона - mov [FDD_Sector],1 ; Сектор - call SetUserInterrupts - call FDDMotorON - call RecalibrateFDD - cmp [FDC_Status],0 - jne fdc_status_error - call SeekTrack - cmp [FDC_Status],0 - jne fdc_status_error - call ReadSectWithRetr - cmp [FDC_Status],0 - jne fdc_status_error - mov esi,flp_label - mov edi,FDD_BUFF+39 - mov ecx,15 - cld - rep cmpsb - je same_label - mov [root_read],0 - mov [flp_fat],0 -same_label: - mov esi,FDD_BUFF+39 - mov edi,flp_label - mov ecx,15 - cld - rep movsb - popad - ret -fdc_status_error: - popad - ret - -save_flp_root: - pusha - call check_label - cmp [FDC_Status],0 - jne unnecessary_root_save - cmp [root_read],0 - je unnecessary_root_save - mov [FDD_Track],0 ; Цилиндр - mov [FDD_Head],1 ; Сторона - mov [FDD_Sector],2 ; Сектор - mov esi,FLOPPY_BUFF - call SeekTrack -save_flp_root_1: - push esi - call take_data_from_application_1 - pop esi - add esi,512 - call WriteSectWithRetr - cmp [FDC_Status],0 - jne unnecessary_root_save - inc [FDD_Sector] - cmp [FDD_Sector],16 - jne save_flp_root_1 -unnecessary_root_save: - mov [fdc_irq_func],fdc_null - popa - ret - -save_flp_fat: - pusha - call check_label - cmp [FDC_Status],0 - jne unnecessary_flp_fat_save - cmp [flp_fat],0 - je unnecessary_flp_fat_save - call restorefatchain_flp - mov [FDD_Track],0 ; Цилиндр - mov [FDD_Head],0 ; Сторона - mov [FDD_Sector],2 ; Сектор - mov esi,FLOPPY_BUFF - call SeekTrack -save_flp_fat_1: - push esi - call take_data_from_application_1 - pop esi - add esi,512 - call WriteSectWithRetr - cmp [FDC_Status],0 - jne unnecessary_flp_fat_save - inc [FDD_Sector] - cmp [FDD_Sector],19 - jne save_flp_fat_1 - mov [FDD_Sector],1 - mov [FDD_Head],1 - call take_data_from_application_1 - call WriteSectWithRetr - cmp [FDC_Status],0 - jne unnecessary_flp_fat_save - mov [root_read],0 -unnecessary_flp_fat_save: - mov [fdc_irq_func],fdc_null - popa - ret - - -restorefatchain_flp: ; restore fat chain - pushad - - mov esi,FLOPPY_FAT - mov edi,FLOPPY_BUFF - - fcnew2_1: - mov eax,dword [esi] - mov ebx,dword [esi+4] - shl ax,4 - shl eax,4 - shl bx,4 - shr ebx,4 - shrd eax,ebx,8 - shr ebx,8 - mov dword [edi],eax - add edi,4 - mov word [edi],bx - add edi,2 - add esi,8 - - cmp edi,FLOPPY_BUFF+0x1200 ;4274 bytes - all used FAT - jb fcnew2_1 - - mov esi,FLOPPY_BUFF ; duplicate fat chain - mov edi,FLOPPY_BUFF+0x1200 - mov ecx,0x1200/4 - cld - rep movsd - - popad - ret - - -save_chs_sector: - call calculate_chs - call WriteSectWithRetr - ret - -calculate_chs: - mov bl,[FDD_Track] - mov [old_track],bl - mov ebx,18 - xor edx,edx - div ebx - inc edx - mov [FDD_Sector],dl - xor edx,edx - mov ebx,2 - div ebx - mov [FDD_Track],al - mov [FDD_Head],0 - test edx,edx - jz no_head_2 - inc [FDD_Head] -no_head_2: - mov dl,[old_track] - cmp dl,[FDD_Track] - je no_seek_track_1 - call SeekTrack -no_seek_track_1: - ret - - -get_cluster_of_a_path_flp: -;--------------------------------------------------------- -; input : EBX = pointer to a path string -; (example: the path "/files/data/document" become -; "files......data.......document...0" -; '.' = space char -; '0' = char(0) (ASCII=0) !!! ) -; output : if (CARRY=1) -> ERROR in the PATH -; if (CARRY=0) -> EAX=cluster -;--------------------------------------------------------- - - push edx - mov edx,ebx - -search_end_of_path_flp: - cmp [save_flag],0 - jne search_end_of_path_flp_1 - cmp byte [edx],0 - je found_end_of_path_flp - jmp search_end_of_path_flp_2 -search_end_of_path_flp_1: - cmp byte [edx+12],0 - je found_end_of_path_flp -search_end_of_path_flp_2: - inc edx ; '/' - call analyze_directory_flp - jc directory_not_found_flp - - mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field - mov ax,[ebx+26] ; read the LOW 16bit cluster field - and eax,0xfff ;[fatMASK] - add edx,11 ; 8+3 (name+extension) - jmp search_end_of_path_flp - -found_end_of_path_flp: - inc edx - mov [pointer_file_name_flp],edx - pop edx - clc ; no errors - ret - -directory_not_found_flp: - pop edx - stc ; errors occour - ret - -analyze_directory_flp: -;-------------------------------- -; input : EAX = first cluster of the directory -; EBX = pointer to filename -; output : IF CARRY=0 EAX = sector where th file is found -; EBX = pointer in buffer -; [buffer .. buffer+511] -; ECX,EDX,EDI,EDI not changed -; IF CARRY=1 -;-------------------------------- - push ebx ;[esp+16] - push ecx - push edx - push esi - push edi - - -adr56_flp: - mov [clust_tmp_flp],eax - add eax,31 - pusha - call read_chs_sector - popa - cmp [FDC_Status],0 - jne not_found_file_analyze_flp - - mov ecx,512/32 - mov ebx,FDD_BUFF - -adr1_analyze_flp: - mov esi,edx ;[esp+16] - mov edi,ebx - cld - push ecx - mov ecx,11 - rep cmpsb - pop ecx - je found_file_analyze_flp - - add ebx,32 - loop adr1_analyze_flp - - mov eax,[clust_tmp_flp] - shl eax,1 ;find next cluster from FAT - add eax,FLOPPY_FAT - mov eax,[eax] - and eax,4095 - cmp eax,0x0ff8 - jb adr56_flp -not_found_file_analyze_flp: - pop edi - pop esi - pop edx - pop ecx - add esp,4 - stc ;file not found - ret - -found_file_analyze_flp: - pop edi - pop esi - pop edx - pop ecx - add esp,4 - clc ;file found - ret - - -; \begin{diamond} -fat_find_lfn: -; in: esi->name -; [esp+4] = next -; [esp+8] = first -; [esp+C]... - possibly parameters for first and next -; out: CF=1 - file not found -; else CF=0, esi->next name component, edi->direntry - pusha - lea eax, [esp+0Ch+20h] - call dword [eax-4] - jc .reterr - sub esp, 262*2 ; reserve place for LFN - mov ebp, esp - push 0 ; for fat_get_name: read ASCII name -.l1: - call fat_get_name - jc .l2 - call fat_compare_name - jz .found -.l2: - lea eax, [esp+0Ch+20h+262*2+4] - call dword [eax-8] - jnc .l1 - add esp, 262*2+4 -.reterr: - stc - popa - ret -.found: - add esp, 262*2+4 -; if this is LFN entry, advance to true entry - cmp byte [edi+11], 0xF - jnz @f - lea eax, [esp+0Ch+20h] - call dword [eax-8] - jc .reterr -@@: - add esp, 8 ; CF=0 - push esi - push edi - popa - ret - -uglobal -; this is for delete support -fd_prev_sector dd ? -fd_prev_prev_sector dd ? -endg - -flp_root_next: - cmp edi, OS_BASE+0xD200-0x20 - jae @f - add edi, 0x20 - ret ; CF=0 -@@: -; read next sector - inc dword [eax] - cmp dword [eax], 14 - jae flp_root_first.readerr - push [fd_prev_sector] - pop [fd_prev_prev_sector] - push eax - mov eax, [eax] - add eax, 19-1 - mov [fd_prev_sector], eax - pop eax -flp_root_first: - mov eax, [eax] - pusha - add eax, 19 - call read_chs_sector - popa - cmp [FDC_Status], 0 - jnz .readerr - mov edi, FDD_BUFF - ret ; CF=0 -.readerr: - stc - ret - -flp_rootmem_first: - mov edi, FLOPPY_BUFF - clc - ret -flp_rootmem_next: - add edi, 0x20 - cmp edi, FLOPPY_BUFF+14*0x200 - cmc -flp_rootmem_next_write: -flp_rootmem_begin_write: -flp_rootmem_end_write: - ret -flp_rootmem_extend_dir: - stc - ret - -flp_notroot_next: - cmp edi, OS_BASE+0xD200-0x20 - jae flp_notroot_next_sector - add edi, 0x20 - ret ; CF=0 -flp_notroot_next_sector: - push ecx - mov ecx, [eax] - push [fd_prev_sector] - pop [fd_prev_prev_sector] - add ecx, 31 - mov [fd_prev_sector], ecx - mov ecx, [(ecx-31)*2+FLOPPY_FAT] - and ecx, 0xFFF - cmp ecx, 2849 - jae flp_notroot_first.err2 - mov [eax], ecx - pop ecx -flp_notroot_first: - mov eax, [eax] - cmp eax, 2 - jb .err - cmp eax, 2849 - jae .err - pusha - add eax, 31 - call read_chs_sector - popa - mov edi, FDD_BUFF - cmp [FDC_Status], 0 - jnz .err - ret ; CF=0 -.err2: - pop ecx -.err: - stc - ret -flp_notroot_begin_write: - pusha - mov eax, [eax] - add eax, 31 - call read_chs_sector - popa - ret -flp_notroot_end_write: - pusha - mov eax, [eax] - add eax, 31 - call save_chs_sector - popa - ret -flp_notroot_next_write: - cmp edi, OS_BASE+0xD200 - jae @f - ret -@@: - call flp_notroot_end_write - jmp flp_notroot_next_sector -flp_notroot_extend_dir: -; find free cluster in FAT - pusha - xor eax, eax - mov edi, FLOPPY_FAT - mov ecx, 2849 - repnz scasw - jnz .notfound - mov word [edi-2], 0xFFF ; mark as last cluster - sub edi, FLOPPY_FAT - shr edi, 1 - dec edi - mov eax, [esp+28] - mov ecx, [eax] - mov [FLOPPY_FAT+ecx*2], di - mov [eax], edi - xor eax, eax - mov edi, FDD_BUFF - mov ecx, 128 - rep stosd - popa - call flp_notroot_end_write - mov edi, FDD_BUFF - clc - ret -.notfound: - popa - stc - ret - -fd_find_lfn: -; in: esi+ebp -> name -; out: CF=1 - file not found -; else CF=0 and edi->direntry, eax=directory cluster (0 for root) - push esi edi - push 0 - push flp_root_first - push flp_root_next -.loop: - call fat_find_lfn - jc .notfound - cmp byte [esi], 0 - jz .found -.continue: - test byte [edi+11], 10h - jz .notfound - movzx eax, word [edi+26] ; cluster - mov [esp+8], eax - mov dword [esp+4], flp_notroot_first - mov dword [esp], flp_notroot_next - jmp .loop -.notfound: - add esp, 12 - pop edi esi - stc - ret -.found: - test ebp, ebp - jz @f - mov esi, ebp - xor ebp, ebp - jmp .continue -@@: - mov eax, [esp+8] - add eax, 31 - cmp dword [esp], flp_root_next - jnz @f - add eax, -31+19 -@@: - add esp, 16 ; CF=0 - pop esi - ret - -;---------------------------------------------------------------- -; -; fs_FloppyRead - LFN variant for reading floppy -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to read, 0+ -; edx mem location to return data -; -; ret ebx = bytes read or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_FloppyRead: - call read_flp_fat - cmp byte [esi], 0 - jnz @f - or ebx, -1 - mov eax, 10 ; access denied - ret -@@: - push edi - call fd_find_lfn - jnc .found - pop edi - or ebx, -1 - mov eax, 5 ; file not found - ret -.found: - test ebx, ebx - jz .l1 - cmp dword [ebx+4], 0 - jz @f - xor ebx, ebx -.reteof: - mov eax, 6 ; EOF - pop edi - ret -@@: - mov ebx, [ebx] -.l1: - push ecx edx - push 0 - mov eax, [edi+28] - sub eax, ebx - jb .eof - cmp eax, ecx - jae @f - mov ecx, eax - mov byte [esp], 6 ; EOF -@@: - movzx edi, word [edi+26] -.new: - jecxz .done - test edi, edi - jz .eof - cmp edi, 0xFF8 - jae .eof - sub ebx, 512 - jae .skip - lea eax, [edi+31] - pusha - call read_chs_sector - popa - cmp [FDC_Status], 0 - jnz .err - lea eax, [FDD_BUFF+ebx+512] - neg ebx - push ecx - cmp ecx, ebx - jbe @f - mov ecx, ebx -@@: - mov ebx, edx - call memmove - add edx, ecx - sub [esp], ecx - pop ecx - xor ebx, ebx -.skip: - movzx edi, word [edi*2+FLOPPY_FAT] - jmp .new -.done: - mov ebx, edx - pop eax edx ecx edi - sub ebx, edx - ret -.eof: - mov ebx, edx - pop eax edx ecx - jmp .reteof -.err: - mov ebx, edx - pop eax edx ecx edi - sub ebx, edx - mov al, 11 - ret - -;---------------------------------------------------------------- -; -; fs_FloppyReadFolder - LFN variant for reading floppy folders -; -; esi points to filename -; ebx pointer to structure: 32-bit number = first wanted block, 0+ -; & flags (bitfields) -; flags: bit 0: 0=ANSI names, 1=UNICODE names -; ecx number of blocks to read, 0+ -; edx mem location to return data -; -; ret ebx = blocks read or 0xffffffff folder not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_FloppyReadFolder: - call read_flp_fat - push edi - cmp byte [esi], 0 - jz .root - call fd_find_lfn - jnc .found - pop edi - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret -.found: - test byte [edi+11], 0x10 ; do not allow read files - jnz .found_dir - pop edi - or ebx, -1 - mov eax, ERROR_ACCESS_DENIED - ret -.found_dir: - movzx eax, word [edi+26] - add eax, 31 - push 0 - jmp .doit -.root: - mov eax, 19 - push 14 -.doit: - push ecx ebp - sub esp, 262*2 ; reserve space for LFN - mov ebp, esp - push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names - mov ebx, [ebx] -; init header - push eax ecx - mov edi, edx - mov ecx, 32/4 - xor eax, eax - rep stosd - pop ecx eax - mov byte [edx], 1 ; version - mov esi, edi ; esi points to BDFE -.main_loop: - pusha - call read_chs_sector - popa - cmp [FDC_Status], 0 - jnz .error - mov edi, FDD_BUFF - push eax -.l1: - call fat_get_name - jc .l2 - cmp byte [edi+11], 0xF - jnz .do_bdfe - add edi, 0x20 - cmp edi, OS_BASE+0xD200 - jb .do_bdfe - pop eax - inc eax - dec byte [esp+262*2+12] - jz .done - jns @f -; read next sector from FAT - mov eax, [(eax-31-1)*2+FLOPPY_FAT] - and eax, 0xFFF - cmp eax, 0xFF8 - jae .done - add eax, 31 - mov byte [esp+262*2+12], 0 -@@: - pusha - call read_chs_sector - popa - cmp [FDC_Status], 0 - jnz .error - mov edi, FDD_BUFF - push eax -.do_bdfe: - inc dword [edx+8] ; new file found - dec ebx - jns .l2 - dec ecx - js .l2 - inc dword [edx+4] ; new file block copied - call fat_entry_to_bdfe -.l2: - add edi, 0x20 - cmp edi, OS_BASE+0xD200 - jb .l1 - pop eax - inc eax - dec byte [esp+262*2+12] - jz .done - jns @f -; read next sector from FAT - mov eax, [(eax-31-1)*2+FLOPPY_FAT] - and eax, 0xFFF - cmp eax, 0xFF8 - jae .done - add eax, 31 - mov byte [esp+262*2+12], 0 -@@: - jmp .main_loop -.error: - add esp, 262*2+4 - pop ebp ecx edi edi - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret -.done: - add esp, 262*2+4 - pop ebp - mov ebx, [edx+4] - xor eax, eax - dec ecx - js @f - mov al, ERROR_END_OF_FILE -@@: - pop ecx edi edi - ret - -;---------------------------------------------------------------- -; -; fs_FloppyRewrite - LFN variant for writing sys floppy -; -; esi points to filename -; ebx ignored (reserved) -; ecx number of bytes to write, 0+ -; edx mem location to data -; -; ret ebx = number of written bytes -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -@@: - mov eax, ERROR_ACCESS_DENIED - xor ebx, ebx - ret -fsfrfe2: - popad -fsfrfe: - mov eax, 11 - xor ebx, ebx - ret - -fs_FloppyCreateFolder: - mov al, 1 - jmp fs_FloppyRewrite.common - -fs_FloppyRewrite: - xor eax, eax -.common: - cmp byte [esi], 0 - jz @b - call read_flp_fat - cmp [FDC_Status], 0 - jnz fsfrfe - pushad - xor edi, edi - push esi - test ebp, ebp - jz @f - mov esi, ebp -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jnz @b - lea edi, [esi-1] - jmp @b -@@: - pop esi - test edi, edi - jnz .noroot - test ebp, ebp - jnz .hasebp - call read_flp_root - cmp [FDC_Status], 0 - jnz fsfrfe2 - push flp_rootmem_extend_dir - push flp_rootmem_end_write - push flp_rootmem_next_write - push flp_rootmem_begin_write - xor ebp, ebp - push ebp - push flp_rootmem_first - push flp_rootmem_next - jmp .common1 -.hasebp: - mov eax, ERROR_ACCESS_DENIED - cmp byte [ebp], 0 - jz .ret1 - push ebp - xor ebp, ebp - call fd_find_lfn - pop esi - jc .notfound0 - jmp .common0 -.noroot: - mov eax, ERROR_ACCESS_DENIED - cmp byte [edi+1], 0 - jz .ret1 -; check existence - mov byte [edi], 0 - push edi - call fd_find_lfn - pop esi - mov byte [esi], '/' - jnc @f -.notfound0: - mov eax, ERROR_FILE_NOT_FOUND -.ret1: - mov [esp+28], eax - popad - xor ebx, ebx - ret -@@: - inc esi -.common0: - test byte [edi+11], 0x10 ; must be directory - mov eax, ERROR_ACCESS_DENIED - jz .ret1 - movzx ebp, word [edi+26] ; ebp=cluster - mov eax, ERROR_FAT_TABLE - cmp ebp, 2 - jb .ret1 - cmp ebp, 2849 - jae .ret1 - push flp_notroot_extend_dir - push flp_notroot_end_write - push flp_notroot_next_write - push flp_notroot_begin_write - push ebp - push flp_notroot_first - push flp_notroot_next -.common1: - call fat_find_lfn - jc .notfound -; found - test byte [edi+11], 10h - jz .exists_file -; found directory; if we are creating directory, return OK, -; if we are creating file, say "access denied" - add esp, 28 - popad - test al, al - mov eax, ERROR_ACCESS_DENIED - jz @f - mov al, 0 -@@: - xor ebx, ebx - ret -.exists_file: -; found file; if we are creating directory, return "access denied", -; if we are creating file, delete existing file and continue - cmp byte [esp+28+28], 0 - jz @f - add esp, 28 - popad - mov eax, ERROR_ACCESS_DENIED - xor ebx, ebx - ret -@@: -; delete FAT chain - push edi - xor eax, eax - mov dword [edi+28], eax ; zero size - xchg ax, word [edi+26] ; start cluster - test eax, eax - jz .done1 -@@: - cmp eax, 0xFF8 - jae .done1 - lea edi, [FLOPPY_FAT + eax*2] ; position in FAT - xor eax, eax - xchg ax, [edi] - jmp @b -.done1: - pop edi - call get_time_for_file - mov [edi+22], ax - call get_date_for_file - mov [edi+24], ax - mov [edi+18], ax - or byte [edi+11], 20h ; set 'archive' attribute - jmp .doit -.notfound: -; file is not found; generate short name - call fat_name_is_legal - jc @f - add esp, 28 - popad - mov eax, ERROR_FILE_NOT_FOUND - xor ebx, ebx - ret -@@: - sub esp, 12 - mov edi, esp - call fat_gen_short_name -.test_short_name_loop: - push esi edi ecx - mov esi, edi - lea eax, [esp+12+12+8] - mov [eax], ebp - call dword [eax-4] - jc .found -.test_short_name_entry: - cmp byte [edi+11], 0xF - jz .test_short_name_cont - mov ecx, 11 - push esi edi - repz cmpsb - pop edi esi - jz .short_name_found -.test_short_name_cont: - lea eax, [esp+12+12+8] - call dword [eax-8] - jnc .test_short_name_entry - jmp .found -.short_name_found: - pop ecx edi esi - call fat_next_short_name - jnc .test_short_name_loop -.disk_full: - add esp, 12+28 - popa - mov eax, ERROR_DISK_FULL - xor ebx, ebx - ret -.found: - pop ecx edi esi -; now find space in directory -; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' - mov al, '~' - push ecx edi - mov ecx, 8 - repnz scasb - push 1 - pop eax ; 1 entry - jnz .notilde -; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total - xor eax, eax -@@: - cmp byte [esi], 0 - jz @f - inc esi - inc eax - jmp @b -@@: - sub esi, eax - add eax, 12+13 - mov ecx, 13 - push edx - cdq - div ecx - pop edx -.notilde: - push -1 - push -1 -; find successive entries in directory - xor ecx, ecx - push eax - lea eax, [esp+12+8+12+8] - mov [eax], ebp - call dword [eax-4] - pop eax - jnc .scan_dir -.fsfrfe3: - add esp, 8+8+12+28 - popad - mov eax, 11 - xor ebx, ebx - ret -.scan_dir: - cmp byte [edi], 0 - jz .free - cmp byte [edi], 0xE5 - jz .free - xor ecx, ecx -.scan_cont: - push eax - lea eax, [esp+12+8+12+8] - call dword [eax-8] - pop eax - jnc .scan_dir - cmp [FDC_Status], 0 - jnz .fsfrfe3 - push eax - lea eax, [esp+12+8+12+8] - call dword [eax+16] ; extend directory - pop eax - jnc .scan_dir - add esp, 8+8+12+28 - popad - mov eax, ERROR_DISK_FULL - xor ebx, ebx - ret -.free: - test ecx, ecx - jnz @f - mov [esp], edi - mov ecx, [esp+8+8+12+8] - mov [esp+4], ecx - xor ecx, ecx -@@: - inc ecx - cmp ecx, eax - jb .scan_cont -; found! -; calculate name checksum - push esi ecx - mov esi, [esp+8+8] - mov ecx, 11 - xor eax, eax -@@: - ror al, 1 - add al, [esi] - inc esi - loop @b - pop ecx esi - pop edi - pop dword [esp+8+12+8] -; edi points to first entry in free chunk - dec ecx - jz .nolfn - push esi - push eax - lea eax, [esp+8+8+12+8] - call dword [eax+4] ; begin write - mov al, 40h -.writelfn: - or al, cl - mov esi, [esp+4] - push ecx - dec ecx - imul ecx, 13 - add esi, ecx - stosb - mov cl, 5 - call fs_RamdiskRewrite.read_symbols - mov ax, 0xF - stosw - mov al, [esp+4] - stosb - mov cl, 6 - call fs_RamdiskRewrite.read_symbols - xor eax, eax - stosw - mov cl, 2 - call fs_RamdiskRewrite.read_symbols - pop ecx - lea eax, [esp+8+8+12+8] - call dword [eax+8] ; next write - xor eax, eax - loop .writelfn - pop eax - pop esi -; lea eax, [esp+8+12+8] -; call dword [eax+12] ; end write -.nolfn: - xchg esi, [esp] - mov ecx, 11 - rep movsb - mov word [edi], 20h ; attributes - sub edi, 11 - pop esi ecx - add esp, 12 - mov byte [edi+13], 0 ; tenths of a second at file creation time - call get_time_for_file - mov [edi+14], ax ; creation time - mov [edi+22], ax ; last write time - call get_date_for_file - mov [edi+16], ax ; creation date - mov [edi+24], ax ; last write date - mov [edi+18], ax ; last access date - and word [edi+20], 0 ; high word of cluster - and word [edi+26], 0 ; low word of cluster - to be filled - and dword [edi+28], 0 ; file size - to be filled - cmp byte [esp+28+28], 0 - jz .doit -; create directory - mov byte [edi+11], 10h ; attributes: folder - mov ecx, 32*2 - mov edx, edi -.doit: - lea eax, [esp+8] - call dword [eax+12] ; flush directory - push ecx - push edi - push 0 - mov esi, edx - test ecx, ecx - jz .done - mov ecx, 2849 - mov edi, FLOPPY_FAT - push 0 ; first cluster -.write_loop: -; allocate new cluster - xor eax, eax - repnz scasw - mov al, ERROR_DISK_FULL - jnz .ret - dec edi - dec edi - - mov eax, edi - sub eax, FLOPPY_FAT - - shr eax, 1 ; eax = cluster - mov word [edi], 0xFFF ; mark as last cluster - xchg edi, [esp+4] - cmp dword [esp], 0 - jz .first - stosw - jmp @f -.first: - mov [esp], eax -@@: - mov edi, [esp+4] - inc ecx -; write data - push ecx edi - mov ecx, 512 - cmp dword [esp+20], ecx - jae @f - mov ecx, [esp+20] -@@: - mov edi, FDD_BUFF - cmp byte [esp+24+28+28], 0 - jnz .writedir - push ecx - rep movsb - pop ecx -.writedircont: - push ecx - sub ecx, 512 - neg ecx - push eax - xor eax, eax - rep stosb - pop eax - add eax, 31 - pusha - call save_chs_sector - popa - pop ecx - cmp [FDC_Status], 0 - jnz .diskerr - sub [esp+20], ecx - pop edi ecx - jnz .write_loop -.done: - xor eax, eax -.ret: - pop ebx edi edi ecx - mov [esp+28+28], eax - lea eax, [esp+8] - call dword [eax+4] - mov [edi+26], bx - mov ebx, esi - sub ebx, edx - mov [edi+28], ebx - call dword [eax+12] - mov [esp+28+16], ebx - test ebp, ebp - jnz @f - call save_flp_root -@@: - add esp, 28 - cmp [FDC_Status], 0 - jnz .err3 - call save_flp_fat - cmp [FDC_Status], 0 - jnz .err3 - popa - ret -.err3: - popa - mov al, 11 - xor ebx, ebx - ret -.diskerr: - sub esi, ecx - mov eax, 11 - pop edi ecx - jmp .ret -.writedir: - push ecx - mov ecx, 32/4 - push ecx esi - rep movsd - pop esi ecx - mov dword [edi-32], '. ' - mov dword [edi-32+4], ' ' - mov dword [edi-32+8], ' ' - mov byte [edi-32+11], 10h - mov word [edi-32+26], ax - push esi - rep movsd - pop esi - mov dword [edi-32], '.. ' - mov dword [edi-32+4], ' ' - mov dword [edi-32+8], ' ' - mov byte [edi-32+11], 10h - mov ecx, [esp+28+8] - mov word [edi-32+26], cx - pop ecx - jmp .writedircont - -;---------------------------------------------------------------- -; -; fs_FloppyWrite - LFN variant for writing to floppy -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to write, 0+ -; edx mem location to data -; -; ret ebx = bytes written (maybe 0) -; eax = 0 ok write or other = errormsg -; -;-------------------------------------------------------------- - -@@: - push ERROR_ACCESS_DENIED -fs_FloppyWrite.ret0: - pop eax - xor ebx, ebx - ret - -fs_FloppyWrite.ret11: - push 11 - jmp fs_FloppyWrite.ret0 - -fs_FloppyWrite: - cmp byte [esi], 0 - jz @b - call read_flp_fat - cmp [FDC_Status], 0 - jnz .ret11 - pushad - call fd_find_lfn - jnc .found - popad - push ERROR_FILE_NOT_FOUND - jmp .ret0 -.found: -; FAT does not support files larger than 4GB - test ebx, ebx - jz .l1 - cmp dword [ebx+4], 0 - jz @f -.eof: - popad - push ERROR_END_OF_FILE - jmp .ret0 -@@: - mov ebx, [ebx] -.l1: -; now edi points to direntry, ebx=start byte to write, -; ecx=number of bytes to write, edx=data pointer - -; extend file if needed - add ecx, ebx - jc .eof ; FAT does not support files larger than 4GB - push eax ; save directory cluster - push 0 ; return value=0 - - call get_time_for_file - mov [edi+22], ax ; last write time - call get_date_for_file - mov [edi+24], ax ; last write date - mov [edi+18], ax ; last access date - - push dword [edi+28] ; save current file size - cmp ecx, [edi+28] - jbe .length_ok - cmp ecx, ebx - jz .length_ok - call floppy_extend_file - jnc .length_ok - mov [esp+4], eax -; floppy_extend_file can return two error codes: FAT table error or disk full. -; First case is fatal error, in second case we may write some data - cmp al, ERROR_DISK_FULL - jz .disk_full - pop eax - pop eax - mov [esp+4+28], eax - pop eax - popad - xor ebx, ebx - ret -.disk_full: -; correct number of bytes to write - mov ecx, [edi+28] - cmp ecx, ebx - ja .length_ok -.ret: - pop eax - pop eax - mov [esp+4+28], eax ; eax=return value - pop eax - sub edx, [esp+20] - mov [esp+16], edx ; ebx=number of written bytes - popad - ret -.length_ok: -; save FAT & directory -; note that directory must be saved first because save_flp_fat uses buffer at 0xD000 - mov esi, [edi+28] - movzx edi, word [edi+26] ; starting cluster - mov eax, [esp+8] - pusha - call save_chs_sector - popa - cmp [FDC_Status], 0 - jnz .device_err - call save_flp_fat - cmp [FDC_Status], 0 - jz @f -.device_err: - mov byte [esp+4], 11 - jmp .ret -@@: - -; now ebx=start pos, ecx=end pos, both lie inside file - sub ecx, ebx - jz .ret - call SetUserInterrupts -.write_loop: -; skip unmodified sectors - cmp dword [esp], 0x200 - jb .modify - sub ebx, 0x200 - jae .skip - add ebx, 0x200 -.modify: - lea eax, [edi+31] ; current sector -; get length of data in current sector - push ecx - sub ebx, 0x200 - jb .hasdata - neg ebx - xor ecx, ecx - jmp @f -.hasdata: - neg ebx - cmp ecx, ebx - jbe @f - mov ecx, ebx -@@: -; load sector if needed - cmp dword [esp+4], 0 ; we don't need to read uninitialized data - jz .noread - cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten - jz .noread - cmp ecx, esi ; (same for the last sector) - jz .noread - pusha - call read_chs_sector - popa - cmp [FDC_Status], 0 - jz @f -.device_err2: - pop ecx - jmp .device_err -@@: -.noread: -; zero uninitialized data if file was extended (because floppy_extend_file does not this) - push eax ecx edi - xor eax, eax - mov ecx, 0x200 - sub ecx, [esp+4+12] - jbe @f - mov edi, FDD_BUFF - add edi, [esp+4+12] - rep stosb -@@: -; zero uninitialized data in the last sector - mov ecx, 0x200 - sub ecx, esi - jbe @f - mov edi, FDD_BUFF - add edi, esi - rep stosb -@@: - pop edi ecx eax -; copy new data - push eax - mov eax, edx - neg ebx - jecxz @f - add ebx, FDD_BUFF+0x200 - call memmove - xor ebx, ebx -@@: - pop eax -; save sector - pusha - call save_chs_sector - popa - cmp [FDC_Status], 0 - jnz .device_err2 - add edx, ecx - sub [esp], ecx - pop ecx - jz .done -.skip: -.next_cluster: - movzx edi, word [edi*2+FLOPPY_FAT] - sub esi, 0x200 - jae @f - xor esi, esi -@@: - sub dword [esp], 0x200 - jae .write_loop - and dword [esp], 0 - jmp .write_loop -.done: - mov [fdc_irq_func], fdc_null - jmp .ret - -floppy_extend_file.zero_size: - xor eax, eax - jmp floppy_extend_file.start_extend - -; extends file on floppy to given size (new data area is undefined) -; in: edi->direntry, ecx=new size -; out: CF=0 => OK, eax=0 -; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) -floppy_extend_file: - push ecx -; find the last cluster of file - movzx eax, word [edi+26] ; first cluster - mov ecx, [edi+28] - jecxz .zero_size -@@: - sub ecx, 0x200 - jbe @f - mov eax, [eax*2+FLOPPY_FAT] - and eax, 0xFFF - jz .fat_err - cmp eax, 0xFF8 - jb @b -.fat_err: - pop ecx - push ERROR_FAT_TABLE - pop eax - stc - ret -@@: - push eax - mov eax, [eax*2+FLOPPY_FAT] - and eax, 0xFFF - cmp eax, 0xFF8 - pop eax - jb .fat_err -; set length to full number of sectors - sub [edi+28], ecx -.start_extend: - pop ecx -; now do extend - push edx esi - mov esi, FLOPPY_FAT+2*2 ; start scan from cluster 2 - mov edx, 2847 ; number of clusters to scan -.extend_loop: - cmp [edi+28], ecx - jae .extend_done -; add new sector - push ecx - push edi -.scan: - mov ecx, edx - mov edi, esi - jecxz .disk_full - push eax - xor eax, eax - repnz scasw - pop eax - jnz .disk_full - mov word [edi-2], 0xFFF - mov esi, edi - mov edx, ecx - sub edi, FLOPPY_FAT - shr edi, 1 - dec edi ; now edi=new cluster - test eax, eax - jz .first_cluster - mov [FLOPPY_FAT+eax*2], di - jmp @f -.first_cluster: - pop eax ; eax->direntry - push eax - mov [eax+26], di -@@: - mov eax, edi ; eax=new cluster - pop edi ; edi->direntry - pop ecx ; ecx=required size - add dword [edi+28], 0x200 - jmp .extend_loop -.extend_done: - mov [edi+28], ecx - pop esi edx - xor eax, eax ; CF=0 - ret -.disk_full: - pop edi ecx - pop esi edx - stc - push ERROR_DISK_FULL - pop eax - ret - -;---------------------------------------------------------------- -; -; fs_FloppySetFileEnd - set end of file on floppy -; -; esi points to filename -; ebx points to 64-bit number = new file size -; ecx ignored (reserved) -; edx ignored (reserved) -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -fs_FloppySetFileEnd: - call read_flp_fat - cmp [FDC_Status], 0 - jnz ret11 - cmp byte [esi], 0 - jnz @f -.access_denied: - push ERROR_ACCESS_DENIED - jmp .ret -@@: - push edi - call fd_find_lfn - jnc @f - pop edi - push ERROR_FILE_NOT_FOUND -.ret: - pop eax - jmp .doret -@@: -; must not be directory - test byte [edi+11], 10h - jz @f - pop edi - jmp .access_denied -@@: -; file size must not exceed 4 Gb - cmp dword [ebx+4], 0 - jz @f - pop edi - push ERROR_END_OF_FILE - jmp .ret -@@: - push eax -; set file modification date/time to current - call fat_update_datetime - mov eax, [ebx] - cmp eax, [edi+28] - jb .truncate - ja .expand - pop eax - pushad - call save_chs_sector - popad - pop edi - xor eax, eax - cmp [FDC_Status], 0 - jz @f - mov al, 11 -@@: -.doret: - mov [fdc_irq_func], fdc_null - ret -.expand: - push ecx - push dword [edi+28] ; save old size - mov ecx, eax - call floppy_extend_file - push eax ; return code - jnc .expand_ok - cmp al, ERROR_DISK_FULL - jz .disk_full - pop eax ecx ecx edi edi - jmp .doret -.device_err: - pop eax -.device_err2: - pop ecx ecx eax edi - push 11 - jmp .ret -.disk_full: -.expand_ok: -; save directory & FAT - mov eax, [edi+28] - xchg eax, [esp+12] - movzx edi, word [edi+26] - pusha - call save_chs_sector - popa - cmp [FDC_Status], 0 - jnz .device_err - call save_flp_fat - cmp [FDC_Status], 0 - jnz .device_err - call SetUserInterrupts -; now zero new data -; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code -.zero_loop: - sub dword [esp+4], 0x200 - jae .next_cluster - cmp dword [esp+4], -0x200 - jz .noread - lea eax, [edi+31] - pusha - call read_chs_sector - popa - cmp [FDC_Status], 0 - jnz .err_next -.noread: - mov ecx, [esp+4] - neg ecx - push edi - mov edi, FDD_BUFF+0x200 - add edi, [esp+8] - xor eax, eax - mov [esp+8], eax - rep stosb - pop edi - lea eax, [edi+31] - pusha - call save_chs_sector - popa - cmp [FDC_Status], 0 - jz .next_cluster -.err_next: - mov byte [esp], 11 -.next_cluster: - sub dword [esp+12], 0x200 - jbe .expand_done - movzx edi, word [FLOPPY_FAT+edi*2] - jmp .zero_loop -.expand_done: - pop eax ecx ecx edi edi - jmp .doret -.truncate: - mov [edi+28], eax - push ecx - movzx ecx, word [edi+26] - test eax, eax - jz .zero_size -; find new last sector -@@: - sub eax, 0x200 - jbe @f - movzx ecx, word [FLOPPY_FAT+ecx*2] - jmp @b -@@: -; we will zero data at the end of last sector - remember it - push ecx -; terminate FAT chain - lea ecx, [FLOPPY_FAT+ecx+ecx] - push dword [ecx] - mov word [ecx], 0xFFF - pop ecx - and ecx, 0xFFF - jmp .delete -.zero_size: - and word [edi+26], 0 - push 0 -.delete: -; delete FAT chain starting with ecx -; mark all clusters as free - cmp ecx, 0xFF8 - jae .deleted - lea ecx, [FLOPPY_FAT+ecx+ecx] - push dword [ecx] - and word [ecx], 0 - pop ecx - and ecx, 0xFFF - jmp .delete -.deleted: - mov edi, [edi+28] -; save directory & FAT - mov eax, [esp+8] - pusha - call save_chs_sector - popa - cmp [FDC_Status], 0 - jnz .device_err2 - call save_flp_fat - cmp [FDC_Status], 0 - jnz .device_err2 -; zero last sector, ignore errors - pop eax - add eax, 31 - and edi, 0x1FF - jz .truncate_done - call SetUserInterrupts - pusha - call read_chs_sector - popa - add edi, FDD_BUFF - mov ecx, FDD_BUFF+0x200 - sub ecx, edi - push eax - xor eax, eax - rep stosb - pop eax - pusha - call save_chs_sector - popa -.truncate_done: - pop ecx eax edi - xor eax, eax - jmp .doret - -fs_FloppyGetFileInfo: - call read_flp_fat - cmp [FDC_Status], 0 - jnz ret11 - cmp byte [esi], 0 - jnz @f - mov eax, 2 ; unsupported - ret -@@: - push edi - call fd_find_lfn - jmp fs_GetFileInfo_finish - -ret11: - mov eax, 11 - ret - -fs_FloppySetFileInfo: - call read_flp_fat - cmp [FDC_Status], 0 - jnz ret11 - cmp byte [esi], 0 - jnz @f - mov eax, 2 ; unsupported - ret -@@: - push edi - call fd_find_lfn - jnc @f - pop edi - mov eax, ERROR_FILE_NOT_FOUND - ret -@@: - push eax - call bdfe_to_fat_entry - pop eax - pusha - call save_chs_sector - popa - pop edi - xor eax, eax - cmp [FDC_Status], al - jz @f - mov al, 11 -@@: - ret - -;---------------------------------------------------------------- -; -; fs_FloppyDelete - delete file or empty folder from floppy -; -; esi points to filename -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -fs_FloppyDelete: - call read_flp_fat - cmp [FDC_Status], 0 - jz @f - push 11 - jmp .pop_ret -@@: - cmp byte [esi], 0 - jnz @f -; cannot delete root! -.access_denied: - push ERROR_ACCESS_DENIED -.pop_ret: - pop eax - ret -@@: - and [fd_prev_sector], 0 - and [fd_prev_prev_sector], 0 - push edi - call fd_find_lfn - jnc .found - pop edi - push ERROR_FILE_NOT_FOUND - jmp .pop_ret -.found: - cmp dword [edi], '. ' - jz .access_denied2 - cmp dword [edi], '.. ' - jz .access_denied2 - test byte [edi+11], 10h - jz .dodel -; we can delete only empty folders! - push eax - movzx eax, word [edi+26] - push ebx - pusha - add eax, 31 - call read_chs_sector - popa - mov ebx, FDD_BUFF + 2*0x20 -.checkempty: - cmp byte [ebx], 0 - jz .empty - cmp byte [ebx], 0xE5 - jnz .notempty - add ebx, 0x20 - cmp ebx, FDD_BUFF + 0x200 - jb .checkempty - movzx eax, word [FLOPPY_FAT + eax*2] - pusha - add eax, 31 - call read_chs_sector - popa - mov ebx, FDD_BUFF - jmp .checkempty -.notempty: - pop ebx - pop eax -.access_denied2: - pop edi - jmp .access_denied -.empty: - pop ebx - pop eax - pusha - call read_chs_sector - popa -.dodel: - push eax - movzx eax, word [edi+26] - xchg eax, [esp] -; delete folder entry - mov byte [edi], 0xE5 -; delete LFN (if present) -.lfndel: - cmp edi, FDD_BUFF - ja @f - cmp [fd_prev_sector], 0 - jz .lfndone - push [fd_prev_sector] - push [fd_prev_prev_sector] - pop [fd_prev_sector] - and [fd_prev_prev_sector], 0 - pusha - call save_chs_sector - popa - pop eax - pusha - call read_chs_sector - popa - mov edi, FDD_BUFF+0x200 -@@: - sub edi, 0x20 - cmp byte [edi], 0xE5 - jz .lfndone - cmp byte [edi+11], 0xF - jnz .lfndone - mov byte [edi], 0xE5 - jmp .lfndel -.lfndone: - pusha - call save_chs_sector - popa -; delete FAT chain - pop eax - test eax, eax - jz .done -@@: - lea eax, [FLOPPY_FAT + eax*2] - push dword [eax] - and word [eax], 0 - pop eax - and eax, 0xFFF - jnz @b -.done: - call save_flp_fat - pop edi - xor eax, eax - ret - -; \end{diamond} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; FAT12.INC ;; +;; (C) 2005 Mario79, License: GPL ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +n_sector dd 0 ; temporary save for sector value +flp_status dd 0 +clust_tmp_flp dd 0 ; used by analyze_directory and analyze_directory_to_write +path_pointer_flp dd 0 +pointer_file_name_flp dd 0 +save_root_flag db 0 +save_flag db 0 +root_read db 0 ; 0-necessary to load root, 1-not to load root +flp_fat db 0 ; 0-necessary to load fat, 1-not to load fat +flp_number db 0 ; 1- Floppy A, 2-Floppy B +old_track db 0 ; old value track +flp_label rb 15 ; Label and ID of inserted floppy disk + +reserve_flp: + + cli + cmp [flp_status], 0 + je reserve_flp_ok + + sti + call change_task + jmp reserve_flp + + reserve_flp_ok: + + push eax + mov eax, [CURRENT_TASK] + shl eax, 5 + mov eax, [eax+CURRENT_TASK+TASKDATA.pid] + mov [flp_status], eax + pop eax + sti + ret + + +floppy_fileread: +;---------------------------------------------------------------- +; +; fileread - sys floppy +; +; eax points to filename 11 chars - for root directory +; ebx first wanted block ; 1+ ; if 0 then set to 1 +; ecx number of blocks to read ; 1+ ; if 0 then set to 1 +; edx mem location to return data +; esi length of filename 12*X +; edi pointer to path /fd/1/...... - for all files in nested directories +; +; ret ebx = size or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; 10 = access denied +;-------------------------------------------------------------- + + mov [save_flag], 0 + mov [path_pointer_flp], edi + test esi, esi ; return ramdisk root + jnz fr_noroot_1 + cmp ebx, 224/16 + jbe fr_do_1 + mov eax, 5 + xor ebx, ebx + mov [flp_status], ebx + ret + +fr_do_1: + push ebx ecx edx + call read_flp_root + pop edx ecx ebx + cmp [FDC_Status], 0 + jne fdc_status_error_1 + mov edi, edx + dec ebx + shl ebx, 9 + mov esi, FLOPPY_BUFF + add esi, ebx + shl ecx, 9 + cld + rep movsb + xor eax, eax + xor ebx, ebx +; mov eax,0 ; ok read +; mov ebx,0 + mov [flp_status], eax + ret +fdc_status_error_1: + xor eax, eax + mov [flp_status], eax + mov eax, 10 + or ebx, -1 + ret + +fr_noroot_1: + sub esp, 32 + call expand_filename +frfloppy_1: + test ebx, ebx + jnz frfl5_1 + mov ebx, 1 +frfl5_1: + test ecx, ecx + jnz frfl6_1 + mov ecx, 1 +frfl6_1: + dec ebx + push eax + push eax ebx ecx edx esi edi + call read_flp_fat + cmp [FDC_Status], 0 + jne fdc_status_error_3_1 + mov [FDD_Track], 0; Цилиндр + mov [FDD_Head], 1; Сторона + mov [FDD_Sector], 2; Сектор + call SeekTrack + mov dh, 14 +l.20_1: + call ReadSectWithRetr + cmp [FDC_Status], 0 + jne fdc_status_error_3_1 + mov dl, 16 + mov edi, FDD_BUFF + inc [FDD_Sector] +l.21_1: + mov esi, eax ;Name of file we want + mov ecx, 11 + cld + rep cmpsb ;Found the file? + je fifound_1 ;Yes + add ecx, 21 + add edi, ecx ;Advance to next entry + dec dl + test dl, dl + jnz l.21_1 + dec dh + test dh, dh + jnz l.20_1 +fdc_status_error_3: + mov eax, 5 ; file not found ? + or ebx, -1 + add esp, 32+28 + mov [flp_status], 0 + ret +fdc_status_error_3_2: + cmp [FDC_Status], 0 + je fdc_status_error_3 +fdc_status_error_3_1: + add esp, 32+28 + jmp fdc_status_error_1 + +fifound_1: + mov eax, [path_pointer_flp] + cmp [eax+36], byte 0 + je fifound_2 + add edi, 0xf + mov eax, [edi] + and eax, 65535 + mov ebx, [path_pointer_flp] + add ebx, 36 + call get_cluster_of_a_path_flp + jc fdc_status_error_3_2 + mov ebx, [ebx-11+28] ;file size + mov [esp+20], ebx + mov [esp+24], ebx + jmp fifound_3 +fifound_2: + mov ebx, [edi-11+28] ;file size + mov [esp+20], ebx + mov [esp+24], ebx + add edi, 0xf + mov eax, [edi] +fifound_3: + and eax, 65535 + mov [n_sector], eax ;eax=cluster +frnew_1: + add eax, 31 ;bootsector+2*fat+filenames + cmp [esp+16], dword 0; wanted cluster ? + jne frfl7_1 + call read_chs_sector + cmp [FDC_Status], 0 + jne fdc_status_error_5 + mov edi, [esp+8] + call give_back_application_data_1 + add [esp+8], dword 512 + dec dword [esp+12] ; last wanted cluster ? + cmp [esp+12], dword 0 + je frnoread_1 + jmp frfl8_1 +frfl7_1: + dec dword [esp+16] +frfl8_1: + mov edi, [n_sector] + shl edi, 1 ;find next cluster from FAT + add edi, FLOPPY_FAT + mov eax, [edi] + and eax, 4095 + mov edi, eax + mov [n_sector], edi + cmp edi, 4095 ;eof - cluster + jz frnoread2_1 + cmp [esp+24], dword 512;eof - size + jb frnoread_1 + sub [esp+24], dword 512 + jmp frnew_1 + +read_chs_sector: + call calculate_chs + call ReadSectWithRetr + ret + +frnoread2_1: + cmp [esp+16], dword 0; eof without read ? + je frnoread_1 + mov [fdc_irq_func], fdc_null + pop edi esi edx ecx + add esp, 4 + pop ebx; ebx <- eax : size of file + add esp, 36 + mov eax, 6; end of file + mov [flp_status], 0 + ret + +frnoread_1: + pop edi esi edx ecx + add esp, 4 + pop ebx; ebx <- eax : size of file + add esp, 36 + xor eax, eax + mov [flp_status], eax + ret + +fdc_status_error_5: + pop edi esi edx ecx + add esp, 4 + pop ebx; ebx <- eax : size of file + add esp, 36 + jmp fdc_status_error_1 + +read_flp_root: + pusha + call check_label + cmp [FDC_Status], 0 + jne unnecessary_root_read + cmp [root_read], 1 + je unnecessary_root_read + mov [FDD_Track], 0; Цилиндр + mov [FDD_Head], 1; Сторона + mov [FDD_Sector], 2; Сектор + mov edi, FLOPPY_BUFF + call SeekTrack +read_flp_root_1: + call ReadSectWithRetr + cmp [FDC_Status], 0 + jne unnecessary_root_read + push edi + call give_back_application_data_1 + pop edi + add edi, 512 + inc [FDD_Sector] + cmp [FDD_Sector], 16 + jne read_flp_root_1 + mov [root_read], 1 +unnecessary_root_read: + popa + ret + + +read_flp_fat: + pusha + call check_label + cmp [FDC_Status], 0 + jne unnecessary_flp_fat + cmp [flp_fat], 1 + je unnecessary_flp_fat + mov [FDD_Track], 0; Цилиндр + mov [FDD_Head], 0; Сторона + mov [FDD_Sector], 2; Сектор + mov edi, FLOPPY_BUFF + call SeekTrack +read_flp_fat_1: + call ReadSectWithRetr + cmp [FDC_Status], 0 + jne unnecessary_flp_fat + push edi + call give_back_application_data_1 + pop edi + add edi, 512 + inc [FDD_Sector] + cmp [FDD_Sector], 19 + jne read_flp_fat_1 + mov [FDD_Sector], 1 + mov [FDD_Head], 1 + call ReadSectWithRetr + cmp [FDC_Status], 0 + jne unnecessary_flp_fat + call give_back_application_data_1 + call calculatefatchain_flp + mov [root_read], 0 + mov [flp_fat], 1 +unnecessary_flp_fat: + popa + ret + +calculatefatchain_flp: + pushad + + mov esi, FLOPPY_BUFF + mov edi, FLOPPY_FAT + + fcnew_1: + mov eax, dword [esi] + mov ebx, dword [esi+4] + mov ecx, dword [esi+8] + mov edx, ecx + shr edx, 4;8 ok + shr dx, 4;7 ok + xor ch, ch + shld ecx, ebx, 20;6 ok + shr cx, 4;5 ok + shld ebx, eax, 12 + and ebx, 0x0fffffff;4 ok + shr bx, 4;3 ok + shl eax, 4 + and eax, 0x0fffffff;2 ok + shr ax, 4;1 ok + mov dword [edi], eax + add edi, 4 + mov dword [edi], ebx + add edi, 4 + mov dword [edi], ecx + add edi, 4 + mov dword [edi], edx + add edi, 4 + add esi, 12 + + cmp edi, FLOPPY_FAT+2856*2;2849 clusters + jnz fcnew_1 + + popad + ret + +check_label: + pushad + mov [FDD_Track], 0; Цилиндр + mov [FDD_Head], 0; Сторона + mov [FDD_Sector], 1; Сектор + call SetUserInterrupts + call FDDMotorON + call RecalibrateFDD + cmp [FDC_Status], 0 + jne fdc_status_error + call SeekTrack + cmp [FDC_Status], 0 + jne fdc_status_error + call ReadSectWithRetr + cmp [FDC_Status], 0 + jne fdc_status_error + mov esi, flp_label + mov edi, FDD_BUFF+39 + mov ecx, 15 + cld + rep cmpsb + je same_label + mov [root_read], 0 + mov [flp_fat], 0 +same_label: + mov esi, FDD_BUFF+39 + mov edi, flp_label + mov ecx, 15 + cld + rep movsb + popad + ret +fdc_status_error: + popad + ret + +save_flp_root: + pusha + call check_label + cmp [FDC_Status], 0 + jne unnecessary_root_save + cmp [root_read], 0 + je unnecessary_root_save + mov [FDD_Track], 0; Цилиндр + mov [FDD_Head], 1; Сторона + mov [FDD_Sector], 2; Сектор + mov esi, FLOPPY_BUFF + call SeekTrack +save_flp_root_1: + push esi + call take_data_from_application_1 + pop esi + add esi, 512 + call WriteSectWithRetr + cmp [FDC_Status], 0 + jne unnecessary_root_save + inc [FDD_Sector] + cmp [FDD_Sector], 16 + jne save_flp_root_1 +unnecessary_root_save: + mov [fdc_irq_func], fdc_null + popa + ret + +save_flp_fat: + pusha + call check_label + cmp [FDC_Status], 0 + jne unnecessary_flp_fat_save + cmp [flp_fat], 0 + je unnecessary_flp_fat_save + call restorefatchain_flp + mov [FDD_Track], 0; Цилиндр + mov [FDD_Head], 0; Сторона + mov [FDD_Sector], 2; Сектор + mov esi, FLOPPY_BUFF + call SeekTrack +save_flp_fat_1: + push esi + call take_data_from_application_1 + pop esi + add esi, 512 + call WriteSectWithRetr + cmp [FDC_Status], 0 + jne unnecessary_flp_fat_save + inc [FDD_Sector] + cmp [FDD_Sector], 19 + jne save_flp_fat_1 + mov [FDD_Sector], 1 + mov [FDD_Head], 1 + call take_data_from_application_1 + call WriteSectWithRetr + cmp [FDC_Status], 0 + jne unnecessary_flp_fat_save + mov [root_read], 0 +unnecessary_flp_fat_save: + mov [fdc_irq_func], fdc_null + popa + ret + + +restorefatchain_flp: ; restore fat chain + pushad + + mov esi, FLOPPY_FAT + mov edi, FLOPPY_BUFF + + fcnew2_1: + mov eax, dword [esi] + mov ebx, dword [esi+4] + shl ax, 4 + shl eax, 4 + shl bx, 4 + shr ebx, 4 + shrd eax, ebx, 8 + shr ebx, 8 + mov dword [edi], eax + add edi, 4 + mov word [edi], bx + add edi, 2 + add esi, 8 + + cmp edi, FLOPPY_BUFF+0x1200;4274 bytes - all used FAT + jb fcnew2_1 + + mov esi, FLOPPY_BUFF ; duplicate fat chain + mov edi, FLOPPY_BUFF+0x1200 + mov ecx, 0x1200/4 + cld + rep movsd + + popad + ret + + +save_chs_sector: + call calculate_chs + call WriteSectWithRetr + ret + +calculate_chs: + mov bl, [FDD_Track] + mov [old_track], bl + mov ebx, 18 + xor edx, edx + div ebx + inc edx + mov [FDD_Sector], dl + xor edx, edx + mov ebx, 2 + div ebx + mov [FDD_Track], al + mov [FDD_Head], 0 + test edx, edx + jz no_head_2 + inc [FDD_Head] +no_head_2: + mov dl, [old_track] + cmp dl, [FDD_Track] + je no_seek_track_1 + call SeekTrack +no_seek_track_1: + ret + + +get_cluster_of_a_path_flp: +;--------------------------------------------------------- +; input : EBX = pointer to a path string +; (example: the path "/files/data/document" become +; "files......data.......document...0" +; '.' = space char +; '0' = char(0) (ASCII=0) !!! ) +; output : if (CARRY=1) -> ERROR in the PATH +; if (CARRY=0) -> EAX=cluster +;--------------------------------------------------------- + + push edx + mov edx, ebx + +search_end_of_path_flp: + cmp [save_flag], 0 + jne search_end_of_path_flp_1 + cmp byte [edx], 0 + je found_end_of_path_flp + jmp search_end_of_path_flp_2 +search_end_of_path_flp_1: + cmp byte [edx+12], 0 + je found_end_of_path_flp +search_end_of_path_flp_2: + inc edx; '/' + call analyze_directory_flp + jc directory_not_found_flp + + mov eax, [ebx+20-2] ; read the HIGH 16bit cluster field + mov ax, [ebx+26] ; read the LOW 16bit cluster field + and eax, 0xfff ;[fatMASK] + add edx, 11 ; 8+3 (name+extension) + jmp search_end_of_path_flp + +found_end_of_path_flp: + inc edx + mov [pointer_file_name_flp], edx + pop edx + clc ; no errors + ret + +directory_not_found_flp: + pop edx + stc ; errors occour + ret + +analyze_directory_flp: +;-------------------------------- +; input : EAX = first cluster of the directory +; EBX = pointer to filename +; output : IF CARRY=0 EAX = sector where th file is found +; EBX = pointer in buffer +; [buffer .. buffer+511] +; ECX,EDX,EDI,EDI not changed +; IF CARRY=1 +;-------------------------------- + push ebx;[esp+16] + push ecx + push edx + push esi + push edi + + +adr56_flp: + mov [clust_tmp_flp], eax + add eax, 31 + pusha + call read_chs_sector + popa + cmp [FDC_Status], 0 + jne not_found_file_analyze_flp + + mov ecx, 512/32 + mov ebx, FDD_BUFF + +adr1_analyze_flp: + mov esi, edx;[esp+16] + mov edi, ebx + cld + push ecx + mov ecx, 11 + rep cmpsb + pop ecx + je found_file_analyze_flp + + add ebx, 32 + loop adr1_analyze_flp + + mov eax, [clust_tmp_flp] + shl eax, 1 ;find next cluster from FAT + add eax, FLOPPY_FAT + mov eax, [eax] + and eax, 4095 + cmp eax, 0x0ff8 + jb adr56_flp +not_found_file_analyze_flp: + pop edi + pop esi + pop edx + pop ecx + add esp, 4 + stc ;file not found + ret + +found_file_analyze_flp: + pop edi + pop esi + pop edx + pop ecx + add esp, 4 + clc ;file found + ret + + +; \begin{diamond} +fat_find_lfn: +; in: esi->name +; [esp+4] = next +; [esp+8] = first +; [esp+C]... - possibly parameters for first and next +; out: CF=1 - file not found +; else CF=0, esi->next name component, edi->direntry + pusha + lea eax, [esp+0Ch+20h] + call dword [eax-4] + jc .reterr + sub esp, 262*2 ; reserve place for LFN + mov ebp, esp + push 0 ; for fat_get_name: read ASCII name +.l1: + call fat_get_name + jc .l2 + call fat_compare_name + jz .found +.l2: + lea eax, [esp+0Ch+20h+262*2+4] + call dword [eax-8] + jnc .l1 + add esp, 262*2+4 +.reterr: + stc + popa + ret +.found: + add esp, 262*2+4 +; if this is LFN entry, advance to true entry + cmp byte [edi+11], 0xF + jnz @f + lea eax, [esp+0Ch+20h] + call dword [eax-8] + jc .reterr +@@: + add esp, 8 ; CF=0 + push esi + push edi + popa + ret + +uglobal +; this is for delete support +fd_prev_sector dd ? +fd_prev_prev_sector dd ? +endg + +flp_root_next: + cmp edi, OS_BASE+0xD200-0x20 + jae @f + add edi, 0x20 + ret ; CF=0 +@@: +; read next sector + inc dword [eax] + cmp dword [eax], 14 + jae flp_root_first.readerr + push [fd_prev_sector] + pop [fd_prev_prev_sector] + push eax + mov eax, [eax] + add eax, 19-1 + mov [fd_prev_sector], eax + pop eax +flp_root_first: + mov eax, [eax] + pusha + add eax, 19 + call read_chs_sector + popa + cmp [FDC_Status], 0 + jnz .readerr + mov edi, FDD_BUFF + ret ; CF=0 +.readerr: + stc + ret + +flp_rootmem_first: + mov edi, FLOPPY_BUFF + clc + ret +flp_rootmem_next: + add edi, 0x20 + cmp edi, FLOPPY_BUFF+14*0x200 + cmc +flp_rootmem_next_write: +flp_rootmem_begin_write: +flp_rootmem_end_write: + ret +flp_rootmem_extend_dir: + stc + ret + +flp_notroot_next: + cmp edi, OS_BASE+0xD200-0x20 + jae flp_notroot_next_sector + add edi, 0x20 + ret ; CF=0 +flp_notroot_next_sector: + push ecx + mov ecx, [eax] + push [fd_prev_sector] + pop [fd_prev_prev_sector] + add ecx, 31 + mov [fd_prev_sector], ecx + mov ecx, [(ecx-31)*2+FLOPPY_FAT] + and ecx, 0xFFF + cmp ecx, 2849 + jae flp_notroot_first.err2 + mov [eax], ecx + pop ecx +flp_notroot_first: + mov eax, [eax] + cmp eax, 2 + jb .err + cmp eax, 2849 + jae .err + pusha + add eax, 31 + call read_chs_sector + popa + mov edi, FDD_BUFF + cmp [FDC_Status], 0 + jnz .err + ret ; CF=0 +.err2: + pop ecx +.err: + stc + ret +flp_notroot_begin_write: + pusha + mov eax, [eax] + add eax, 31 + call read_chs_sector + popa + ret +flp_notroot_end_write: + pusha + mov eax, [eax] + add eax, 31 + call save_chs_sector + popa + ret +flp_notroot_next_write: + cmp edi, OS_BASE+0xD200 + jae @f + ret +@@: + call flp_notroot_end_write + jmp flp_notroot_next_sector +flp_notroot_extend_dir: +; find free cluster in FAT + pusha + xor eax, eax + mov edi, FLOPPY_FAT + mov ecx, 2849 + repnz scasw + jnz .notfound + mov word [edi-2], 0xFFF ; mark as last cluster + sub edi, FLOPPY_FAT + shr edi, 1 + dec edi + mov eax, [esp+28] + mov ecx, [eax] + mov [FLOPPY_FAT+ecx*2], di + mov [eax], edi + xor eax, eax + mov edi, FDD_BUFF + mov ecx, 128 + rep stosd + popa + call flp_notroot_end_write + mov edi, FDD_BUFF + clc + ret +.notfound: + popa + stc + ret + +fd_find_lfn: +; in: esi+ebp -> name +; out: CF=1 - file not found +; else CF=0 and edi->direntry, eax=directory cluster (0 for root) + push esi edi + push 0 + push flp_root_first + push flp_root_next +.loop: + call fat_find_lfn + jc .notfound + cmp byte [esi], 0 + jz .found +.continue: + test byte [edi+11], 10h + jz .notfound + movzx eax, word [edi+26] ; cluster + mov [esp+8], eax + mov dword [esp+4], flp_notroot_first + mov dword [esp], flp_notroot_next + jmp .loop +.notfound: + add esp, 12 + pop edi esi + stc + ret +.found: + test ebp, ebp + jz @f + mov esi, ebp + xor ebp, ebp + jmp .continue +@@: + mov eax, [esp+8] + add eax, 31 + cmp dword [esp], flp_root_next + jnz @f + add eax, -31+19 +@@: + add esp, 16 ; CF=0 + pop esi + ret + +;---------------------------------------------------------------- +; +; fs_FloppyRead - LFN variant for reading floppy +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to read, 0+ +; edx mem location to return data +; +; ret ebx = bytes read or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_FloppyRead: + call read_flp_fat + cmp byte [esi], 0 + jnz @f + or ebx, -1 + mov eax, 10 ; access denied + ret +@@: + push edi + call fd_find_lfn + jnc .found + pop edi + or ebx, -1 + mov eax, 5 ; file not found + ret +.found: + test ebx, ebx + jz .l1 + cmp dword [ebx+4], 0 + jz @f + xor ebx, ebx +.reteof: + mov eax, 6 ; EOF + pop edi + ret +@@: + mov ebx, [ebx] +.l1: + push ecx edx + push 0 + mov eax, [edi+28] + sub eax, ebx + jb .eof + cmp eax, ecx + jae @f + mov ecx, eax + mov byte [esp], 6 ; EOF +@@: + movzx edi, word [edi+26] +.new: + jecxz .done + test edi, edi + jz .eof + cmp edi, 0xFF8 + jae .eof + sub ebx, 512 + jae .skip + lea eax, [edi+31] + pusha + call read_chs_sector + popa + cmp [FDC_Status], 0 + jnz .err + lea eax, [FDD_BUFF+ebx+512] + neg ebx + push ecx + cmp ecx, ebx + jbe @f + mov ecx, ebx +@@: + mov ebx, edx + call memmove + add edx, ecx + sub [esp], ecx + pop ecx + xor ebx, ebx +.skip: + movzx edi, word [edi*2+FLOPPY_FAT] + jmp .new +.done: + mov ebx, edx + pop eax edx ecx edi + sub ebx, edx + ret +.eof: + mov ebx, edx + pop eax edx ecx + jmp .reteof +.err: + mov ebx, edx + pop eax edx ecx edi + sub ebx, edx + mov al, 11 + ret + +;---------------------------------------------------------------- +; +; fs_FloppyReadFolder - LFN variant for reading floppy folders +; +; esi points to filename +; ebx pointer to structure: 32-bit number = first wanted block, 0+ +; & flags (bitfields) +; flags: bit 0: 0=ANSI names, 1=UNICODE names +; ecx number of blocks to read, 0+ +; edx mem location to return data +; +; ret ebx = blocks read or 0xffffffff folder not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_FloppyReadFolder: + call read_flp_fat + push edi + cmp byte [esi], 0 + jz .root + call fd_find_lfn + jnc .found + pop edi + or ebx, -1 + mov eax, ERROR_FILE_NOT_FOUND + ret +.found: + test byte [edi+11], 0x10 ; do not allow read files + jnz .found_dir + pop edi + or ebx, -1 + mov eax, ERROR_ACCESS_DENIED + ret +.found_dir: + movzx eax, word [edi+26] + add eax, 31 + push 0 + jmp .doit +.root: + mov eax, 19 + push 14 +.doit: + push ecx ebp + sub esp, 262*2 ; reserve space for LFN + mov ebp, esp + push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE names + mov ebx, [ebx] +; init header + push eax ecx + mov edi, edx + mov ecx, 32/4 + xor eax, eax + rep stosd + pop ecx eax + mov byte [edx], 1 ; version + mov esi, edi ; esi points to BDFE +.main_loop: + pusha + call read_chs_sector + popa + cmp [FDC_Status], 0 + jnz .error + mov edi, FDD_BUFF + push eax +.l1: + call fat_get_name + jc .l2 + cmp byte [edi+11], 0xF + jnz .do_bdfe + add edi, 0x20 + cmp edi, OS_BASE+0xD200 + jb .do_bdfe + pop eax + inc eax + dec byte [esp+262*2+12] + jz .done + jns @f +; read next sector from FAT + mov eax, [(eax-31-1)*2+FLOPPY_FAT] + and eax, 0xFFF + cmp eax, 0xFF8 + jae .done + add eax, 31 + mov byte [esp+262*2+12], 0 +@@: + pusha + call read_chs_sector + popa + cmp [FDC_Status], 0 + jnz .error + mov edi, FDD_BUFF + push eax +.do_bdfe: + inc dword [edx+8] ; new file found + dec ebx + jns .l2 + dec ecx + js .l2 + inc dword [edx+4] ; new file block copied + call fat_entry_to_bdfe +.l2: + add edi, 0x20 + cmp edi, OS_BASE+0xD200 + jb .l1 + pop eax + inc eax + dec byte [esp+262*2+12] + jz .done + jns @f +; read next sector from FAT + mov eax, [(eax-31-1)*2+FLOPPY_FAT] + and eax, 0xFFF + cmp eax, 0xFF8 + jae .done + add eax, 31 + mov byte [esp+262*2+12], 0 +@@: + jmp .main_loop +.error: + add esp, 262*2+4 + pop ebp ecx edi edi + or ebx, -1 + mov eax, ERROR_FILE_NOT_FOUND + ret +.done: + add esp, 262*2+4 + pop ebp + mov ebx, [edx+4] + xor eax, eax + dec ecx + js @f + mov al, ERROR_END_OF_FILE +@@: + pop ecx edi edi + ret + +;---------------------------------------------------------------- +; +; fs_FloppyRewrite - LFN variant for writing sys floppy +; +; esi points to filename +; ebx ignored (reserved) +; ecx number of bytes to write, 0+ +; edx mem location to data +; +; ret ebx = number of written bytes +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +@@: + mov eax, ERROR_ACCESS_DENIED + xor ebx, ebx + ret +fsfrfe2: + popad +fsfrfe: + mov eax, 11 + xor ebx, ebx + ret + +fs_FloppyCreateFolder: + mov al, 1 + jmp fs_FloppyRewrite.common + +fs_FloppyRewrite: + xor eax, eax +.common: + cmp byte [esi], 0 + jz @b + call read_flp_fat + cmp [FDC_Status], 0 + jnz fsfrfe + pushad + xor edi, edi + push esi + test ebp, ebp + jz @f + mov esi, ebp +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jnz @b + lea edi, [esi-1] + jmp @b +@@: + pop esi + test edi, edi + jnz .noroot + test ebp, ebp + jnz .hasebp + call read_flp_root + cmp [FDC_Status], 0 + jnz fsfrfe2 + push flp_rootmem_extend_dir + push flp_rootmem_end_write + push flp_rootmem_next_write + push flp_rootmem_begin_write + xor ebp, ebp + push ebp + push flp_rootmem_first + push flp_rootmem_next + jmp .common1 +.hasebp: + mov eax, ERROR_ACCESS_DENIED + cmp byte [ebp], 0 + jz .ret1 + push ebp + xor ebp, ebp + call fd_find_lfn + pop esi + jc .notfound0 + jmp .common0 +.noroot: + mov eax, ERROR_ACCESS_DENIED + cmp byte [edi+1], 0 + jz .ret1 +; check existence + mov byte [edi], 0 + push edi + call fd_find_lfn + pop esi + mov byte [esi], '/' + jnc @f +.notfound0: + mov eax, ERROR_FILE_NOT_FOUND +.ret1: + mov [esp+28], eax + popad + xor ebx, ebx + ret +@@: + inc esi +.common0: + test byte [edi+11], 0x10 ; must be directory + mov eax, ERROR_ACCESS_DENIED + jz .ret1 + movzx ebp, word [edi+26] ; ebp=cluster + mov eax, ERROR_FAT_TABLE + cmp ebp, 2 + jb .ret1 + cmp ebp, 2849 + jae .ret1 + push flp_notroot_extend_dir + push flp_notroot_end_write + push flp_notroot_next_write + push flp_notroot_begin_write + push ebp + push flp_notroot_first + push flp_notroot_next +.common1: + call fat_find_lfn + jc .notfound +; found + test byte [edi+11], 10h + jz .exists_file +; found directory; if we are creating directory, return OK, +; if we are creating file, say "access denied" + add esp, 28 + popad + test al, al + mov eax, ERROR_ACCESS_DENIED + jz @f + mov al, 0 +@@: + xor ebx, ebx + ret +.exists_file: +; found file; if we are creating directory, return "access denied", +; if we are creating file, delete existing file and continue + cmp byte [esp+28+28], 0 + jz @f + add esp, 28 + popad + mov eax, ERROR_ACCESS_DENIED + xor ebx, ebx + ret +@@: +; delete FAT chain + push edi + xor eax, eax + mov dword [edi+28], eax ; zero size + xchg ax, word [edi+26] ; start cluster + test eax, eax + jz .done1 +@@: + cmp eax, 0xFF8 + jae .done1 + lea edi, [FLOPPY_FAT + eax*2] ; position in FAT + xor eax, eax + xchg ax, [edi] + jmp @b +.done1: + pop edi + call get_time_for_file + mov [edi+22], ax + call get_date_for_file + mov [edi+24], ax + mov [edi+18], ax + or byte [edi+11], 20h ; set 'archive' attribute + jmp .doit +.notfound: +; file is not found; generate short name + call fat_name_is_legal + jc @f + add esp, 28 + popad + mov eax, ERROR_FILE_NOT_FOUND + xor ebx, ebx + ret +@@: + sub esp, 12 + mov edi, esp + call fat_gen_short_name +.test_short_name_loop: + push esi edi ecx + mov esi, edi + lea eax, [esp+12+12+8] + mov [eax], ebp + call dword [eax-4] + jc .found +.test_short_name_entry: + cmp byte [edi+11], 0xF + jz .test_short_name_cont + mov ecx, 11 + push esi edi + repz cmpsb + pop edi esi + jz .short_name_found +.test_short_name_cont: + lea eax, [esp+12+12+8] + call dword [eax-8] + jnc .test_short_name_entry + jmp .found +.short_name_found: + pop ecx edi esi + call fat_next_short_name + jnc .test_short_name_loop +.disk_full: + add esp, 12+28 + popa + mov eax, ERROR_DISK_FULL + xor ebx, ebx + ret +.found: + pop ecx edi esi +; now find space in directory +; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' + mov al, '~' + push ecx edi + mov ecx, 8 + repnz scasb + push 1 + pop eax ; 1 entry + jnz .notilde +; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total + xor eax, eax +@@: + cmp byte [esi], 0 + jz @f + inc esi + inc eax + jmp @b +@@: + sub esi, eax + add eax, 12+13 + mov ecx, 13 + push edx + cdq + div ecx + pop edx +.notilde: + push -1 + push -1 +; find successive entries in directory + xor ecx, ecx + push eax + lea eax, [esp+12+8+12+8] + mov [eax], ebp + call dword [eax-4] + pop eax + jnc .scan_dir +.fsfrfe3: + add esp, 8+8+12+28 + popad + mov eax, 11 + xor ebx, ebx + ret +.scan_dir: + cmp byte [edi], 0 + jz .free + cmp byte [edi], 0xE5 + jz .free + xor ecx, ecx +.scan_cont: + push eax + lea eax, [esp+12+8+12+8] + call dword [eax-8] + pop eax + jnc .scan_dir + cmp [FDC_Status], 0 + jnz .fsfrfe3 + push eax + lea eax, [esp+12+8+12+8] + call dword [eax+16] ; extend directory + pop eax + jnc .scan_dir + add esp, 8+8+12+28 + popad + mov eax, ERROR_DISK_FULL + xor ebx, ebx + ret +.free: + test ecx, ecx + jnz @f + mov [esp], edi + mov ecx, [esp+8+8+12+8] + mov [esp+4], ecx + xor ecx, ecx +@@: + inc ecx + cmp ecx, eax + jb .scan_cont +; found! +; calculate name checksum + push esi ecx + mov esi, [esp+8+8] + mov ecx, 11 + xor eax, eax +@@: + ror al, 1 + add al, [esi] + inc esi + loop @b + pop ecx esi + pop edi + pop dword [esp+8+12+8] +; edi points to first entry in free chunk + dec ecx + jz .nolfn + push esi + push eax + lea eax, [esp+8+8+12+8] + call dword [eax+4] ; begin write + mov al, 40h +.writelfn: + or al, cl + mov esi, [esp+4] + push ecx + dec ecx + imul ecx, 13 + add esi, ecx + stosb + mov cl, 5 + call fs_RamdiskRewrite.read_symbols + mov ax, 0xF + stosw + mov al, [esp+4] + stosb + mov cl, 6 + call fs_RamdiskRewrite.read_symbols + xor eax, eax + stosw + mov cl, 2 + call fs_RamdiskRewrite.read_symbols + pop ecx + lea eax, [esp+8+8+12+8] + call dword [eax+8] ; next write + xor eax, eax + loop .writelfn + pop eax + pop esi +; lea eax, [esp+8+12+8] +; call dword [eax+12] ; end write +.nolfn: + xchg esi, [esp] + mov ecx, 11 + rep movsb + mov word [edi], 20h ; attributes + sub edi, 11 + pop esi ecx + add esp, 12 + mov byte [edi+13], 0 ; tenths of a second at file creation time + call get_time_for_file + mov [edi+14], ax ; creation time + mov [edi+22], ax ; last write time + call get_date_for_file + mov [edi+16], ax ; creation date + mov [edi+24], ax ; last write date + mov [edi+18], ax ; last access date + and word [edi+20], 0 ; high word of cluster + and word [edi+26], 0 ; low word of cluster - to be filled + and dword [edi+28], 0 ; file size - to be filled + cmp byte [esp+28+28], 0 + jz .doit +; create directory + mov byte [edi+11], 10h ; attributes: folder + mov ecx, 32*2 + mov edx, edi +.doit: + lea eax, [esp+8] + call dword [eax+12] ; flush directory + push ecx + push edi + push 0 + mov esi, edx + test ecx, ecx + jz .done + mov ecx, 2849 + mov edi, FLOPPY_FAT + push 0 ; first cluster +.write_loop: +; allocate new cluster + xor eax, eax + repnz scasw + mov al, ERROR_DISK_FULL + jnz .ret + dec edi + dec edi + + mov eax, edi + sub eax, FLOPPY_FAT + + shr eax, 1 ; eax = cluster + mov word [edi], 0xFFF ; mark as last cluster + xchg edi, [esp+4] + cmp dword [esp], 0 + jz .first + stosw + jmp @f +.first: + mov [esp], eax +@@: + mov edi, [esp+4] + inc ecx +; write data + push ecx edi + mov ecx, 512 + cmp dword [esp+20], ecx + jae @f + mov ecx, [esp+20] +@@: + mov edi, FDD_BUFF + cmp byte [esp+24+28+28], 0 + jnz .writedir + push ecx + rep movsb + pop ecx +.writedircont: + push ecx + sub ecx, 512 + neg ecx + push eax + xor eax, eax + rep stosb + pop eax + add eax, 31 + pusha + call save_chs_sector + popa + pop ecx + cmp [FDC_Status], 0 + jnz .diskerr + sub [esp+20], ecx + pop edi ecx + jnz .write_loop +.done: + xor eax, eax +.ret: + pop ebx edi edi ecx + mov [esp+28+28], eax + lea eax, [esp+8] + call dword [eax+4] + mov [edi+26], bx + mov ebx, esi + sub ebx, edx + mov [edi+28], ebx + call dword [eax+12] + mov [esp+28+16], ebx + test ebp, ebp + jnz @f + call save_flp_root +@@: + add esp, 28 + cmp [FDC_Status], 0 + jnz .err3 + call save_flp_fat + cmp [FDC_Status], 0 + jnz .err3 + popa + ret +.err3: + popa + mov al, 11 + xor ebx, ebx + ret +.diskerr: + sub esi, ecx + mov eax, 11 + pop edi ecx + jmp .ret +.writedir: + push ecx + mov ecx, 32/4 + push ecx esi + rep movsd + pop esi ecx + mov dword [edi-32], '. ' + mov dword [edi-32+4], ' ' + mov dword [edi-32+8], ' ' + mov byte [edi-32+11], 10h + mov word [edi-32+26], ax + push esi + rep movsd + pop esi + mov dword [edi-32], '.. ' + mov dword [edi-32+4], ' ' + mov dword [edi-32+8], ' ' + mov byte [edi-32+11], 10h + mov ecx, [esp+28+8] + mov word [edi-32+26], cx + pop ecx + jmp .writedircont + +;---------------------------------------------------------------- +; +; fs_FloppyWrite - LFN variant for writing to floppy +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to write, 0+ +; edx mem location to data +; +; ret ebx = bytes written (maybe 0) +; eax = 0 ok write or other = errormsg +; +;-------------------------------------------------------------- + +@@: + push ERROR_ACCESS_DENIED +fs_FloppyWrite.ret0: + pop eax + xor ebx, ebx + ret + +fs_FloppyWrite.ret11: + push 11 + jmp fs_FloppyWrite.ret0 + +fs_FloppyWrite: + cmp byte [esi], 0 + jz @b + call read_flp_fat + cmp [FDC_Status], 0 + jnz .ret11 + pushad + call fd_find_lfn + jnc .found + popad + push ERROR_FILE_NOT_FOUND + jmp .ret0 +.found: +; FAT does not support files larger than 4GB + test ebx, ebx + jz .l1 + cmp dword [ebx+4], 0 + jz @f +.eof: + popad + push ERROR_END_OF_FILE + jmp .ret0 +@@: + mov ebx, [ebx] +.l1: +; now edi points to direntry, ebx=start byte to write, +; ecx=number of bytes to write, edx=data pointer + +; extend file if needed + add ecx, ebx + jc .eof ; FAT does not support files larger than 4GB + push eax ; save directory cluster + push 0 ; return value=0 + + call get_time_for_file + mov [edi+22], ax ; last write time + call get_date_for_file + mov [edi+24], ax ; last write date + mov [edi+18], ax ; last access date + + push dword [edi+28] ; save current file size + cmp ecx, [edi+28] + jbe .length_ok + cmp ecx, ebx + jz .length_ok + call floppy_extend_file + jnc .length_ok + mov [esp+4], eax +; floppy_extend_file can return two error codes: FAT table error or disk full. +; First case is fatal error, in second case we may write some data + cmp al, ERROR_DISK_FULL + jz .disk_full + pop eax + pop eax + mov [esp+4+28], eax + pop eax + popad + xor ebx, ebx + ret +.disk_full: +; correct number of bytes to write + mov ecx, [edi+28] + cmp ecx, ebx + ja .length_ok +.ret: + pop eax + pop eax + mov [esp+4+28], eax ; eax=return value + pop eax + sub edx, [esp+20] + mov [esp+16], edx ; ebx=number of written bytes + popad + ret +.length_ok: +; save FAT & directory +; note that directory must be saved first because save_flp_fat uses buffer at 0xD000 + mov esi, [edi+28] + movzx edi, word [edi+26] ; starting cluster + mov eax, [esp+8] + pusha + call save_chs_sector + popa + cmp [FDC_Status], 0 + jnz .device_err + call save_flp_fat + cmp [FDC_Status], 0 + jz @f +.device_err: + mov byte [esp+4], 11 + jmp .ret +@@: + +; now ebx=start pos, ecx=end pos, both lie inside file + sub ecx, ebx + jz .ret + call SetUserInterrupts +.write_loop: +; skip unmodified sectors + cmp dword [esp], 0x200 + jb .modify + sub ebx, 0x200 + jae .skip + add ebx, 0x200 +.modify: + lea eax, [edi+31] ; current sector +; get length of data in current sector + push ecx + sub ebx, 0x200 + jb .hasdata + neg ebx + xor ecx, ecx + jmp @f +.hasdata: + neg ebx + cmp ecx, ebx + jbe @f + mov ecx, ebx +@@: +; load sector if needed + cmp dword [esp+4], 0 ; we don't need to read uninitialized data + jz .noread + cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten + jz .noread + cmp ecx, esi ; (same for the last sector) + jz .noread + pusha + call read_chs_sector + popa + cmp [FDC_Status], 0 + jz @f +.device_err2: + pop ecx + jmp .device_err +@@: +.noread: +; zero uninitialized data if file was extended (because floppy_extend_file does not this) + push eax ecx edi + xor eax, eax + mov ecx, 0x200 + sub ecx, [esp+4+12] + jbe @f + mov edi, FDD_BUFF + add edi, [esp+4+12] + rep stosb +@@: +; zero uninitialized data in the last sector + mov ecx, 0x200 + sub ecx, esi + jbe @f + mov edi, FDD_BUFF + add edi, esi + rep stosb +@@: + pop edi ecx eax +; copy new data + push eax + mov eax, edx + neg ebx + jecxz @f + add ebx, FDD_BUFF+0x200 + call memmove + xor ebx, ebx +@@: + pop eax +; save sector + pusha + call save_chs_sector + popa + cmp [FDC_Status], 0 + jnz .device_err2 + add edx, ecx + sub [esp], ecx + pop ecx + jz .done +.skip: +.next_cluster: + movzx edi, word [edi*2+FLOPPY_FAT] + sub esi, 0x200 + jae @f + xor esi, esi +@@: + sub dword [esp], 0x200 + jae .write_loop + and dword [esp], 0 + jmp .write_loop +.done: + mov [fdc_irq_func], fdc_null + jmp .ret + +floppy_extend_file.zero_size: + xor eax, eax + jmp floppy_extend_file.start_extend + +; extends file on floppy to given size (new data area is undefined) +; in: edi->direntry, ecx=new size +; out: CF=0 => OK, eax=0 +; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL) +floppy_extend_file: + push ecx +; find the last cluster of file + movzx eax, word [edi+26] ; first cluster + mov ecx, [edi+28] + jecxz .zero_size +@@: + sub ecx, 0x200 + jbe @f + mov eax, [eax*2+FLOPPY_FAT] + and eax, 0xFFF + jz .fat_err + cmp eax, 0xFF8 + jb @b +.fat_err: + pop ecx + push ERROR_FAT_TABLE + pop eax + stc + ret +@@: + push eax + mov eax, [eax*2+FLOPPY_FAT] + and eax, 0xFFF + cmp eax, 0xFF8 + pop eax + jb .fat_err +; set length to full number of sectors + sub [edi+28], ecx +.start_extend: + pop ecx +; now do extend + push edx esi + mov esi, FLOPPY_FAT+2*2 ; start scan from cluster 2 + mov edx, 2847 ; number of clusters to scan +.extend_loop: + cmp [edi+28], ecx + jae .extend_done +; add new sector + push ecx + push edi +.scan: + mov ecx, edx + mov edi, esi + jecxz .disk_full + push eax + xor eax, eax + repnz scasw + pop eax + jnz .disk_full + mov word [edi-2], 0xFFF + mov esi, edi + mov edx, ecx + sub edi, FLOPPY_FAT + shr edi, 1 + dec edi ; now edi=new cluster + test eax, eax + jz .first_cluster + mov [FLOPPY_FAT+eax*2], di + jmp @f +.first_cluster: + pop eax ; eax->direntry + push eax + mov [eax+26], di +@@: + mov eax, edi ; eax=new cluster + pop edi ; edi->direntry + pop ecx ; ecx=required size + add dword [edi+28], 0x200 + jmp .extend_loop +.extend_done: + mov [edi+28], ecx + pop esi edx + xor eax, eax ; CF=0 + ret +.disk_full: + pop edi ecx + pop esi edx + stc + push ERROR_DISK_FULL + pop eax + ret + +;---------------------------------------------------------------- +; +; fs_FloppySetFileEnd - set end of file on floppy +; +; esi points to filename +; ebx points to 64-bit number = new file size +; ecx ignored (reserved) +; edx ignored (reserved) +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +fs_FloppySetFileEnd: + call read_flp_fat + cmp [FDC_Status], 0 + jnz ret11 + cmp byte [esi], 0 + jnz @f +.access_denied: + push ERROR_ACCESS_DENIED + jmp .ret +@@: + push edi + call fd_find_lfn + jnc @f + pop edi + push ERROR_FILE_NOT_FOUND +.ret: + pop eax + jmp .doret +@@: +; must not be directory + test byte [edi+11], 10h + jz @f + pop edi + jmp .access_denied +@@: +; file size must not exceed 4 Gb + cmp dword [ebx+4], 0 + jz @f + pop edi + push ERROR_END_OF_FILE + jmp .ret +@@: + push eax +; set file modification date/time to current + call fat_update_datetime + mov eax, [ebx] + cmp eax, [edi+28] + jb .truncate + ja .expand + pop eax + pushad + call save_chs_sector + popad + pop edi + xor eax, eax + cmp [FDC_Status], 0 + jz @f + mov al, 11 +@@: +.doret: + mov [fdc_irq_func], fdc_null + ret +.expand: + push ecx + push dword [edi+28] ; save old size + mov ecx, eax + call floppy_extend_file + push eax ; return code + jnc .expand_ok + cmp al, ERROR_DISK_FULL + jz .disk_full + pop eax ecx ecx edi edi + jmp .doret +.device_err: + pop eax +.device_err2: + pop ecx ecx eax edi + push 11 + jmp .ret +.disk_full: +.expand_ok: +; save directory & FAT + mov eax, [edi+28] + xchg eax, [esp+12] + movzx edi, word [edi+26] + pusha + call save_chs_sector + popa + cmp [FDC_Status], 0 + jnz .device_err + call save_flp_fat + cmp [FDC_Status], 0 + jnz .device_err + call SetUserInterrupts +; now zero new data +; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code +.zero_loop: + sub dword [esp+4], 0x200 + jae .next_cluster + cmp dword [esp+4], -0x200 + jz .noread + lea eax, [edi+31] + pusha + call read_chs_sector + popa + cmp [FDC_Status], 0 + jnz .err_next +.noread: + mov ecx, [esp+4] + neg ecx + push edi + mov edi, FDD_BUFF+0x200 + add edi, [esp+8] + xor eax, eax + mov [esp+8], eax + rep stosb + pop edi + lea eax, [edi+31] + pusha + call save_chs_sector + popa + cmp [FDC_Status], 0 + jz .next_cluster +.err_next: + mov byte [esp], 11 +.next_cluster: + sub dword [esp+12], 0x200 + jbe .expand_done + movzx edi, word [FLOPPY_FAT+edi*2] + jmp .zero_loop +.expand_done: + pop eax ecx ecx edi edi + jmp .doret +.truncate: + mov [edi+28], eax + push ecx + movzx ecx, word [edi+26] + test eax, eax + jz .zero_size +; find new last sector +@@: + sub eax, 0x200 + jbe @f + movzx ecx, word [FLOPPY_FAT+ecx*2] + jmp @b +@@: +; we will zero data at the end of last sector - remember it + push ecx +; terminate FAT chain + lea ecx, [FLOPPY_FAT+ecx+ecx] + push dword [ecx] + mov word [ecx], 0xFFF + pop ecx + and ecx, 0xFFF + jmp .delete +.zero_size: + and word [edi+26], 0 + push 0 +.delete: +; delete FAT chain starting with ecx +; mark all clusters as free + cmp ecx, 0xFF8 + jae .deleted + lea ecx, [FLOPPY_FAT+ecx+ecx] + push dword [ecx] + and word [ecx], 0 + pop ecx + and ecx, 0xFFF + jmp .delete +.deleted: + mov edi, [edi+28] +; save directory & FAT + mov eax, [esp+8] + pusha + call save_chs_sector + popa + cmp [FDC_Status], 0 + jnz .device_err2 + call save_flp_fat + cmp [FDC_Status], 0 + jnz .device_err2 +; zero last sector, ignore errors + pop eax + add eax, 31 + and edi, 0x1FF + jz .truncate_done + call SetUserInterrupts + pusha + call read_chs_sector + popa + add edi, FDD_BUFF + mov ecx, FDD_BUFF+0x200 + sub ecx, edi + push eax + xor eax, eax + rep stosb + pop eax + pusha + call save_chs_sector + popa +.truncate_done: + pop ecx eax edi + xor eax, eax + jmp .doret + +fs_FloppyGetFileInfo: + call read_flp_fat + cmp [FDC_Status], 0 + jnz ret11 + cmp byte [esi], 0 + jnz @f + mov eax, 2 ; unsupported + ret +@@: + push edi + call fd_find_lfn + jmp fs_GetFileInfo_finish + +ret11: + mov eax, 11 + ret + +fs_FloppySetFileInfo: + call read_flp_fat + cmp [FDC_Status], 0 + jnz ret11 + cmp byte [esi], 0 + jnz @f + mov eax, 2 ; unsupported + ret +@@: + push edi + call fd_find_lfn + jnc @f + pop edi + mov eax, ERROR_FILE_NOT_FOUND + ret +@@: + push eax + call bdfe_to_fat_entry + pop eax + pusha + call save_chs_sector + popa + pop edi + xor eax, eax + cmp [FDC_Status], al + jz @f + mov al, 11 +@@: + ret + +;---------------------------------------------------------------- +; +; fs_FloppyDelete - delete file or empty folder from floppy +; +; esi points to filename +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +fs_FloppyDelete: + call read_flp_fat + cmp [FDC_Status], 0 + jz @f + push 11 + jmp .pop_ret +@@: + cmp byte [esi], 0 + jnz @f +; cannot delete root! +.access_denied: + push ERROR_ACCESS_DENIED +.pop_ret: + pop eax + ret +@@: + and [fd_prev_sector], 0 + and [fd_prev_prev_sector], 0 + push edi + call fd_find_lfn + jnc .found + pop edi + push ERROR_FILE_NOT_FOUND + jmp .pop_ret +.found: + cmp dword [edi], '. ' + jz .access_denied2 + cmp dword [edi], '.. ' + jz .access_denied2 + test byte [edi+11], 10h + jz .dodel +; we can delete only empty folders! + push eax + movzx eax, word [edi+26] + push ebx + pusha + add eax, 31 + call read_chs_sector + popa + mov ebx, FDD_BUFF + 2*0x20 +.checkempty: + cmp byte [ebx], 0 + jz .empty + cmp byte [ebx], 0xE5 + jnz .notempty + add ebx, 0x20 + cmp ebx, FDD_BUFF + 0x200 + jb .checkempty + movzx eax, word [FLOPPY_FAT + eax*2] + pusha + add eax, 31 + call read_chs_sector + popa + mov ebx, FDD_BUFF + jmp .checkempty +.notempty: + pop ebx + pop eax +.access_denied2: + pop edi + jmp .access_denied +.empty: + pop ebx + pop eax + pusha + call read_chs_sector + popa +.dodel: + push eax + movzx eax, word [edi+26] + xchg eax, [esp] +; delete folder entry + mov byte [edi], 0xE5 +; delete LFN (if present) +.lfndel: + cmp edi, FDD_BUFF + ja @f + cmp [fd_prev_sector], 0 + jz .lfndone + push [fd_prev_sector] + push [fd_prev_prev_sector] + pop [fd_prev_sector] + and [fd_prev_prev_sector], 0 + pusha + call save_chs_sector + popa + pop eax + pusha + call read_chs_sector + popa + mov edi, FDD_BUFF+0x200 +@@: + sub edi, 0x20 + cmp byte [edi], 0xE5 + jz .lfndone + cmp byte [edi+11], 0xF + jnz .lfndone + mov byte [edi], 0xE5 + jmp .lfndel +.lfndone: + pusha + call save_chs_sector + popa +; delete FAT chain + pop eax + test eax, eax + jz .done +@@: + lea eax, [FLOPPY_FAT + eax*2] + push dword [eax] + and word [eax], 0 + pop eax + and eax, 0xFFF + jnz @b +.done: + call save_flp_fat + pop edi + xor eax, eax + ret + +; \end{diamond} diff --git a/kernel/trunk/fs/fat32.inc b/kernel/trunk/fs/fat32.inc index c56d788f8..8b7c0d313 100644 --- a/kernel/trunk/fs/fat32.inc +++ b/kernel/trunk/fs/fat32.inc @@ -1,2935 +1,2940 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; FAT32.INC ;; -;; ;; -;; FAT16/32 functions for KolibriOS ;; -;; ;; -;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; -;; ;; -;; See file COPYING for details ;; -;; 04.02.2007 LFN create folder - diamond ;; -;; 08.10.2006 LFN delete file/folder - diamond ;; -;; 20.08.2006 LFN set file size (truncate/extend) - diamond ;; -;; 17.08.2006 LFN write/append to file - diamond ;; -;; 23.06.2006 LFN start application - diamond ;; -;; 15.06.2006 LFN get/set file/folder info - diamond ;; -;; 27.05.2006 LFN create/rewrite file - diamond ;; -;; 04.05.2006 LFN read folder - diamond ;; -;; 29.04.2006 Elimination of hangup after the ;; -;; expiration hd_wait_timeout - Mario79 ;; -;; 23.04.2006 LFN read file - diamond ;; -;; 28.01.2006 find all Fat16/32 partition in all input point ;; -;; to MBR, see file part_set.inc - Mario79 ;; -;; 15.01.2005 get file size/attr/date, file_append - ATV ;; -;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;; -;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;; -;; 23.11.2004 don't allow overwrite dir with file - ATV ;; -;; 18.11.2004 get_disk_info and more error codes - ATV ;; -;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;; -;; 10.11.2004 removedir clear whole directory structure - ATV ;; -;; 08.11.2004 rename - ATV ;; -;; 30.10.2004 file_read return also dirsize in bytes - ATV ;; -;; 20.10.2004 Makedir/Removedir - ATV ;; -;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;; -;; 06.9.2004 Fix free space by Mario79 added - MH ;; -;; 24.5.2004 Write back buffer for File_write -VT ;; -;; 20.5.2004 File_read function to work with syscall 58 - VT ;; -;; 30.3.2004 Error parameters at function return - VT ;; -;; 01.5.2002 Bugfix in device write - VT ;; -;; 20.5.2002 Hd status check - VT ;; -;; 29.6.2002 Improved fat32 verification - VT ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00 - -ERROR_SUCCESS = 0 -ERROR_DISK_BASE = 1 -ERROR_UNSUPPORTED_FS = 2 -ERROR_UNKNOWN_FS = 3 -ERROR_PARTITION = 4 -ERROR_FILE_NOT_FOUND = 5 -ERROR_END_OF_FILE = 6 -ERROR_MEMORY_POINTER = 7 -ERROR_DISK_FULL = 8 -ERROR_FAT_TABLE = 9 -ERROR_ACCESS_DENIED = 10 -ERROR_DEVICE = 11 - -PUSHAD_EAX equ [esp+28] -PUSHAD_ECX equ [esp+24] -PUSHAD_EDX equ [esp+20] -PUSHAD_EBX equ [esp+16] -PUSHAD_EBP equ [esp+8] -PUSHAD_ESI equ [esp+4] -PUSHAD_EDI equ [esp+0] - -uglobal -align 4 -partition_count dd 0 ; partitions found by set_FAT32_variables -longname_sec1 dd 0 ; used by analyze_directory to save 2 previous -longname_sec2 dd 0 ; directory sectors for delete long filename - -hd_error dd 0 ; set by wait_for_sector_buffer -hd_setup dd 0 -hd_wait_timeout dd 0 - -cluster_tmp dd 0 ; used by analyze_directory - ; and analyze_directory_to_write - -file_size dd 0 ; used by file_read - -cache_search_start dd 0 ; used by find_empty_slot -endg - -iglobal -fat_in_cache dd -1 -endg - -uglobal -align 4 -fat_cache: times 512 db 0 - Sector512: ; label for dev_hdcd.inc - buffer: times 512 db 0 - fsinfo_buffer: times 512 db 0 -endg - -uglobal - fat16_root db 0 ; flag for fat16 rootdir - fat_change db 0 ; 1=fat has changed -endg - -reserve_hd1: - - cli - cmp [hd1_status],0 - je reserve_ok1 - - sti - call change_task - jmp reserve_hd1 - - reserve_ok1: - - push eax - mov eax,[CURRENT_TASK] - shl eax,5 - mov eax,[eax+CURRENT_TASK+TASKDATA.pid] - mov [hd1_status],eax - pop eax - sti - ret -;******************************************** - -uglobal -hd_in_cache db ? -endg - -reserve_hd_channel: -; BIOS disk accesses are protected with common mutex hd1_status -; This must be modified when hd1_status will not be valid! - cmp [hdpos], 0x80 - jae .ret - cmp [hdbase], 0x1F0 - jne .IDE_Channel_2 -.IDE_Channel_1: - cli - cmp [IDE_Channel_1],0 - je .reserve_ok_1 - sti - call change_task - jmp .IDE_Channel_1 -.IDE_Channel_2: - cli - cmp [IDE_Channel_2],0 - je .reserve_ok_2 - sti - call change_task - jmp .IDE_Channel_2 -.reserve_ok_1: - mov [IDE_Channel_1], 1 - push eax - mov al, 1 - jmp @f -.reserve_ok_2: - mov [IDE_Channel_2], 1 - push eax - mov al, 3 -@@: - cmp [hdid], 1 - sbb al, -1 - cmp al, [hd_in_cache] - jz @f - mov [hd_in_cache], al - call clear_hd_cache -@@: - pop eax - sti -.ret: - ret - -free_hd_channel: -; see comment at reserve_hd_channel - cmp [hdpos], 0x80 - jae .ret - cmp [hdbase], 0x1F0 - jne .IDE_Channel_2 -.IDE_Channel_1: - mov [IDE_Channel_1],0 -.ret: - ret -.IDE_Channel_2: - mov [IDE_Channel_2],0 - ret -;******************************************** -problem_partition db 0 ; used for partitions search - -include 'part_set.inc' - -set_FAT: -;-------------------------------- -; input : EAX = cluster -; EDX = value to save -; output : EDX = old value -;-------------------------------- - push eax ebx esi - - cmp eax,2 - jb sfc_error - cmp eax,[LAST_CLUSTER] - ja sfc_error - cmp [fs_type],16 - je sfc_1 - add eax,eax - sfc_1: - add eax,eax - mov esi,511 - and esi,eax ; esi = position in fat sector - shr eax,9 ; eax = fat sector - add eax,[FAT_START] - mov ebx,fat_cache - - cmp eax,[fat_in_cache] ; is fat sector already in memory? - je sfc_in_cache ; yes - - cmp [fat_change],0 ; is fat changed? - je sfc_no_change ; no - call write_fat_sector ; yes. write it into disk - cmp [hd_error],0 - jne sfc_error - - sfc_no_change: - mov [fat_in_cache],eax ; save fat sector - call hd_read - cmp [hd_error],0 - jne sfc_error - - - sfc_in_cache: - cmp [fs_type],16 - jne sfc_test32 - - sfc_set16: - xchg [ebx+esi],dx ; save new value and get old value - jmp sfc_write - - sfc_test32: - mov eax,[fatMASK] - - sfc_set32: - and edx,eax - xor eax,-1 ; mask for high bits - and eax,[ebx+esi] ; get high 4 bits - or eax,edx - mov edx,[ebx+esi] ; get old value - mov [ebx+esi],eax ; save new value - - sfc_write: - mov [fat_change],1 ; fat has changed - - sfc_nonzero: - and edx,[fatMASK] - - sfc_error: - pop esi ebx eax - ret - - -get_FAT: -;-------------------------------- -; input : EAX = cluster -; output : EAX = next cluster -;-------------------------------- - push ebx esi - - cmp [fs_type],16 - je gfc_1 - add eax,eax - gfc_1: - add eax,eax - mov esi,511 - and esi,eax ; esi = position in fat sector - shr eax,9 ; eax = fat sector - add eax,[FAT_START] - mov ebx,fat_cache - - cmp eax,[fat_in_cache] ; is fat sector already in memory? - je gfc_in_cache - - cmp [fat_change],0 ; is fat changed? - je gfc_no_change ; no - call write_fat_sector ; yes. write it into disk - cmp [hd_error],0 - jne hd_error_01 - - gfc_no_change: - mov [fat_in_cache],eax - call hd_read - cmp [hd_error],0 - jne hd_error_01 - - gfc_in_cache: - mov eax,[ebx+esi] - and eax,[fatMASK] - hd_error_01: - pop esi ebx - ret - - -get_free_FAT: -;----------------------------------------------------------- -; output : if CARRY=0 EAX = # first cluster found free -; if CARRY=1 disk full -; Note : for more speed need to use fat_cache directly -;----------------------------------------------------------- - push ecx - mov ecx,[LAST_CLUSTER] ; counter for full disk - sub ecx,2 - mov eax,[fatStartScan] - cmp eax,2 - jb gff_reset - - gff_test: - cmp eax,[LAST_CLUSTER] ; if above last cluster start at cluster 2 - jbe gff_in_range - gff_reset: - mov eax,2 - - gff_in_range: - push eax - call get_FAT ; get cluster state - cmp [hd_error],0 - jne gff_not_found_1 - - test eax,eax ; is it free? - pop eax - je gff_found ; yes - inc eax ; next cluster - dec ecx ; is all checked? - jns gff_test ; no - - gff_not_found_1: - add esp,4 - gff_not_found: - pop ecx ; yes. disk is full - stc - ret - - gff_found: - lea ecx,[eax+1] - mov [fatStartScan],ecx - pop ecx - clc - ret - - -write_fat_sector: -;----------------------------------------------------------- -; write changed fat to disk -;----------------------------------------------------------- - push eax ebx ecx - - mov [fat_change],0 - mov eax,[fat_in_cache] - cmp eax,-1 - jz write_fat_not_used - mov ebx,fat_cache - mov ecx,[NUMBER_OF_FATS] - - write_next_fat: - call hd_write - cmp [hd_error],0 - jne write_fat_not_used - - add eax,[SECTORS_PER_FAT] - dec ecx - jnz write_next_fat - - write_fat_not_used: - pop ecx ebx eax - ret - - -analyze_directory: -;----------------------------------------------------------- -; input : EAX = first cluster of the directory -; EBX = pointer to filename -; output : IF CARRY=0 EAX = sector where th file is found -; EBX = pointer in buffer -; [buffer .. buffer+511] -; ECX,EDX,ESI,EDI not changed -; IF CARRY=1 filename not found -; Note : if cluster=0 it's changed to read rootdir -; save 2 previous directory sectors in longname_sec -;----------------------------------------------------------- - push ecx edx esi edi ebx ; ebx = [esp+0] - mov [longname_sec1],0 - mov [longname_sec2],0 - - adr_new_cluster: - mov [cluster_tmp],eax - mov [fat16_root],0 - cmp eax,[LAST_CLUSTER] - ja adr_not_found ; too big cluster number, something is wrong - cmp eax,2 - jnb adr_data_cluster - - mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir - cmp [fs_type],16 - jne adr_data_cluster - mov eax,[ROOT_START] - mov edx,[ROOT_SECTORS] - mov [fat16_root],1 ; flag for fat16 rootdir - jmp adr_new_sector - - adr_data_cluster: - sub eax,2 - mov edx,[SECTORS_PER_CLUSTER] - imul eax,edx - add eax,[DATA_START] - - adr_new_sector: - mov ebx,buffer - call hd_read - cmp [hd_error],0 - jne adr_not_found - - mov ecx,512/32 ; count of dir entrys per sector = 16 - - adr_analyze: - mov edi,[ebx+11] ; file attribute - and edi,0xf - cmp edi,0xf - je adr_long_filename - test edi,0x8 ; skip over volume label - jne adr_long_filename ; Note: label can be same name as file/dir - - mov esi,[esp+0] ; filename need to be uppercase - mov edi,ebx - push ecx - mov ecx,11 - cld - rep cmpsb ; compare 8+3 filename - pop ecx - je adr_found - - adr_long_filename: - add ebx,32 ; position of next dir entry - dec ecx - jnz adr_analyze - - mov ecx,[longname_sec1] ; save 2 previous directory sectors - mov [longname_sec1],eax ; for delete long filename - mov [longname_sec2],ecx - inc eax ; next sector - dec edx - jne adr_new_sector - cmp [fat16_root],1 ; end of fat16 rootdir - je adr_not_found - - adr_next_cluster: - mov eax,[cluster_tmp] - call get_FAT ; get next cluster - cmp [hd_error],0 - jne adr_not_found - - cmp eax,2 ; incorrect fat chain? - jb adr_not_found ; yes - cmp eax,[fatRESERVED] ; is it end of directory? - jb adr_new_cluster ; no. analyse it - - adr_not_found: - pop edi edi esi edx ecx ; first edi will remove ebx - stc ; file not found - ret - - adr_found: - pop edi edi esi edx ecx ; first edi will remove ebx - clc ; file found - ret - - -get_data_cluster: -;----------------------------------------------------------- -; input : EAX = cluster -; EBX = pointer to buffer -; EDX = # blocks to read in buffer -; ESI = # blocks to skip over -; output : if CARRY=0 ok EBX/EDX/ESI updated -; if CARRY=1 cluster out of range -; Note : if cluster=0 it's changed to read rootdir -;----------------------------------------------------------- - push eax ecx - - mov [fat16_root],0 - cmp eax,[LAST_CLUSTER] - ja gdc_error ; too big cluster number, something is wrong - cmp eax,2 - jnb gdc_cluster - - mov eax,[ROOT_CLUSTER] ; if cluster < 2 then read rootdir - cmp [fs_type],16 - jne gdc_cluster - mov eax,[ROOT_START] - mov ecx,[ROOT_SECTORS] ; Note: not cluster size - mov [fat16_root],1 ; flag for fat16 rootdir - jmp gdc_read - - gdc_cluster: - sub eax,2 - mov ecx,[SECTORS_PER_CLUSTER] - imul eax,ecx - add eax,[DATA_START] - - gdc_read: - test esi,esi ; first wanted block - je gdcl1 ; yes, skip count is 0 - dec esi - jmp gdcl2 - - gdcl1: - call hd_read - cmp [hd_error],0 - jne gdc_error - - add ebx,512 ; update pointer - dec edx - - gdcl2: - test edx,edx ; is all read? - je out_of_read - - inc eax ; next sector - dec ecx - jnz gdc_read - - out_of_read: - pop ecx eax - clc - ret - - gdc_error: - pop ecx eax - stc - ret - - -get_cluster_of_a_path: -;--------------------------------------------------------- -; input : EBX = pointer to a path string -; (example: the path "/files/data/document" become -; "files......data.......document...0" -; '.' = space char -; '0' = char(0) (ASCII=0) !!! ) -; output : if (CARRY=1) -> ERROR in the PATH -; if (CARRY=0) -> EAX=cluster -;--------------------------------------------------------- - push ebx edx - - mov eax,[ROOT_CLUSTER] - mov edx,ebx - -search_end_of_path: - cmp byte [edx],0 - je found_end_of_path - - inc edx ; '/' - mov ebx,edx - call analyze_directory - jc directory_not_found - - mov eax,[ebx+20-2] ; read the HIGH 16bit cluster field - mov ax,[ebx+26] ; read the LOW 16bit cluster field - and eax,[fatMASK] - add edx,11 ; 8+3 (name+extension) - jmp search_end_of_path - -found_end_of_path: - pop edx ebx - clc ; no errors - ret - -directory_not_found: - pop edx ebx - stc ; errors occour - ret - - -bcd2bin: -;---------------------------------- -; input : AL=BCD number (eg. 0x11) -; output : AH=0 -; AL=decimal number (eg. 11) -;---------------------------------- - xor ah,ah - shl ax,4 - shr al,4 - aad - ret - - -get_date_for_file: -;----------------------------------------------------- -; Get date from CMOS and pack day,month,year in AX -; DATE bits 0..4 : day of month 0..31 -; 5..8 : month of year 1..12 -; 9..15 : count of years from 1980 -;----------------------------------------------------- - mov al,0x7 ;day - out 0x70,al - in al,0x71 - call bcd2bin - ror eax,5 - - mov al,0x8 ;month - out 0x70,al - in al,0x71 - call bcd2bin - ror eax,4 - - mov al,0x9 ;year - out 0x70,al - in al,0x71 - call bcd2bin - add ax,20 ;because CMOS return only the two last - ;digit (eg. 2000 -> 00 , 2001 -> 01) and we - rol eax,9 ;need the difference with 1980 (eg. 2001-1980) - ret - - -get_time_for_file: -;----------------------------------------------------- -; Get time from CMOS and pack hour,minute,second in AX -; TIME bits 0..4 : second (the low bit is lost) -; 5..10 : minute 0..59 -; 11..15 : hour 0..23 -;----------------------------------------------------- - mov al,0x0 ;second - out 0x70,al - in al,0x71 - call bcd2bin - ror eax,6 - - mov al,0x2 ;minute - out 0x70,al - in al,0x71 - call bcd2bin - ror eax,6 - - mov al,0x4 ;hour - out 0x70,al - in al,0x71 - call bcd2bin - rol eax,11 - ret - - -set_current_time_for_entry: -;----------------------------------------------------- -; Set current time/date for file entry -; input : ebx = file entry pointer -;----------------------------------------------------- - push eax - call get_time_for_file ; update files date/time - mov [ebx+22],ax - call get_date_for_file - mov [ebx+24],ax - pop eax - ret - - - -add_disk_free_space: -;----------------------------------------------------- -; input : ecx = cluster count -; Note : negative = remove clusters from free space -; positive = add clusters to free space -;----------------------------------------------------- - test ecx,ecx ; no change - je add_dfs_no - cmp [fs_type],32 ; free disk space only used by fat32 - jne add_dfs_no - - push eax ebx - mov eax,[ADR_FSINFO] - mov ebx,fsinfo_buffer - call hd_read - cmp [hd_error],0 - jne add_not_fs - - cmp dword [ebx+0x1fc],0xaa550000 ; check sector id - jne add_not_fs - - add [ebx+0x1e8],ecx - push [fatStartScan] - pop dword [ebx+0x1ec] - call hd_write -; cmp [hd_error],0 -; jne add_not_fs - - add_not_fs: - pop ebx eax - - add_dfs_no: - ret - - -file_read: -;-------------------------------------------------------------------------- -; INPUT : user-register register-in-this meaning symbol-in-this -; -; EAX EDI system call to write / -; EBX EAX (PAR0) pointer to file-name PAR0 -; EDX ECX (PAR1) pointer to buffer PAR1 -; ECX EBX (PAR2) vt file blocks to read PAR2 -; ESI EDX (PAR3) pointer to path PAR3 -; EDI ESI vt first 512 block to read -; EDI if 0 - read root -; -; output : eax = 0 - ok -; 3 - unknown FS -; 5 - file not found -; 6 - end of file -; 9 - fat table corrupted -; 10 - access denied -; ebx = size of file/directory -;-------------------------------------------------------------------------- - cmp [fs_type], 16 - jz fat_ok_for_reading - cmp [fs_type], 32 - jz fat_ok_for_reading - xor ebx,ebx - mov eax,ERROR_UNKNOWN_FS - mov [hd1_status], ebx - ret - - fat_ok_for_reading: -; call reserve_hd1 - - pushad - - mov ebx,edx - call get_cluster_of_a_path - jc file_to_read_not_found - - test edi,edi ; read rootdir - jne no_read_root - - xor eax,eax - call get_dir_size ; return rootdir size - cmp [hd_error],0 - jne file_access_denied - - mov [file_size],eax - mov eax,[ROOT_CLUSTER] - jmp file_read_start - - no_read_root: - mov ebx,PUSHAD_EAX ; file name - call analyze_directory - jc file_to_read_not_found - - mov eax,[ebx+28] ; file size - test byte [ebx+11],0x10 ; is it directory? - jz read_set_size ; no - - mov eax,[ebx+20-2] ; FAT entry - mov ax,[ebx+26] - and eax,[fatMASK] - call get_dir_size - cmp [hd_error],0 - jne file_access_denied - - read_set_size: - mov [file_size],eax - - mov eax,[ebx+20-2] ; FAT entry - mov ax,[ebx+26] - and eax,[fatMASK] - - file_read_start: - mov ebx,PUSHAD_ECX ; pointer to buffer - mov edx,PUSHAD_EBX ; file blocks to read - mov esi,PUSHAD_ESI ; first 512 block to read - - file_read_new_cluster: - call get_data_cluster - jc file_read_eof ; end of file or cluster out of range - - test edx,edx ; is all read? - je file_read_OK ; yes - - call get_FAT ; get next cluster - cmp [hd_error],0 - jne file_access_denied - - cmp eax,[fatRESERVED] ; end of file - jnb file_read_eof - cmp eax,2 ; incorrect fat chain - jnb file_read_new_cluster - - popad - mov [hd1_status],0 - mov ebx,[file_size] - mov eax,ERROR_FAT_TABLE - ret - - file_read_eof: - cmp [hd_error],0 - jne file_access_denied - popad - mov [hd1_status],0 - mov ebx,[file_size] - mov eax,ERROR_END_OF_FILE - ret - - file_read_OK: - popad - mov [hd1_status],0 - mov ebx,[file_size] - xor eax,eax - ret - - file_to_read_not_found: - cmp [hd_error],0 - jne file_access_denied - popad - mov [hd1_status],0 - xor ebx,ebx - mov eax,ERROR_FILE_NOT_FOUND - ret - - file_access_denied: - popad - mov [hd1_status],0 - xor ebx,ebx - mov eax,ERROR_ACCESS_DENIED - ret - -get_dir_size: -;----------------------------------------------------- -; input : eax = first cluster (0=rootdir) -; output : eax = directory size in bytes -;----------------------------------------------------- - push edx - xor edx,edx ; count of directory clusters - test eax,eax - jnz dir_size_next - - mov eax,[ROOT_SECTORS] - shl eax,9 ; fat16 rootdir size in bytes - cmp [fs_type],16 - je dir_size_ret - mov eax,[ROOT_CLUSTER] - - dir_size_next: - cmp eax,2 ; incorrect fat chain - jb dir_size_end - cmp eax,[fatRESERVED] ; end of directory - ja dir_size_end - call get_FAT ; get next cluster - cmp [hd_error],0 - jne dir_size_ret - - inc edx - jmp dir_size_next - - dir_size_end: - imul eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes - imul eax,edx - - dir_size_ret: - pop edx - ret - - -clear_cluster_chain: -;----------------------------------------------------- -; input : eax = first cluster -;----------------------------------------------------- - push eax ecx edx - xor ecx,ecx ; cluster count - - clean_new_chain: - cmp eax,[LAST_CLUSTER] ; end of file - ja delete_OK - cmp eax,2 ; unfinished fat chain or zero length file - jb delete_OK - cmp eax,[ROOT_CLUSTER] ; don't remove root cluster - jz delete_OK - - xor edx,edx - call set_FAT ; clear fat entry - cmp [hd_error],0 - jne access_denied_01 - - inc ecx ; update cluster count - mov eax,edx ; old cluster - jmp clean_new_chain - - delete_OK: - call add_disk_free_space ; add clusters to free disk space - access_denied_01: - pop edx ecx eax - ret - - -get_hd_info: -;----------------------------------------------------------- -; output : eax = 0 - ok -; 3 - unknown FS -; 10 - access denied -; edx = cluster size in bytes -; ebx = total clusters on disk -; ecx = free clusters on disk -;----------------------------------------------------------- - cmp [fs_type], 16 - jz info_fat_ok - cmp [fs_type], 32 - jz info_fat_ok - xor edx,edx - xor ebx,ebx - xor ecx,ecx - mov eax,ERROR_UNKNOWN_FS - ret - - info_fat_ok: -; call reserve_hd1 - - xor ecx,ecx ; count of free clusters - mov eax,2 - mov ebx,[LAST_CLUSTER] - - info_cluster: - push eax - call get_FAT ; get cluster info - cmp [hd_error],0 - jne info_access_denied - - test eax,eax ; is it free? - jnz info_used ; no - inc ecx - - info_used: - pop eax - inc eax - cmp eax,ebx ; is above last cluster? - jbe info_cluster ; no. test next cluster - - dec ebx ; cluster count - imul edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes - mov [hd1_status],0 - xor eax,eax - ret - - info_access_denied: - add esp,4 - xor edx,edx - xor ebx,ebx - xor ecx,ecx - mov eax,ERROR_ACCESS_DENIED - ret - -update_disk: -;----------------------------------------------------------- -; write changed fat and cache to disk -;----------------------------------------------------------- - cmp [fat_change],0 ; is fat changed? - je upd_no_change - - call write_fat_sector - cmp [hd_error],0 - jne update_disk_acces_denied - - upd_no_change: - - call write_cache - update_disk_acces_denied: - ret - - -; \begin{diamond} -hd_find_lfn: -; in: esi+ebp -> name -; out: CF=1 - file not found -; else CF=0 and edi->direntry, eax=sector -; destroys eax - push esi edi - push 0 - push 0 - push fat16_root_first - push fat16_root_next - mov eax, [ROOT_CLUSTER] - cmp [fs_type], 32 - jz .fat32 -.loop: - call fat_find_lfn - jc .notfound - cmp byte [esi], 0 - jz .found -.continue: - test byte [edi+11], 10h - jz .notfound - and dword [esp+12], 0 - mov eax, [edi+20-2] - mov ax, [edi+26] ; cluster -.fat32: - mov [esp+8], eax - mov dword [esp+4], fat_notroot_first - mov dword [esp], fat_notroot_next - jmp .loop -.notfound: - add esp, 16 - pop edi esi - stc - ret -.found: - test ebp, ebp - jz @f - mov esi, ebp - xor ebp, ebp - jmp .continue -@@: - lea eax, [esp+8] - cmp dword [eax], 0 - jz .root - call fat_get_sector - jmp .cmn -.root: - mov eax, [eax+4] - add eax, [ROOT_START] -.cmn: - add esp, 20 ; CF=0 - pop esi - ret - -;---------------------------------------------------------------- -; -; fs_HdRead - LFN variant for reading hard disk -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to read, 0+ -; edx mem location to return data -; -; ret ebx = bytes read or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_HdRead: - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jz @f - cmp [fs_type], 1 - jz ntfs_HdRead - cmp [fs_type], 2 - jz ext2_HdRead - or ebx, -1 - mov eax, ERROR_UNKNOWN_FS - ret -@@: - push edi - cmp byte [esi], 0 - jnz @f -.noaccess: - pop edi -.noaccess_2: - or ebx, -1 - mov eax, ERROR_ACCESS_DENIED - ret - -@@: - call hd_find_lfn - jnc .found - pop edi - cmp [hd_error],0 - jne .noaccess_2 - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret - -.found: - test byte [edi+11], 0x10 ; do not allow read directories - jnz .noaccess - test ebx, ebx - jz .l1 - cmp dword [ebx+4], 0 - jz @f - xor ebx, ebx -.reteof: - mov eax, 6 - pop edi - ret -@@: - mov ebx, [ebx] -.l1: - push ecx edx - push 0 - mov eax, [edi+28] - sub eax, ebx - jb .eof - cmp eax, ecx - jae @f - mov ecx, eax - mov byte [esp], 6 -@@: - mov eax, [edi+20-2] - mov ax, [edi+26] -; now eax=cluster, ebx=position, ecx=count, edx=buffer for data -.new_cluster: - jecxz .new_sector - test eax, eax - jz .eof - cmp eax, [fatRESERVED] - jae .eof - mov [cluster_tmp], eax - dec eax - dec eax - mov edi, [SECTORS_PER_CLUSTER] - imul eax, edi - add eax, [DATA_START] -.new_sector: - test ecx, ecx - jz .done - sub ebx, 512 - jae .skip - add ebx, 512 - jnz .force_buf - cmp ecx, 512 - jb .force_buf -; we may read directly to given buffer - push ebx - mov ebx, edx - call hd_read - pop ebx - cmp [hd_error],0 - jne .noaccess_1 - add edx, 512 - sub ecx, 512 - jmp .skip -.force_buf: -; we must read sector to temporary buffer and then copy it to destination - push eax ebx - mov ebx, buffer - call hd_read - mov eax, ebx - pop ebx - cmp [hd_error],0 - jne .noaccess_3 - add eax, ebx - push ecx - add ecx, ebx - cmp ecx, 512 - jbe @f - mov ecx, 512 -@@: - sub ecx, ebx - mov ebx, edx - call memmove - add edx, ecx - sub [esp], ecx - pop ecx - pop eax - xor ebx, ebx -.skip: - inc eax - dec edi - jnz .new_sector - mov eax, [cluster_tmp] - call get_FAT - cmp [hd_error],0 - jne .noaccess_1 - - jmp .new_cluster -.noaccess_3: - pop eax -.noaccess_1: - pop eax - push 11 -.done: - mov ebx, edx - pop eax edx ecx edi - sub ebx, edx - ret -.eof: - mov ebx, edx - pop eax edx ecx - sub ebx, edx - jmp .reteof - -;---------------------------------------------------------------- -; -; fs_HdReadFolder - LFN variant for reading hard disk folder -; -; esi points to filename -; ebx pointer to structure 32-bit number = first wanted block, 0+ -; & flags (bitfields) -; flags: bit 0: 0=ANSI names, 1=UNICODE names -; ecx number of blocks to read, 0+ -; edx mem location to return data -; -; ret ebx = blocks read or 0xffffffff folder not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_HdReadFolder: - cmp [fs_type], 1 - jz ntfs_HdReadFolder - cmp [fs_type], 2 - jz ext2_HdReadFolder - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jz @f - push ERROR_UNSUPPORTED_FS - pop eax - or ebx, -1 - ret -@@: - mov eax, [ROOT_CLUSTER] - push edi - cmp byte [esi], 0 - jz .doit - call hd_find_lfn - jnc .found - pop edi - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret -.found: - test byte [edi+11], 0x10 ; do not allow read files - jnz .found_dir - pop edi - or ebx, -1 - mov eax, ERROR_ACCESS_DENIED - ret -.found_dir: - mov eax, [edi+20-2] - mov ax, [edi+26] ; eax=cluster -.doit: - push esi ecx - push ebp - sub esp, 262*2 ; reserve space for LFN - mov ebp, esp - push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE name - mov ebx, [ebx] -; init header - push eax ecx - mov edi, edx - mov ecx, 32/4 - xor eax, eax - rep stosd - pop ecx eax - mov byte [edx], 1 ; version - mov esi, edi ; esi points to BDFE -.new_cluster: - mov [cluster_tmp], eax - test eax, eax - jnz @f - cmp [fs_type], 32 - jz .notfound - mov eax, [ROOT_START] - push [ROOT_SECTORS] - push ebx - jmp .new_sector -@@: - dec eax - dec eax - imul eax, [SECTORS_PER_CLUSTER] - push [SECTORS_PER_CLUSTER] - add eax, [DATA_START] - push ebx -.new_sector: - mov ebx, buffer - mov edi, ebx - call hd_read - cmp [hd_error], 0 - jnz .notfound2 - add ebx, 512 - push eax -.l1: - call fat_get_name - jc .l2 - cmp byte [edi+11], 0xF - jnz .do_bdfe - add edi, 0x20 - cmp edi, ebx - jb .do_bdfe - pop eax - inc eax - dec dword [esp+4] - jnz @f - mov eax, [cluster_tmp] - test eax, eax - jz .done - call get_FAT - cmp [hd_error], 0 - jnz .notfound2 - cmp eax, 2 - jb .done - cmp eax, [fatRESERVED] - jae .done - push eax - mov eax, [SECTORS_PER_CLUSTER] - mov [esp+8], eax - pop eax - mov [cluster_tmp], eax - dec eax - dec eax - imul eax, [SECTORS_PER_CLUSTER] - add eax, [DATA_START] -@@: - mov ebx, buffer - mov edi, ebx - call hd_read - cmp [hd_error], 0 - jnz .notfound2 - add ebx, 512 - push eax -.do_bdfe: - inc dword [edx+8] ; new file found - dec dword [esp+4] - jns .l2 - dec ecx - js .l2 - inc dword [edx+4] ; new file block copied - call fat_entry_to_bdfe -.l2: - add edi, 0x20 - cmp edi, ebx - jb .l1 - pop eax - inc eax - dec dword [esp+4] - jnz .new_sector - mov eax, [cluster_tmp] - test eax, eax - jz .done - call get_FAT - cmp [hd_error], 0 - jnz .notfound2 - cmp eax, 2 - jb .done - cmp eax, [fatRESERVED] - jae .done - push eax - mov eax, [SECTORS_PER_CLUSTER] - mov [esp+8], eax - pop eax - pop ebx - add esp, 4 - jmp .new_cluster -.notfound2: - add esp, 8 -.notfound: - add esp, 262*2+4 - pop ebp ecx esi edi - mov eax, ERROR_FILE_NOT_FOUND - or ebx, -1 - ret -.done: - add esp, 262*2+4+8 - pop ebp - mov ebx, [edx+4] - xor eax, eax - dec ecx - js @f - mov al, ERROR_END_OF_FILE -@@: - pop ecx esi edi - ret - -fat16_root_next: - cmp edi, buffer+0x200-0x20 - jae fat16_root_next_sector - add edi, 0x20 - ret ; CF=0 -fat16_root_next_sector: -; read next sector - push [longname_sec2] - pop [longname_sec1] - push ecx - mov ecx, [eax+4] - push ecx - add ecx, [ROOT_START] - mov [longname_sec2], ecx - pop ecx - inc ecx - mov [eax+4], ecx - cmp ecx, [ROOT_SECTORS] - pop ecx - jae fat16_root_first.readerr -fat16_root_first: - mov eax, [eax+4] - add eax, [ROOT_START] - push ebx - mov edi, buffer - mov ebx, edi - call hd_read - pop ebx - cmp [hd_error], 0 - jnz .readerr - ret ; CF=0 -.readerr: - stc - ret -fat16_root_begin_write: - push edi eax - call fat16_root_first - pop eax edi - ret -fat16_root_end_write: - pusha - mov eax, [eax+4] - add eax, [ROOT_START] - mov ebx, buffer - call hd_write - popa - ret -fat16_root_next_write: - cmp edi, buffer+0x200 - jae @f - ret -@@: - call fat16_root_end_write - jmp fat16_root_next_sector -fat16_root_extend_dir: - stc - ret - -fat_notroot_next: - cmp edi, buffer+0x200-0x20 - jae fat_notroot_next_sector - add edi, 0x20 - ret ; CF=0 -fat_notroot_next_sector: - push [longname_sec2] - pop [longname_sec1] - push eax - call fat_get_sector - mov [longname_sec2], eax - pop eax - push ecx - mov ecx, [eax+4] - inc ecx - cmp ecx, [SECTORS_PER_CLUSTER] - jae fat_notroot_next_cluster - mov [eax+4], ecx - jmp @f -fat_notroot_next_cluster: - push eax - mov eax, [eax] - call get_FAT - mov ecx, eax - pop eax - cmp [hd_error], 0 - jnz fat_notroot_next_err - cmp ecx, [fatRESERVED] - jae fat_notroot_next_err - mov [eax], ecx - and dword [eax+4], 0 -@@: - pop ecx -fat_notroot_first: - call fat_get_sector - push ebx - mov edi, buffer - mov ebx, edi - call hd_read - pop ebx - cmp [hd_error], 0 - jnz @f - ret ; CF=0 -fat_notroot_next_err: - pop ecx -@@: - stc - ret -fat_notroot_begin_write: - push eax edi - call fat_notroot_first - pop edi eax - ret -fat_notroot_end_write: - call fat_get_sector - push ebx - mov ebx, buffer - call hd_write - pop ebx - ret -fat_notroot_next_write: - cmp edi, buffer+0x200 - jae @f - ret -@@: - push eax - call fat_notroot_end_write - pop eax - jmp fat_notroot_next_sector -fat_notroot_extend_dir: - push eax - call get_free_FAT - jnc .found - pop eax - ret ; CF=1 -.found: - push edx - mov edx, [fatEND] - call set_FAT - mov edx, eax - mov eax, [esp+4] - mov eax, [eax] - push edx - call set_FAT - pop edx - cmp [hd_error], 0 - jz @f - pop edx - pop eax - stc - ret -@@: - push ecx - or ecx, -1 - call add_disk_free_space -; zero new cluster - mov ecx, 512/4 - mov edi, buffer - push edi - xor eax, eax - rep stosd - pop edi - pop ecx - mov eax, [esp+4] - mov [eax], edx - and dword [eax+4], 0 - pop edx - mov eax, [eax] - dec eax - dec eax - push ebx ecx - mov ecx, [SECTORS_PER_CLUSTER] - imul eax, ecx - add eax, [DATA_START] - mov ebx, edi -@@: - call hd_write - inc eax - loop @b - pop ecx ebx eax - clc - ret - -fat_get_sector: - push ecx - mov ecx, [eax] - dec ecx - dec ecx - imul ecx, [SECTORS_PER_CLUSTER] - add ecx, [DATA_START] - add ecx, [eax+4] - mov eax, ecx - pop ecx - ret - -;---------------------------------------------------------------- -; -; fs_HdRewrite - LFN variant for writing hard disk -; -; esi points to filename -; ebx ignored (reserved) -; ecx number of bytes to write, 0+ -; edx mem location to data -; -; ret ebx = number of written bytes -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fshrad: - mov eax, ERROR_ACCESS_DENIED - xor ebx, ebx - ret -fshrfs: - mov eax, ERROR_UNKNOWN_FS - xor ebx, ebx - ret - -fs_HdCreateFolder: - mov al, 1 - jmp fs_HdRewrite.common - -fs_HdRewrite: - xor eax, eax -.common: - cmp [fs_type], 1 - jz ntfs_HdRewrite - cmp [fs_type], 2 - jz ext2_HdRewrite - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jnz fshrfs -@@: - cmp byte [esi], 0 - jz fshrad - pushad - xor edi, edi - push esi - test ebp, ebp - jz @f - mov esi, ebp -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jnz @b - lea edi, [esi-1] - jmp @b -@@: - pop esi - test edi, edi - jnz .noroot - test ebp, ebp - jnz .hasebp - mov ebp, [ROOT_CLUSTER] - cmp [fs_type], 32 - jz .pushnotroot - push fat16_root_extend_dir - push fat16_root_end_write - push fat16_root_next_write - push fat16_root_begin_write - xor ebp, ebp - push ebp - push ebp - push fat16_root_first - push fat16_root_next - jmp .common1 -.hasebp: - mov eax, ERROR_ACCESS_DENIED - cmp byte [ebp], 0 - jz .ret1 - push ebp - xor ebp, ebp - call hd_find_lfn - pop esi - jc .notfound0 - jmp .common0 -.noroot: - mov eax, ERROR_ACCESS_DENIED - cmp byte [edi+1], 0 - jz .ret1 -; check existence - mov byte [edi], 0 - push edi - call hd_find_lfn - pop esi - mov byte [esi], '/' - jnc @f -.notfound0: - mov eax, ERROR_FILE_NOT_FOUND -.ret1: - mov [esp+28], eax - popad - xor ebx, ebx - ret -@@: - inc esi -.common0: - test byte [edi+11], 0x10 ; must be directory - mov eax, ERROR_ACCESS_DENIED - jz .ret1 - mov ebp, [edi+20-2] - mov bp, [edi+26] ; ebp=cluster - mov eax, ERROR_FAT_TABLE - cmp ebp, 2 - jb .ret1 -.pushnotroot: - push fat_notroot_extend_dir - push fat_notroot_end_write - push fat_notroot_next_write - push fat_notroot_begin_write - push 0 - push ebp - push fat_notroot_first - push fat_notroot_next -.common1: - call fat_find_lfn - jc .notfound -; found - test byte [edi+11], 10h - jz .exists_file -; found directory; if we are creating directory, return OK, -; if we are creating file, say "access denied" - add esp, 32 - popad - test al, al - mov eax, ERROR_ACCESS_DENIED - jz @f - mov al, 0 -@@: - xor ebx, ebx - ret -.exists_file: -; found file; if we are creating directory, return "access denied", -; if we are creating file, delete existing file and continue - cmp byte [esp+32+28], 0 - jz @f - add esp, 32 - popad - mov eax, ERROR_ACCESS_DENIED - xor ebx, ebx - ret -@@: -; delete FAT chain - push edi - xor eax, eax - mov dword [edi+28], eax ; zero size - xor ecx, ecx - mov eax, [edi+20-2] - mov ax, [edi+26] - mov word [edi+20], cx - mov word [edi+26], cx - test eax, eax - jz .done1 -@@: - cmp eax, [fatRESERVED] - jae .done1 - push edx - xor edx, edx - call set_FAT - mov eax, edx - pop edx - inc ecx - jmp @b -.done1: - pop edi - call get_time_for_file - mov [edi+22], ax - call get_date_for_file - mov [edi+24], ax - mov [edi+18], ax - or byte [edi+11], 20h ; set 'archive' attribute - jmp .doit -.notfound: -; file is not found; generate short name - call fat_name_is_legal - jc @f - add esp, 32 - popad - mov eax, ERROR_FILE_NOT_FOUND - xor ebx, ebx - ret -@@: - sub esp, 12 - mov edi, esp - call fat_gen_short_name -.test_short_name_loop: - push esi edi ecx - mov esi, edi - lea eax, [esp+12+12+8] - mov [eax], ebp - and dword [eax+4], 0 - call dword [eax-4] - jc .found -.test_short_name_entry: - cmp byte [edi+11], 0xF - jz .test_short_name_cont - mov ecx, 11 - push esi edi - repz cmpsb - pop edi esi - jz .short_name_found -.test_short_name_cont: - lea eax, [esp+12+12+8] - call dword [eax-8] - jnc .test_short_name_entry - jmp .found -.short_name_found: - pop ecx edi esi - call fat_next_short_name - jnc .test_short_name_loop -.disk_full: - add esp, 12+32 - popa - mov eax, ERROR_DISK_FULL - xor ebx, ebx - ret -.found: - pop ecx edi esi -; now find space in directory -; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' - mov al, '~' - push ecx edi - mov ecx, 8 - repnz scasb - push 1 - pop eax ; 1 entry - jnz .notilde -; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total - xor eax, eax -@@: - cmp byte [esi], 0 - jz @f - inc esi - inc eax - jmp @b -@@: - sub esi, eax - add eax, 12+13 - mov ecx, 13 - push edx - cdq - div ecx - pop edx -.notilde: - push -1 - push -1 - push -1 -; find successive entries in directory - xor ecx, ecx - push eax - lea eax, [esp+16+8+12+8] - mov [eax], ebp - and dword [eax+4], 0 - call dword [eax-4] - pop eax - jnc .scan_dir -.fsfrfe3: - add esp, 12+8+12+32 - popad - mov eax, 11 - xor ebx, ebx - ret -.scan_dir: - cmp byte [edi], 0 - jz .free - cmp byte [edi], 0xE5 - jz .free - xor ecx, ecx -.scan_cont: - push eax - lea eax, [esp+16+8+12+8] - call dword [eax-8] - pop eax - jnc .scan_dir - cmp [hd_error], 0 - jnz .fsfrfe3 - push eax - lea eax, [esp+16+8+12+8] - call dword [eax+20] ; extend directory - pop eax - jnc .scan_dir - add esp, 12+8+12+32 - popad - mov eax, ERROR_DISK_FULL - xor ebx, ebx - ret -.free: - test ecx, ecx - jnz @f - mov [esp], edi - mov ecx, [esp+12+8+12+8] - mov [esp+4], ecx - mov ecx, [esp+12+8+12+12] - mov [esp+8], ecx - xor ecx, ecx -@@: - inc ecx - cmp ecx, eax - jb .scan_cont -; found! -; calculate name checksum - push esi ecx - mov esi, [esp+8+12] - mov ecx, 11 - xor eax, eax -@@: - ror al, 1 - add al, [esi] - inc esi - loop @b - pop ecx esi - pop edi - pop dword [esp+8+12+12] - pop dword [esp+8+12+12] -; edi points to first entry in free chunk - dec ecx - jz .nolfn - push esi - push eax - lea eax, [esp+8+8+12+8] - call dword [eax+8] ; begin write - mov al, 40h -.writelfn: - or al, cl - mov esi, [esp+4] - push ecx - dec ecx - imul ecx, 13 - add esi, ecx - stosb - mov cl, 5 - call fs_RamdiskRewrite.read_symbols - mov ax, 0xF - stosw - mov al, [esp+4] - stosb - mov cl, 6 - call fs_RamdiskRewrite.read_symbols - xor eax, eax - stosw - mov cl, 2 - call fs_RamdiskRewrite.read_symbols - pop ecx - lea eax, [esp+8+8+12+8] - call dword [eax+12] ; next write - xor eax, eax - loop .writelfn - pop eax - pop esi -; lea eax, [esp+8+12+8] -; call dword [eax+16] ; end write -.nolfn: - xchg esi, [esp] - mov ecx, 11 - rep movsb - mov word [edi], 20h ; attributes - sub edi, 11 - pop esi ecx - add esp, 12 - mov byte [edi+13], 0 ; tenths of a second at file creation time - call get_time_for_file - mov [edi+14], ax ; creation time - mov [edi+22], ax ; last write time - call get_date_for_file - mov [edi+16], ax ; creation date - mov [edi+24], ax ; last write date - mov [edi+18], ax ; last access date - xor ecx, ecx - mov word [edi+20], cx ; high word of cluster - mov word [edi+26], cx ; low word of cluster - to be filled - mov dword [edi+28], ecx ; file size - to be filled - cmp byte [esp+32+28], cl - jz .doit -; create directory - mov byte [edi+11], 10h ; attributes: folder - mov edx, edi - lea eax, [esp+8] - call dword [eax+16] ; flush directory - push ecx - mov ecx, [SECTORS_PER_CLUSTER] - shl ecx, 9 - jmp .doit2 -.doit: - lea eax, [esp+8] - call dword [eax+16] ; flush directory - push ecx - mov ecx, [esp+4+32+24] -.doit2: - push ecx - push edi - mov esi, edx - test ecx, ecx - jz .done - call get_free_FAT - jc .diskfull - push eax - mov [edi+26], ax - shr eax, 16 - mov [edi+20], ax - lea eax, [esp+16+8] - call dword [eax+16] ; flush directory - pop eax - push edx - mov edx, [fatEND] - call set_FAT - pop edx -.write_cluster: - push eax - dec eax - dec eax - mov ebp, [SECTORS_PER_CLUSTER] - imul eax, ebp - add eax, [DATA_START] -; write data -.write_sector: - cmp byte [esp+16+32+28], 0 - jnz .writedir - mov ecx, 512 - cmp dword [esp+8], ecx - jb .writeshort -; we can write directly from given buffer - mov ebx, esi - add esi, ecx - jmp .writecommon -.writeshort: - mov ecx, [esp+8] - push ecx - mov edi, buffer - mov ebx, edi - rep movsb -.writedircont: - mov ecx, buffer+0x200 - sub ecx, edi - push eax - xor eax, eax - rep stosb - pop eax - pop ecx -.writecommon: - call hd_write - cmp [hd_error], 0 - jnz .writeerr - inc eax - sub dword [esp+8], ecx - jz .writedone - dec ebp - jnz .write_sector -; allocate new cluster - pop eax - mov ecx, eax - call get_free_FAT - jc .diskfull - push edx - mov edx, [fatEND] - call set_FAT - xchg eax, ecx - mov edx, ecx - call set_FAT - pop edx - xchg eax, ecx - jmp .write_cluster -.diskfull: - mov eax, ERROR_DISK_FULL - jmp .ret -.writeerr: - pop eax - sub esi, ecx - mov eax, 11 - jmp .ret -.writedone: - pop eax -.done: - xor eax, eax -.ret: - pop edi ecx - mov ebx, esi - sub ebx, edx - pop ebp - mov [esp+32+28], eax - lea eax, [esp+8] - call dword [eax+8] - mov [edi+28], ebx - call dword [eax+16] - mov [esp+32+16], ebx - lea eax, [ebx+511] - shr eax, 9 - mov ecx, [SECTORS_PER_CLUSTER] - lea eax, [eax+ecx-1] - xor edx, edx - div ecx - mov ecx, ebp - sub ecx, eax - call add_disk_free_space - add esp, 32 - call update_disk - popad - ret -.writedir: - push 512 - mov edi, buffer - mov ebx, edi - mov ecx, [SECTORS_PER_CLUSTER] - shl ecx, 9 - cmp ecx, [esp+12] - jnz .writedircont - dec dword [esp+16] - push esi - mov ecx, 32/4 - rep movsd - pop esi - mov dword [edi-32], '. ' - mov dword [edi-32+4], ' ' - mov dword [edi-32+8], ' ' - mov byte [edi-32+11], 10h - push esi - mov ecx, 32/4 - rep movsd - pop esi - mov dword [edi-32], '.. ' - mov dword [edi-32+4], ' ' - mov dword [edi-32+8], ' ' - mov byte [edi-32+11], 10h - mov ecx, [esp+20+8] - cmp ecx, [ROOT_CLUSTER] - jnz @f - xor ecx, ecx -@@: - mov word [edi-32+26], cx - shr ecx, 16 - mov [edi-32+20], cx - jmp .writedircont - -;---------------------------------------------------------------- -; -; fs_HdWrite - LFN variant for writing to hard disk -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to write, 0+ -; edx mem location to data -; -; ret ebx = bytes written (maybe 0) -; eax = 0 ok write or other = errormsg -; -;-------------------------------------------------------------- -fs_HdWrite.access_denied: - push ERROR_ACCESS_DENIED -fs_HdWrite.ret0: - pop eax - xor ebx, ebx - ret - -fs_HdWrite.ret11: - push 11 - jmp fs_HdWrite.ret0 - -fs_HdWrite: - cmp [fs_type], 1 - jz ntfs_HdWrite - cmp [fs_type], 2 - jz ext2_HdWrite - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jz @f - push ERROR_UNKNOWN_FS - jmp .ret0 -@@: - cmp byte [esi], 0 - jz .access_denied - pushad - call hd_find_lfn - pushfd - cmp [hd_error], 0 - jz @f - popfd - popad - push 11 - jmp .ret0 -@@: - popfd - jnc .found - popad - push ERROR_FILE_NOT_FOUND - jmp .ret0 -.found: -; FAT does not support files larger than 4GB - test ebx, ebx - jz .l1 - cmp dword [ebx+4], 0 - jz @f -.eof: - popad - push ERROR_END_OF_FILE - jmp .ret0 -@@: - mov ebx, [ebx] -.l1: -; now edi points to direntry, ebx=start byte to write, -; ecx=number of bytes to write, edx=data pointer - -; extend file if needed - add ecx, ebx - jc .eof ; FAT does not support files larger than 4GB - push eax ; save directory sector - push 0 ; return value=0 - - call get_time_for_file - mov [edi+22], ax ; last write time - call get_date_for_file - mov [edi+24], ax ; last write date - mov [edi+18], ax ; last access date - - push dword [edi+28] ; save current file size - cmp ecx, [edi+28] - jbe .length_ok - cmp ecx, ebx - jz .length_ok - call hd_extend_file - jnc .length_ok - mov [esp+4], eax -; hd_extend_file can return three error codes: FAT table error, device error or disk full. -; First two cases are fatal errors, in third case we may write some data - cmp al, ERROR_DISK_FULL - jz .disk_full - pop eax - pop eax - mov [esp+4+28], eax - pop eax - popad - xor ebx, ebx - ret -.disk_full: -; correct number of bytes to write - mov ecx, [edi+28] - cmp ecx, ebx - ja .length_ok -.ret: - call update_disk - cmp [hd_error], 0 - jz @f - mov byte [esp+4], 11 -@@: - pop eax - pop eax - mov [esp+4+28], eax ; eax=return value - pop eax - sub edx, [esp+20] - mov [esp+16], edx ; ebx=number of written bytes - popad - ret -.length_ok: - mov esi, [edi+28] - mov eax, [edi+20-2] - mov ax, [edi+26] - mov edi, eax ; edi=current cluster - xor ebp, ebp ; ebp=current sector in cluster -; save directory - mov eax, [esp+8] - push ebx - mov ebx, buffer - call hd_write - pop ebx - cmp [hd_error], 0 - jz @f -.device_err: - mov byte [esp+4], 11 - jmp .ret -@@: - -; now ebx=start pos, ecx=end pos, both lie inside file - sub ecx, ebx - jz .ret -.write_loop: -; skip unmodified sectors - cmp dword [esp], 0x200 - jb .modify - sub ebx, 0x200 - jae .skip - add ebx, 0x200 -.modify: -; get length of data in current sector - push ecx - sub ebx, 0x200 - jb .hasdata - neg ebx - xor ecx, ecx - jmp @f -.hasdata: - neg ebx - cmp ecx, ebx - jbe @f - mov ecx, ebx -@@: -; get current sector number - mov eax, edi - dec eax - dec eax - imul eax, [SECTORS_PER_CLUSTER] - add eax, [DATA_START] - add eax, ebp -; load sector if needed - cmp dword [esp+4], 0 ; we don't need to read uninitialized data - jz .noread - cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten - jz .noread - cmp ecx, esi ; (same for the last sector) - jz .noread - push ebx - mov ebx, buffer - call hd_read - pop ebx - cmp [hd_error], 0 - jz @f -.device_err2: - pop ecx - jmp .device_err -@@: -.noread: -; zero uninitialized data if file was extended (because hd_extend_file does not this) - push eax ecx edi - xor eax, eax - mov ecx, 0x200 - sub ecx, [esp+4+12] - jbe @f - mov edi, buffer - add edi, [esp+4+12] - rep stosb -@@: -; zero uninitialized data in the last sector - mov ecx, 0x200 - sub ecx, esi - jbe @f - mov edi, buffer - add edi, esi - rep stosb -@@: - pop edi ecx -; copy new data - mov eax, edx - neg ebx - jecxz @f - add ebx, buffer+0x200 - call memmove - xor ebx, ebx -@@: - pop eax -; save sector - push ebx - mov ebx, buffer - call hd_write - pop ebx - cmp [hd_error], 0 - jnz .device_err2 - add edx, ecx - sub [esp], ecx - pop ecx - jz .ret -.skip: -; next sector - inc ebp - cmp ebp, [SECTORS_PER_CLUSTER] - jb @f - xor ebp, ebp - mov eax, edi - call get_FAT - mov edi, eax - cmp [hd_error], 0 - jnz .device_err -@@: - sub esi, 0x200 - jae @f - xor esi, esi -@@: - sub dword [esp], 0x200 - jae @f - and dword [esp], 0 -@@: jmp .write_loop - -hd_extend_file.zero_size: - xor eax, eax - jmp hd_extend_file.start_extend - -; extends file on hd to given size (new data area is undefined) -; in: edi->direntry, ecx=new size -; out: CF=0 => OK, eax=0 -; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11) -hd_extend_file: - push ebp - mov ebp, [SECTORS_PER_CLUSTER] - imul ebp, [BYTES_PER_SECTOR] - push ecx -; find the last cluster of file - mov eax, [edi+20-2] - mov ax, [edi+26] - mov ecx, [edi+28] - jecxz .zero_size -.last_loop: - sub ecx, ebp - jbe .last_found - call get_FAT - cmp [hd_error], 0 - jz @f -.device_err: - pop ecx -.device_err2: - pop ebp - push 11 -.ret_err: - pop eax - stc - ret -@@: - cmp eax, 2 - jb .fat_err - cmp eax, [fatRESERVED] - jb .last_loop -.fat_err: - pop ecx ebp - push ERROR_FAT_TABLE - jmp .ret_err -.last_found: - push eax - call get_FAT - cmp [hd_error], 0 - jz @f - pop eax - jmp .device_err -@@: - cmp eax, [fatRESERVED] - pop eax - jb .fat_err -; set length to full number of clusters - sub [edi+28], ecx -.start_extend: - pop ecx -; now do extend - push edx - mov edx, 2 ; start scan from cluster 2 -.extend_loop: - cmp [edi+28], ecx - jae .extend_done -; add new cluster - push eax - call get_free_FAT - jc .disk_full - mov edx, [fatEND] - call set_FAT - mov edx, eax - pop eax - test eax, eax - jz .first_cluster - push edx - call set_FAT - pop edx - jmp @f -.first_cluster: - ror edx, 16 - mov [edi+20], dx - ror edx, 16 - mov [edi+26], dx -@@: - push ecx - mov ecx, -1 - call add_disk_free_space - pop ecx - mov eax, edx - cmp [hd_error], 0 - jnz .device_err3 - add [edi+28], ebp - jmp .extend_loop -.extend_done: - mov [edi+28], ecx - pop edx ebp - xor eax, eax ; CF=0 - ret -.device_err3: - pop edx - jmp .device_err2 -.disk_full: - pop eax edx ebp - push ERROR_DISK_FULL - pop eax - cmp [hd_error], 0 - jz @f - mov al, 11 -@@: stc - ret - -;---------------------------------------------------------------- -; -; fs_HdSetFileEnd - set end of file on hard disk -; -; esi points to filename -; ebx points to 64-bit number = new file size -; ecx ignored (reserved) -; edx ignored (reserved) -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -fs_HdSetFileEnd: - cmp [fs_type], 1 - jz ntfs_HdSetFileEnd - cmp [fs_type], 2 - jz ext2_HdSetFileEnd - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jz @f - push ERROR_UNKNOWN_FS -.ret: - pop eax - ret -@@: - cmp byte [esi], 0 - jnz @f -.access_denied: - push ERROR_ACCESS_DENIED - jmp .ret -@@: - push edi - call hd_find_lfn - pushfd - cmp [hd_error], 0 - jz @f - popfd - push 11 - jmp .ret -@@: - popfd - jnc @f - pop edi - push ERROR_FILE_NOT_FOUND - jmp .ret -@@: -; must not be directory - test byte [edi+11], 10h - jz @f - pop edi - jmp .access_denied -@@: -; file size must not exceed 4 Gb - cmp dword [ebx+4], 0 - jz @f - pop edi - push ERROR_END_OF_FILE - jmp .ret -@@: - push eax ; save directory sector -; set file modification date/time to current - call fat_update_datetime - mov eax, [ebx] - cmp eax, [edi+28] - jb .truncate - ja .expand - pop eax - mov ebx, buffer - call hd_write - pop edi - xor eax, eax - cmp [hd_error], 0 - jz @f - mov al, 11 -@@: - ret -.expand: - push ebx ebp ecx - push dword [edi+28] ; save old size - mov ecx, eax - call hd_extend_file - push eax ; return code - jnc .expand_ok - cmp al, ERROR_DISK_FULL - jz .disk_full -.pop_ret: - call update_disk - pop eax ecx ebp ebx ecx edi edi - ret -.expand_ok: -.disk_full: -; save directory - mov eax, [edi+28] - xchg eax, [esp+20] - mov ebx, buffer - call hd_write - mov eax, [edi+20-2] - mov ax, [edi+26] - mov edi, eax - cmp [hd_error], 0 - jz @f -.pop_ret11: - mov byte [esp], 11 - jmp .pop_ret -@@: -; now zero new data - xor ebp, ebp -; edi=current cluster, ebp=sector in cluster -; [esp+20]=new size, [esp+4]=old size, [esp]=return code -.zero_loop: - sub dword [esp+4], 0x200 - jae .next_cluster - lea eax, [edi-2] - imul eax, [SECTORS_PER_CLUSTER] - add eax, [DATA_START] - add eax, ebp - cmp dword [esp+4], -0x200 - jz .noread - mov ebx, buffer - call hd_read - cmp [hd_error], 0 - jnz .err_next -.noread: - mov ecx, [esp+4] - neg ecx - push edi - mov edi, buffer+0x200 - add edi, [esp+8] - push eax - xor eax, eax - mov [esp+12], eax - rep stosb - pop eax - pop edi - call hd_write - cmp [hd_error], 0 - jz .next_cluster -.err_next: - mov byte [esp], 11 -.next_cluster: - sub dword [esp+20], 0x200 - jbe .pop_ret - inc ebp - cmp ebp, [SECTORS_PER_CLUSTER] - jb .zero_loop - xor ebp, ebp - mov eax, edi - call get_FAT - mov edi, eax - cmp [hd_error], 0 - jnz .pop_ret11 - jmp .zero_loop -.truncate: - mov [edi+28], eax - push ecx - mov ecx, [edi+20-2] - mov cx, [edi+26] - push eax - test eax, eax - jz .zero_size -; find new last cluster -@@: - mov eax, [SECTORS_PER_CLUSTER] - shl eax, 9 - sub [esp], eax - jbe @f - mov eax, ecx - call get_FAT - mov ecx, eax - cmp [hd_error], 0 - jz @b -.device_err3: - pop eax ecx eax edi - push 11 - pop eax - ret -@@: -; we will zero data at the end of last sector - remember it - push ecx -; terminate FAT chain - push edx - mov eax, ecx - mov edx, [fatEND] - call set_FAT - mov eax, edx - pop edx - cmp [hd_error], 0 - jz @f -.device_err4: - pop ecx - jmp .device_err3 -.zero_size: - and word [edi+20], 0 - and word [edi+26], 0 - push 0 - mov eax, ecx -@@: -; delete FAT chain - call clear_cluster_chain - cmp [hd_error], 0 - jnz .device_err4 -; save directory - mov eax, [esp+12] - push ebx - mov ebx, buffer - call hd_write - pop ebx - cmp [hd_error], 0 - jnz .device_err4 -; zero last sector, ignore errors - pop ecx - pop eax - dec ecx - imul ecx, [SECTORS_PER_CLUSTER] - add ecx, [DATA_START] - push eax - sar eax, 9 - add ecx, eax - pop eax - and eax, 0x1FF - jz .truncate_done - push ebx eax - mov eax, ecx - mov ebx, buffer - call hd_read - pop eax - lea edi, [buffer+eax] - push ecx - mov ecx, 0x200 - sub ecx, eax - xor eax, eax - rep stosb - pop eax - call hd_write - pop ebx -.truncate_done: - pop ecx eax edi - call update_disk - xor eax, eax - cmp [hd_error], 0 - jz @f - mov al, 11 -@@: - ret - -fs_HdGetFileInfo: - cmp [fs_type], 1 - jz ntfs_HdGetFileInfo - cmp [fs_type], 2 - jz ext2_HdGetFileInfo - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jz @f - mov eax, ERROR_UNKNOWN_FS - ret -@@: - cmp byte [esi], 0 - jnz @f - mov eax, 2 - ret -@@: - push edi - call hd_find_lfn - pushfd - cmp [hd_error], 0 - jz @f - popfd - pop edi - mov eax, 11 - ret -@@: - popfd - jmp fs_GetFileInfo_finish - -fs_HdSetFileInfo: - cmp [fs_type], 1 - jz ntfs_HdSetFileInfo - cmp [fs_type], 2 - jz ext2_HdSetFileInfo - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jz @f - mov eax, ERROR_UNKNOWN_FS - ret -@@: - cmp byte [esi], 0 - jnz @f - mov eax, 2 - ret -@@: - push edi - call hd_find_lfn - pushfd - cmp [hd_error], 0 - jz @f - popfd - pop edi - mov eax, 11 - ret -@@: - popfd - jnc @f - pop edi - mov eax, ERROR_FILE_NOT_FOUND - ret -@@: - push eax - call bdfe_to_fat_entry - pop eax - mov ebx, buffer - call hd_write - call update_disk - pop edi - xor eax, eax - ret - -;---------------------------------------------------------------- -; -; fs_HdDelete - delete file or empty folder from hard disk -; -; esi points to filename -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -fs_HdDelete: - cmp [fs_type], 1 - jz ntfs_HdDelete - cmp [fs_type], 2 - jz ext2_HdDelete - cmp [fs_type], 16 - jz @f - cmp [fs_type], 32 - jz @f - push ERROR_UNKNOWN_FS -.pop_ret: - pop eax - ret -@@: - cmp byte [esi], 0 - jnz @f -; cannot delete root! -.access_denied: - push ERROR_ACCESS_DENIED - jmp .pop_ret -@@: - and [longname_sec1], 0 - and [longname_sec2], 0 - push edi - call hd_find_lfn - jnc .found - pop edi - push ERROR_FILE_NOT_FOUND - jmp .pop_ret -.found: - cmp dword [edi], '. ' - jz .access_denied2 - cmp dword [edi], '.. ' - jz .access_denied2 - test byte [edi+11], 10h - jz .dodel -; we can delete only empty folders! - pushad - mov ebp, [edi+20-2] - mov bp, [edi+26] - xor ecx, ecx - lea eax, [ebp-2] - imul eax, [SECTORS_PER_CLUSTER] - add eax, [DATA_START] - mov ebx, buffer - call hd_read - cmp [hd_error], 0 - jnz .err1 - add ebx, 2*0x20 -.checkempty: - cmp byte [ebx], 0 - jz .empty - cmp byte [ebx], 0xE5 - jnz .notempty - add ebx, 0x20 - cmp ebx, buffer+0x200 - jb .checkempty - inc ecx - cmp ecx, [SECTORS_PER_CLUSTER] - jb @f - mov eax, ebp - call get_FAT - cmp [hd_error], 0 - jnz .err1 - mov ebp, eax - xor ecx, ecx -@@: - lea eax, [ebp-2] - imul eax, [SECTORS_PER_CLUSTER] - add eax, [DATA_START] - add eax, ecx - mov ebx, buffer - call hd_read - cmp [hd_error], 0 - jz .checkempty -.err1: - popad -.err2: - pop edi - push 11 - pop eax - ret -.notempty: - popad -.access_denied2: - pop edi - push ERROR_ACCESS_DENIED - pop eax - ret -.empty: - popad - push ebx - mov ebx, buffer - call hd_read - pop ebx - cmp [hd_error], 0 - jnz .err2 -.dodel: - push eax - mov eax, [edi+20-2] - mov ax, [edi+26] - xchg eax, [esp] -; delete folder entry - mov byte [edi], 0xE5 -; delete LFN (if present) -.lfndel: - cmp edi, buffer - ja @f - cmp [longname_sec2], 0 - jz .lfndone - push [longname_sec2] - push [longname_sec1] - pop [longname_sec2] - and [longname_sec1], 0 - push ebx - mov ebx, buffer - call hd_write - mov eax, [esp+4] - call hd_read - pop ebx - pop eax - mov edi, buffer+0x200 -@@: - sub edi, 0x20 - cmp byte [edi], 0xE5 - jz .lfndone - cmp byte [edi+11], 0xF - jnz .lfndone - mov byte [edi], 0xE5 - jmp .lfndel -.lfndone: - push ebx - mov ebx, buffer - call hd_write - pop ebx -; delete FAT chain - pop eax - call clear_cluster_chain - call update_disk - pop edi - xor eax, eax - cmp [hd_error], 0 - jz @f - mov al, 11 -@@: - ret - -; \end{diamond} +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; FAT32.INC ;; +;; ;; +;; FAT16/32 functions for KolibriOS ;; +;; ;; +;; Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it ;; +;; ;; +;; See file COPYING for details ;; +;; 04.02.2007 LFN create folder - diamond ;; +;; 08.10.2006 LFN delete file/folder - diamond ;; +;; 20.08.2006 LFN set file size (truncate/extend) - diamond ;; +;; 17.08.2006 LFN write/append to file - diamond ;; +;; 23.06.2006 LFN start application - diamond ;; +;; 15.06.2006 LFN get/set file/folder info - diamond ;; +;; 27.05.2006 LFN create/rewrite file - diamond ;; +;; 04.05.2006 LFN read folder - diamond ;; +;; 29.04.2006 Elimination of hangup after the ;; +;; expiration hd_wait_timeout - Mario79 ;; +;; 23.04.2006 LFN read file - diamond ;; +;; 28.01.2006 find all Fat16/32 partition in all input point ;; +;; to MBR, see file part_set.inc - Mario79 ;; +;; 15.01.2005 get file size/attr/date, file_append - ATV ;; +;; 04.12.2004 skip volume label, file delete bug fixed - ATV ;; +;; 29.11.2004 get_free_FAT changed, append dir bug fixed - ATV ;; +;; 23.11.2004 don't allow overwrite dir with file - ATV ;; +;; 18.11.2004 get_disk_info and more error codes - ATV ;; +;; 17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV ;; +;; 10.11.2004 removedir clear whole directory structure - ATV ;; +;; 08.11.2004 rename - ATV ;; +;; 30.10.2004 file_read return also dirsize in bytes - ATV ;; +;; 20.10.2004 Makedir/Removedir - ATV ;; +;; 14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx) ;; +;; 06.9.2004 Fix free space by Mario79 added - MH ;; +;; 24.5.2004 Write back buffer for File_write -VT ;; +;; 20.5.2004 File_read function to work with syscall 58 - VT ;; +;; 30.3.2004 Error parameters at function return - VT ;; +;; 01.5.2002 Bugfix in device write - VT ;; +;; 20.5.2002 Hd status check - VT ;; +;; 29.6.2002 Improved fat32 verification - VT ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +cache_max equ 1919 ; max. is 1919*512+0x610000=0x6ffe00 + +ERROR_SUCCESS = 0 +ERROR_DISK_BASE = 1 +ERROR_UNSUPPORTED_FS = 2 +ERROR_UNKNOWN_FS = 3 +ERROR_PARTITION = 4 +ERROR_FILE_NOT_FOUND = 5 +ERROR_END_OF_FILE = 6 +ERROR_MEMORY_POINTER = 7 +ERROR_DISK_FULL = 8 +ERROR_FAT_TABLE = 9 +ERROR_ACCESS_DENIED = 10 +ERROR_DEVICE = 11 + +PUSHAD_EAX equ [esp+28] +PUSHAD_ECX equ [esp+24] +PUSHAD_EDX equ [esp+20] +PUSHAD_EBX equ [esp+16] +PUSHAD_EBP equ [esp+8] +PUSHAD_ESI equ [esp+4] +PUSHAD_EDI equ [esp+0] + +uglobal +align 4 +partition_count dd 0 ; partitions found by set_FAT32_variables +longname_sec1 dd 0 ; used by analyze_directory to save 2 previous +longname_sec2 dd 0 ; directory sectors for delete long filename + +hd_error dd 0 ; set by wait_for_sector_buffer +hd_setup dd 0 +hd_wait_timeout dd 0 + +cluster_tmp dd 0 ; used by analyze_directory + ; and analyze_directory_to_write + +file_size dd 0 ; used by file_read + +cache_search_start dd 0 ; used by find_empty_slot +endg + +iglobal +fat_in_cache dd -1 +endg + +uglobal +align 4 +fat_cache: + times 512 db 0 + Sector512: ; label for dev_hdcd.inc + buffer: + times 512 db 0 + fsinfo_buffer: + times 512 db 0 +endg + +uglobal + fat16_root db 0 ; flag for fat16 rootdir + fat_change db 0 ; 1=fat has changed +endg + +reserve_hd1: + + cli + cmp [hd1_status], 0 + je reserve_ok1 + + sti + call change_task + jmp reserve_hd1 + + reserve_ok1: + + push eax + mov eax, [CURRENT_TASK] + shl eax, 5 + mov eax, [eax+CURRENT_TASK+TASKDATA.pid] + mov [hd1_status], eax + pop eax + sti + ret +;******************************************** + +uglobal +hd_in_cache db ? +endg + +reserve_hd_channel: +; BIOS disk accesses are protected with common mutex hd1_status +; This must be modified when hd1_status will not be valid! + cmp [hdpos], 0x80 + jae .ret + cmp [hdbase], 0x1F0 + jne .IDE_Channel_2 +.IDE_Channel_1: + cli + cmp [IDE_Channel_1], 0 + je .reserve_ok_1 + sti + call change_task + jmp .IDE_Channel_1 +.IDE_Channel_2: + cli + cmp [IDE_Channel_2], 0 + je .reserve_ok_2 + sti + call change_task + jmp .IDE_Channel_2 +.reserve_ok_1: + mov [IDE_Channel_1], 1 + push eax + mov al, 1 + jmp @f +.reserve_ok_2: + mov [IDE_Channel_2], 1 + push eax + mov al, 3 +@@: + cmp [hdid], 1 + sbb al, -1 + cmp al, [hd_in_cache] + jz @f + mov [hd_in_cache], al + call clear_hd_cache +@@: + pop eax + sti +.ret: + ret + +free_hd_channel: +; see comment at reserve_hd_channel + cmp [hdpos], 0x80 + jae .ret + cmp [hdbase], 0x1F0 + jne .IDE_Channel_2 +.IDE_Channel_1: + mov [IDE_Channel_1], 0 +.ret: + ret +.IDE_Channel_2: + mov [IDE_Channel_2], 0 + ret +;******************************************** +problem_partition db 0 ; used for partitions search + +include 'part_set.inc' + +set_FAT: +;-------------------------------- +; input : EAX = cluster +; EDX = value to save +; output : EDX = old value +;-------------------------------- + push eax ebx esi + + cmp eax, 2 + jb sfc_error + cmp eax, [LAST_CLUSTER] + ja sfc_error + cmp [fs_type], 16 + je sfc_1 + add eax, eax + sfc_1: + add eax, eax + mov esi, 511 + and esi, eax ; esi = position in fat sector + shr eax, 9 ; eax = fat sector + add eax, [FAT_START] + mov ebx, fat_cache + + cmp eax, [fat_in_cache]; is fat sector already in memory? + je sfc_in_cache ; yes + + cmp [fat_change], 0 ; is fat changed? + je sfc_no_change ; no + call write_fat_sector; yes. write it into disk + cmp [hd_error], 0 + jne sfc_error + + sfc_no_change: + mov [fat_in_cache], eax; save fat sector + call hd_read + cmp [hd_error], 0 + jne sfc_error + + + sfc_in_cache: + cmp [fs_type], 16 + jne sfc_test32 + + sfc_set16: + xchg [ebx+esi], dx ; save new value and get old value + jmp sfc_write + + sfc_test32: + mov eax, [fatMASK] + + sfc_set32: + and edx, eax + xor eax, -1 ; mask for high bits + and eax, [ebx+esi] ; get high 4 bits + or eax, edx + mov edx, [ebx+esi] ; get old value + mov [ebx+esi], eax ; save new value + + sfc_write: + mov [fat_change], 1 ; fat has changed + + sfc_nonzero: + and edx, [fatMASK] + + sfc_error: + pop esi ebx eax + ret + + +get_FAT: +;-------------------------------- +; input : EAX = cluster +; output : EAX = next cluster +;-------------------------------- + push ebx esi + + cmp [fs_type], 16 + je gfc_1 + add eax, eax + gfc_1: + add eax, eax + mov esi, 511 + and esi, eax ; esi = position in fat sector + shr eax, 9 ; eax = fat sector + add eax, [FAT_START] + mov ebx, fat_cache + + cmp eax, [fat_in_cache]; is fat sector already in memory? + je gfc_in_cache + + cmp [fat_change], 0 ; is fat changed? + je gfc_no_change ; no + call write_fat_sector; yes. write it into disk + cmp [hd_error], 0 + jne hd_error_01 + + gfc_no_change: + mov [fat_in_cache], eax + call hd_read + cmp [hd_error], 0 + jne hd_error_01 + + gfc_in_cache: + mov eax, [ebx+esi] + and eax, [fatMASK] + hd_error_01: + pop esi ebx + ret + + +get_free_FAT: +;----------------------------------------------------------- +; output : if CARRY=0 EAX = # first cluster found free +; if CARRY=1 disk full +; Note : for more speed need to use fat_cache directly +;----------------------------------------------------------- + push ecx + mov ecx, [LAST_CLUSTER]; counter for full disk + sub ecx, 2 + mov eax, [fatStartScan] + cmp eax, 2 + jb gff_reset + + gff_test: + cmp eax, [LAST_CLUSTER]; if above last cluster start at cluster 2 + jbe gff_in_range + gff_reset: + mov eax, 2 + + gff_in_range: + push eax + call get_FAT ; get cluster state + cmp [hd_error], 0 + jne gff_not_found_1 + + test eax, eax ; is it free? + pop eax + je gff_found ; yes + inc eax ; next cluster + dec ecx ; is all checked? + jns gff_test ; no + + gff_not_found_1: + add esp, 4 + gff_not_found: + pop ecx ; yes. disk is full + stc + ret + + gff_found: + lea ecx, [eax+1] + mov [fatStartScan], ecx + pop ecx + clc + ret + + +write_fat_sector: +;----------------------------------------------------------- +; write changed fat to disk +;----------------------------------------------------------- + push eax ebx ecx + + mov [fat_change], 0 + mov eax, [fat_in_cache] + cmp eax, -1 + jz write_fat_not_used + mov ebx, fat_cache + mov ecx, [NUMBER_OF_FATS] + + write_next_fat: + call hd_write + cmp [hd_error], 0 + jne write_fat_not_used + + add eax, [SECTORS_PER_FAT] + dec ecx + jnz write_next_fat + + write_fat_not_used: + pop ecx ebx eax + ret + + +analyze_directory: +;----------------------------------------------------------- +; input : EAX = first cluster of the directory +; EBX = pointer to filename +; output : IF CARRY=0 EAX = sector where th file is found +; EBX = pointer in buffer +; [buffer .. buffer+511] +; ECX,EDX,ESI,EDI not changed +; IF CARRY=1 filename not found +; Note : if cluster=0 it's changed to read rootdir +; save 2 previous directory sectors in longname_sec +;----------------------------------------------------------- + push ecx edx esi edi ebx; ebx = [esp+0] + mov [longname_sec1], 0 + mov [longname_sec2], 0 + + adr_new_cluster: + mov [cluster_tmp], eax + mov [fat16_root], 0 + cmp eax, [LAST_CLUSTER] + ja adr_not_found ; too big cluster number, something is wrong + cmp eax, 2 + jnb adr_data_cluster + + mov eax, [ROOT_CLUSTER]; if cluster < 2 then read rootdir + cmp [fs_type], 16 + jne adr_data_cluster + mov eax, [ROOT_START] + mov edx, [ROOT_SECTORS] + mov [fat16_root], 1 ; flag for fat16 rootdir + jmp adr_new_sector + + adr_data_cluster: + sub eax, 2 + mov edx, [SECTORS_PER_CLUSTER] + imul eax, edx + add eax, [DATA_START] + + adr_new_sector: + mov ebx, buffer + call hd_read + cmp [hd_error], 0 + jne adr_not_found + + mov ecx, 512/32 ; count of dir entrys per sector = 16 + + adr_analyze: + mov edi, [ebx+11] ; file attribute + and edi, 0xf + cmp edi, 0xf + je adr_long_filename + test edi, 0x8 ; skip over volume label + jne adr_long_filename; Note: label can be same name as file/dir + + mov esi, [esp+0] ; filename need to be uppercase + mov edi, ebx + push ecx + mov ecx, 11 + cld + rep cmpsb ; compare 8+3 filename + pop ecx + je adr_found + + adr_long_filename: + add ebx, 32 ; position of next dir entry + dec ecx + jnz adr_analyze + + mov ecx, [longname_sec1]; save 2 previous directory sectors + mov [longname_sec1], eax; for delete long filename + mov [longname_sec2], ecx + inc eax ; next sector + dec edx + jne adr_new_sector + cmp [fat16_root], 1 ; end of fat16 rootdir + je adr_not_found + + adr_next_cluster: + mov eax, [cluster_tmp] + call get_FAT ; get next cluster + cmp [hd_error], 0 + jne adr_not_found + + cmp eax, 2 ; incorrect fat chain? + jb adr_not_found ; yes + cmp eax, [fatRESERVED]; is it end of directory? + jb adr_new_cluster ; no. analyse it + + adr_not_found: + pop edi edi esi edx ecx; first edi will remove ebx + stc ; file not found + ret + + adr_found: + pop edi edi esi edx ecx; first edi will remove ebx + clc ; file found + ret + + +get_data_cluster: +;----------------------------------------------------------- +; input : EAX = cluster +; EBX = pointer to buffer +; EDX = # blocks to read in buffer +; ESI = # blocks to skip over +; output : if CARRY=0 ok EBX/EDX/ESI updated +; if CARRY=1 cluster out of range +; Note : if cluster=0 it's changed to read rootdir +;----------------------------------------------------------- + push eax ecx + + mov [fat16_root], 0 + cmp eax, [LAST_CLUSTER] + ja gdc_error ; too big cluster number, something is wrong + cmp eax, 2 + jnb gdc_cluster + + mov eax, [ROOT_CLUSTER]; if cluster < 2 then read rootdir + cmp [fs_type], 16 + jne gdc_cluster + mov eax, [ROOT_START] + mov ecx, [ROOT_SECTORS]; Note: not cluster size + mov [fat16_root], 1 ; flag for fat16 rootdir + jmp gdc_read + + gdc_cluster: + sub eax, 2 + mov ecx, [SECTORS_PER_CLUSTER] + imul eax, ecx + add eax, [DATA_START] + + gdc_read: + test esi, esi ; first wanted block + je gdcl1 ; yes, skip count is 0 + dec esi + jmp gdcl2 + + gdcl1: + call hd_read + cmp [hd_error], 0 + jne gdc_error + + add ebx, 512 ; update pointer + dec edx + + gdcl2: + test edx, edx ; is all read? + je out_of_read + + inc eax ; next sector + dec ecx + jnz gdc_read + + out_of_read: + pop ecx eax + clc + ret + + gdc_error: + pop ecx eax + stc + ret + + +get_cluster_of_a_path: +;--------------------------------------------------------- +; input : EBX = pointer to a path string +; (example: the path "/files/data/document" become +; "files......data.......document...0" +; '.' = space char +; '0' = char(0) (ASCII=0) !!! ) +; output : if (CARRY=1) -> ERROR in the PATH +; if (CARRY=0) -> EAX=cluster +;--------------------------------------------------------- + push ebx edx + + mov eax, [ROOT_CLUSTER] + mov edx, ebx + +search_end_of_path: + cmp byte [edx], 0 + je found_end_of_path + + inc edx; '/' + mov ebx, edx + call analyze_directory + jc directory_not_found + + mov eax, [ebx+20-2] ; read the HIGH 16bit cluster field + mov ax, [ebx+26] ; read the LOW 16bit cluster field + and eax, [fatMASK] + add edx, 11 ; 8+3 (name+extension) + jmp search_end_of_path + +found_end_of_path: + pop edx ebx + clc ; no errors + ret + +directory_not_found: + pop edx ebx + stc ; errors occour + ret + + +bcd2bin: +;---------------------------------- +; input : AL=BCD number (eg. 0x11) +; output : AH=0 +; AL=decimal number (eg. 11) +;---------------------------------- + xor ah, ah + shl ax, 4 + shr al, 4 + aad + ret + + +get_date_for_file: +;----------------------------------------------------- +; Get date from CMOS and pack day,month,year in AX +; DATE bits 0..4 : day of month 0..31 +; 5..8 : month of year 1..12 +; 9..15 : count of years from 1980 +;----------------------------------------------------- + mov al, 0x7 ;day + out 0x70, al + in al, 0x71 + call bcd2bin + ror eax, 5 + + mov al, 0x8 ;month + out 0x70, al + in al, 0x71 + call bcd2bin + ror eax, 4 + + mov al, 0x9 ;year + out 0x70, al + in al, 0x71 + call bcd2bin + add ax, 20 ;because CMOS return only the two last + ;digit (eg. 2000 -> 00 , 2001 -> 01) and we + rol eax, 9 ;need the difference with 1980 (eg. 2001-1980) + ret + + +get_time_for_file: +;----------------------------------------------------- +; Get time from CMOS and pack hour,minute,second in AX +; TIME bits 0..4 : second (the low bit is lost) +; 5..10 : minute 0..59 +; 11..15 : hour 0..23 +;----------------------------------------------------- + mov al, 0x0 ;second + out 0x70, al + in al, 0x71 + call bcd2bin + ror eax, 6 + + mov al, 0x2 ;minute + out 0x70, al + in al, 0x71 + call bcd2bin + ror eax, 6 + + mov al, 0x4 ;hour + out 0x70, al + in al, 0x71 + call bcd2bin + rol eax, 11 + ret + + +set_current_time_for_entry: +;----------------------------------------------------- +; Set current time/date for file entry +; input : ebx = file entry pointer +;----------------------------------------------------- + push eax + call get_time_for_file; update files date/time + mov [ebx+22], ax + call get_date_for_file + mov [ebx+24], ax + pop eax + ret + + + +add_disk_free_space: +;----------------------------------------------------- +; input : ecx = cluster count +; Note : negative = remove clusters from free space +; positive = add clusters to free space +;----------------------------------------------------- + test ecx, ecx ; no change + je add_dfs_no + cmp [fs_type], 32 ; free disk space only used by fat32 + jne add_dfs_no + + push eax ebx + mov eax, [ADR_FSINFO] + mov ebx, fsinfo_buffer + call hd_read + cmp [hd_error], 0 + jne add_not_fs + + cmp dword [ebx+0x1fc], 0xaa550000; check sector id + jne add_not_fs + + add [ebx+0x1e8], ecx + push [fatStartScan] + pop dword [ebx+0x1ec] + call hd_write +; cmp [hd_error],0 +; jne add_not_fs + + add_not_fs: + pop ebx eax + + add_dfs_no: + ret + + +file_read: +;-------------------------------------------------------------------------- +; INPUT : user-register register-in-this meaning symbol-in-this +; +; EAX EDI system call to write / +; EBX EAX (PAR0) pointer to file-name PAR0 +; EDX ECX (PAR1) pointer to buffer PAR1 +; ECX EBX (PAR2) vt file blocks to read PAR2 +; ESI EDX (PAR3) pointer to path PAR3 +; EDI ESI vt first 512 block to read +; EDI if 0 - read root +; +; output : eax = 0 - ok +; 3 - unknown FS +; 5 - file not found +; 6 - end of file +; 9 - fat table corrupted +; 10 - access denied +; ebx = size of file/directory +;-------------------------------------------------------------------------- + cmp [fs_type], 16 + jz fat_ok_for_reading + cmp [fs_type], 32 + jz fat_ok_for_reading + xor ebx, ebx + mov eax, ERROR_UNKNOWN_FS + mov [hd1_status], ebx + ret + + fat_ok_for_reading: +; call reserve_hd1 + + pushad + + mov ebx, edx + call get_cluster_of_a_path + jc file_to_read_not_found + + test edi, edi ; read rootdir + jne no_read_root + + xor eax, eax + call get_dir_size ; return rootdir size + cmp [hd_error], 0 + jne file_access_denied + + mov [file_size], eax + mov eax, [ROOT_CLUSTER] + jmp file_read_start + + no_read_root: + mov ebx, PUSHAD_EAX ; file name + call analyze_directory + jc file_to_read_not_found + + mov eax, [ebx+28] ; file size + test byte [ebx+11], 0x10; is it directory? + jz read_set_size ; no + + mov eax, [ebx+20-2] ; FAT entry + mov ax, [ebx+26] + and eax, [fatMASK] + call get_dir_size + cmp [hd_error], 0 + jne file_access_denied + + read_set_size: + mov [file_size], eax + + mov eax, [ebx+20-2] ; FAT entry + mov ax, [ebx+26] + and eax, [fatMASK] + + file_read_start: + mov ebx, PUSHAD_ECX ; pointer to buffer + mov edx, PUSHAD_EBX ; file blocks to read + mov esi, PUSHAD_ESI ; first 512 block to read + + file_read_new_cluster: + call get_data_cluster + jc file_read_eof ; end of file or cluster out of range + + test edx, edx ; is all read? + je file_read_OK ; yes + + call get_FAT ; get next cluster + cmp [hd_error], 0 + jne file_access_denied + + cmp eax, [fatRESERVED]; end of file + jnb file_read_eof + cmp eax, 2 ; incorrect fat chain + jnb file_read_new_cluster + + popad + mov [hd1_status], 0 + mov ebx, [file_size] + mov eax, ERROR_FAT_TABLE + ret + + file_read_eof: + cmp [hd_error], 0 + jne file_access_denied + popad + mov [hd1_status], 0 + mov ebx, [file_size] + mov eax, ERROR_END_OF_FILE + ret + + file_read_OK: + popad + mov [hd1_status], 0 + mov ebx, [file_size] + xor eax, eax + ret + + file_to_read_not_found: + cmp [hd_error], 0 + jne file_access_denied + popad + mov [hd1_status], 0 + xor ebx, ebx + mov eax, ERROR_FILE_NOT_FOUND + ret + + file_access_denied: + popad + mov [hd1_status], 0 + xor ebx, ebx + mov eax, ERROR_ACCESS_DENIED + ret + +get_dir_size: +;----------------------------------------------------- +; input : eax = first cluster (0=rootdir) +; output : eax = directory size in bytes +;----------------------------------------------------- + push edx + xor edx, edx ; count of directory clusters + test eax, eax + jnz dir_size_next + + mov eax, [ROOT_SECTORS] + shl eax, 9 ; fat16 rootdir size in bytes + cmp [fs_type], 16 + je dir_size_ret + mov eax, [ROOT_CLUSTER] + + dir_size_next: + cmp eax, 2 ; incorrect fat chain + jb dir_size_end + cmp eax, [fatRESERVED]; end of directory + ja dir_size_end + call get_FAT ; get next cluster + cmp [hd_error], 0 + jne dir_size_ret + + inc edx + jmp dir_size_next + + dir_size_end: + imul eax, [SECTORS_PER_CLUSTER], 512; cluster size in bytes + imul eax, edx + + dir_size_ret: + pop edx + ret + + +clear_cluster_chain: +;----------------------------------------------------- +; input : eax = first cluster +;----------------------------------------------------- + push eax ecx edx + xor ecx, ecx ; cluster count + + clean_new_chain: + cmp eax, [LAST_CLUSTER]; end of file + ja delete_OK + cmp eax, 2 ; unfinished fat chain or zero length file + jb delete_OK + cmp eax, [ROOT_CLUSTER]; don't remove root cluster + jz delete_OK + + xor edx, edx + call set_FAT ; clear fat entry + cmp [hd_error], 0 + jne access_denied_01 + + inc ecx ; update cluster count + mov eax, edx ; old cluster + jmp clean_new_chain + + delete_OK: + call add_disk_free_space; add clusters to free disk space + access_denied_01: + pop edx ecx eax + ret + + +get_hd_info: +;----------------------------------------------------------- +; output : eax = 0 - ok +; 3 - unknown FS +; 10 - access denied +; edx = cluster size in bytes +; ebx = total clusters on disk +; ecx = free clusters on disk +;----------------------------------------------------------- + cmp [fs_type], 16 + jz info_fat_ok + cmp [fs_type], 32 + jz info_fat_ok + xor edx, edx + xor ebx, ebx + xor ecx, ecx + mov eax, ERROR_UNKNOWN_FS + ret + + info_fat_ok: +; call reserve_hd1 + + xor ecx, ecx ; count of free clusters + mov eax, 2 + mov ebx, [LAST_CLUSTER] + + info_cluster: + push eax + call get_FAT ; get cluster info + cmp [hd_error], 0 + jne info_access_denied + + test eax, eax ; is it free? + jnz info_used ; no + inc ecx + + info_used: + pop eax + inc eax + cmp eax, ebx ; is above last cluster? + jbe info_cluster ; no. test next cluster + + dec ebx ; cluster count + imul edx, [SECTORS_PER_CLUSTER], 512; cluster size in bytes + mov [hd1_status], 0 + xor eax, eax + ret + + info_access_denied: + add esp, 4 + xor edx, edx + xor ebx, ebx + xor ecx, ecx + mov eax, ERROR_ACCESS_DENIED + ret + +update_disk: +;----------------------------------------------------------- +; write changed fat and cache to disk +;----------------------------------------------------------- + cmp [fat_change], 0 ; is fat changed? + je upd_no_change + + call write_fat_sector + cmp [hd_error], 0 + jne update_disk_acces_denied + + upd_no_change: + + call write_cache + update_disk_acces_denied: + ret + + +; \begin{diamond} +hd_find_lfn: +; in: esi+ebp -> name +; out: CF=1 - file not found +; else CF=0 and edi->direntry, eax=sector +; destroys eax + push esi edi + push 0 + push 0 + push fat16_root_first + push fat16_root_next + mov eax, [ROOT_CLUSTER] + cmp [fs_type], 32 + jz .fat32 +.loop: + call fat_find_lfn + jc .notfound + cmp byte [esi], 0 + jz .found +.continue: + test byte [edi+11], 10h + jz .notfound + and dword [esp+12], 0 + mov eax, [edi+20-2] + mov ax, [edi+26] ; cluster +.fat32: + mov [esp+8], eax + mov dword [esp+4], fat_notroot_first + mov dword [esp], fat_notroot_next + jmp .loop +.notfound: + add esp, 16 + pop edi esi + stc + ret +.found: + test ebp, ebp + jz @f + mov esi, ebp + xor ebp, ebp + jmp .continue +@@: + lea eax, [esp+8] + cmp dword [eax], 0 + jz .root + call fat_get_sector + jmp .cmn +.root: + mov eax, [eax+4] + add eax, [ROOT_START] +.cmn: + add esp, 20 ; CF=0 + pop esi + ret + +;---------------------------------------------------------------- +; +; fs_HdRead - LFN variant for reading hard disk +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to read, 0+ +; edx mem location to return data +; +; ret ebx = bytes read or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_HdRead: + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jz @f + cmp [fs_type], 1 + jz ntfs_HdRead + cmp [fs_type], 2 + jz ext2_HdRead + or ebx, -1 + mov eax, ERROR_UNKNOWN_FS + ret +@@: + push edi + cmp byte [esi], 0 + jnz @f +.noaccess: + pop edi +.noaccess_2: + or ebx, -1 + mov eax, ERROR_ACCESS_DENIED + ret + +@@: + call hd_find_lfn + jnc .found + pop edi + cmp [hd_error], 0 + jne .noaccess_2 + or ebx, -1 + mov eax, ERROR_FILE_NOT_FOUND + ret + +.found: + test byte [edi+11], 0x10; do not allow read directories + jnz .noaccess + test ebx, ebx + jz .l1 + cmp dword [ebx+4], 0 + jz @f + xor ebx, ebx +.reteof: + mov eax, 6 + pop edi + ret +@@: + mov ebx, [ebx] +.l1: + push ecx edx + push 0 + mov eax, [edi+28] + sub eax, ebx + jb .eof + cmp eax, ecx + jae @f + mov ecx, eax + mov byte [esp], 6 +@@: + mov eax, [edi+20-2] + mov ax, [edi+26] +; now eax=cluster, ebx=position, ecx=count, edx=buffer for data +.new_cluster: + jecxz .new_sector + test eax, eax + jz .eof + cmp eax, [fatRESERVED] + jae .eof + mov [cluster_tmp], eax + dec eax + dec eax + mov edi, [SECTORS_PER_CLUSTER] + imul eax, edi + add eax, [DATA_START] +.new_sector: + test ecx, ecx + jz .done + sub ebx, 512 + jae .skip + add ebx, 512 + jnz .force_buf + cmp ecx, 512 + jb .force_buf +; we may read directly to given buffer + push ebx + mov ebx, edx + call hd_read + pop ebx + cmp [hd_error], 0 + jne .noaccess_1 + add edx, 512 + sub ecx, 512 + jmp .skip +.force_buf: +; we must read sector to temporary buffer and then copy it to destination + push eax ebx + mov ebx, buffer + call hd_read + mov eax, ebx + pop ebx + cmp [hd_error], 0 + jne .noaccess_3 + add eax, ebx + push ecx + add ecx, ebx + cmp ecx, 512 + jbe @f + mov ecx, 512 +@@: + sub ecx, ebx + mov ebx, edx + call memmove + add edx, ecx + sub [esp], ecx + pop ecx + pop eax + xor ebx, ebx +.skip: + inc eax + dec edi + jnz .new_sector + mov eax, [cluster_tmp] + call get_FAT + cmp [hd_error], 0 + jne .noaccess_1 + + jmp .new_cluster +.noaccess_3: + pop eax +.noaccess_1: + pop eax + push 11 +.done: + mov ebx, edx + pop eax edx ecx edi + sub ebx, edx + ret +.eof: + mov ebx, edx + pop eax edx ecx + sub ebx, edx + jmp .reteof + +;---------------------------------------------------------------- +; +; fs_HdReadFolder - LFN variant for reading hard disk folder +; +; esi points to filename +; ebx pointer to structure 32-bit number = first wanted block, 0+ +; & flags (bitfields) +; flags: bit 0: 0=ANSI names, 1=UNICODE names +; ecx number of blocks to read, 0+ +; edx mem location to return data +; +; ret ebx = blocks read or 0xffffffff folder not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_HdReadFolder: + cmp [fs_type], 1 + jz ntfs_HdReadFolder + cmp [fs_type], 2 + jz ext2_HdReadFolder + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jz @f + push ERROR_UNSUPPORTED_FS + pop eax + or ebx, -1 + ret +@@: + mov eax, [ROOT_CLUSTER] + push edi + cmp byte [esi], 0 + jz .doit + call hd_find_lfn + jnc .found + pop edi + or ebx, -1 + mov eax, ERROR_FILE_NOT_FOUND + ret +.found: + test byte [edi+11], 0x10 ; do not allow read files + jnz .found_dir + pop edi + or ebx, -1 + mov eax, ERROR_ACCESS_DENIED + ret +.found_dir: + mov eax, [edi+20-2] + mov ax, [edi+26] ; eax=cluster +.doit: + push esi ecx + push ebp + sub esp, 262*2 ; reserve space for LFN + mov ebp, esp + push dword [ebx+4] ; for fat_get_name: read ANSI/UNICODE name + mov ebx, [ebx] +; init header + push eax ecx + mov edi, edx + mov ecx, 32/4 + xor eax, eax + rep stosd + pop ecx eax + mov byte [edx], 1 ; version + mov esi, edi ; esi points to BDFE +.new_cluster: + mov [cluster_tmp], eax + test eax, eax + jnz @f + cmp [fs_type], 32 + jz .notfound + mov eax, [ROOT_START] + push [ROOT_SECTORS] + push ebx + jmp .new_sector +@@: + dec eax + dec eax + imul eax, [SECTORS_PER_CLUSTER] + push [SECTORS_PER_CLUSTER] + add eax, [DATA_START] + push ebx +.new_sector: + mov ebx, buffer + mov edi, ebx + call hd_read + cmp [hd_error], 0 + jnz .notfound2 + add ebx, 512 + push eax +.l1: + call fat_get_name + jc .l2 + cmp byte [edi+11], 0xF + jnz .do_bdfe + add edi, 0x20 + cmp edi, ebx + jb .do_bdfe + pop eax + inc eax + dec dword [esp+4] + jnz @f + mov eax, [cluster_tmp] + test eax, eax + jz .done + call get_FAT + cmp [hd_error], 0 + jnz .notfound2 + cmp eax, 2 + jb .done + cmp eax, [fatRESERVED] + jae .done + push eax + mov eax, [SECTORS_PER_CLUSTER] + mov [esp+8], eax + pop eax + mov [cluster_tmp], eax + dec eax + dec eax + imul eax, [SECTORS_PER_CLUSTER] + add eax, [DATA_START] +@@: + mov ebx, buffer + mov edi, ebx + call hd_read + cmp [hd_error], 0 + jnz .notfound2 + add ebx, 512 + push eax +.do_bdfe: + inc dword [edx+8] ; new file found + dec dword [esp+4] + jns .l2 + dec ecx + js .l2 + inc dword [edx+4] ; new file block copied + call fat_entry_to_bdfe +.l2: + add edi, 0x20 + cmp edi, ebx + jb .l1 + pop eax + inc eax + dec dword [esp+4] + jnz .new_sector + mov eax, [cluster_tmp] + test eax, eax + jz .done + call get_FAT + cmp [hd_error], 0 + jnz .notfound2 + cmp eax, 2 + jb .done + cmp eax, [fatRESERVED] + jae .done + push eax + mov eax, [SECTORS_PER_CLUSTER] + mov [esp+8], eax + pop eax + pop ebx + add esp, 4 + jmp .new_cluster +.notfound2: + add esp, 8 +.notfound: + add esp, 262*2+4 + pop ebp ecx esi edi + mov eax, ERROR_FILE_NOT_FOUND + or ebx, -1 + ret +.done: + add esp, 262*2+4+8 + pop ebp + mov ebx, [edx+4] + xor eax, eax + dec ecx + js @f + mov al, ERROR_END_OF_FILE +@@: + pop ecx esi edi + ret + +fat16_root_next: + cmp edi, buffer+0x200-0x20 + jae fat16_root_next_sector + add edi, 0x20 + ret ; CF=0 +fat16_root_next_sector: +; read next sector + push [longname_sec2] + pop [longname_sec1] + push ecx + mov ecx, [eax+4] + push ecx + add ecx, [ROOT_START] + mov [longname_sec2], ecx + pop ecx + inc ecx + mov [eax+4], ecx + cmp ecx, [ROOT_SECTORS] + pop ecx + jae fat16_root_first.readerr +fat16_root_first: + mov eax, [eax+4] + add eax, [ROOT_START] + push ebx + mov edi, buffer + mov ebx, edi + call hd_read + pop ebx + cmp [hd_error], 0 + jnz .readerr + ret ; CF=0 +.readerr: + stc + ret +fat16_root_begin_write: + push edi eax + call fat16_root_first + pop eax edi + ret +fat16_root_end_write: + pusha + mov eax, [eax+4] + add eax, [ROOT_START] + mov ebx, buffer + call hd_write + popa + ret +fat16_root_next_write: + cmp edi, buffer+0x200 + jae @f + ret +@@: + call fat16_root_end_write + jmp fat16_root_next_sector +fat16_root_extend_dir: + stc + ret + +fat_notroot_next: + cmp edi, buffer+0x200-0x20 + jae fat_notroot_next_sector + add edi, 0x20 + ret ; CF=0 +fat_notroot_next_sector: + push [longname_sec2] + pop [longname_sec1] + push eax + call fat_get_sector + mov [longname_sec2], eax + pop eax + push ecx + mov ecx, [eax+4] + inc ecx + cmp ecx, [SECTORS_PER_CLUSTER] + jae fat_notroot_next_cluster + mov [eax+4], ecx + jmp @f +fat_notroot_next_cluster: + push eax + mov eax, [eax] + call get_FAT + mov ecx, eax + pop eax + cmp [hd_error], 0 + jnz fat_notroot_next_err + cmp ecx, [fatRESERVED] + jae fat_notroot_next_err + mov [eax], ecx + and dword [eax+4], 0 +@@: + pop ecx +fat_notroot_first: + call fat_get_sector + push ebx + mov edi, buffer + mov ebx, edi + call hd_read + pop ebx + cmp [hd_error], 0 + jnz @f + ret ; CF=0 +fat_notroot_next_err: + pop ecx +@@: + stc + ret +fat_notroot_begin_write: + push eax edi + call fat_notroot_first + pop edi eax + ret +fat_notroot_end_write: + call fat_get_sector + push ebx + mov ebx, buffer + call hd_write + pop ebx + ret +fat_notroot_next_write: + cmp edi, buffer+0x200 + jae @f + ret +@@: + push eax + call fat_notroot_end_write + pop eax + jmp fat_notroot_next_sector +fat_notroot_extend_dir: + push eax + call get_free_FAT + jnc .found + pop eax + ret ; CF=1 +.found: + push edx + mov edx, [fatEND] + call set_FAT + mov edx, eax + mov eax, [esp+4] + mov eax, [eax] + push edx + call set_FAT + pop edx + cmp [hd_error], 0 + jz @f + pop edx + pop eax + stc + ret +@@: + push ecx + or ecx, -1 + call add_disk_free_space +; zero new cluster + mov ecx, 512/4 + mov edi, buffer + push edi + xor eax, eax + rep stosd + pop edi + pop ecx + mov eax, [esp+4] + mov [eax], edx + and dword [eax+4], 0 + pop edx + mov eax, [eax] + dec eax + dec eax + push ebx ecx + mov ecx, [SECTORS_PER_CLUSTER] + imul eax, ecx + add eax, [DATA_START] + mov ebx, edi +@@: + call hd_write + inc eax + loop @b + pop ecx ebx eax + clc + ret + +fat_get_sector: + push ecx + mov ecx, [eax] + dec ecx + dec ecx + imul ecx, [SECTORS_PER_CLUSTER] + add ecx, [DATA_START] + add ecx, [eax+4] + mov eax, ecx + pop ecx + ret + +;---------------------------------------------------------------- +; +; fs_HdRewrite - LFN variant for writing hard disk +; +; esi points to filename +; ebx ignored (reserved) +; ecx number of bytes to write, 0+ +; edx mem location to data +; +; ret ebx = number of written bytes +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fshrad: + mov eax, ERROR_ACCESS_DENIED + xor ebx, ebx + ret +fshrfs: + mov eax, ERROR_UNKNOWN_FS + xor ebx, ebx + ret + +fs_HdCreateFolder: + mov al, 1 + jmp fs_HdRewrite.common + +fs_HdRewrite: + xor eax, eax +.common: + cmp [fs_type], 1 + jz ntfs_HdRewrite + cmp [fs_type], 2 + jz ext2_HdRewrite + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jnz fshrfs +@@: + cmp byte [esi], 0 + jz fshrad + pushad + xor edi, edi + push esi + test ebp, ebp + jz @f + mov esi, ebp +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jnz @b + lea edi, [esi-1] + jmp @b +@@: + pop esi + test edi, edi + jnz .noroot + test ebp, ebp + jnz .hasebp + mov ebp, [ROOT_CLUSTER] + cmp [fs_type], 32 + jz .pushnotroot + push fat16_root_extend_dir + push fat16_root_end_write + push fat16_root_next_write + push fat16_root_begin_write + xor ebp, ebp + push ebp + push ebp + push fat16_root_first + push fat16_root_next + jmp .common1 +.hasebp: + mov eax, ERROR_ACCESS_DENIED + cmp byte [ebp], 0 + jz .ret1 + push ebp + xor ebp, ebp + call hd_find_lfn + pop esi + jc .notfound0 + jmp .common0 +.noroot: + mov eax, ERROR_ACCESS_DENIED + cmp byte [edi+1], 0 + jz .ret1 +; check existence + mov byte [edi], 0 + push edi + call hd_find_lfn + pop esi + mov byte [esi], '/' + jnc @f +.notfound0: + mov eax, ERROR_FILE_NOT_FOUND +.ret1: + mov [esp+28], eax + popad + xor ebx, ebx + ret +@@: + inc esi +.common0: + test byte [edi+11], 0x10 ; must be directory + mov eax, ERROR_ACCESS_DENIED + jz .ret1 + mov ebp, [edi+20-2] + mov bp, [edi+26] ; ebp=cluster + mov eax, ERROR_FAT_TABLE + cmp ebp, 2 + jb .ret1 +.pushnotroot: + push fat_notroot_extend_dir + push fat_notroot_end_write + push fat_notroot_next_write + push fat_notroot_begin_write + push 0 + push ebp + push fat_notroot_first + push fat_notroot_next +.common1: + call fat_find_lfn + jc .notfound +; found + test byte [edi+11], 10h + jz .exists_file +; found directory; if we are creating directory, return OK, +; if we are creating file, say "access denied" + add esp, 32 + popad + test al, al + mov eax, ERROR_ACCESS_DENIED + jz @f + mov al, 0 +@@: + xor ebx, ebx + ret +.exists_file: +; found file; if we are creating directory, return "access denied", +; if we are creating file, delete existing file and continue + cmp byte [esp+32+28], 0 + jz @f + add esp, 32 + popad + mov eax, ERROR_ACCESS_DENIED + xor ebx, ebx + ret +@@: +; delete FAT chain + push edi + xor eax, eax + mov dword [edi+28], eax ; zero size + xor ecx, ecx + mov eax, [edi+20-2] + mov ax, [edi+26] + mov word [edi+20], cx + mov word [edi+26], cx + test eax, eax + jz .done1 +@@: + cmp eax, [fatRESERVED] + jae .done1 + push edx + xor edx, edx + call set_FAT + mov eax, edx + pop edx + inc ecx + jmp @b +.done1: + pop edi + call get_time_for_file + mov [edi+22], ax + call get_date_for_file + mov [edi+24], ax + mov [edi+18], ax + or byte [edi+11], 20h ; set 'archive' attribute + jmp .doit +.notfound: +; file is not found; generate short name + call fat_name_is_legal + jc @f + add esp, 32 + popad + mov eax, ERROR_FILE_NOT_FOUND + xor ebx, ebx + ret +@@: + sub esp, 12 + mov edi, esp + call fat_gen_short_name +.test_short_name_loop: + push esi edi ecx + mov esi, edi + lea eax, [esp+12+12+8] + mov [eax], ebp + and dword [eax+4], 0 + call dword [eax-4] + jc .found +.test_short_name_entry: + cmp byte [edi+11], 0xF + jz .test_short_name_cont + mov ecx, 11 + push esi edi + repz cmpsb + pop edi esi + jz .short_name_found +.test_short_name_cont: + lea eax, [esp+12+12+8] + call dword [eax-8] + jnc .test_short_name_entry + jmp .found +.short_name_found: + pop ecx edi esi + call fat_next_short_name + jnc .test_short_name_loop +.disk_full: + add esp, 12+32 + popa + mov eax, ERROR_DISK_FULL + xor ebx, ebx + ret +.found: + pop ecx edi esi +; now find space in directory +; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~' + mov al, '~' + push ecx edi + mov ecx, 8 + repnz scasb + push 1 + pop eax ; 1 entry + jnz .notilde +; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total + xor eax, eax +@@: + cmp byte [esi], 0 + jz @f + inc esi + inc eax + jmp @b +@@: + sub esi, eax + add eax, 12+13 + mov ecx, 13 + push edx + cdq + div ecx + pop edx +.notilde: + push -1 + push -1 + push -1 +; find successive entries in directory + xor ecx, ecx + push eax + lea eax, [esp+16+8+12+8] + mov [eax], ebp + and dword [eax+4], 0 + call dword [eax-4] + pop eax + jnc .scan_dir +.fsfrfe3: + add esp, 12+8+12+32 + popad + mov eax, 11 + xor ebx, ebx + ret +.scan_dir: + cmp byte [edi], 0 + jz .free + cmp byte [edi], 0xE5 + jz .free + xor ecx, ecx +.scan_cont: + push eax + lea eax, [esp+16+8+12+8] + call dword [eax-8] + pop eax + jnc .scan_dir + cmp [hd_error], 0 + jnz .fsfrfe3 + push eax + lea eax, [esp+16+8+12+8] + call dword [eax+20] ; extend directory + pop eax + jnc .scan_dir + add esp, 12+8+12+32 + popad + mov eax, ERROR_DISK_FULL + xor ebx, ebx + ret +.free: + test ecx, ecx + jnz @f + mov [esp], edi + mov ecx, [esp+12+8+12+8] + mov [esp+4], ecx + mov ecx, [esp+12+8+12+12] + mov [esp+8], ecx + xor ecx, ecx +@@: + inc ecx + cmp ecx, eax + jb .scan_cont +; found! +; calculate name checksum + push esi ecx + mov esi, [esp+8+12] + mov ecx, 11 + xor eax, eax +@@: + ror al, 1 + add al, [esi] + inc esi + loop @b + pop ecx esi + pop edi + pop dword [esp+8+12+12] + pop dword [esp+8+12+12] +; edi points to first entry in free chunk + dec ecx + jz .nolfn + push esi + push eax + lea eax, [esp+8+8+12+8] + call dword [eax+8] ; begin write + mov al, 40h +.writelfn: + or al, cl + mov esi, [esp+4] + push ecx + dec ecx + imul ecx, 13 + add esi, ecx + stosb + mov cl, 5 + call fs_RamdiskRewrite.read_symbols + mov ax, 0xF + stosw + mov al, [esp+4] + stosb + mov cl, 6 + call fs_RamdiskRewrite.read_symbols + xor eax, eax + stosw + mov cl, 2 + call fs_RamdiskRewrite.read_symbols + pop ecx + lea eax, [esp+8+8+12+8] + call dword [eax+12] ; next write + xor eax, eax + loop .writelfn + pop eax + pop esi +; lea eax, [esp+8+12+8] +; call dword [eax+16] ; end write +.nolfn: + xchg esi, [esp] + mov ecx, 11 + rep movsb + mov word [edi], 20h ; attributes + sub edi, 11 + pop esi ecx + add esp, 12 + mov byte [edi+13], 0 ; tenths of a second at file creation time + call get_time_for_file + mov [edi+14], ax ; creation time + mov [edi+22], ax ; last write time + call get_date_for_file + mov [edi+16], ax ; creation date + mov [edi+24], ax ; last write date + mov [edi+18], ax ; last access date + xor ecx, ecx + mov word [edi+20], cx ; high word of cluster + mov word [edi+26], cx ; low word of cluster - to be filled + mov dword [edi+28], ecx ; file size - to be filled + cmp byte [esp+32+28], cl + jz .doit +; create directory + mov byte [edi+11], 10h ; attributes: folder + mov edx, edi + lea eax, [esp+8] + call dword [eax+16] ; flush directory + push ecx + mov ecx, [SECTORS_PER_CLUSTER] + shl ecx, 9 + jmp .doit2 +.doit: + lea eax, [esp+8] + call dword [eax+16] ; flush directory + push ecx + mov ecx, [esp+4+32+24] +.doit2: + push ecx + push edi + mov esi, edx + test ecx, ecx + jz .done + call get_free_FAT + jc .diskfull + push eax + mov [edi+26], ax + shr eax, 16 + mov [edi+20], ax + lea eax, [esp+16+8] + call dword [eax+16] ; flush directory + pop eax + push edx + mov edx, [fatEND] + call set_FAT + pop edx +.write_cluster: + push eax + dec eax + dec eax + mov ebp, [SECTORS_PER_CLUSTER] + imul eax, ebp + add eax, [DATA_START] +; write data +.write_sector: + cmp byte [esp+16+32+28], 0 + jnz .writedir + mov ecx, 512 + cmp dword [esp+8], ecx + jb .writeshort +; we can write directly from given buffer + mov ebx, esi + add esi, ecx + jmp .writecommon +.writeshort: + mov ecx, [esp+8] + push ecx + mov edi, buffer + mov ebx, edi + rep movsb +.writedircont: + mov ecx, buffer+0x200 + sub ecx, edi + push eax + xor eax, eax + rep stosb + pop eax + pop ecx +.writecommon: + call hd_write + cmp [hd_error], 0 + jnz .writeerr + inc eax + sub dword [esp+8], ecx + jz .writedone + dec ebp + jnz .write_sector +; allocate new cluster + pop eax + mov ecx, eax + call get_free_FAT + jc .diskfull + push edx + mov edx, [fatEND] + call set_FAT + xchg eax, ecx + mov edx, ecx + call set_FAT + pop edx + xchg eax, ecx + jmp .write_cluster +.diskfull: + mov eax, ERROR_DISK_FULL + jmp .ret +.writeerr: + pop eax + sub esi, ecx + mov eax, 11 + jmp .ret +.writedone: + pop eax +.done: + xor eax, eax +.ret: + pop edi ecx + mov ebx, esi + sub ebx, edx + pop ebp + mov [esp+32+28], eax + lea eax, [esp+8] + call dword [eax+8] + mov [edi+28], ebx + call dword [eax+16] + mov [esp+32+16], ebx + lea eax, [ebx+511] + shr eax, 9 + mov ecx, [SECTORS_PER_CLUSTER] + lea eax, [eax+ecx-1] + xor edx, edx + div ecx + mov ecx, ebp + sub ecx, eax + call add_disk_free_space + add esp, 32 + call update_disk + popad + ret +.writedir: + push 512 + mov edi, buffer + mov ebx, edi + mov ecx, [SECTORS_PER_CLUSTER] + shl ecx, 9 + cmp ecx, [esp+12] + jnz .writedircont + dec dword [esp+16] + push esi + mov ecx, 32/4 + rep movsd + pop esi + mov dword [edi-32], '. ' + mov dword [edi-32+4], ' ' + mov dword [edi-32+8], ' ' + mov byte [edi-32+11], 10h + push esi + mov ecx, 32/4 + rep movsd + pop esi + mov dword [edi-32], '.. ' + mov dword [edi-32+4], ' ' + mov dword [edi-32+8], ' ' + mov byte [edi-32+11], 10h + mov ecx, [esp+20+8] + cmp ecx, [ROOT_CLUSTER] + jnz @f + xor ecx, ecx +@@: + mov word [edi-32+26], cx + shr ecx, 16 + mov [edi-32+20], cx + jmp .writedircont + +;---------------------------------------------------------------- +; +; fs_HdWrite - LFN variant for writing to hard disk +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to write, 0+ +; edx mem location to data +; +; ret ebx = bytes written (maybe 0) +; eax = 0 ok write or other = errormsg +; +;-------------------------------------------------------------- +fs_HdWrite.access_denied: + push ERROR_ACCESS_DENIED +fs_HdWrite.ret0: + pop eax + xor ebx, ebx + ret + +fs_HdWrite.ret11: + push 11 + jmp fs_HdWrite.ret0 + +fs_HdWrite: + cmp [fs_type], 1 + jz ntfs_HdWrite + cmp [fs_type], 2 + jz ext2_HdWrite + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jz @f + push ERROR_UNKNOWN_FS + jmp .ret0 +@@: + cmp byte [esi], 0 + jz .access_denied + pushad + call hd_find_lfn + pushfd + cmp [hd_error], 0 + jz @f + popfd + popad + push 11 + jmp .ret0 +@@: + popfd + jnc .found + popad + push ERROR_FILE_NOT_FOUND + jmp .ret0 +.found: +; FAT does not support files larger than 4GB + test ebx, ebx + jz .l1 + cmp dword [ebx+4], 0 + jz @f +.eof: + popad + push ERROR_END_OF_FILE + jmp .ret0 +@@: + mov ebx, [ebx] +.l1: +; now edi points to direntry, ebx=start byte to write, +; ecx=number of bytes to write, edx=data pointer + +; extend file if needed + add ecx, ebx + jc .eof ; FAT does not support files larger than 4GB + push eax ; save directory sector + push 0 ; return value=0 + + call get_time_for_file + mov [edi+22], ax ; last write time + call get_date_for_file + mov [edi+24], ax ; last write date + mov [edi+18], ax ; last access date + + push dword [edi+28] ; save current file size + cmp ecx, [edi+28] + jbe .length_ok + cmp ecx, ebx + jz .length_ok + call hd_extend_file + jnc .length_ok + mov [esp+4], eax +; hd_extend_file can return three error codes: FAT table error, device error or disk full. +; First two cases are fatal errors, in third case we may write some data + cmp al, ERROR_DISK_FULL + jz .disk_full + pop eax + pop eax + mov [esp+4+28], eax + pop eax + popad + xor ebx, ebx + ret +.disk_full: +; correct number of bytes to write + mov ecx, [edi+28] + cmp ecx, ebx + ja .length_ok +.ret: + call update_disk + cmp [hd_error], 0 + jz @f + mov byte [esp+4], 11 +@@: + pop eax + pop eax + mov [esp+4+28], eax ; eax=return value + pop eax + sub edx, [esp+20] + mov [esp+16], edx ; ebx=number of written bytes + popad + ret +.length_ok: + mov esi, [edi+28] + mov eax, [edi+20-2] + mov ax, [edi+26] + mov edi, eax ; edi=current cluster + xor ebp, ebp ; ebp=current sector in cluster +; save directory + mov eax, [esp+8] + push ebx + mov ebx, buffer + call hd_write + pop ebx + cmp [hd_error], 0 + jz @f +.device_err: + mov byte [esp+4], 11 + jmp .ret +@@: + +; now ebx=start pos, ecx=end pos, both lie inside file + sub ecx, ebx + jz .ret +.write_loop: +; skip unmodified sectors + cmp dword [esp], 0x200 + jb .modify + sub ebx, 0x200 + jae .skip + add ebx, 0x200 +.modify: +; get length of data in current sector + push ecx + sub ebx, 0x200 + jb .hasdata + neg ebx + xor ecx, ecx + jmp @f +.hasdata: + neg ebx + cmp ecx, ebx + jbe @f + mov ecx, ebx +@@: +; get current sector number + mov eax, edi + dec eax + dec eax + imul eax, [SECTORS_PER_CLUSTER] + add eax, [DATA_START] + add eax, ebp +; load sector if needed + cmp dword [esp+4], 0 ; we don't need to read uninitialized data + jz .noread + cmp ecx, 0x200 ; we don't need to read sector if it is fully rewritten + jz .noread + cmp ecx, esi ; (same for the last sector) + jz .noread + push ebx + mov ebx, buffer + call hd_read + pop ebx + cmp [hd_error], 0 + jz @f +.device_err2: + pop ecx + jmp .device_err +@@: +.noread: +; zero uninitialized data if file was extended (because hd_extend_file does not this) + push eax ecx edi + xor eax, eax + mov ecx, 0x200 + sub ecx, [esp+4+12] + jbe @f + mov edi, buffer + add edi, [esp+4+12] + rep stosb +@@: +; zero uninitialized data in the last sector + mov ecx, 0x200 + sub ecx, esi + jbe @f + mov edi, buffer + add edi, esi + rep stosb +@@: + pop edi ecx +; copy new data + mov eax, edx + neg ebx + jecxz @f + add ebx, buffer+0x200 + call memmove + xor ebx, ebx +@@: + pop eax +; save sector + push ebx + mov ebx, buffer + call hd_write + pop ebx + cmp [hd_error], 0 + jnz .device_err2 + add edx, ecx + sub [esp], ecx + pop ecx + jz .ret +.skip: +; next sector + inc ebp + cmp ebp, [SECTORS_PER_CLUSTER] + jb @f + xor ebp, ebp + mov eax, edi + call get_FAT + mov edi, eax + cmp [hd_error], 0 + jnz .device_err +@@: + sub esi, 0x200 + jae @f + xor esi, esi +@@: + sub dword [esp], 0x200 + jae @f + and dword [esp], 0 +@@: + jmp .write_loop + +hd_extend_file.zero_size: + xor eax, eax + jmp hd_extend_file.start_extend + +; extends file on hd to given size (new data area is undefined) +; in: edi->direntry, ecx=new size +; out: CF=0 => OK, eax=0 +; CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or 11) +hd_extend_file: + push ebp + mov ebp, [SECTORS_PER_CLUSTER] + imul ebp, [BYTES_PER_SECTOR] + push ecx +; find the last cluster of file + mov eax, [edi+20-2] + mov ax, [edi+26] + mov ecx, [edi+28] + jecxz .zero_size +.last_loop: + sub ecx, ebp + jbe .last_found + call get_FAT + cmp [hd_error], 0 + jz @f +.device_err: + pop ecx +.device_err2: + pop ebp + push 11 +.ret_err: + pop eax + stc + ret +@@: + cmp eax, 2 + jb .fat_err + cmp eax, [fatRESERVED] + jb .last_loop +.fat_err: + pop ecx ebp + push ERROR_FAT_TABLE + jmp .ret_err +.last_found: + push eax + call get_FAT + cmp [hd_error], 0 + jz @f + pop eax + jmp .device_err +@@: + cmp eax, [fatRESERVED] + pop eax + jb .fat_err +; set length to full number of clusters + sub [edi+28], ecx +.start_extend: + pop ecx +; now do extend + push edx + mov edx, 2 ; start scan from cluster 2 +.extend_loop: + cmp [edi+28], ecx + jae .extend_done +; add new cluster + push eax + call get_free_FAT + jc .disk_full + mov edx, [fatEND] + call set_FAT + mov edx, eax + pop eax + test eax, eax + jz .first_cluster + push edx + call set_FAT + pop edx + jmp @f +.first_cluster: + ror edx, 16 + mov [edi+20], dx + ror edx, 16 + mov [edi+26], dx +@@: + push ecx + mov ecx, -1 + call add_disk_free_space + pop ecx + mov eax, edx + cmp [hd_error], 0 + jnz .device_err3 + add [edi+28], ebp + jmp .extend_loop +.extend_done: + mov [edi+28], ecx + pop edx ebp + xor eax, eax ; CF=0 + ret +.device_err3: + pop edx + jmp .device_err2 +.disk_full: + pop eax edx ebp + push ERROR_DISK_FULL + pop eax + cmp [hd_error], 0 + jz @f + mov al, 11 +@@: + stc + ret + +;---------------------------------------------------------------- +; +; fs_HdSetFileEnd - set end of file on hard disk +; +; esi points to filename +; ebx points to 64-bit number = new file size +; ecx ignored (reserved) +; edx ignored (reserved) +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +fs_HdSetFileEnd: + cmp [fs_type], 1 + jz ntfs_HdSetFileEnd + cmp [fs_type], 2 + jz ext2_HdSetFileEnd + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jz @f + push ERROR_UNKNOWN_FS +.ret: + pop eax + ret +@@: + cmp byte [esi], 0 + jnz @f +.access_denied: + push ERROR_ACCESS_DENIED + jmp .ret +@@: + push edi + call hd_find_lfn + pushfd + cmp [hd_error], 0 + jz @f + popfd + push 11 + jmp .ret +@@: + popfd + jnc @f + pop edi + push ERROR_FILE_NOT_FOUND + jmp .ret +@@: +; must not be directory + test byte [edi+11], 10h + jz @f + pop edi + jmp .access_denied +@@: +; file size must not exceed 4 Gb + cmp dword [ebx+4], 0 + jz @f + pop edi + push ERROR_END_OF_FILE + jmp .ret +@@: + push eax ; save directory sector +; set file modification date/time to current + call fat_update_datetime + mov eax, [ebx] + cmp eax, [edi+28] + jb .truncate + ja .expand + pop eax + mov ebx, buffer + call hd_write + pop edi + xor eax, eax + cmp [hd_error], 0 + jz @f + mov al, 11 +@@: + ret +.expand: + push ebx ebp ecx + push dword [edi+28] ; save old size + mov ecx, eax + call hd_extend_file + push eax ; return code + jnc .expand_ok + cmp al, ERROR_DISK_FULL + jz .disk_full +.pop_ret: + call update_disk + pop eax ecx ebp ebx ecx edi edi + ret +.expand_ok: +.disk_full: +; save directory + mov eax, [edi+28] + xchg eax, [esp+20] + mov ebx, buffer + call hd_write + mov eax, [edi+20-2] + mov ax, [edi+26] + mov edi, eax + cmp [hd_error], 0 + jz @f +.pop_ret11: + mov byte [esp], 11 + jmp .pop_ret +@@: +; now zero new data + xor ebp, ebp +; edi=current cluster, ebp=sector in cluster +; [esp+20]=new size, [esp+4]=old size, [esp]=return code +.zero_loop: + sub dword [esp+4], 0x200 + jae .next_cluster + lea eax, [edi-2] + imul eax, [SECTORS_PER_CLUSTER] + add eax, [DATA_START] + add eax, ebp + cmp dword [esp+4], -0x200 + jz .noread + mov ebx, buffer + call hd_read + cmp [hd_error], 0 + jnz .err_next +.noread: + mov ecx, [esp+4] + neg ecx + push edi + mov edi, buffer+0x200 + add edi, [esp+8] + push eax + xor eax, eax + mov [esp+12], eax + rep stosb + pop eax + pop edi + call hd_write + cmp [hd_error], 0 + jz .next_cluster +.err_next: + mov byte [esp], 11 +.next_cluster: + sub dword [esp+20], 0x200 + jbe .pop_ret + inc ebp + cmp ebp, [SECTORS_PER_CLUSTER] + jb .zero_loop + xor ebp, ebp + mov eax, edi + call get_FAT + mov edi, eax + cmp [hd_error], 0 + jnz .pop_ret11 + jmp .zero_loop +.truncate: + mov [edi+28], eax + push ecx + mov ecx, [edi+20-2] + mov cx, [edi+26] + push eax + test eax, eax + jz .zero_size +; find new last cluster +@@: + mov eax, [SECTORS_PER_CLUSTER] + shl eax, 9 + sub [esp], eax + jbe @f + mov eax, ecx + call get_FAT + mov ecx, eax + cmp [hd_error], 0 + jz @b +.device_err3: + pop eax ecx eax edi + push 11 + pop eax + ret +@@: +; we will zero data at the end of last sector - remember it + push ecx +; terminate FAT chain + push edx + mov eax, ecx + mov edx, [fatEND] + call set_FAT + mov eax, edx + pop edx + cmp [hd_error], 0 + jz @f +.device_err4: + pop ecx + jmp .device_err3 +.zero_size: + and word [edi+20], 0 + and word [edi+26], 0 + push 0 + mov eax, ecx +@@: +; delete FAT chain + call clear_cluster_chain + cmp [hd_error], 0 + jnz .device_err4 +; save directory + mov eax, [esp+12] + push ebx + mov ebx, buffer + call hd_write + pop ebx + cmp [hd_error], 0 + jnz .device_err4 +; zero last sector, ignore errors + pop ecx + pop eax + dec ecx + imul ecx, [SECTORS_PER_CLUSTER] + add ecx, [DATA_START] + push eax + sar eax, 9 + add ecx, eax + pop eax + and eax, 0x1FF + jz .truncate_done + push ebx eax + mov eax, ecx + mov ebx, buffer + call hd_read + pop eax + lea edi, [buffer+eax] + push ecx + mov ecx, 0x200 + sub ecx, eax + xor eax, eax + rep stosb + pop eax + call hd_write + pop ebx +.truncate_done: + pop ecx eax edi + call update_disk + xor eax, eax + cmp [hd_error], 0 + jz @f + mov al, 11 +@@: + ret + +fs_HdGetFileInfo: + cmp [fs_type], 1 + jz ntfs_HdGetFileInfo + cmp [fs_type], 2 + jz ext2_HdGetFileInfo + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jz @f + mov eax, ERROR_UNKNOWN_FS + ret +@@: + cmp byte [esi], 0 + jnz @f + mov eax, 2 + ret +@@: + push edi + call hd_find_lfn + pushfd + cmp [hd_error], 0 + jz @f + popfd + pop edi + mov eax, 11 + ret +@@: + popfd + jmp fs_GetFileInfo_finish + +fs_HdSetFileInfo: + cmp [fs_type], 1 + jz ntfs_HdSetFileInfo + cmp [fs_type], 2 + jz ext2_HdSetFileInfo + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jz @f + mov eax, ERROR_UNKNOWN_FS + ret +@@: + cmp byte [esi], 0 + jnz @f + mov eax, 2 + ret +@@: + push edi + call hd_find_lfn + pushfd + cmp [hd_error], 0 + jz @f + popfd + pop edi + mov eax, 11 + ret +@@: + popfd + jnc @f + pop edi + mov eax, ERROR_FILE_NOT_FOUND + ret +@@: + push eax + call bdfe_to_fat_entry + pop eax + mov ebx, buffer + call hd_write + call update_disk + pop edi + xor eax, eax + ret + +;---------------------------------------------------------------- +; +; fs_HdDelete - delete file or empty folder from hard disk +; +; esi points to filename +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +fs_HdDelete: + cmp [fs_type], 1 + jz ntfs_HdDelete + cmp [fs_type], 2 + jz ext2_HdDelete + cmp [fs_type], 16 + jz @f + cmp [fs_type], 32 + jz @f + push ERROR_UNKNOWN_FS +.pop_ret: + pop eax + ret +@@: + cmp byte [esi], 0 + jnz @f +; cannot delete root! +.access_denied: + push ERROR_ACCESS_DENIED + jmp .pop_ret +@@: + and [longname_sec1], 0 + and [longname_sec2], 0 + push edi + call hd_find_lfn + jnc .found + pop edi + push ERROR_FILE_NOT_FOUND + jmp .pop_ret +.found: + cmp dword [edi], '. ' + jz .access_denied2 + cmp dword [edi], '.. ' + jz .access_denied2 + test byte [edi+11], 10h + jz .dodel +; we can delete only empty folders! + pushad + mov ebp, [edi+20-2] + mov bp, [edi+26] + xor ecx, ecx + lea eax, [ebp-2] + imul eax, [SECTORS_PER_CLUSTER] + add eax, [DATA_START] + mov ebx, buffer + call hd_read + cmp [hd_error], 0 + jnz .err1 + add ebx, 2*0x20 +.checkempty: + cmp byte [ebx], 0 + jz .empty + cmp byte [ebx], 0xE5 + jnz .notempty + add ebx, 0x20 + cmp ebx, buffer+0x200 + jb .checkempty + inc ecx + cmp ecx, [SECTORS_PER_CLUSTER] + jb @f + mov eax, ebp + call get_FAT + cmp [hd_error], 0 + jnz .err1 + mov ebp, eax + xor ecx, ecx +@@: + lea eax, [ebp-2] + imul eax, [SECTORS_PER_CLUSTER] + add eax, [DATA_START] + add eax, ecx + mov ebx, buffer + call hd_read + cmp [hd_error], 0 + jz .checkempty +.err1: + popad +.err2: + pop edi + push 11 + pop eax + ret +.notempty: + popad +.access_denied2: + pop edi + push ERROR_ACCESS_DENIED + pop eax + ret +.empty: + popad + push ebx + mov ebx, buffer + call hd_read + pop ebx + cmp [hd_error], 0 + jnz .err2 +.dodel: + push eax + mov eax, [edi+20-2] + mov ax, [edi+26] + xchg eax, [esp] +; delete folder entry + mov byte [edi], 0xE5 +; delete LFN (if present) +.lfndel: + cmp edi, buffer + ja @f + cmp [longname_sec2], 0 + jz .lfndone + push [longname_sec2] + push [longname_sec1] + pop [longname_sec2] + and [longname_sec1], 0 + push ebx + mov ebx, buffer + call hd_write + mov eax, [esp+4] + call hd_read + pop ebx + pop eax + mov edi, buffer+0x200 +@@: + sub edi, 0x20 + cmp byte [edi], 0xE5 + jz .lfndone + cmp byte [edi+11], 0xF + jnz .lfndone + mov byte [edi], 0xE5 + jmp .lfndel +.lfndone: + push ebx + mov ebx, buffer + call hd_write + pop ebx +; delete FAT chain + pop eax + call clear_cluster_chain + call update_disk + pop edi + xor eax, eax + cmp [hd_error], 0 + jz @f + mov al, 11 +@@: + ret + +; \end{diamond} diff --git a/kernel/trunk/fs/fs.inc b/kernel/trunk/fs/fs.inc index dc1afdbfd..463809b51 100644 --- a/kernel/trunk/fs/fs.inc +++ b/kernel/trunk/fs/fs.inc @@ -1,797 +1,801 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ;; -;; System service for filesystem call ;; -;; (C) 2004 Ville Turjanmaa, License: GPL ;; -;; 29.04.2006 Elimination of hangup after the ;; -;; expiration hd_wait_timeout (for LBA) - Mario79 ;; -;; 15.01.2005 get file size/attr/date, ;; -;; file_append (only for hd) - ATV ;; -;; 23.11.2004 test if hd/partition is set - ATV ;; -;; 18.11.2004 get_disk_info and more error codes - ATV ;; -;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;; -;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -iglobal -dir0: db 'HARDDISK ' - db 'RAMDISK ' - db 'FLOPPYDISK ' - db 0 - -dir1: db 'FIRST ' - db 'SECOND ' - db 'THIRD ' - db 'FOURTH ' - db 0 - -not_select_IDE db 0 - -hd_address_table: dd 0x1f0,0x00,0x1f0,0x10 - dd 0x170,0x00,0x170,0x10 -endg - -file_system: - -; IN: -; -; eax = 0 ; read file /RamDisk/First 6 -; eax = 8 ; lba read -; eax = 15 ; get_disk_info -; -; OUT: -; -; eax = 0 : read ok -; eax = 1 : no hd base and/or partition defined -; eax = 2 : function is unsupported for this FS -; eax = 3 : unknown FS -; eax = 4 : partition not defined at hd -; eax = 5 : file not found -; eax = 6 : end of file -; eax = 7 : memory pointer not in application area -; eax = 8 : disk full -; eax = 9 : fat table corrupted -; eax = 10 : access denied -; eax = 11 : disk error -; -; ebx = size - -; \begin{diamond}[18.03.2006] -; for subfunction 16 (start application) error codes must be negative -; because positive values are valid PIDs -; so possible return values are: -; eax > 0 : process created, eax=PID - -; -0x10 <= eax < 0 : -eax is filesystem error code: -; eax = -1 = 0xFFFFFFFF : no hd base and/or partition defined -; eax = -3 = 0xFFFFFFFD : unknown FS -; eax = -5 = 0xFFFFFFFB : file not found -; eax = -6 = 0xFFFFFFFA : unexpected end of file (probably not executable file) -; eax = -9 = 0xFFFFFFF7 : fat table corrupted -; eax = -10 = 0xFFFFFFF6 : access denied - -; -0x20 <= eax < -0x10: eax is process creation error code: -; eax = -0x20 = 0xFFFFFFE0 : too many processes -; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable -; eax = -0x1E = 0xFFFFFFE2 : no memory - -; ebx is not changed - -; \end{diamond}[18.03.2006] - - ; Extract parameters - ; add eax, std_application_base_address ; abs start of info block - - cmp dword [eax+0],15 ; GET_DISK_INFO - je fs_info - - cmp dword [CURRENT_TASK],1 ; no memory checks for kernel requests - jz no_checks_for_kernel - mov edx,eax - cmp dword [eax+0],1 - jnz .usual_check - mov ebx,[eax+12] - ; add ebx,std_application_base_address - mov ecx,[eax+8] - call check_region - test eax,eax - jnz area_in_app_mem - -.error_output: - mov esi,buffer_failed - call sys_msg_board_str -; mov eax,7 - mov dword [esp+36],7 - ret -iglobal - buffer_failed db 'K : Buffer check failed',13,10,0 -endg -.usual_check: - cmp dword [eax+0],0 - mov ecx,512 - jnz .small_size - mov ecx,[eax+8] - shl ecx,9 -.small_size: - mov ebx,[eax+12] - ; add ebx,std_application_base_address - call check_region - test eax,eax - jz .error_output - area_in_app_mem: - mov eax,edx - no_checks_for_kernel: - - fs_read: - - mov ebx,[eax+20] ; program wants root directory ? - test bl,bl - je fs_getroot - test bh,bh - jne fs_noroot - fs_getroot: -; \begin{diamond}[18.03.2006] -; root - only read is allowed -; other operations return "access denied", eax=10 -; (execute operation returns eax=-10) - cmp dword [eax], 0 - jz .read_root - mov dword [esp+36], 10 - ret -.read_root: -; \end{diamond}[18.03.2006] - mov esi,dir0 - mov edi,[eax+12] - ; add edi,std_application_base_address - mov ecx,11 - push ecx -; cld ; already is - rep movsb - mov al,0x10 - stosb - add edi,32-11-1 - pop ecx - rep movsb - stosb - and dword [esp+36],0 ; ok read - mov dword [esp+24],32*2 ; size of root - ret - - fs_info: ;start of code - Mihasik - push eax - cmp [eax+21],byte 'h' - je fs_info_h - cmp [eax+21],byte 'H' - je fs_info_h - cmp [eax+21],byte 'r' - je fs_info_r - cmp [eax+21],byte 'R' - je fs_info_r - mov eax,3 ;if unknown disk - xor ebx,ebx - xor ecx,ecx - xor edx,edx - jmp fs_info1 - fs_info_r: - call ramdisk_free_space ;if ramdisk - mov ecx,edi ;free space in ecx - shr ecx,9 ;free clusters - mov ebx,2847 ;total clusters - mov edx,512 ;cluster size - xor eax,eax ;always 0 - jmp fs_info1 - fs_info_h: ;if harddisk - call get_hd_info - fs_info1: - pop edi - mov [esp+36],eax - mov [esp+24],ebx ; total clusters on disk - mov [esp+32],ecx ; free clusters on disk - mov [edi],edx ; cluster size in bytes - ret ;end of code - Mihasik - - fs_noroot: - - push dword [eax+0] ; read/write/delete/.../makedir/rename/lba/run - push dword [eax+4] ; 512 block number to read - push dword [eax+8] ; bytes to write/append or 512 blocks to read - mov ebx,[eax+12] - ; add ebx,std_application_base_address - push ebx ; abs start of return/save area - - lea esi,[eax+20] ; abs start of dir + filename - mov edi,[eax+16] - ; add edi,std_application_base_address ; abs start of work area - - call expand_pathz - - push edi ; dir start - push ebx ; name of file start - - mov eax,[edi+1] - cmp eax,'RD ' - je fs_yesramdisk - cmp eax,'RAMD' - jne fs_noramdisk - - fs_yesramdisk: - - cmp byte [edi+1+11],0 - je fs_give_dir1 - - mov eax,[edi+1+12] - cmp eax,'1 ' - je fs_yesramdisk_first - cmp eax,'FIRS' - jne fs_noramdisk - - fs_yesramdisk_first: - - cmp dword [esp+20],8 ; LBA read ramdisk - jne fs_no_LBA_read_ramdisk - - mov eax,[esp+16] ; LBA block to read - mov ecx,[esp+8] ; abs pointer to return area - - call LBA_read_ramdisk - jmp file_system_return - - - fs_no_LBA_read_ramdisk: - - cmp dword [esp+20],0 ; READ - jne fs_noramdisk_read - - mov eax,[esp+4] ; fname - add eax,2*12+1 - mov ebx,[esp+16] ; block start - inc ebx - mov ecx,[esp+12] ; block count - mov edx,[esp+8] ; return - mov esi,[esp+0] - sub esi,eax - add esi,12+1 ; file name length - call fileread - - jmp file_system_return - - - fs_noramdisk_read: - fs_noramdisk: - - ;******************************************************************** - mov eax,[edi+1] - cmp eax,'FD ' - je fs_yesflpdisk - cmp eax,'FLOP' - jne fs_noflpdisk - - fs_yesflpdisk: - call reserve_flp - - cmp byte [edi+1+11],0 - je fs_give_dir1 - - mov eax,[edi+1+12] - cmp eax,'1 ' - je fs_yesflpdisk_first - cmp eax,'FIRS' - je fs_yesflpdisk_first - cmp eax,'2 ' - je fs_yesflpdisk_second - cmp eax,'SECO' - jne fs_noflpdisk - jmp fs_yesflpdisk_second - - fs_yesflpdisk_first: - mov [flp_number],1 - jmp fs_yesflpdisk_start - fs_yesflpdisk_second: - mov [flp_number],2 - fs_yesflpdisk_start: - cmp dword [esp+20],0 ; READ - jne fs_noflpdisk_read - - mov eax,[esp+4] ; fname - add eax,2*12+1 - mov ebx,[esp+16] ; block start - inc ebx - mov ecx,[esp+12] ; block count - mov edx,[esp+8] ; return - mov esi,[esp+0] - sub esi,eax - add esi,12+1 ; file name length - call floppy_fileread - - jmp file_system_return - - - fs_noflpdisk_read: - fs_noflpdisk: - ;***************************************************************** - - mov eax,[edi+1] - cmp eax,'HD0 ' - je fs_yesharddisk_IDE0 - cmp eax,'HD1 ' - je fs_yesharddisk_IDE1 - cmp eax,'HD2 ' - je fs_yesharddisk_IDE2 - cmp eax,'HD3 ' - je fs_yesharddisk_IDE3 - jmp old_path_harddisk -fs_yesharddisk_IDE0: - call reserve_hd1 - mov [hdbase],0x1f0 - mov [hdid],0x0 - mov [hdpos],1 - jmp fs_yesharddisk_partition -fs_yesharddisk_IDE1: - call reserve_hd1 - mov [hdbase],0x1f0 - mov [hdid],0x10 - mov [hdpos],2 - jmp fs_yesharddisk_partition -fs_yesharddisk_IDE2: - call reserve_hd1 - mov [hdbase],0x170 - mov [hdid],0x0 - mov [hdpos],3 - jmp fs_yesharddisk_partition -fs_yesharddisk_IDE3: - call reserve_hd1 - mov [hdbase],0x170 - mov [hdid],0x10 - mov [hdpos],4 -fs_yesharddisk_partition: - call reserve_hd_channel -; call choice_necessity_partition -; jmp fs_yesharddisk_all - jmp fs_for_new_semantic - -choice_necessity_partition: - mov eax,[edi+1+12] - call StringToNumber - mov [fat32part],eax -choice_necessity_partition_1: - mov ecx,[hdpos] - xor eax,eax - mov [hd_entries], eax ; entries in hd cache - mov edx,DRIVE_DATA+2 - cmp ecx,0x80 - jb search_partition_array - mov ecx,4 - search_partition_array: - mov bl,[edx] - movzx ebx,bl - add eax,ebx - inc edx - loop search_partition_array - mov ecx,[hdpos] - mov edx,BiosDiskPartitions - sub ecx,0x80 - jb .s - je .f - @@: - mov ebx,[edx] - add edx,4 - add eax,ebx - loop @b - jmp .f - .s: - sub eax,ebx - .f: - add eax, [known_part] ; add eax,[fat32part] - dec eax - xor edx,edx - imul eax,100 - add eax,DRIVE_DATA+0xa - mov [transfer_adress],eax - call partition_data_transfer_1 - ret - - old_path_harddisk: - mov eax,[edi+1] - cmp eax,'HD ' - je fs_yesharddisk - cmp eax,'HARD' - jne fs_noharddisk - - fs_yesharddisk: - cmp dword [esp+20],8 ; LBA read - jne fs_no_LBA_read - mov eax,[esp+16] ; LBA block to read - lea ebx,[edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH - mov ecx,[esp+8] ; abs pointer to return area - call LBA_read - jmp file_system_return - - fs_no_LBA_read: - - cmp byte [edi+1+11],0 ; directory read - je fs_give_dir1 - call reserve_hd1 - fs_for_new_semantic: - call choice_necessity_partition - - fs_yesharddisk_all: - mov eax,1 - mov ebx, [esp+24+24] - cmp [hdpos],0 ; is hd base set? - jz hd_err_return - cmp [fat32part],0 ; is partition set? - jnz @f -hd_err_return: - call free_hd_channel - and [hd1_status], 0 - jmp file_system_return -@@: - - cmp dword [esp+20],0 ; READ - jne fs_noharddisk_read - - mov eax,[esp+0] ; /fname - lea edi,[eax+12] - mov byte [eax],0 ; path to asciiz - inc eax ; filename start - - mov ebx,[esp+12] ; count to read - mov ecx,[esp+8] ; buffer - mov edx,[esp+4] - add edx,12*2 ; dir start - sub edi,edx ; path length - mov esi,[esp+16] ; blocks to read - - call file_read - - mov edi,[esp+0] - mov byte [edi],'/' - - call free_hd_channel - and [hd1_status], 0 - jmp file_system_return - - fs_noharddisk_read: - - call free_hd_channel - and [hd1_status], 0 - - fs_noharddisk: -; \begin{diamond}[18.03.2006] - mov eax, 5 ; file not found -; а может быть, возвращать другой код ошибки? - mov ebx, [esp+24+24] ; do not change ebx in application -; \end{diamond}[18.03.2006] - - file_system_return: - - add esp,24 - - mov [esp+36],eax - mov [esp+24],ebx - ret - - - fs_give_dir1: - -; \begin{diamond}[18.03.2006] -; /RD,/FD,/HD - only read is allowed -; other operations return "access denied", eax=10 -; (execute operation returns eax=-10) - cmp dword [esp+20], 0 - jz .read - add esp, 20 - pop ecx - mov dword [esp+36], 10 - ret -.read: -; \end{diamond}[18.03.2006] - mov al,0x10 - mov ebx,1 - mov edi,[esp+8] - mov esi,dir1 - fs_d1_new: - mov ecx,11 -; cld - rep movsb - stosb - add edi,32-11-1 - dec ebx - jne fs_d1_new - - add esp,24 - - and dword [esp+36],0 ; ok read - mov dword [esp+24],32*1 ; dir/data size - ret - - - -LBA_read_ramdisk: - - cmp [lba_read_enabled],1 - je lbarrl1 - - xor ebx,ebx - mov eax,2 - ret - - lbarrl1: - - cmp eax,18*2*80 - jb lbarrl2 - xor ebx,ebx - mov eax,3 - ret - - lbarrl2: - - pushad - - call restorefatchain - - mov edi,ecx - mov esi,eax - - shl esi,9 - add esi,RAMDISK - mov ecx,512/4 -; cld - rep movsd - - popad - - xor ebx,ebx - xor eax,eax - ret - -LBA_read: - -; IN: -; -; eax = LBA block to read -; ebx = pointer to FIRST/SECOND/THIRD/FOURTH -; ecx = abs pointer to return area - - cmp [lba_read_enabled],1 - je lbarl1 - mov eax,2 - ret - - lbarl1: - - call reserve_hd1 - - push eax - push ecx - - mov edi,hd_address_table - mov esi,dir1 - mov eax,[ebx] - mov edx,'1 ' - mov ecx,4 - blar0: - cmp eax,[esi] - je blar2 - cmp eax,edx - je blar2 - inc edx - add edi,8 - add esi,11 - dec ecx - jnz blar0 - - mov eax,1 - mov ebx,1 - jmp LBA_read_ret - - blar2: - mov eax,[edi+0] - mov ebx,[edi+4] - - mov [hdbase],eax - mov [hdid],ebx - - call wait_for_hd_idle - cmp [hd_error],0 - jne hd_lba_error - - ; eax = hd port - ; ebx = set for primary (0x00) or slave (0x10) - - cli - - mov edx,eax - inc edx - xor eax,eax - out dx,al - inc edx - inc eax - out dx,al - inc edx - mov eax,[esp+4] - out dx,al - shr eax,8 - inc edx - out dx,al - shr eax,8 - inc edx - out dx,al - shr eax,8 - inc edx - and al,1+2+4+8 - add al,bl - add al,128+64+32 - out dx,al - - inc edx - mov al,20h - out dx,al - - sti - - call wait_for_sector_buffer - cmp [hd_error],0 - jne hd_lba_error - - cli - - mov edi,[esp+0] - mov ecx,256 - sub edx,7 - cld - rep insw - - sti - - xor eax,eax - xor ebx,ebx - - LBA_read_ret: - mov [hd_error],0 - mov [hd1_status],0 - add esp,2*4 - - ret - - -expand_pathz: -; IN: -; esi = asciiz path & file -; edi = buffer for path & file name -; OUT: -; edi = directory & file : / 11 + / 11 + / 11 - zero terminated -; ebx = /file name - zero terminated -; esi = pointer after source - - push eax - push ecx - push edi ;[esp+0] - - pathz_start: - mov byte [edi],'/' - inc edi - mov al,32 - mov ecx,11 - cld - rep stosb ; clear filename area - sub edi,11 - mov ebx,edi ; start of dir/file name - - pathz_new_char: - mov al,[esi] - inc esi - cmp al,0 - je pathz_end - - cmp al,'/' - jne pathz_not_path - cmp edi,ebx ; skip first '/' - jz pathz_new_char - lea edi,[ebx+11] ; start of next directory - jmp pathz_start - - pathz_not_path: - cmp al,'.' - jne pathz_not_ext - lea edi,[ebx+8] ; start of extension - jmp pathz_new_char - - pathz_not_ext: - cmp al,'a' - jb pathz_not_low - cmp al,'z' - ja pathz_not_low - sub al,0x20 ; char to uppercase - - pathz_not_low: - mov [edi],al - inc edi - mov eax,[esp+0] ; start_of_dest_path - add eax,512 ; keep maximum path under 512 bytes - cmp edi,eax - jb pathz_new_char - - pathz_end: - cmp ebx,edi ; if path end with '/' - jnz pathz_put_zero ; go back 1 level - sub ebx,12 - - pathz_put_zero: - mov byte [ebx+11],0 - dec ebx ; include '/' char into file name - pop edi - pop ecx - pop eax - ret - -;******************************************* -;* string to number -;* input eax - 4 byte string -;* output eax - number -;******************************************* -StringToNumber: -; ПЕРЕВОД СТРОКОВОГО ЧИСЛА В ЧИСЛОВОЙ ВИД -; Вход: -; EDI - адрес строки с числом. Конец числа отмечен кодом 0Dh -; Выход: -; CF - индикатор ошибок: -; 0 - ошибок нет; -; 1 - ошибка -; Если CF=0, то AX - число. - - push bx - push cx - push dx - push edi - mov [partition_string],eax - mov edi,partition_string - xor cx,cx -i1: - mov al,[edi] - cmp al,32 ;13 - je i_exit -; cmp al,'0' -; jb err -; cmp al,'9' -; ja err - sub al,48 - shl cx,1 - jc error - mov bx,cx - shl cx,1 - jc error - shl cx,1 - jc error - add cx,bx - jc error - cbw - add cx,ax - jc error -i3: - inc edi - jmp i1 -i_exit: - mov ax,cx - clc -i4: - movzx eax,ax - pop edi - pop dx - pop cx - pop bx - ret - -error: - stc - jmp i4 - -partition_string: dd 0 - db 32 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; System service for filesystem call ;; +;; (C) 2004 Ville Turjanmaa, License: GPL ;; +;; 29.04.2006 Elimination of hangup after the ;; +;; expiration hd_wait_timeout (for LBA) - Mario79 ;; +;; 15.01.2005 get file size/attr/date, ;; +;; file_append (only for hd) - ATV ;; +;; 23.11.2004 test if hd/partition is set - ATV ;; +;; 18.11.2004 get_disk_info and more error codes - ATV ;; +;; 08.11.2004 expand_pathz and rename (only for hd) - ATV ;; +;; 20.10.2004 Makedir/Removedir (only for hd) - ATV ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +iglobal +dir0: + db 'HARDDISK ' + db 'RAMDISK ' + db 'FLOPPYDISK ' + db 0 + +dir1: + db 'FIRST ' + db 'SECOND ' + db 'THIRD ' + db 'FOURTH ' + db 0 + +not_select_IDE db 0 + +hd_address_table: + dd 0x1f0,0x00,0x1f0,0x10 + dd 0x170,0x00,0x170,0x10 +endg + +file_system: + +; IN: +; +; eax = 0 ; read file /RamDisk/First 6 +; eax = 8 ; lba read +; eax = 15 ; get_disk_info +; +; OUT: +; +; eax = 0 : read ok +; eax = 1 : no hd base and/or partition defined +; eax = 2 : function is unsupported for this FS +; eax = 3 : unknown FS +; eax = 4 : partition not defined at hd +; eax = 5 : file not found +; eax = 6 : end of file +; eax = 7 : memory pointer not in application area +; eax = 8 : disk full +; eax = 9 : fat table corrupted +; eax = 10 : access denied +; eax = 11 : disk error +; +; ebx = size + +; \begin{diamond}[18.03.2006] +; for subfunction 16 (start application) error codes must be negative +; because positive values are valid PIDs +; so possible return values are: +; eax > 0 : process created, eax=PID + +; -0x10 <= eax < 0 : -eax is filesystem error code: +; eax = -1 = 0xFFFFFFFF : no hd base and/or partition defined +; eax = -3 = 0xFFFFFFFD : unknown FS +; eax = -5 = 0xFFFFFFFB : file not found +; eax = -6 = 0xFFFFFFFA : unexpected end of file (probably not executable file) +; eax = -9 = 0xFFFFFFF7 : fat table corrupted +; eax = -10 = 0xFFFFFFF6 : access denied + +; -0x20 <= eax < -0x10: eax is process creation error code: +; eax = -0x20 = 0xFFFFFFE0 : too many processes +; eax = -0x1F = 0xFFFFFFE1 : not Menuet/Kolibri executable +; eax = -0x1E = 0xFFFFFFE2 : no memory + +; ebx is not changed + +; \end{diamond}[18.03.2006] + + ; Extract parameters + ; add eax, std_application_base_address ; abs start of info block + + cmp dword [eax+0], 15; GET_DISK_INFO + je fs_info + + cmp dword [CURRENT_TASK], 1; no memory checks for kernel requests + jz no_checks_for_kernel + mov edx, eax + cmp dword [eax+0], 1 + jnz .usual_check + mov ebx, [eax+12] + ; add ebx,std_application_base_address + mov ecx, [eax+8] + call check_region + test eax, eax + jnz area_in_app_mem + +.error_output: + mov esi, buffer_failed + call sys_msg_board_str +; mov eax,7 + mov dword [esp+36], 7 + ret +iglobal + buffer_failed db 'K : Buffer check failed',13,10,0 +endg +.usual_check: + cmp dword [eax+0], 0 + mov ecx, 512 + jnz .small_size + mov ecx, [eax+8] + shl ecx, 9 +.small_size: + mov ebx, [eax+12] + ; add ebx,std_application_base_address + call check_region + test eax, eax + jz .error_output + area_in_app_mem: + mov eax, edx + no_checks_for_kernel: + + fs_read: + + mov ebx, [eax+20] ; program wants root directory ? + test bl, bl + je fs_getroot + test bh, bh + jne fs_noroot + fs_getroot: +; \begin{diamond}[18.03.2006] +; root - only read is allowed +; other operations return "access denied", eax=10 +; (execute operation returns eax=-10) + cmp dword [eax], 0 + jz .read_root + mov dword [esp+36], 10 + ret +.read_root: +; \end{diamond}[18.03.2006] + mov esi, dir0 + mov edi, [eax+12] + ; add edi,std_application_base_address + mov ecx, 11 + push ecx +; cld ; already is + rep movsb + mov al, 0x10 + stosb + add edi, 32-11-1 + pop ecx + rep movsb + stosb + and dword [esp+36], 0; ok read + mov dword [esp+24], 32*2; size of root + ret + + fs_info: ;start of code - Mihasik + push eax + cmp [eax+21], byte 'h' + je fs_info_h + cmp [eax+21], byte 'H' + je fs_info_h + cmp [eax+21], byte 'r' + je fs_info_r + cmp [eax+21], byte 'R' + je fs_info_r + mov eax, 3 ;if unknown disk + xor ebx, ebx + xor ecx, ecx + xor edx, edx + jmp fs_info1 + fs_info_r: + call ramdisk_free_space;if ramdisk + mov ecx, edi ;free space in ecx + shr ecx, 9 ;free clusters + mov ebx, 2847 ;total clusters + mov edx, 512 ;cluster size + xor eax, eax ;always 0 + jmp fs_info1 + fs_info_h: ;if harddisk + call get_hd_info + fs_info1: + pop edi + mov [esp+36], eax + mov [esp+24], ebx ; total clusters on disk + mov [esp+32], ecx ; free clusters on disk + mov [edi], edx ; cluster size in bytes + ret ;end of code - Mihasik + + fs_noroot: + + push dword [eax+0] ; read/write/delete/.../makedir/rename/lba/run + push dword [eax+4] ; 512 block number to read + push dword [eax+8] ; bytes to write/append or 512 blocks to read + mov ebx, [eax+12] + ; add ebx,std_application_base_address + push ebx ; abs start of return/save area + + lea esi, [eax+20] ; abs start of dir + filename + mov edi, [eax+16] + ; add edi,std_application_base_address ; abs start of work area + + call expand_pathz + + push edi ; dir start + push ebx ; name of file start + + mov eax, [edi+1] + cmp eax, 'RD ' + je fs_yesramdisk + cmp eax, 'RAMD' + jne fs_noramdisk + + fs_yesramdisk: + + cmp byte [edi+1+11], 0 + je fs_give_dir1 + + mov eax, [edi+1+12] + cmp eax, '1 ' + je fs_yesramdisk_first + cmp eax, 'FIRS' + jne fs_noramdisk + + fs_yesramdisk_first: + + cmp dword [esp+20], 8; LBA read ramdisk + jne fs_no_LBA_read_ramdisk + + mov eax, [esp+16] ; LBA block to read + mov ecx, [esp+8] ; abs pointer to return area + + call LBA_read_ramdisk + jmp file_system_return + + + fs_no_LBA_read_ramdisk: + + cmp dword [esp+20], 0; READ + jne fs_noramdisk_read + + mov eax, [esp+4] ; fname + add eax, 2*12+1 + mov ebx, [esp+16] ; block start + inc ebx + mov ecx, [esp+12] ; block count + mov edx, [esp+8] ; return + mov esi, [esp+0] + sub esi, eax + add esi, 12+1 ; file name length + call fileread + + jmp file_system_return + + + fs_noramdisk_read: + fs_noramdisk: + + ;******************************************************************** + mov eax, [edi+1] + cmp eax, 'FD ' + je fs_yesflpdisk + cmp eax, 'FLOP' + jne fs_noflpdisk + + fs_yesflpdisk: + call reserve_flp + + cmp byte [edi+1+11], 0 + je fs_give_dir1 + + mov eax, [edi+1+12] + cmp eax, '1 ' + je fs_yesflpdisk_first + cmp eax, 'FIRS' + je fs_yesflpdisk_first + cmp eax, '2 ' + je fs_yesflpdisk_second + cmp eax, 'SECO' + jne fs_noflpdisk + jmp fs_yesflpdisk_second + + fs_yesflpdisk_first: + mov [flp_number], 1 + jmp fs_yesflpdisk_start + fs_yesflpdisk_second: + mov [flp_number], 2 + fs_yesflpdisk_start: + cmp dword [esp+20], 0; READ + jne fs_noflpdisk_read + + mov eax, [esp+4] ; fname + add eax, 2*12+1 + mov ebx, [esp+16] ; block start + inc ebx + mov ecx, [esp+12] ; block count + mov edx, [esp+8] ; return + mov esi, [esp+0] + sub esi, eax + add esi, 12+1 ; file name length + call floppy_fileread + + jmp file_system_return + + + fs_noflpdisk_read: + fs_noflpdisk: + ;***************************************************************** + + mov eax, [edi+1] + cmp eax, 'HD0 ' + je fs_yesharddisk_IDE0 + cmp eax, 'HD1 ' + je fs_yesharddisk_IDE1 + cmp eax, 'HD2 ' + je fs_yesharddisk_IDE2 + cmp eax, 'HD3 ' + je fs_yesharddisk_IDE3 + jmp old_path_harddisk +fs_yesharddisk_IDE0: + call reserve_hd1 + mov [hdbase], 0x1f0 + mov [hdid], 0x0 + mov [hdpos], 1 + jmp fs_yesharddisk_partition +fs_yesharddisk_IDE1: + call reserve_hd1 + mov [hdbase], 0x1f0 + mov [hdid], 0x10 + mov [hdpos], 2 + jmp fs_yesharddisk_partition +fs_yesharddisk_IDE2: + call reserve_hd1 + mov [hdbase], 0x170 + mov [hdid], 0x0 + mov [hdpos], 3 + jmp fs_yesharddisk_partition +fs_yesharddisk_IDE3: + call reserve_hd1 + mov [hdbase], 0x170 + mov [hdid], 0x10 + mov [hdpos], 4 +fs_yesharddisk_partition: + call reserve_hd_channel +; call choice_necessity_partition +; jmp fs_yesharddisk_all + jmp fs_for_new_semantic + +choice_necessity_partition: + mov eax, [edi+1+12] + call StringToNumber + mov [fat32part], eax +choice_necessity_partition_1: + mov ecx, [hdpos] + xor eax, eax + mov [hd_entries], eax; entries in hd cache + mov edx, DRIVE_DATA+2 + cmp ecx, 0x80 + jb search_partition_array + mov ecx, 4 + search_partition_array: + mov bl, [edx] + movzx ebx, bl + add eax, ebx + inc edx + loop search_partition_array + mov ecx, [hdpos] + mov edx, BiosDiskPartitions + sub ecx, 0x80 + jb .s + je .f + @@: + mov ebx, [edx] + add edx, 4 + add eax, ebx + loop @b + jmp .f + .s: + sub eax, ebx + .f: + add eax, [known_part]; add eax,[fat32part] + dec eax + xor edx, edx + imul eax, 100 + add eax, DRIVE_DATA+0xa + mov [transfer_adress], eax + call partition_data_transfer_1 + ret + + old_path_harddisk: + mov eax, [edi+1] + cmp eax, 'HD ' + je fs_yesharddisk + cmp eax, 'HARD' + jne fs_noharddisk + + fs_yesharddisk: + cmp dword [esp+20], 8; LBA read + jne fs_no_LBA_read + mov eax, [esp+16] ; LBA block to read + lea ebx, [edi+1+12] ; pointer to FIRST/SECOND/THIRD/FOURTH + mov ecx, [esp+8] ; abs pointer to return area + call LBA_read + jmp file_system_return + + fs_no_LBA_read: + + cmp byte [edi+1+11], 0; directory read + je fs_give_dir1 + call reserve_hd1 + fs_for_new_semantic: + call choice_necessity_partition + + fs_yesharddisk_all: + mov eax, 1 + mov ebx, [esp+24+24] + cmp [hdpos], 0 ; is hd base set? + jz hd_err_return + cmp [fat32part], 0 ; is partition set? + jnz @f +hd_err_return: + call free_hd_channel + and [hd1_status], 0 + jmp file_system_return +@@: + + cmp dword [esp+20], 0; READ + jne fs_noharddisk_read + + mov eax, [esp+0] ; /fname + lea edi, [eax+12] + mov byte [eax], 0 ; path to asciiz + inc eax ; filename start + + mov ebx, [esp+12] ; count to read + mov ecx, [esp+8] ; buffer + mov edx, [esp+4] + add edx, 12*2 ; dir start + sub edi, edx ; path length + mov esi, [esp+16] ; blocks to read + + call file_read + + mov edi, [esp+0] + mov byte [edi], '/' + + call free_hd_channel + and [hd1_status], 0 + jmp file_system_return + + fs_noharddisk_read: + + call free_hd_channel + and [hd1_status], 0 + + fs_noharddisk: +; \begin{diamond}[18.03.2006] + mov eax, 5 ; file not found +; а может быть, возвращать другой код ошибки? + mov ebx, [esp+24+24]; do not change ebx in application +; \end{diamond}[18.03.2006] + + file_system_return: + + add esp, 24 + + mov [esp+36], eax + mov [esp+24], ebx + ret + + + fs_give_dir1: + +; \begin{diamond}[18.03.2006] +; /RD,/FD,/HD - only read is allowed +; other operations return "access denied", eax=10 +; (execute operation returns eax=-10) + cmp dword [esp+20], 0 + jz .read + add esp, 20 + pop ecx + mov dword [esp+36], 10 + ret +.read: +; \end{diamond}[18.03.2006] + mov al, 0x10 + mov ebx, 1 + mov edi, [esp+8] + mov esi, dir1 + fs_d1_new: + mov ecx, 11 +; cld + rep movsb + stosb + add edi, 32-11-1 + dec ebx + jne fs_d1_new + + add esp, 24 + + and dword [esp+36], 0; ok read + mov dword [esp+24], 32*1; dir/data size + ret + + + +LBA_read_ramdisk: + + cmp [lba_read_enabled], 1 + je lbarrl1 + + xor ebx, ebx + mov eax, 2 + ret + + lbarrl1: + + cmp eax, 18*2*80 + jb lbarrl2 + xor ebx, ebx + mov eax, 3 + ret + + lbarrl2: + + pushad + + call restorefatchain + + mov edi, ecx + mov esi, eax + + shl esi, 9 + add esi, RAMDISK + mov ecx, 512/4 +; cld + rep movsd + + popad + + xor ebx, ebx + xor eax, eax + ret + +LBA_read: + +; IN: +; +; eax = LBA block to read +; ebx = pointer to FIRST/SECOND/THIRD/FOURTH +; ecx = abs pointer to return area + + cmp [lba_read_enabled], 1 + je lbarl1 + mov eax, 2 + ret + + lbarl1: + + call reserve_hd1 + + push eax + push ecx + + mov edi, hd_address_table + mov esi, dir1 + mov eax, [ebx] + mov edx, '1 ' + mov ecx, 4 + blar0: + cmp eax, [esi] + je blar2 + cmp eax, edx + je blar2 + inc edx + add edi, 8 + add esi, 11 + dec ecx + jnz blar0 + + mov eax, 1 + mov ebx, 1 + jmp LBA_read_ret + + blar2: + mov eax, [edi+0] + mov ebx, [edi+4] + + mov [hdbase], eax + mov [hdid], ebx + + call wait_for_hd_idle + cmp [hd_error], 0 + jne hd_lba_error + + ; eax = hd port + ; ebx = set for primary (0x00) or slave (0x10) + + cli + + mov edx, eax + inc edx + xor eax, eax + out dx, al + inc edx + inc eax + out dx, al + inc edx + mov eax, [esp+4] + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + out dx, al + shr eax, 8 + inc edx + and al, 1+2+4+8 + add al, bl + add al, 128+64+32 + out dx, al + + inc edx + mov al, 20h + out dx, al + + sti + + call wait_for_sector_buffer + cmp [hd_error], 0 + jne hd_lba_error + + cli + + mov edi, [esp+0] + mov ecx, 256 + sub edx, 7 + cld + rep insw + + sti + + xor eax, eax + xor ebx, ebx + + LBA_read_ret: + mov [hd_error], 0 + mov [hd1_status], 0 + add esp, 2*4 + + ret + + +expand_pathz: +; IN: +; esi = asciiz path & file +; edi = buffer for path & file name +; OUT: +; edi = directory & file : / 11 + / 11 + / 11 - zero terminated +; ebx = /file name - zero terminated +; esi = pointer after source + + push eax + push ecx + push edi;[esp+0] + + pathz_start: + mov byte [edi], '/' + inc edi + mov al, 32 + mov ecx, 11 + cld + rep stosb ; clear filename area + sub edi, 11 + mov ebx, edi ; start of dir/file name + + pathz_new_char: + mov al, [esi] + inc esi + cmp al, 0 + je pathz_end + + cmp al, '/' + jne pathz_not_path + cmp edi, ebx ; skip first '/' + jz pathz_new_char + lea edi, [ebx+11] ; start of next directory + jmp pathz_start + + pathz_not_path: + cmp al, '.' + jne pathz_not_ext + lea edi, [ebx+8] ; start of extension + jmp pathz_new_char + + pathz_not_ext: + cmp al, 'a' + jb pathz_not_low + cmp al, 'z' + ja pathz_not_low + sub al, 0x20 ; char to uppercase + + pathz_not_low: + mov [edi], al + inc edi + mov eax, [esp+0] ; start_of_dest_path + add eax, 512 ; keep maximum path under 512 bytes + cmp edi, eax + jb pathz_new_char + + pathz_end: + cmp ebx, edi ; if path end with '/' + jnz pathz_put_zero ; go back 1 level + sub ebx, 12 + + pathz_put_zero: + mov byte [ebx+11], 0 + dec ebx ; include '/' char into file name + pop edi + pop ecx + pop eax + ret + +;******************************************* +;* string to number +;* input eax - 4 byte string +;* output eax - number +;******************************************* +StringToNumber: +; ПЕРЕВОД СТРОКОВОГО ЧИСЛА В ЧИСЛОВОЙ ВИД +; Вход: +; EDI - адрес строки с числом. Конец числа отмечен кодом 0Dh +; Выход: +; CF - индикатор ошибок: +; 0 - ошибок нет; +; 1 - ошибка +; Если CF=0, то AX - число. + + push bx + push cx + push dx + push edi + mov [partition_string], eax + mov edi, partition_string + xor cx, cx +i1: + mov al, [edi] + cmp al, 32;13 + je i_exit +; cmp al,'0' +; jb err +; cmp al,'9' +; ja err + sub al, 48 + shl cx, 1 + jc error + mov bx, cx + shl cx, 1 + jc error + shl cx, 1 + jc error + add cx, bx + jc error + cbw + add cx, ax + jc error +i3: + inc edi + jmp i1 +i_exit: + mov ax, cx + clc +i4: + movzx eax, ax + pop edi + pop dx + pop cx + pop bx + ret + +error: + stc + jmp i4 + +partition_string: + dd 0 + db 32 diff --git a/kernel/trunk/fs/fs_lfn.inc b/kernel/trunk/fs/fs_lfn.inc index 6142e9754..571da993a 100644 --- a/kernel/trunk/fs/fs_lfn.inc +++ b/kernel/trunk/fs/fs_lfn.inc @@ -1,1148 +1,1150 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -image_of_eax EQU esp+32 -image_of_ebx EQU esp+20 - -; System function 70 - files with long names (LFN) -; diamond, 2006 - -iglobal -; in this table names must be in lowercase -rootdirs: - db 2,'rd' - dd fs_OnRamdisk - dd fs_NextRamdisk - db 7,'ramdisk' - dd fs_OnRamdisk - dd fs_NextRamdisk - db 2,'fd' - dd fs_OnFloppy - dd fs_NextFloppy - db 10,'floppydisk' - dd fs_OnFloppy - dd fs_NextFloppy - db 3,'hd0' - dd fs_OnHd0 - dd fs_NextHd0 - db 3,'hd1' - dd fs_OnHd1 - dd fs_NextHd1 - db 3,'hd2' - dd fs_OnHd2 - dd fs_NextHd2 - db 3,'hd3' - dd fs_OnHd3 - dd fs_NextHd3 -;********************************************** - db 3,'cd0' - dd fs_OnCd0 - dd fs_NextCd - db 3,'cd1' - dd fs_OnCd1 - dd fs_NextCd - db 3,'cd2' - dd fs_OnCd2 - dd fs_NextCd - db 3,'cd3' - dd fs_OnCd3 - dd fs_NextCd -;*********************************************** - db 0 - - -virtual_root_query: - dd fs_HasRamdisk - db 'rd',0 - dd fs_HasFloppy - db 'fd',0 - dd fs_HasHd0 - db 'hd0',0 - dd fs_HasHd1 - db 'hd1',0 - dd fs_HasHd2 - db 'hd2',0 - dd fs_HasHd3 - db 'hd3',0 -;********************************************** - dd fs_HasCd0 - db 'cd0',0 - dd fs_HasCd1 - db 'cd1',0 - dd fs_HasCd2 - db 'cd2',0 - dd fs_HasCd3 - db 'cd3',0 -;********************************************** - dd 0 - -fs_additional_handlers: - dd biosdisk_handler, biosdisk_enum_root - dd dyndisk_handler, dyndisk_enum_root -; add new handlers here - dd 0 - -endg -file_system_lfn: -; in: ebx->fileinfo block -; operation codes: -; 0 : read file -; 1 : read folder -; 2 : create/rewrite file -; 3 : write/append to file -; 4 : set end of file -; 5 : get file/directory attributes structure -; 6 : set file/directory attributes structure -; 7 : start application -; 8 : delete file -; 9 : create directory - -; parse file name - lea esi, [ebx+20] - lodsb - test al, al - jnz @f - mov esi, [esi] - lodsb -@@: - cmp al, '/' - jz .notcurdir - dec esi - mov ebp, esi - test al, al - jnz @f - xor ebp, ebp -@@: - mov esi, [current_slot] - mov esi, [esi+APPDATA.cur_dir] - jmp .parse_normal -.notcurdir: - cmp byte [esi], 0 - jz .rootdir - call process_replace_file_name -.parse_normal: - cmp dword [ebx], 7 - jne @F - mov edx, [ebx+4] - mov ebx, [ebx+8] - call fs_execute ; esi+ebp, ebx, edx - mov [image_of_eax], eax - ret -@@: - mov edi, rootdirs-8 - xor ecx, ecx - push esi -.scan1: - pop esi - add edi, ecx - scasd - scasd - mov cl, byte [edi] - test cl, cl - jz .notfound_try - inc edi - push esi -@@: - lodsb - or al, 20h - scasb - loopz @b - jnz .scan1 - lodsb - cmp al, '/' - jz .found1 - test al, al - jnz .scan1 - pop eax -; directory /xxx -.maindir: - mov esi, [edi+4] -.maindir_noesi: - cmp dword [ebx], 1 - jnz .access_denied - xor eax, eax - mov ebp, [ebx+12] ;количество блоков для считывания - mov edx, [ebx+16] ;РєСѓРґР° записывать рузельтат - ; add edx, std_application_base_address - push dword [ebx+4] ; first block - mov ebx, [ebx+8] ; flags -; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler - mov edi, edx - push ecx - mov ecx, 32/4 - rep stosd - pop ecx - mov byte [edx], 1 ; version -.maindir_loop: - call esi - jc .maindir_done - inc dword [edx+8] - dec dword [esp] - jns .maindir_loop - dec ebp - js .maindir_loop - inc dword [edx+4] - mov dword [edi], 0x10 ; attributes: folder - mov dword [edi+4], 1 ; name type: UNICODE - push eax - xor eax, eax - add edi, 8 - push ecx - mov ecx, 40/4-2 - rep stosd - pop ecx - pop eax - push eax edx -; convert number in eax to decimal UNICODE string - push edi - push ecx - push -'0' - mov ecx, 10 -@@: - xor edx, edx - div ecx - push edx - test eax, eax - jnz @b -@@: - pop eax - add al, '0' - stosb - test bl, 1 ; UNICODE name? - jz .ansi2 - mov byte [edi], 0 - inc edi -.ansi2: - test al, al - jnz @b - mov byte [edi-1], 0 - pop ecx - pop edi -; UNICODE name length is 520 bytes, ANSI - 264 - add edi, 520 - test bl, 1 - jnz @f - sub edi, 520-264 -@@: - pop edx eax - jmp .maindir_loop -.maindir_done: - pop eax - mov ebx, [edx+4] - xor eax, eax - dec ebp - js @f - mov al, ERROR_END_OF_FILE -@@: - mov [image_of_eax], eax - mov [image_of_ebx], ebx - ret -; directory / -.rootdir: - cmp dword [ebx], 1 ; read folder? - jz .readroot -.access_denied: - mov dword [image_of_eax], 10 ; access denied - ret - -.readroot: -; virtual root folder - special handler - mov esi, virtual_root_query - mov ebp, [ebx+12] - mov edx, [ebx+16] - ; add edx, std_application_base_address - push dword [ebx+4] ; first block - mov ebx, [ebx+8] ; flags - xor eax, eax -; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area - mov edi, edx - mov ecx, 32/4 - rep stosd - mov byte [edx], 1 ; version -.readroot_loop: - cmp dword [esi], eax - jz .readroot_done_static - call dword [esi] - add esi, 4 - test eax, eax - jnz @f -.readroot_next: - or ecx, -1 - xchg esi, edi - repnz scasb - xchg esi, edi - jmp .readroot_loop -@@: - xor eax, eax - inc dword [edx+8] - dec dword [esp] - jns .readroot_next - dec ebp - js .readroot_next - inc dword [edx+4] - mov dword [edi], 0x10 ; attributes: folder - mov dword [edi+4], ebx ; name type: UNICODE - add edi, 8 - mov ecx, 40/4-2 - rep stosd - push edi -@@: - lodsb - stosb - test bl, 1 - jz .ansi - mov byte [edi], 0 - inc edi -.ansi: - test eax, eax - jnz @b - pop edi - add edi, 520 - test bl, 1 - jnz .readroot_loop - sub edi, 520-264 - jmp .readroot_loop -.readroot_done_static: - mov esi, fs_additional_handlers-8 - sub esp, 16 -.readroot_ah_loop: - add esi, 8 - cmp dword [esi], 0 - jz .readroot_done - xor eax, eax -.readroot_ah_loop2: - push edi - lea edi, [esp+4] - call dword [esi+4] - pop edi - test eax, eax - jz .readroot_ah_loop - inc dword [edx+8] - dec dword [esp+16] - jns .readroot_ah_loop2 - dec ebp - js .readroot_ah_loop2 - push eax - xor eax, eax - inc dword [edx+4] - mov dword [edi], 0x10 ; attributes: folder - mov dword [edi+4], ebx - add edi, 8 - mov ecx, 40/4-2 - rep stosd - push esi edi - lea esi, [esp+12] -@@: - lodsb - stosb - test bl, 1 - jz .ansi3 - mov byte [edi], 0 - inc edi -.ansi3: - test al, al - jnz @b - pop edi esi eax - add edi, 520 - test bl, 1 - jnz .readroot_ah_loop2 - sub edi, 520-264 - jmp .readroot_ah_loop2 -.readroot_done: - add esp, 16 - pop eax - mov ebx, [edx+4] - xor eax, eax - dec ebp - js @f - mov al, ERROR_END_OF_FILE -@@: - mov [image_of_eax], eax - mov [image_of_ebx], ebx - ret -.notfound_try: - mov edi, fs_additional_handlers -@@: - cmp dword [edi], 0 - jz .notfound - call dword [edi] - scasd - scasd - jmp @b -.notfound: - mov dword [image_of_eax], ERROR_FILE_NOT_FOUND - and dword [image_of_ebx], 0 - ret - -.notfounda: - cmp edi, esp - jnz .notfound - call dword [edi+4] - add esp, 16 - jmp .notfound - -.found1: - pop eax - cmp byte [esi], 0 - jz .maindir -.found2: -; read partition number - xor ecx, ecx - xor eax, eax -@@: - lodsb - cmp al, '/' - jz .done1 - test al, al - jz .done1 - sub al, '0' - cmp al, 9 - ja .notfounda - lea ecx, [ecx*5] - lea ecx, [ecx*2+eax] - jmp @b -.done1: - jecxz .notfounda - test al, al - jnz @f - dec esi -@@: - cmp byte [esi], 0 - jnz @f - test ebp, ebp - jz @f - mov esi, ebp - xor ebp, ebp -@@: -; now [edi] contains handler address, ecx - partition number, -; esi points to ASCIIZ string - rest of name - jmp dword [edi] - -; handlers for devices -; in: ecx = 0 => query virtual directory /xxx -; in: ecx = partition number -; esi -> relative (for device) name -; ebx -> fileinfo -; ebp = 0 or pointer to rest of name from folder addressed by esi -; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx - -fs_OnRamdisk: - cmp ecx, 1 - jnz file_system_lfn.notfound - mov eax, [ebx] - cmp eax, fs_NumRamdiskServices - jae .not_impl - mov ecx, [ebx+12] - mov edx, [ebx+16] - ; add edx, std_application_base_address - add ebx, 4 - call dword [fs_RamdiskServices + eax*4] - mov [image_of_eax], eax - mov [image_of_ebx], ebx - ret -.not_impl: - mov dword [image_of_eax], 2 ; not implemented - ret - -fs_NotImplemented: - mov eax, 2 - ret - -fs_RamdiskServices: - dd fs_RamdiskRead - dd fs_RamdiskReadFolder - dd fs_RamdiskRewrite - dd fs_RamdiskWrite - dd fs_RamdiskSetFileEnd - dd fs_RamdiskGetFileInfo - dd fs_RamdiskSetFileInfo - dd 0 - dd fs_RamdiskDelete - dd fs_RamdiskCreateFolder -fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4 - -fs_OnFloppy: - cmp ecx, 2 - ja file_system_lfn.notfound - mov eax, [ebx] - cmp eax, fs_NumFloppyServices - jae fs_OnRamdisk.not_impl - call reserve_flp - mov [flp_number], cl - mov ecx, [ebx+12] - mov edx, [ebx+16] - ; add edx, std_application_base_address - add ebx, 4 - call dword [fs_FloppyServices + eax*4] - and [flp_status], 0 - mov [image_of_eax], eax - mov [image_of_ebx], ebx - ret - -fs_FloppyServices: - dd fs_FloppyRead - dd fs_FloppyReadFolder - dd fs_FloppyRewrite - dd fs_FloppyWrite - dd fs_FloppySetFileEnd - dd fs_FloppyGetFileInfo - dd fs_FloppySetFileInfo - dd 0 - dd fs_FloppyDelete - dd fs_FloppyCreateFolder -fs_NumFloppyServices = ($ - fs_FloppyServices)/4 - -fs_OnHd0: - call reserve_hd1 - mov [hdbase], 0x1F0 - mov [hdid], 0 - push 1 - jmp fs_OnHd -fs_OnHd1: - call reserve_hd1 - mov [hdbase], 0x1F0 - mov [hdid], 0x10 - push 2 - jmp fs_OnHd -fs_OnHd2: - call reserve_hd1 - mov [hdbase], 0x170 - mov [hdid], 0 - push 3 - jmp fs_OnHd -fs_OnHd3: - call reserve_hd1 - mov [hdbase], 0x170 - mov [hdid], 0x10 - push 4 -fs_OnHd: - call reserve_hd_channel - pop eax - mov [hdpos], eax - cmp ecx, 0x100 - jae fs_OnHdAndBd.nf - cmp cl, [DRIVE_DATA+1+eax] -fs_OnHdAndBd: - jbe @f -.nf: - call free_hd_channel - and [hd1_status], 0 - mov dword [image_of_eax], 5 ; not found - ret -@@: - mov [known_part], ecx ; mov [fat32part], ecx - push ebx esi - call choice_necessity_partition_1 - pop esi ebx - mov ecx, [ebx+12] - mov edx, [ebx+16] - ; add edx, std_application_base_address - mov eax, [ebx] - cmp eax, fs_NumHdServices - jae .not_impl - add ebx, 4 - call dword [fs_HdServices + eax*4] - call free_hd_channel - and [hd1_status], 0 - mov [image_of_eax], eax - mov [image_of_ebx], ebx - ret -.not_impl: - call free_hd_channel - and [hd1_status], 0 - mov dword [image_of_eax], 2 ; not implemented - ret - -fs_HdServices: - dd fs_HdRead - dd fs_HdReadFolder - dd fs_HdRewrite - dd fs_HdWrite - dd fs_HdSetFileEnd - dd fs_HdGetFileInfo - dd fs_HdSetFileInfo - dd 0 - dd fs_HdDelete - dd fs_HdCreateFolder -fs_NumHdServices = ($ - fs_HdServices)/4 - -;******************************************************* -fs_OnCd0: - call reserve_cd - mov [ChannelNumber],1 - mov [DiskNumber],0 - push 6 - push 1 - jmp fs_OnCd -fs_OnCd1: - call reserve_cd - mov [ChannelNumber],1 - mov [DiskNumber],1 - push 4 - push 2 - jmp fs_OnCd -fs_OnCd2: - call reserve_cd - mov [ChannelNumber],2 - mov [DiskNumber],0 - push 2 - push 3 - jmp fs_OnCd -fs_OnCd3: - call reserve_cd - mov [ChannelNumber],2 - mov [DiskNumber],1 - push 0 - push 4 -fs_OnCd: - call reserve_cd_channel - pop eax - mov [cdpos], eax - pop eax - cmp ecx, 0x100 - jae .nf - push ecx ebx - mov cl,al - mov bl,[DRIVE_DATA+1] - shr bl,cl - test bl,2 - pop ebx ecx - - jnz @f -.nf: - call free_cd_channel - and [cd_status], 0 - mov dword [image_of_eax], 5 ; not found - ret -@@: - mov ecx, [ebx+12] - mov edx, [ebx+16] - ; add edx, std_application_base_address - mov eax, [ebx] - cmp eax,fs_NumCdServices - jae .not_impl - add ebx, 4 - call dword [fs_CdServices + eax*4] - call free_cd_channel - and [cd_status], 0 - mov [image_of_eax], eax - mov [image_of_ebx], ebx - ret -.not_impl: - call free_cd_channel - and [cd_status], 0 - mov dword [image_of_eax], 2 ; not implemented - ret - -fs_CdServices: - dd fs_CdRead - dd fs_CdReadFolder - dd fs_NotImplemented - dd fs_NotImplemented - dd fs_NotImplemented - dd fs_CdGetFileInfo - dd fs_NotImplemented - dd 0 - dd fs_NotImplemented - dd fs_NotImplemented -fs_NumCdServices = ($ - fs_CdServices)/4 - -;******************************************************* - -fs_HasRamdisk: - mov al, 1 ; we always have ramdisk - ret - -fs_HasFloppy: - cmp byte [DRIVE_DATA], 0 - setnz al - ret - -fs_HasHd0: - mov al, [DRIVE_DATA+1] - and al, 11000000b - cmp al, 01000000b - setz al - ret -fs_HasHd1: - mov al, [DRIVE_DATA+1] - and al, 00110000b - cmp al, 00010000b - setz al - ret -fs_HasHd2: - mov al, [DRIVE_DATA+1] - and al, 00001100b - cmp al, 00000100b - setz al - ret -fs_HasHd3: - mov al, [DRIVE_DATA+1] - and al, 00000011b - cmp al, 00000001b - setz al - ret - -;******************************************************* -fs_HasCd0: - mov al, [DRIVE_DATA+1] - and al, 11000000b - cmp al, 10000000b - setz al - ret -fs_HasCd1: - mov al, [DRIVE_DATA+1] - and al, 00110000b - cmp al, 00100000b - setz al - ret -fs_HasCd2: - mov al, [DRIVE_DATA+1] - and al, 00001100b - cmp al, 00001000b - setz al - ret -fs_HasCd3: - mov al, [DRIVE_DATA+1] - and al, 00000011b - cmp al, 00000010b - setz al - ret -;******************************************************* - -; fs_NextXXX functions: -; in: eax = partition number, from which start to scan -; out: CF=1 => no more partitions -; CF=0 => eax=next partition number - -fs_NextRamdisk: -; we always have /rd/1 - test eax, eax - stc - jnz @f - mov al, 1 - clc -@@: - ret - -fs_NextFloppy: -; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0) - test byte [DRIVE_DATA], 0xF0 - jz .no1 - test eax, eax - jnz .no1 - inc eax - ret ; CF cleared -.no1: - test byte [DRIVE_DATA], 0x0F - jz .no2 - cmp al, 2 - jae .no2 - mov al, 2 - clc - ret -.no2: - stc - ret - -; on hdx, we have partitions from 1 to [0x40002+x] -fs_NextHd0: - push 0 - jmp fs_NextHd -fs_NextHd1: - push 1 - jmp fs_NextHd -fs_NextHd2: - push 2 - jmp fs_NextHd -fs_NextHd3: - push 3 -fs_NextHd: - pop ecx - movzx ecx, byte [DRIVE_DATA+2+ecx] - cmp eax, ecx - jae fs_NextFloppy.no2 - inc eax - clc - ret - -;******************************************************* -fs_NextCd: -; we always have /cdX/1 - test eax, eax - stc - jnz @f - mov al, 1 - clc -@@: - ret -;******************************************************* - -; Additional FS handlers. -; This handler gets the control each time when fn 70 is called -; with unknown item of root subdirectory. -; in: esi -> name -; ebp = 0 or rest of name relative to esi -; out: if the handler processes path, he must not return in file_system_lfn, -; but instead pop return address and return directly to the caller -; otherwise simply return - -; here we test for /bd/... - BIOS disks -biosdisk_handler: - cmp [NumBiosDisks], 0 - jz .ret - mov al, [esi] - or al, 20h - cmp al, 'b' - jnz .ret - mov al, [esi+1] - or al, 20h - cmp al, 'd' - jnz .ret - push esi - inc esi - inc esi - cmp byte [esi], '0' - jb .ret2 - cmp byte [esi], '9' - ja .ret2 - xor edx, edx -@@: - lodsb - test al, al - jz .ok - cmp al, '/' - jz .ok - sub al, '0' - cmp al, 9 - ja .ret2 - lea edx, [edx*5] - lea edx, [edx*2+eax] - jmp @b -.ret2: - pop esi -.ret: - ret -.ok: - cmp al, '/' - jz @f - dec esi -@@: - add dl, 80h - xor ecx, ecx -@@: - cmp dl, [BiosDisksData+ecx*4] - jz .ok2 - inc ecx - cmp ecx, [NumBiosDisks] - jb @b - jmp .ret2 -.ok2: - add esp, 8 - test al, al - jnz @f - mov esi, fs_BdNext - jmp file_system_lfn.maindir_noesi -@@: - push ecx - push ecx - push biosdisk_cleanup - push fs_OnBd - mov edi, esp - jmp file_system_lfn.found2 - -fs_BdNext: - cmp eax, [BiosDiskPartitions+ecx*4] - inc eax - cmc -biosdisk_cleanup: - ret - -fs_OnBd: - pop edx edx edx edx -; edx = disk number, ecx = partition number -; esi+ebp = name - call reserve_hd1 - add edx, 0x80 - mov [hdpos], edx - cmp ecx, [BiosDiskPartitions+(edx-0x80)*4] - jmp fs_OnHdAndBd - -; This handler is called when virtual root is enumerated -; and must return all items which can be handled by this. -; It is called several times, first time with eax=0 -; in: eax = 0 for first call, previously returned value for subsequent calls -; out: eax = 0 => no more items -; eax != 0 => buffer pointed to by edi contains name of item - -; here we enumerate existing BIOS disks /bd -biosdisk_enum_root: - cmp eax, [NumBiosDisks] - jae .end - push eax - movzx eax, byte [BiosDisksData+eax*4] - sub al, 80h - push eax - mov al, 'b' - stosb - mov al, 'd' - stosb - pop eax - cmp al, 10 - jae .big - add al, '0' - stosb - mov byte [edi], 0 - pop eax - inc eax - ret -.end: - xor eax, eax - ret -.big: - push ecx edx - push -'0' - mov ecx, 10 -@@: - xor edx, edx - div ecx - push edx - test eax, eax - jnz @b - xchg eax, edx -@@: - pop eax - add al, '0' - stosb - jnz @b - pop edx ecx - pop eax - inc eax - ret - -process_replace_file_name: - mov ebp, [full_file_name_table] - mov edi, [full_file_name_table.size] - dec edi - shl edi, 7 - add edi, ebp -.loop: - cmp edi, ebp - jb .notfound - push esi edi -@@: - cmp byte [edi], 0 - jz .dest_done - lodsb - test al, al - jz .cont - or al, 20h - scasb - jz @b - jmp .cont -.dest_done: - cmp byte [esi], 0 - jz .found - cmp byte [esi], '/' - jnz .cont - inc esi - jmp .found -.cont: - pop edi esi - sub edi, 128 - jmp .loop -.found: - pop edi eax - mov ebp, esi - cmp byte [esi], 0 - lea esi, [edi+64] - jnz .ret -.notfound: - xor ebp, ebp -.ret: - ret - -sys_current_directory: -; mov esi, [current_slot] -; mov esi, [esi+APPDATA.cur_dir] -; mov edx, esi - -;get length string of appdata.cur_dir - mov eax, [current_slot] - mov edi, [eax+APPDATA.cur_dir] - - dec ebx - jz .set - dec ebx - jz .get - ret -.get: -; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len -; for our code: ebx->buffer,ecx=len -max_cur_dir equ 0x1000 - - mov ebx,edi - - push ecx - push edi - - xor eax,eax - mov ecx,max_cur_dir - - repne scasb ;find zerro at and string - jnz .error ; no zero in cur_dir: internal error, should not happen - - sub edi,ebx ;lenght for copy - inc edi - mov [esp+32+8],edi ;return in eax - - cmp edx, edi - jbe @f - mov edx, edi -@@: -;source string - pop esi -;destination string - pop edi - cmp edx, 1 - jbe .ret - - mov al,'/' ;start string with '/' - stosb - mov ecx,edx - rep movsb ;copy string -.ret: ret - -.error: add esp,8 - or dword [esp+32],-1 ;error not found zerro at string ->[eax+APPDATA.cur_dir] - ret -.set: -; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string -; for our code: ebx->string to set -; use generic resolver with APPDATA.cur_dir as destination - push max_cur_dir ;0x1000 - push edi ;destination - mov ebx,ecx - call get_full_file_name - ret - -; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination -; destroys all registers except ebp,esp -get_full_file_name: - push ebp - mov esi, [current_slot] - mov esi, [esi+APPDATA.cur_dir] - mov edx, esi -@@: - inc esi - cmp byte [esi-1], 0 - jnz @b - dec esi - cmp byte [ebx], '/' - jz .set_absolute -; string gives relative path - mov edi, [esp+8] ; destination -.relative: - cmp byte [ebx], 0 - jz .set_ok - cmp word [ebx], '.' - jz .set_ok - cmp word [ebx], './' - jnz @f - add ebx, 2 - jmp .relative -@@: - cmp word [ebx], '..' - jnz .doset_relative - cmp byte [ebx+2], 0 - jz @f - cmp byte [ebx+2], '/' - jnz .doset_relative -@@: - dec esi - cmp byte [esi], '/' - jnz @b - add ebx, 3 - jmp .relative -.set_ok: - cmp edx, edi ; is destination equal to APPDATA.cur_dir? - jz .set_ok.cur_dir - sub esi, edx - cmp esi, [esp+12] - jb .set_ok.copy -.fail: - mov byte [edi], 0 - xor eax, eax ; fail - pop ebp - ret 8 -.set_ok.copy: - mov ecx, esi - mov esi, edx - rep movsb - mov byte [edi], 0 -.ret.ok: - mov al, 1 ; ok - pop ebp - ret 8 -.set_ok.cur_dir: - mov byte [esi], 0 - jmp .ret.ok -.doset_relative: - cmp edx, edi - jz .doset_relative.cur_dir - sub esi, edx - cmp esi, [esp+12] - jae .fail - mov ecx, esi - mov esi, edx - mov edx, edi - rep movsb - jmp .doset_relative.copy -.doset_relative.cur_dir: - mov edi, esi -.doset_relative.copy: - add edx, [esp+12] - mov byte [edi], '/' - inc edi - cmp edi, edx - jae .overflow -@@: - mov al, [ebx] - inc ebx - stosb - test al, al - jz .ret.ok - cmp edi, edx - jb @b -.overflow: - dec edi - jmp .fail -.set_absolute: - lea esi, [ebx+1] - call process_replace_file_name - mov edi, [esp+8] - mov edx, [esp+12] - add edx, edi -.set_copy: - lodsb - stosb - test al, al - jz .set_part2 -.set_copy_cont: - cmp edi, edx - jb .set_copy - jmp .overflow -.set_part2: - mov esi, ebp - xor ebp, ebp - test esi, esi - jz .ret.ok - mov byte [edi-1], '/' - jmp .set_copy_cont +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +image_of_eax EQU esp+32 +image_of_ebx EQU esp+20 + +; System function 70 - files with long names (LFN) +; diamond, 2006 + +iglobal +; in this table names must be in lowercase +rootdirs: + db 2,'rd' + dd fs_OnRamdisk + dd fs_NextRamdisk + db 7,'ramdisk' + dd fs_OnRamdisk + dd fs_NextRamdisk + db 2,'fd' + dd fs_OnFloppy + dd fs_NextFloppy + db 10,'floppydisk' + dd fs_OnFloppy + dd fs_NextFloppy + db 3,'hd0' + dd fs_OnHd0 + dd fs_NextHd0 + db 3,'hd1' + dd fs_OnHd1 + dd fs_NextHd1 + db 3,'hd2' + dd fs_OnHd2 + dd fs_NextHd2 + db 3,'hd3' + dd fs_OnHd3 + dd fs_NextHd3 +;********************************************** + db 3,'cd0' + dd fs_OnCd0 + dd fs_NextCd + db 3,'cd1' + dd fs_OnCd1 + dd fs_NextCd + db 3,'cd2' + dd fs_OnCd2 + dd fs_NextCd + db 3,'cd3' + dd fs_OnCd3 + dd fs_NextCd +;*********************************************** + db 0 + + +virtual_root_query: + dd fs_HasRamdisk + db 'rd',0 + dd fs_HasFloppy + db 'fd',0 + dd fs_HasHd0 + db 'hd0',0 + dd fs_HasHd1 + db 'hd1',0 + dd fs_HasHd2 + db 'hd2',0 + dd fs_HasHd3 + db 'hd3',0 +;********************************************** + dd fs_HasCd0 + db 'cd0',0 + dd fs_HasCd1 + db 'cd1',0 + dd fs_HasCd2 + db 'cd2',0 + dd fs_HasCd3 + db 'cd3',0 +;********************************************** + dd 0 + +fs_additional_handlers: + dd biosdisk_handler, biosdisk_enum_root + dd dyndisk_handler, dyndisk_enum_root +; add new handlers here + dd 0 + +endg +file_system_lfn: +; in: ebx->fileinfo block +; operation codes: +; 0 : read file +; 1 : read folder +; 2 : create/rewrite file +; 3 : write/append to file +; 4 : set end of file +; 5 : get file/directory attributes structure +; 6 : set file/directory attributes structure +; 7 : start application +; 8 : delete file +; 9 : create directory + +; parse file name + lea esi, [ebx+20] + lodsb + test al, al + jnz @f + mov esi, [esi] + lodsb +@@: + cmp al, '/' + jz .notcurdir + dec esi + mov ebp, esi + test al, al + jnz @f + xor ebp, ebp +@@: + mov esi, [current_slot] + mov esi, [esi+APPDATA.cur_dir] + jmp .parse_normal +.notcurdir: + cmp byte [esi], 0 + jz .rootdir + call process_replace_file_name +.parse_normal: + cmp dword [ebx], 7 + jne @F + mov edx, [ebx+4] + mov ebx, [ebx+8] + call fs_execute; esi+ebp, ebx, edx + mov [image_of_eax], eax + ret +@@: + mov edi, rootdirs-8 + xor ecx, ecx + push esi +.scan1: + pop esi + add edi, ecx + scasd + scasd + mov cl, byte [edi] + test cl, cl + jz .notfound_try + inc edi + push esi +@@: + lodsb + or al, 20h + scasb + loopz @b + jnz .scan1 + lodsb + cmp al, '/' + jz .found1 + test al, al + jnz .scan1 + pop eax +; directory /xxx +.maindir: + mov esi, [edi+4] +.maindir_noesi: + cmp dword [ebx], 1 + jnz .access_denied + xor eax, eax + mov ebp, [ebx+12] ;количество блоков для считывания + mov edx, [ebx+16] ;РєСѓРґР° записывать рузельтат + ; add edx, std_application_base_address + push dword [ebx+4] ; first block + mov ebx, [ebx+8] ; flags +; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler + mov edi, edx + push ecx + mov ecx, 32/4 + rep stosd + pop ecx + mov byte [edx], 1 ; version +.maindir_loop: + call esi + jc .maindir_done + inc dword [edx+8] + dec dword [esp] + jns .maindir_loop + dec ebp + js .maindir_loop + inc dword [edx+4] + mov dword [edi], 0x10 ; attributes: folder + mov dword [edi+4], 1 ; name type: UNICODE + push eax + xor eax, eax + add edi, 8 + push ecx + mov ecx, 40/4-2 + rep stosd + pop ecx + pop eax + push eax edx +; convert number in eax to decimal UNICODE string + push edi + push ecx + push -'0' + mov ecx, 10 +@@: + xor edx, edx + div ecx + push edx + test eax, eax + jnz @b +@@: + pop eax + add al, '0' + stosb + test bl, 1 ; UNICODE name? + jz .ansi2 + mov byte [edi], 0 + inc edi +.ansi2: + test al, al + jnz @b + mov byte [edi-1], 0 + pop ecx + pop edi +; UNICODE name length is 520 bytes, ANSI - 264 + add edi, 520 + test bl, 1 + jnz @f + sub edi, 520-264 +@@: + pop edx eax + jmp .maindir_loop +.maindir_done: + pop eax + mov ebx, [edx+4] + xor eax, eax + dec ebp + js @f + mov al, ERROR_END_OF_FILE +@@: + mov [image_of_eax], eax + mov [image_of_ebx], ebx + ret +; directory / +.rootdir: + cmp dword [ebx], 1 ; read folder? + jz .readroot +.access_denied: + mov dword [image_of_eax], 10 ; access denied + ret + +.readroot: +; virtual root folder - special handler + mov esi, virtual_root_query + mov ebp, [ebx+12] + mov edx, [ebx+16] + ; add edx, std_application_base_address + push dword [ebx+4] ; first block + mov ebx, [ebx+8] ; flags + xor eax, eax +; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area + mov edi, edx + mov ecx, 32/4 + rep stosd + mov byte [edx], 1 ; version +.readroot_loop: + cmp dword [esi], eax + jz .readroot_done_static + call dword [esi] + add esi, 4 + test eax, eax + jnz @f +.readroot_next: + or ecx, -1 + xchg esi, edi + repnz scasb + xchg esi, edi + jmp .readroot_loop +@@: + xor eax, eax + inc dword [edx+8] + dec dword [esp] + jns .readroot_next + dec ebp + js .readroot_next + inc dword [edx+4] + mov dword [edi], 0x10 ; attributes: folder + mov dword [edi+4], ebx ; name type: UNICODE + add edi, 8 + mov ecx, 40/4-2 + rep stosd + push edi +@@: + lodsb + stosb + test bl, 1 + jz .ansi + mov byte [edi], 0 + inc edi +.ansi: + test eax, eax + jnz @b + pop edi + add edi, 520 + test bl, 1 + jnz .readroot_loop + sub edi, 520-264 + jmp .readroot_loop +.readroot_done_static: + mov esi, fs_additional_handlers-8 + sub esp, 16 +.readroot_ah_loop: + add esi, 8 + cmp dword [esi], 0 + jz .readroot_done + xor eax, eax +.readroot_ah_loop2: + push edi + lea edi, [esp+4] + call dword [esi+4] + pop edi + test eax, eax + jz .readroot_ah_loop + inc dword [edx+8] + dec dword [esp+16] + jns .readroot_ah_loop2 + dec ebp + js .readroot_ah_loop2 + push eax + xor eax, eax + inc dword [edx+4] + mov dword [edi], 0x10 ; attributes: folder + mov dword [edi+4], ebx + add edi, 8 + mov ecx, 40/4-2 + rep stosd + push esi edi + lea esi, [esp+12] +@@: + lodsb + stosb + test bl, 1 + jz .ansi3 + mov byte [edi], 0 + inc edi +.ansi3: + test al, al + jnz @b + pop edi esi eax + add edi, 520 + test bl, 1 + jnz .readroot_ah_loop2 + sub edi, 520-264 + jmp .readroot_ah_loop2 +.readroot_done: + add esp, 16 + pop eax + mov ebx, [edx+4] + xor eax, eax + dec ebp + js @f + mov al, ERROR_END_OF_FILE +@@: + mov [image_of_eax], eax + mov [image_of_ebx], ebx + ret +.notfound_try: + mov edi, fs_additional_handlers +@@: + cmp dword [edi], 0 + jz .notfound + call dword [edi] + scasd + scasd + jmp @b +.notfound: + mov dword [image_of_eax], ERROR_FILE_NOT_FOUND + and dword [image_of_ebx], 0 + ret + +.notfounda: + cmp edi, esp + jnz .notfound + call dword [edi+4] + add esp, 16 + jmp .notfound + +.found1: + pop eax + cmp byte [esi], 0 + jz .maindir +.found2: +; read partition number + xor ecx, ecx + xor eax, eax +@@: + lodsb + cmp al, '/' + jz .done1 + test al, al + jz .done1 + sub al, '0' + cmp al, 9 + ja .notfounda + lea ecx, [ecx*5] + lea ecx, [ecx*2+eax] + jmp @b +.done1: + jecxz .notfounda + test al, al + jnz @f + dec esi +@@: + cmp byte [esi], 0 + jnz @f + test ebp, ebp + jz @f + mov esi, ebp + xor ebp, ebp +@@: +; now [edi] contains handler address, ecx - partition number, +; esi points to ASCIIZ string - rest of name + jmp dword [edi] + +; handlers for devices +; in: ecx = 0 => query virtual directory /xxx +; in: ecx = partition number +; esi -> relative (for device) name +; ebx -> fileinfo +; ebp = 0 or pointer to rest of name from folder addressed by esi +; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx + +fs_OnRamdisk: + cmp ecx, 1 + jnz file_system_lfn.notfound + mov eax, [ebx] + cmp eax, fs_NumRamdiskServices + jae .not_impl + mov ecx, [ebx+12] + mov edx, [ebx+16] + ; add edx, std_application_base_address + add ebx, 4 + call dword [fs_RamdiskServices + eax*4] + mov [image_of_eax], eax + mov [image_of_ebx], ebx + ret +.not_impl: + mov dword [image_of_eax], 2 ; not implemented + ret + +fs_NotImplemented: + mov eax, 2 + ret + +fs_RamdiskServices: + dd fs_RamdiskRead + dd fs_RamdiskReadFolder + dd fs_RamdiskRewrite + dd fs_RamdiskWrite + dd fs_RamdiskSetFileEnd + dd fs_RamdiskGetFileInfo + dd fs_RamdiskSetFileInfo + dd 0 + dd fs_RamdiskDelete + dd fs_RamdiskCreateFolder +fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4 + +fs_OnFloppy: + cmp ecx, 2 + ja file_system_lfn.notfound + mov eax, [ebx] + cmp eax, fs_NumFloppyServices + jae fs_OnRamdisk.not_impl + call reserve_flp + mov [flp_number], cl + mov ecx, [ebx+12] + mov edx, [ebx+16] + ; add edx, std_application_base_address + add ebx, 4 + call dword [fs_FloppyServices + eax*4] + and [flp_status], 0 + mov [image_of_eax], eax + mov [image_of_ebx], ebx + ret + +fs_FloppyServices: + dd fs_FloppyRead + dd fs_FloppyReadFolder + dd fs_FloppyRewrite + dd fs_FloppyWrite + dd fs_FloppySetFileEnd + dd fs_FloppyGetFileInfo + dd fs_FloppySetFileInfo + dd 0 + dd fs_FloppyDelete + dd fs_FloppyCreateFolder +fs_NumFloppyServices = ($ - fs_FloppyServices)/4 + +fs_OnHd0: + call reserve_hd1 + mov [hdbase], 0x1F0 + mov [hdid], 0 + push 1 + jmp fs_OnHd +fs_OnHd1: + call reserve_hd1 + mov [hdbase], 0x1F0 + mov [hdid], 0x10 + push 2 + jmp fs_OnHd +fs_OnHd2: + call reserve_hd1 + mov [hdbase], 0x170 + mov [hdid], 0 + push 3 + jmp fs_OnHd +fs_OnHd3: + call reserve_hd1 + mov [hdbase], 0x170 + mov [hdid], 0x10 + push 4 +fs_OnHd: + call reserve_hd_channel + pop eax + mov [hdpos], eax + cmp ecx, 0x100 + jae fs_OnHdAndBd.nf + cmp cl, [DRIVE_DATA+1+eax] +fs_OnHdAndBd: + jbe @f +.nf: + call free_hd_channel + and [hd1_status], 0 + mov dword [image_of_eax], 5 ; not found + ret +@@: + mov [known_part], ecx ; mov [fat32part], ecx + push ebx esi + call choice_necessity_partition_1 + pop esi ebx + mov ecx, [ebx+12] + mov edx, [ebx+16] + ; add edx, std_application_base_address + mov eax, [ebx] + cmp eax, fs_NumHdServices + jae .not_impl + add ebx, 4 + call dword [fs_HdServices + eax*4] + call free_hd_channel + and [hd1_status], 0 + mov [image_of_eax], eax + mov [image_of_ebx], ebx + ret +.not_impl: + call free_hd_channel + and [hd1_status], 0 + mov dword [image_of_eax], 2 ; not implemented + ret + +fs_HdServices: + dd fs_HdRead + dd fs_HdReadFolder + dd fs_HdRewrite + dd fs_HdWrite + dd fs_HdSetFileEnd + dd fs_HdGetFileInfo + dd fs_HdSetFileInfo + dd 0 + dd fs_HdDelete + dd fs_HdCreateFolder +fs_NumHdServices = ($ - fs_HdServices)/4 + +;******************************************************* +fs_OnCd0: + call reserve_cd + mov [ChannelNumber], 1 + mov [DiskNumber], 0 + push 6 + push 1 + jmp fs_OnCd +fs_OnCd1: + call reserve_cd + mov [ChannelNumber], 1 + mov [DiskNumber], 1 + push 4 + push 2 + jmp fs_OnCd +fs_OnCd2: + call reserve_cd + mov [ChannelNumber], 2 + mov [DiskNumber], 0 + push 2 + push 3 + jmp fs_OnCd +fs_OnCd3: + call reserve_cd + mov [ChannelNumber], 2 + mov [DiskNumber], 1 + push 0 + push 4 +fs_OnCd: + call reserve_cd_channel + pop eax + mov [cdpos], eax + pop eax + cmp ecx, 0x100 + jae .nf + push ecx ebx + mov cl, al + mov bl, [DRIVE_DATA+1] + shr bl, cl + test bl, 2 + pop ebx ecx + + jnz @f +.nf: + call free_cd_channel + and [cd_status], 0 + mov dword [image_of_eax], 5 ; not found + ret +@@: + mov ecx, [ebx+12] + mov edx, [ebx+16] + ; add edx, std_application_base_address + mov eax, [ebx] + cmp eax, fs_NumCdServices + jae .not_impl + add ebx, 4 + call dword [fs_CdServices + eax*4] + call free_cd_channel + and [cd_status], 0 + mov [image_of_eax], eax + mov [image_of_ebx], ebx + ret +.not_impl: + call free_cd_channel + and [cd_status], 0 + mov dword [image_of_eax], 2 ; not implemented + ret + +fs_CdServices: + dd fs_CdRead + dd fs_CdReadFolder + dd fs_NotImplemented + dd fs_NotImplemented + dd fs_NotImplemented + dd fs_CdGetFileInfo + dd fs_NotImplemented + dd 0 + dd fs_NotImplemented + dd fs_NotImplemented +fs_NumCdServices = ($ - fs_CdServices)/4 + +;******************************************************* + +fs_HasRamdisk: + mov al, 1 ; we always have ramdisk + ret + +fs_HasFloppy: + cmp byte [DRIVE_DATA], 0 + setnz al + ret + +fs_HasHd0: + mov al, [DRIVE_DATA+1] + and al, 11000000b + cmp al, 01000000b + setz al + ret +fs_HasHd1: + mov al, [DRIVE_DATA+1] + and al, 00110000b + cmp al, 00010000b + setz al + ret +fs_HasHd2: + mov al, [DRIVE_DATA+1] + and al, 00001100b + cmp al, 00000100b + setz al + ret +fs_HasHd3: + mov al, [DRIVE_DATA+1] + and al, 00000011b + cmp al, 00000001b + setz al + ret + +;******************************************************* +fs_HasCd0: + mov al, [DRIVE_DATA+1] + and al, 11000000b + cmp al, 10000000b + setz al + ret +fs_HasCd1: + mov al, [DRIVE_DATA+1] + and al, 00110000b + cmp al, 00100000b + setz al + ret +fs_HasCd2: + mov al, [DRIVE_DATA+1] + and al, 00001100b + cmp al, 00001000b + setz al + ret +fs_HasCd3: + mov al, [DRIVE_DATA+1] + and al, 00000011b + cmp al, 00000010b + setz al + ret +;******************************************************* + +; fs_NextXXX functions: +; in: eax = partition number, from which start to scan +; out: CF=1 => no more partitions +; CF=0 => eax=next partition number + +fs_NextRamdisk: +; we always have /rd/1 + test eax, eax + stc + jnz @f + mov al, 1 + clc +@@: + ret + +fs_NextFloppy: +; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0) + test byte [DRIVE_DATA], 0xF0 + jz .no1 + test eax, eax + jnz .no1 + inc eax + ret ; CF cleared +.no1: + test byte [DRIVE_DATA], 0x0F + jz .no2 + cmp al, 2 + jae .no2 + mov al, 2 + clc + ret +.no2: + stc + ret + +; on hdx, we have partitions from 1 to [0x40002+x] +fs_NextHd0: + push 0 + jmp fs_NextHd +fs_NextHd1: + push 1 + jmp fs_NextHd +fs_NextHd2: + push 2 + jmp fs_NextHd +fs_NextHd3: + push 3 +fs_NextHd: + pop ecx + movzx ecx, byte [DRIVE_DATA+2+ecx] + cmp eax, ecx + jae fs_NextFloppy.no2 + inc eax + clc + ret + +;******************************************************* +fs_NextCd: +; we always have /cdX/1 + test eax, eax + stc + jnz @f + mov al, 1 + clc +@@: + ret +;******************************************************* + +; Additional FS handlers. +; This handler gets the control each time when fn 70 is called +; with unknown item of root subdirectory. +; in: esi -> name +; ebp = 0 or rest of name relative to esi +; out: if the handler processes path, he must not return in file_system_lfn, +; but instead pop return address and return directly to the caller +; otherwise simply return + +; here we test for /bd/... - BIOS disks +biosdisk_handler: + cmp [NumBiosDisks], 0 + jz .ret + mov al, [esi] + or al, 20h + cmp al, 'b' + jnz .ret + mov al, [esi+1] + or al, 20h + cmp al, 'd' + jnz .ret + push esi + inc esi + inc esi + cmp byte [esi], '0' + jb .ret2 + cmp byte [esi], '9' + ja .ret2 + xor edx, edx +@@: + lodsb + test al, al + jz .ok + cmp al, '/' + jz .ok + sub al, '0' + cmp al, 9 + ja .ret2 + lea edx, [edx*5] + lea edx, [edx*2+eax] + jmp @b +.ret2: + pop esi +.ret: + ret +.ok: + cmp al, '/' + jz @f + dec esi +@@: + add dl, 80h + xor ecx, ecx +@@: + cmp dl, [BiosDisksData+ecx*4] + jz .ok2 + inc ecx + cmp ecx, [NumBiosDisks] + jb @b + jmp .ret2 +.ok2: + add esp, 8 + test al, al + jnz @f + mov esi, fs_BdNext + jmp file_system_lfn.maindir_noesi +@@: + push ecx + push ecx + push biosdisk_cleanup + push fs_OnBd + mov edi, esp + jmp file_system_lfn.found2 + +fs_BdNext: + cmp eax, [BiosDiskPartitions+ecx*4] + inc eax + cmc +biosdisk_cleanup: + ret + +fs_OnBd: + pop edx edx edx edx +; edx = disk number, ecx = partition number +; esi+ebp = name + call reserve_hd1 + add edx, 0x80 + mov [hdpos], edx + cmp ecx, [BiosDiskPartitions+(edx-0x80)*4] + jmp fs_OnHdAndBd + +; This handler is called when virtual root is enumerated +; and must return all items which can be handled by this. +; It is called several times, first time with eax=0 +; in: eax = 0 for first call, previously returned value for subsequent calls +; out: eax = 0 => no more items +; eax != 0 => buffer pointed to by edi contains name of item + +; here we enumerate existing BIOS disks /bd +biosdisk_enum_root: + cmp eax, [NumBiosDisks] + jae .end + push eax + movzx eax, byte [BiosDisksData+eax*4] + sub al, 80h + push eax + mov al, 'b' + stosb + mov al, 'd' + stosb + pop eax + cmp al, 10 + jae .big + add al, '0' + stosb + mov byte [edi], 0 + pop eax + inc eax + ret +.end: + xor eax, eax + ret +.big: + push ecx edx + push -'0' + mov ecx, 10 +@@: + xor edx, edx + div ecx + push edx + test eax, eax + jnz @b + xchg eax, edx +@@: + pop eax + add al, '0' + stosb + jnz @b + pop edx ecx + pop eax + inc eax + ret + +process_replace_file_name: + mov ebp, [full_file_name_table] + mov edi, [full_file_name_table.size] + dec edi + shl edi, 7 + add edi, ebp +.loop: + cmp edi, ebp + jb .notfound + push esi edi +@@: + cmp byte [edi], 0 + jz .dest_done + lodsb + test al, al + jz .cont + or al, 20h + scasb + jz @b + jmp .cont +.dest_done: + cmp byte [esi], 0 + jz .found + cmp byte [esi], '/' + jnz .cont + inc esi + jmp .found +.cont: + pop edi esi + sub edi, 128 + jmp .loop +.found: + pop edi eax + mov ebp, esi + cmp byte [esi], 0 + lea esi, [edi+64] + jnz .ret +.notfound: + xor ebp, ebp +.ret: + ret + +sys_current_directory: +; mov esi, [current_slot] +; mov esi, [esi+APPDATA.cur_dir] +; mov edx, esi + +;get length string of appdata.cur_dir + mov eax, [current_slot] + mov edi, [eax+APPDATA.cur_dir] + + dec ebx + jz .set + dec ebx + jz .get + ret +.get: +; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len +; for our code: ebx->buffer,ecx=len +max_cur_dir equ 0x1000 + + mov ebx, edi + + push ecx + push edi + + xor eax, eax + mov ecx, max_cur_dir + + repne scasb ;find zerro at and string + jnz .error ; no zero in cur_dir: internal error, should not happen + + sub edi, ebx ;lenght for copy + inc edi + mov [esp+32+8], edi ;return in eax + + cmp edx, edi + jbe @f + mov edx, edi +@@: +;source string + pop esi +;destination string + pop edi + cmp edx, 1 + jbe .ret + + mov al, '/' ;start string with '/' + stosb + mov ecx, edx + rep movsb ;copy string +.ret: + ret + +.error: + add esp, 8 + or dword [esp+32], -1 ;error not found zerro at string ->[eax+APPDATA.cur_dir] + ret +.set: +; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string +; for our code: ebx->string to set +; use generic resolver with APPDATA.cur_dir as destination + push max_cur_dir ;0x1000 + push edi ;destination + mov ebx, ecx + call get_full_file_name + ret + +; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination +; destroys all registers except ebp,esp +get_full_file_name: + push ebp + mov esi, [current_slot] + mov esi, [esi+APPDATA.cur_dir] + mov edx, esi +@@: + inc esi + cmp byte [esi-1], 0 + jnz @b + dec esi + cmp byte [ebx], '/' + jz .set_absolute +; string gives relative path + mov edi, [esp+8] ; destination +.relative: + cmp byte [ebx], 0 + jz .set_ok + cmp word [ebx], '.' + jz .set_ok + cmp word [ebx], './' + jnz @f + add ebx, 2 + jmp .relative +@@: + cmp word [ebx], '..' + jnz .doset_relative + cmp byte [ebx+2], 0 + jz @f + cmp byte [ebx+2], '/' + jnz .doset_relative +@@: + dec esi + cmp byte [esi], '/' + jnz @b + add ebx, 3 + jmp .relative +.set_ok: + cmp edx, edi ; is destination equal to APPDATA.cur_dir? + jz .set_ok.cur_dir + sub esi, edx + cmp esi, [esp+12] + jb .set_ok.copy +.fail: + mov byte [edi], 0 + xor eax, eax ; fail + pop ebp + ret 8 +.set_ok.copy: + mov ecx, esi + mov esi, edx + rep movsb + mov byte [edi], 0 +.ret.ok: + mov al, 1 ; ok + pop ebp + ret 8 +.set_ok.cur_dir: + mov byte [esi], 0 + jmp .ret.ok +.doset_relative: + cmp edx, edi + jz .doset_relative.cur_dir + sub esi, edx + cmp esi, [esp+12] + jae .fail + mov ecx, esi + mov esi, edx + mov edx, edi + rep movsb + jmp .doset_relative.copy +.doset_relative.cur_dir: + mov edi, esi +.doset_relative.copy: + add edx, [esp+12] + mov byte [edi], '/' + inc edi + cmp edi, edx + jae .overflow +@@: + mov al, [ebx] + inc ebx + stosb + test al, al + jz .ret.ok + cmp edi, edx + jb @b +.overflow: + dec edi + jmp .fail +.set_absolute: + lea esi, [ebx+1] + call process_replace_file_name + mov edi, [esp+8] + mov edx, [esp+12] + add edx, edi +.set_copy: + lodsb + stosb + test al, al + jz .set_part2 +.set_copy_cont: + cmp edi, edx + jb .set_copy + jmp .overflow +.set_part2: + mov esi, ebp + xor ebp, ebp + test esi, esi + jz .ret.ok + mov byte [edi-1], '/' + jmp .set_copy_cont diff --git a/kernel/trunk/fs/iso9660.inc b/kernel/trunk/fs/iso9660.inc index e23229647..99c3893b0 100644 --- a/kernel/trunk/fs/iso9660.inc +++ b/kernel/trunk/fs/iso9660.inc @@ -1,761 +1,761 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -uglobal -cd_current_pointer_of_input dd 0 -cd_current_pointer_of_input_2 dd 0 -cd_mem_location dd 0 -cd_counter_block dd 0 -IDE_Channel_1 db 0 -IDE_Channel_2 db 0 -endg - -reserve_cd: - - cli - cmp [cd_status],0 - je reserve_ok2 - - sti - call change_task - jmp reserve_cd - - reserve_ok2: - - push eax - mov eax,[CURRENT_TASK] - shl eax,5 - mov eax,[eax+CURRENT_TASK+TASKDATA.pid] - mov [cd_status],eax - pop eax - sti - ret - -reserve_cd_channel: - cmp [ChannelNumber],1 - jne .IDE_Channel_2 -.IDE_Channel_1: - cli - cmp [IDE_Channel_1],0 - je .reserve_ok_1 - sti - call change_task - jmp .IDE_Channel_1 -.IDE_Channel_2: - cli - cmp [IDE_Channel_2],0 - je .reserve_ok_2 - sti - call change_task - jmp .IDE_Channel_2 -.reserve_ok_1: - mov [IDE_Channel_1],1 - sti - ret -.reserve_ok_2: - mov [IDE_Channel_2],1 - sti - ret - -free_cd_channel: - cmp [ChannelNumber],1 - jne .IDE_Channel_2 -.IDE_Channel_1: - mov [IDE_Channel_1],0 - sti - ret -.IDE_Channel_2: - mov [IDE_Channel_2],0 - sti - ret - -uglobal -cd_status dd 0 -endg - -;---------------------------------------------------------------- -; -; fs_CdRead - LFN variant for reading CD disk -; -; esi points to filename /dir1/dir2/.../dirn/file,0 -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to read, 0+ -; edx mem location to return data -; -; ret ebx = bytes read or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_CdRead: - push edi - cmp byte [esi], 0 - jnz @f -.noaccess: - pop edi -.noaccess_2: - or ebx, -1 - mov eax, ERROR_ACCESS_DENIED - ret - -.noaccess_3: - pop eax edx ecx edi - jmp .noaccess_2 - -@@: - call cd_find_lfn - jnc .found - pop edi - cmp [DevErrorCode],0 - jne .noaccess_2 - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret - -.found: - mov edi,[cd_current_pointer_of_input] - test byte [edi+25],10b ; do not allow read directories - jnz .noaccess - test ebx, ebx - jz .l1 - cmp dword [ebx+4], 0 - jz @f - xor ebx, ebx -.reteof: - mov eax, 6 ; end of file - pop edi - ret -@@: - mov ebx, [ebx] -.l1: - push ecx edx - push 0 - mov eax, [edi+10] ; реальный размер файловой секции - sub eax, ebx - jb .eof - cmp eax, ecx - jae @f - mov ecx, eax - mov byte [esp], 6 -@@: - mov eax,[edi+2] - mov [CDSectorAddress],eax -; now eax=cluster, ebx=position, ecx=count, edx=buffer for data -.new_sector: - test ecx, ecx - jz .done - sub ebx, 2048 - jae .next - add ebx, 2048 - jnz .incomplete_sector - cmp ecx, 2048 - jb .incomplete_sector -; we may read and memmove complete sector - mov [CDDataBuf_pointer],edx - call ReadCDWRetr ; читаем сектор файла - cmp [DevErrorCode],0 - jne .noaccess_3 - add edx, 2048 - sub ecx, 2048 -.next: - inc dword [CDSectorAddress] - jmp .new_sector -.incomplete_sector: -; we must read and memmove incomplete sector - mov [CDDataBuf_pointer],CDDataBuf - call ReadCDWRetr ; читаем сектор файла - cmp [DevErrorCode],0 - jne .noaccess_3 - push ecx - add ecx, ebx - cmp ecx, 2048 - jbe @f - mov ecx, 2048 -@@: - sub ecx, ebx - push edi esi ecx - mov edi,edx - lea esi, [CDDataBuf + ebx] - cld - rep movsb - pop ecx esi edi - add edx, ecx - sub [esp], ecx - pop ecx - xor ebx, ebx - jmp .next - -.done: - mov ebx, edx - pop eax edx ecx edi - sub ebx, edx - ret -.eof: - mov ebx, edx - pop eax edx ecx - sub ebx, edx - jmp .reteof - -;---------------------------------------------------------------- -; -; fs_CdReadFolder - LFN variant for reading CD disk folder -; -; esi points to filename /dir1/dir2/.../dirn/file,0 -; ebx pointer to structure 32-bit number = first wanted block, 0+ -; & flags (bitfields) -; flags: bit 0: 0=ANSI names, 1=UNICODE names -; ecx number of blocks to read, 0+ -; edx mem location to return data -; -; ret ebx = blocks read or 0xffffffff folder not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -fs_CdReadFolder: - push edi - call cd_find_lfn - jnc .found - pop edi - cmp [DevErrorCode], 0 - jne .noaccess_1 - or ebx, -1 - mov eax, ERROR_FILE_NOT_FOUND - ret -.found: - mov edi, [cd_current_pointer_of_input] - test byte [edi+25], 10b ; do not allow read directories - jnz .found_dir - pop edi -.noaccess_1: - or ebx, -1 - mov eax, ERROR_ACCESS_DENIED - ret -.found_dir: - mov eax, [edi+2] ; eax=cluster - mov [CDSectorAddress], eax - mov eax, [edi+10] ; размер директрории -.doit: -; init header - push eax ecx - mov edi, edx - mov ecx, 32/4 - xor eax, eax - rep stosd - pop ecx eax - mov byte [edx], 1 ; version - mov [cd_mem_location], edx - add [cd_mem_location], 32 -; начинаем переброску БДВК в УСВК -;.mainloop: - mov [cd_counter_block], dword 0 - dec dword [CDSectorAddress] - push ecx -.read_to_buffer: - inc dword [CDSectorAddress] - mov [CDDataBuf_pointer], CDDataBuf - call ReadCDWRetr ; читаем сектор директории - cmp [DevErrorCode], 0 - jne .noaccess_1 - call .get_names_from_buffer - sub eax,2048 -; директория закончилась? - ja .read_to_buffer - mov edi, [cd_counter_block] - mov [edx+8], edi - mov edi, [ebx] - sub [edx+4], edi - xor eax, eax - dec ecx - js @f - mov al, ERROR_END_OF_FILE -@@: - pop ecx edi - mov ebx, [edx+4] - ret - -.get_names_from_buffer: - mov [cd_current_pointer_of_input_2],CDDataBuf - push eax esi edi edx -.get_names_from_buffer_1: - call cd_get_name - jc .end_buffer - inc dword [cd_counter_block] - mov eax,[cd_counter_block] - cmp [ebx],eax - jae .get_names_from_buffer_1 - test ecx, ecx - jz .get_names_from_buffer_1 - mov edi,[cd_counter_block] - mov [edx+4],edi - dec ecx - mov esi,ebp - mov edi,[cd_mem_location] - add edi,40 - test dword [ebx+4], 1 ; 0=ANSI, 1=UNICODE - jnz .unicode -; jmp .unicode -.ansi: - cmp [cd_counter_block],2 - jbe .ansi_parent_directory - cld - lodsw - xchg ah,al - call uni2ansi_char - cld - stosb -; проверка конца файла - mov ax,[esi] - cmp ax,word 3B00h ; сепаратор конца файла ';' - je .cd_get_parameters_of_file_1 -; проверка для файлов не заканчивающихся сепаратором - movzx eax,byte [ebp-33] - add eax,ebp - sub eax,34 - cmp esi,eax - je .cd_get_parameters_of_file_1 -; проверка конца папки - movzx eax,byte [ebp-1] - add eax,ebp - cmp esi,eax - jb .ansi -.cd_get_parameters_of_file_1: - mov [edi],byte 0 - call cd_get_parameters_of_file - add [cd_mem_location],304 - jmp .get_names_from_buffer_1 - -.ansi_parent_directory: - cmp [cd_counter_block],2 - je @f - mov [edi],byte '.' - inc edi - jmp .cd_get_parameters_of_file_1 -@@: - mov [edi],word '..' - add edi,2 - jmp .cd_get_parameters_of_file_1 - -.unicode: - cmp [cd_counter_block],2 - jbe .unicode_parent_directory - cld - movsw -; проверка конца файла - mov ax,[esi] - cmp ax,word 3B00h ; сепаратор конца файла ';' - je .cd_get_parameters_of_file_2 -; проверка для файлов не заканчивающихся сепаратором - movzx eax,byte [ebp-33] - add eax,ebp - sub eax,34 - cmp esi,eax - je .cd_get_parameters_of_file_2 -; проверка конца папки - movzx eax,byte [ebp-1] - add eax,ebp - cmp esi,eax - jb .unicode -.cd_get_parameters_of_file_2: - mov [edi],word 0 - call cd_get_parameters_of_file - add [cd_mem_location],560 - jmp .get_names_from_buffer_1 - -.unicode_parent_directory: - cmp [cd_counter_block],2 - je @f - mov [edi],word 2E00h ; '.' - add edi,2 - jmp .cd_get_parameters_of_file_2 -@@: - mov [edi],dword 2E002E00h ; '..' - add edi,4 - jmp .cd_get_parameters_of_file_2 - -.end_buffer: - pop edx edi esi eax - ret - -cd_get_parameters_of_file: - mov edi,[cd_mem_location] -cd_get_parameters_of_file_1: -; получаем атрибуты файла - xor eax,eax -; файл не архивировался - inc eax - shl eax,1 -; это каталог? - test [ebp-8],byte 2 - jz .file - inc eax -.file: -; метка тома не как в FAT, в этом виде отсутсвует -; файл не является системным - shl eax,3 -; файл является скрытым? (атрибут существование) - test [ebp-8],byte 1 - jz .hidden - inc eax -.hidden: - shl eax,1 -; файл всегда только для чтения, так как это CD - inc eax - mov [edi],eax -; получаем время для файла -;час - movzx eax,byte [ebp-12] - shl eax,8 -;минута - mov al,[ebp-11] - shl eax,8 -;секунда - mov al,[ebp-10] -;время создания файла - mov [edi+8],eax -;время последнего доступа - mov [edi+16],eax -;время последней записи - mov [edi+24],eax -; получаем дату для файла -;год - movzx eax,byte [ebp-15] - add eax,1900 - shl eax,8 -;месяц - mov al,[ebp-14] - shl eax,8 -;день - mov al,[ebp-13] -;дата создания файла - mov [edi+12],eax -;время последнего доступа - mov [edi+20],eax -;время последней записи - mov [edi+28],eax -; получаем тип данных имени - xor eax,eax - test dword [ebx+4], 1 ; 0=ANSI, 1=UNICODE - jnz .unicode_1 - mov [edi+4],eax - jmp @f -.unicode_1: - inc eax - mov [edi+4],eax -@@: -; получаем размер файла в байтах - xor eax,eax - mov [edi+32+4],eax - mov eax,[ebp-23] - mov [edi+32],eax - ret - -;---------------------------------------------------------------- -; -; fs_CdGetFileInfo - LFN variant for CD -; get file/directory attributes structure -; -;---------------------------------------------------------------- -fs_CdGetFileInfo: - cmp byte [esi], 0 - jnz @f - mov eax, 2 - ret -@@: - push edi - call cd_find_lfn - pushfd - cmp [DevErrorCode], 0 - jz @f - popfd - pop edi - mov eax, 11 - ret -@@: - popfd - jnc @f - pop edi - mov eax, ERROR_FILE_NOT_FOUND - ret -@@: - - mov edi, edx - push ebp - mov ebp, [cd_current_pointer_of_input] - add ebp, 33 - call cd_get_parameters_of_file_1 - pop ebp - and dword [edi+4], 0 - pop edi - xor eax, eax - ret - -;---------------------------------------------------------------- -cd_find_lfn: - mov [cd_appl_data],0 -; in: esi+ebp -> name -; out: CF=1 - file not found -; else CF=0 and [cd_current_pointer_of_input] direntry - push eax esi -; 16 сектор начало набора дескрипторов томов - - call WaitUnitReady - cmp [DevErrorCode],0 - jne .access_denied - - call prevent_medium_removal -; тестовое чтение - mov [CDSectorAddress],dword 16 - mov [CDDataBuf_pointer],CDDataBuf - call ReadCDWRetr ;_1 - cmp [DevErrorCode],0 - jne .access_denied - -; вычисление последней сессии - call WaitUnitReady - cmp [DevErrorCode],0 - jne .access_denied - call Read_TOC - mov ah,[CDDataBuf+4+4] - mov al,[CDDataBuf+4+5] - shl eax,16 - mov ah,[CDDataBuf+4+6] - mov al,[CDDataBuf+4+7] - add eax,15 - mov [CDSectorAddress],eax -; mov [CDSectorAddress],dword 15 - mov [CDDataBuf_pointer],CDDataBuf - -.start: - inc dword [CDSectorAddress] - call ReadCDWRetr ;_1 - cmp [DevErrorCode],0 - jne .access_denied - -.start_check: -; проверка на вшивость - cmp [CDDataBuf+1],dword 'CD00' - jne .access_denied - cmp [CDDataBuf+5],byte '1' - jne .access_denied -; сектор является терминатором набор дескрипторов томов? - cmp [CDDataBuf],byte 0xff - je .access_denied -; сектор является дополнительным и улучшенным дескриптором тома? - cmp [CDDataBuf],byte 0x2 - jne .start -; сектор является дополнительным дескриптором тома? - cmp [CDDataBuf+6],byte 0x1 - jne .start - -; параметры root директрории - mov eax,[CDDataBuf+0x9c+2] ; начало root директрории - mov [CDSectorAddress],eax - mov eax,[CDDataBuf+0x9c+10] ; размер root директрории - cmp byte [esi], 0 - jnz @f - mov [cd_current_pointer_of_input],CDDataBuf+0x9c - jmp .done -@@: -; начинаем поиск -.mainloop: - dec dword [CDSectorAddress] -.read_to_buffer: - inc dword [CDSectorAddress] - mov [CDDataBuf_pointer],CDDataBuf - call ReadCDWRetr ; читаем сектор директории - cmp [DevErrorCode],0 - jne .access_denied - push ebp - call cd_find_name_in_buffer - pop ebp - jnc .found - sub eax,2048 -; директория закончилась? - cmp eax,0 - ja .read_to_buffer -; нет искомого элемента цепочки -.access_denied: - pop esi eax - mov [cd_appl_data],1 - stc - ret -; искомый элемент цепочки найден - .found: -; конец пути файла - cmp byte [esi-1], 0 - jz .done - .nested: - mov eax,[cd_current_pointer_of_input] - push dword [eax+2] - pop dword [CDSectorAddress] ; начало директории - mov eax,[eax+2+8] ; размер директории - jmp .mainloop -; указатель файла найден - .done: - test ebp, ebp - jz @f - mov esi, ebp - xor ebp, ebp - jmp .nested -@@: - pop esi eax - mov [cd_appl_data],1 - clc - ret - -cd_find_name_in_buffer: - mov [cd_current_pointer_of_input_2],CDDataBuf -.start: - call cd_get_name - jc .not_found - call cd_compare_name - jc .start -.found: - clc - ret -.not_found: - stc - ret - -cd_get_name: - push eax - mov ebp,[cd_current_pointer_of_input_2] - mov [cd_current_pointer_of_input],ebp - mov eax,[ebp] - test eax,eax ; входы закончились? - jz .next_sector - cmp ebp,CDDataBuf+2048 ; буфер закончился? - jae .next_sector - movzx eax, byte [ebp] - add [cd_current_pointer_of_input_2],eax ; следующий вход каталога - add ebp,33 ; указатель установлен на начало имени - pop eax - clc - ret -.next_sector: - pop eax - stc - ret - -cd_compare_name: -; compares ASCIIZ-names, case-insensitive (cp866 encoding) -; in: esi->name, ebp->name -; out: if names match: ZF=1 and esi->next component of name -; else: ZF=0, esi is not changed -; destroys eax - push esi eax edi - mov edi,ebp -.loop: - cld - lodsb - push eax - call char_todown - call ansi2uni_char - xchg ah,al - scasw - pop eax - je .coincides - call char_toupper - call ansi2uni_char - xchg ah,al - sub edi,2 - scasw - jne .name_not_coincide -.coincides: - cmp [esi],byte '/' ; разделитель пути, конец имени текущего элемента - je .done - cmp [esi],byte 0 ; разделитель пути, конец имени текущего элемента - je .done - jmp .loop -.name_not_coincide: - pop edi eax esi - stc - ret -.done: -; проверка конца файла - cmp [edi],word 3B00h ; сепаратор конца файла ';' - je .done_1 -; проверка для файлов не заканчивающихся сепаратором - movzx eax,byte [ebp-33] - add eax,ebp - sub eax,34 - cmp edi,eax - je .done_1 -; проверка конца папки - movzx eax,byte [ebp-1] - add eax,ebp - cmp edi,eax - jne .name_not_coincide -.done_1: - pop edi eax - add esp,4 - inc esi - clc - ret - -char_todown: -; convert character to uppercase, using cp866 encoding -; in: al=symbol -; out: al=converted symbol - cmp al, 'A' - jb .ret - cmp al, 'Z' - jbe .az - cmp al, 'Ђ' - jb .ret - cmp al, 'ђ' - jb .rus1 - cmp al, 'џ' - ja .ret -; 0x90-0x9F -> 0xE0-0xEF - add al, 'а'-'ђ' -.ret: - ret -.rus1: -; 0x80-0x8F -> 0xA0-0xAF -.az: - add al, 0x20 - ret - -uni2ansi_char: -; convert UNICODE character in al to ANSI character in ax, using cp866 encoding -; in: ax=UNICODE character -; out: al=converted ANSI character - cmp ax, 0x80 - jb .ascii - cmp ax, 0x401 - jz .yo1 - cmp ax, 0x451 - jz .yo2 - cmp ax, 0x410 - jb .unk - cmp ax, 0x440 - jb .rus1 - cmp ax, 0x450 - jb .rus2 -.unk: - mov al, '_' - jmp .doit -.yo1: - mov al, 'р' - jmp .doit -.yo2: - mov al, 'с' - jmp .doit -.rus1: -; 0x410-0x43F -> 0x80-0xAF - add al, 0x70 - jmp .doit -.rus2: -; 0x440-0x44F -> 0xE0-0xEF - add al, 0xA0 -.ascii: -.doit: - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +uglobal +cd_current_pointer_of_input dd 0 +cd_current_pointer_of_input_2 dd 0 +cd_mem_location dd 0 +cd_counter_block dd 0 +IDE_Channel_1 db 0 +IDE_Channel_2 db 0 +endg + +reserve_cd: + + cli + cmp [cd_status], 0 + je reserve_ok2 + + sti + call change_task + jmp reserve_cd + + reserve_ok2: + + push eax + mov eax, [CURRENT_TASK] + shl eax, 5 + mov eax, [eax+CURRENT_TASK+TASKDATA.pid] + mov [cd_status], eax + pop eax + sti + ret + +reserve_cd_channel: + cmp [ChannelNumber], 1 + jne .IDE_Channel_2 +.IDE_Channel_1: + cli + cmp [IDE_Channel_1], 0 + je .reserve_ok_1 + sti + call change_task + jmp .IDE_Channel_1 +.IDE_Channel_2: + cli + cmp [IDE_Channel_2], 0 + je .reserve_ok_2 + sti + call change_task + jmp .IDE_Channel_2 +.reserve_ok_1: + mov [IDE_Channel_1], 1 + sti + ret +.reserve_ok_2: + mov [IDE_Channel_2], 1 + sti + ret + +free_cd_channel: + cmp [ChannelNumber], 1 + jne .IDE_Channel_2 +.IDE_Channel_1: + mov [IDE_Channel_1], 0 + sti + ret +.IDE_Channel_2: + mov [IDE_Channel_2], 0 + sti + ret + +uglobal +cd_status dd 0 +endg + +;---------------------------------------------------------------- +; +; fs_CdRead - LFN variant for reading CD disk +; +; esi points to filename /dir1/dir2/.../dirn/file,0 +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to read, 0+ +; edx mem location to return data +; +; ret ebx = bytes read or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_CdRead: + push edi + cmp byte [esi], 0 + jnz @f +.noaccess: + pop edi +.noaccess_2: + or ebx, -1 + mov eax, ERROR_ACCESS_DENIED + ret + +.noaccess_3: + pop eax edx ecx edi + jmp .noaccess_2 + +@@: + call cd_find_lfn + jnc .found + pop edi + cmp [DevErrorCode], 0 + jne .noaccess_2 + or ebx, -1 + mov eax, ERROR_FILE_NOT_FOUND + ret + +.found: + mov edi, [cd_current_pointer_of_input] + test byte [edi+25], 10b; do not allow read directories + jnz .noaccess + test ebx, ebx + jz .l1 + cmp dword [ebx+4], 0 + jz @f + xor ebx, ebx +.reteof: + mov eax, 6; end of file + pop edi + ret +@@: + mov ebx, [ebx] +.l1: + push ecx edx + push 0 + mov eax, [edi+10] ; реальный размер файловой секции + sub eax, ebx + jb .eof + cmp eax, ecx + jae @f + mov ecx, eax + mov byte [esp], 6 +@@: + mov eax, [edi+2] + mov [CDSectorAddress], eax +; now eax=cluster, ebx=position, ecx=count, edx=buffer for data +.new_sector: + test ecx, ecx + jz .done + sub ebx, 2048 + jae .next + add ebx, 2048 + jnz .incomplete_sector + cmp ecx, 2048 + jb .incomplete_sector +; we may read and memmove complete sector + mov [CDDataBuf_pointer], edx + call ReadCDWRetr; читаем сектор файла + cmp [DevErrorCode], 0 + jne .noaccess_3 + add edx, 2048 + sub ecx, 2048 +.next: + inc dword [CDSectorAddress] + jmp .new_sector +.incomplete_sector: +; we must read and memmove incomplete sector + mov [CDDataBuf_pointer], CDDataBuf + call ReadCDWRetr; читаем сектор файла + cmp [DevErrorCode], 0 + jne .noaccess_3 + push ecx + add ecx, ebx + cmp ecx, 2048 + jbe @f + mov ecx, 2048 +@@: + sub ecx, ebx + push edi esi ecx + mov edi, edx + lea esi, [CDDataBuf + ebx] + cld + rep movsb + pop ecx esi edi + add edx, ecx + sub [esp], ecx + pop ecx + xor ebx, ebx + jmp .next + +.done: + mov ebx, edx + pop eax edx ecx edi + sub ebx, edx + ret +.eof: + mov ebx, edx + pop eax edx ecx + sub ebx, edx + jmp .reteof + +;---------------------------------------------------------------- +; +; fs_CdReadFolder - LFN variant for reading CD disk folder +; +; esi points to filename /dir1/dir2/.../dirn/file,0 +; ebx pointer to structure 32-bit number = first wanted block, 0+ +; & flags (bitfields) +; flags: bit 0: 0=ANSI names, 1=UNICODE names +; ecx number of blocks to read, 0+ +; edx mem location to return data +; +; ret ebx = blocks read or 0xffffffff folder not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +fs_CdReadFolder: + push edi + call cd_find_lfn + jnc .found + pop edi + cmp [DevErrorCode], 0 + jne .noaccess_1 + or ebx, -1 + mov eax, ERROR_FILE_NOT_FOUND + ret +.found: + mov edi, [cd_current_pointer_of_input] + test byte [edi+25], 10b ; do not allow read directories + jnz .found_dir + pop edi +.noaccess_1: + or ebx, -1 + mov eax, ERROR_ACCESS_DENIED + ret +.found_dir: + mov eax, [edi+2] ; eax=cluster + mov [CDSectorAddress], eax + mov eax, [edi+10] ; размер директрории +.doit: +; init header + push eax ecx + mov edi, edx + mov ecx, 32/4 + xor eax, eax + rep stosd + pop ecx eax + mov byte [edx], 1 ; version + mov [cd_mem_location], edx + add [cd_mem_location], 32 +; начинаем переброску БДВК в УСВК +;.mainloop: + mov [cd_counter_block], dword 0 + dec dword [CDSectorAddress] + push ecx +.read_to_buffer: + inc dword [CDSectorAddress] + mov [CDDataBuf_pointer], CDDataBuf + call ReadCDWRetr ; читаем сектор директории + cmp [DevErrorCode], 0 + jne .noaccess_1 + call .get_names_from_buffer + sub eax, 2048 +; директория закончилась? + ja .read_to_buffer + mov edi, [cd_counter_block] + mov [edx+8], edi + mov edi, [ebx] + sub [edx+4], edi + xor eax, eax + dec ecx + js @f + mov al, ERROR_END_OF_FILE +@@: + pop ecx edi + mov ebx, [edx+4] + ret + +.get_names_from_buffer: + mov [cd_current_pointer_of_input_2], CDDataBuf + push eax esi edi edx +.get_names_from_buffer_1: + call cd_get_name + jc .end_buffer + inc dword [cd_counter_block] + mov eax, [cd_counter_block] + cmp [ebx], eax + jae .get_names_from_buffer_1 + test ecx, ecx + jz .get_names_from_buffer_1 + mov edi, [cd_counter_block] + mov [edx+4], edi + dec ecx + mov esi, ebp + mov edi, [cd_mem_location] + add edi, 40 + test dword [ebx+4], 1; 0=ANSI, 1=UNICODE + jnz .unicode +; jmp .unicode +.ansi: + cmp [cd_counter_block], 2 + jbe .ansi_parent_directory + cld + lodsw + xchg ah, al + call uni2ansi_char + cld + stosb +; проверка конца файла + mov ax, [esi] + cmp ax, word 3B00h; сепаратор конца файла ';' + je .cd_get_parameters_of_file_1 +; проверка для файлов не заканчивающихся сепаратором + movzx eax, byte [ebp-33] + add eax, ebp + sub eax, 34 + cmp esi, eax + je .cd_get_parameters_of_file_1 +; проверка конца папки + movzx eax, byte [ebp-1] + add eax, ebp + cmp esi, eax + jb .ansi +.cd_get_parameters_of_file_1: + mov [edi], byte 0 + call cd_get_parameters_of_file + add [cd_mem_location], 304 + jmp .get_names_from_buffer_1 + +.ansi_parent_directory: + cmp [cd_counter_block], 2 + je @f + mov [edi], byte '.' + inc edi + jmp .cd_get_parameters_of_file_1 +@@: + mov [edi], word '..' + add edi, 2 + jmp .cd_get_parameters_of_file_1 + +.unicode: + cmp [cd_counter_block], 2 + jbe .unicode_parent_directory + cld + movsw +; проверка конца файла + mov ax, [esi] + cmp ax, word 3B00h; сепаратор конца файла ';' + je .cd_get_parameters_of_file_2 +; проверка для файлов не заканчивающихся сепаратором + movzx eax, byte [ebp-33] + add eax, ebp + sub eax, 34 + cmp esi, eax + je .cd_get_parameters_of_file_2 +; проверка конца папки + movzx eax, byte [ebp-1] + add eax, ebp + cmp esi, eax + jb .unicode +.cd_get_parameters_of_file_2: + mov [edi], word 0 + call cd_get_parameters_of_file + add [cd_mem_location], 560 + jmp .get_names_from_buffer_1 + +.unicode_parent_directory: + cmp [cd_counter_block], 2 + je @f + mov [edi], word 2E00h; '.' + add edi, 2 + jmp .cd_get_parameters_of_file_2 +@@: + mov [edi], dword 2E002E00h; '..' + add edi, 4 + jmp .cd_get_parameters_of_file_2 + +.end_buffer: + pop edx edi esi eax + ret + +cd_get_parameters_of_file: + mov edi, [cd_mem_location] +cd_get_parameters_of_file_1: +; получаем атрибуты файла + xor eax, eax +; файл не архивировался + inc eax + shl eax, 1 +; это каталог? + test [ebp-8], byte 2 + jz .file + inc eax +.file: +; метка тома не как в FAT, в этом виде отсутсвует +; файл не является системным + shl eax, 3 +; файл является скрытым? (атрибут существование) + test [ebp-8], byte 1 + jz .hidden + inc eax +.hidden: + shl eax, 1 +; файл всегда только для чтения, так как это CD + inc eax + mov [edi], eax +; получаем время для файла +;час + movzx eax, byte [ebp-12] + shl eax, 8 +;минута + mov al, [ebp-11] + shl eax, 8 +;секунда + mov al, [ebp-10] +;время создания файла + mov [edi+8], eax +;время последнего доступа + mov [edi+16], eax +;время последней записи + mov [edi+24], eax +; получаем дату для файла +;год + movzx eax, byte [ebp-15] + add eax, 1900 + shl eax, 8 +;месяц + mov al, [ebp-14] + shl eax, 8 +;день + mov al, [ebp-13] +;дата создания файла + mov [edi+12], eax +;время последнего доступа + mov [edi+20], eax +;время последней записи + mov [edi+28], eax +; получаем тип данных имени + xor eax, eax + test dword [ebx+4], 1; 0=ANSI, 1=UNICODE + jnz .unicode_1 + mov [edi+4], eax + jmp @f +.unicode_1: + inc eax + mov [edi+4], eax +@@: +; получаем размер файла в байтах + xor eax, eax + mov [edi+32+4], eax + mov eax, [ebp-23] + mov [edi+32], eax + ret + +;---------------------------------------------------------------- +; +; fs_CdGetFileInfo - LFN variant for CD +; get file/directory attributes structure +; +;---------------------------------------------------------------- +fs_CdGetFileInfo: + cmp byte [esi], 0 + jnz @f + mov eax, 2 + ret +@@: + push edi + call cd_find_lfn + pushfd + cmp [DevErrorCode], 0 + jz @f + popfd + pop edi + mov eax, 11 + ret +@@: + popfd + jnc @f + pop edi + mov eax, ERROR_FILE_NOT_FOUND + ret +@@: + + mov edi, edx + push ebp + mov ebp, [cd_current_pointer_of_input] + add ebp, 33 + call cd_get_parameters_of_file_1 + pop ebp + and dword [edi+4], 0 + pop edi + xor eax, eax + ret + +;---------------------------------------------------------------- +cd_find_lfn: + mov [cd_appl_data], 0 +; in: esi+ebp -> name +; out: CF=1 - file not found +; else CF=0 and [cd_current_pointer_of_input] direntry + push eax esi +; 16 сектор начало набора дескрипторов томов + + call WaitUnitReady + cmp [DevErrorCode], 0 + jne .access_denied + + call prevent_medium_removal +; тестовое чтение + mov [CDSectorAddress], dword 16 + mov [CDDataBuf_pointer], CDDataBuf + call ReadCDWRetr;_1 + cmp [DevErrorCode], 0 + jne .access_denied + +; вычисление последней сессии + call WaitUnitReady + cmp [DevErrorCode], 0 + jne .access_denied + call Read_TOC + mov ah, [CDDataBuf+4+4] + mov al, [CDDataBuf+4+5] + shl eax, 16 + mov ah, [CDDataBuf+4+6] + mov al, [CDDataBuf+4+7] + add eax, 15 + mov [CDSectorAddress], eax +; mov [CDSectorAddress],dword 15 + mov [CDDataBuf_pointer], CDDataBuf + +.start: + inc dword [CDSectorAddress] + call ReadCDWRetr;_1 + cmp [DevErrorCode], 0 + jne .access_denied + +.start_check: +; проверка на вшивость + cmp [CDDataBuf+1], dword 'CD00' + jne .access_denied + cmp [CDDataBuf+5], byte '1' + jne .access_denied +; сектор является терминатором набор дескрипторов томов? + cmp [CDDataBuf], byte 0xff + je .access_denied +; сектор является дополнительным и улучшенным дескриптором тома? + cmp [CDDataBuf], byte 0x2 + jne .start +; сектор является дополнительным дескриптором тома? + cmp [CDDataBuf+6], byte 0x1 + jne .start + +; параметры root директрории + mov eax, [CDDataBuf+0x9c+2]; начало root директрории + mov [CDSectorAddress], eax + mov eax, [CDDataBuf+0x9c+10]; размер root директрории + cmp byte [esi], 0 + jnz @f + mov [cd_current_pointer_of_input], CDDataBuf+0x9c + jmp .done +@@: +; начинаем поиск +.mainloop: + dec dword [CDSectorAddress] +.read_to_buffer: + inc dword [CDSectorAddress] + mov [CDDataBuf_pointer], CDDataBuf + call ReadCDWRetr ; читаем сектор директории + cmp [DevErrorCode], 0 + jne .access_denied + push ebp + call cd_find_name_in_buffer + pop ebp + jnc .found + sub eax, 2048 +; директория закончилась? + cmp eax, 0 + ja .read_to_buffer +; нет искомого элемента цепочки +.access_denied: + pop esi eax + mov [cd_appl_data], 1 + stc + ret +; искомый элемент цепочки найден + .found: +; конец пути файла + cmp byte [esi-1], 0 + jz .done + .nested: + mov eax, [cd_current_pointer_of_input] + push dword [eax+2] + pop dword [CDSectorAddress] ; начало директории + mov eax, [eax+2+8]; размер директории + jmp .mainloop +; указатель файла найден + .done: + test ebp, ebp + jz @f + mov esi, ebp + xor ebp, ebp + jmp .nested +@@: + pop esi eax + mov [cd_appl_data], 1 + clc + ret + +cd_find_name_in_buffer: + mov [cd_current_pointer_of_input_2], CDDataBuf +.start: + call cd_get_name + jc .not_found + call cd_compare_name + jc .start +.found: + clc + ret +.not_found: + stc + ret + +cd_get_name: + push eax + mov ebp, [cd_current_pointer_of_input_2] + mov [cd_current_pointer_of_input], ebp + mov eax, [ebp] + test eax, eax ; входы закончились? + jz .next_sector + cmp ebp, CDDataBuf+2048 ; буфер закончился? + jae .next_sector + movzx eax, byte [ebp] + add [cd_current_pointer_of_input_2], eax; следующий вход каталога + add ebp, 33; указатель установлен на начало имени + pop eax + clc + ret +.next_sector: + pop eax + stc + ret + +cd_compare_name: +; compares ASCIIZ-names, case-insensitive (cp866 encoding) +; in: esi->name, ebp->name +; out: if names match: ZF=1 and esi->next component of name +; else: ZF=0, esi is not changed +; destroys eax + push esi eax edi + mov edi, ebp +.loop: + cld + lodsb + push eax + call char_todown + call ansi2uni_char + xchg ah, al + scasw + pop eax + je .coincides + call char_toupper + call ansi2uni_char + xchg ah, al + sub edi, 2 + scasw + jne .name_not_coincide +.coincides: + cmp [esi], byte '/'; разделитель пути, конец имени текущего элемента + je .done + cmp [esi], byte 0; разделитель пути, конец имени текущего элемента + je .done + jmp .loop +.name_not_coincide: + pop edi eax esi + stc + ret +.done: +; проверка конца файла + cmp [edi], word 3B00h; сепаратор конца файла ';' + je .done_1 +; проверка для файлов не заканчивающихся сепаратором + movzx eax, byte [ebp-33] + add eax, ebp + sub eax, 34 + cmp edi, eax + je .done_1 +; проверка конца папки + movzx eax, byte [ebp-1] + add eax, ebp + cmp edi, eax + jne .name_not_coincide +.done_1: + pop edi eax + add esp, 4 + inc esi + clc + ret + +char_todown: +; convert character to uppercase, using cp866 encoding +; in: al=symbol +; out: al=converted symbol + cmp al, 'A' + jb .ret + cmp al, 'Z' + jbe .az + cmp al, 'Ђ' + jb .ret + cmp al, 'ђ' + jb .rus1 + cmp al, 'џ' + ja .ret +; 0x90-0x9F -> 0xE0-0xEF + add al, 'а'-'ђ' +.ret: + ret +.rus1: +; 0x80-0x8F -> 0xA0-0xAF +.az: + add al, 0x20 + ret + +uni2ansi_char: +; convert UNICODE character in al to ANSI character in ax, using cp866 encoding +; in: ax=UNICODE character +; out: al=converted ANSI character + cmp ax, 0x80 + jb .ascii + cmp ax, 0x401 + jz .yo1 + cmp ax, 0x451 + jz .yo2 + cmp ax, 0x410 + jb .unk + cmp ax, 0x440 + jb .rus1 + cmp ax, 0x450 + jb .rus2 +.unk: + mov al, '_' + jmp .doit +.yo1: + mov al, 'р' + jmp .doit +.yo2: + mov al, 'с' + jmp .doit +.rus1: +; 0x410-0x43F -> 0x80-0xAF + add al, 0x70 + jmp .doit +.rus2: +; 0x440-0x44F -> 0xE0-0xEF + add al, 0xA0 +.ascii: +.doit: + ret diff --git a/kernel/trunk/fs/ntfs.inc b/kernel/trunk/fs/ntfs.inc index 9e62db6be..e85c2a23c 100644 --- a/kernel/trunk/fs/ntfs.inc +++ b/kernel/trunk/fs/ntfs.inc @@ -1,1829 +1,1829 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -ntfs_test_bootsec: -; in: ebx->buffer, edx=size of partition -; out: CF set <=> invalid -; 1. Name=='NTFS ' - cmp dword [ebx+3], 'NTFS' - jnz .no - cmp dword [ebx+7], ' ' - jnz .no -; 2. Number of bytes per sector is the same as for physical device -; (that is, 0x200 for hard disk) - cmp word [ebx+11], 0x200 - jnz .no -; 3. Number of sectors per cluster must be power of 2 - movzx eax, byte [ebx+13] - dec eax - js .no - test al, [ebx+13] - jnz .no -; 4. FAT parameters must be zero - cmp word [ebx+14], 0 - jnz .no - cmp dword [ebx+16], 0 - jnz .no - cmp byte [ebx+20], 0 - jnz .no - cmp word [ebx+22], 0 - jnz .no - cmp dword [ebx+32], 0 - jnz .no -; 5. Number of sectors <= partition size - cmp dword [ebx+0x2C], 0 - ja .no - cmp [ebx+0x28], edx - ja .no -; 6. $MFT and $MFTMirr clusters must be within partition - cmp dword [ebx+0x34], 0 - ja .no - push edx - movzx eax, byte [ebx+13] - mul dword [ebx+0x30] - test edx, edx - pop edx - jnz .no - cmp eax, edx - ja .no - cmp dword [ebx+0x3C], 0 - ja .no - push edx - movzx eax, byte [ebx+13] - mul dword [ebx+0x38] - test edx, edx - pop edx - jnz .no - cmp eax, edx - ja .no -; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2 - movsx eax, byte [ebx+0x40] - cmp al, -31 - jl .no - cmp al, -9 - jle @f - dec eax - js .no - test [ebx+0x40], al - jnz .no -@@: -; 8. Same for clusters per IndexAllocationBuffer - movsx eax, byte [ebx+0x44] - cmp al, -31 - jl .no - cmp al, -9 - jle @f - dec eax - js .no - test [ebx+0x44], al - jnz .no -@@: -; OK, this is correct NTFS bootsector - clc - ret -.no: -; No, this bootsector isn't NTFS - stc - ret - -ntfs_setup: ; CODE XREF: part_set.inc -; By given bootsector, initialize some NTFS variables -; call ntfs_test_bootsec ; checking boot sector was already -; jc problem_fat_dec_count - movzx eax, byte [ebx+13] - mov [ntfs_data.sectors_per_cluster], eax - mov eax, [ebx+0x28] - add eax, [PARTITION_START] - dec eax - mov [PARTITION_END], eax - mov [fs_type], 1 - mov eax, [ebx+0x30] - mov [ntfs_data.mft_cluster], eax - mov eax, [ebx+0x38] - mov [ntfs_data.mftmirr_cluster], eax - movsx eax, byte [ebx+0x40] - test eax, eax - js .1 - mul [ntfs_data.sectors_per_cluster] - shl eax, 9 - jmp .2 -.1: - neg eax - mov ecx, eax - mov eax, 1 - shl eax, cl -.2: - mov [ntfs_data.frs_size], eax - movsx eax, byte [ebx+0x44] - test eax, eax - js .3 - mul [ntfs_data.sectors_per_cluster] - shl eax, 9 - jmp .4 -.3: - neg eax - mov ecx, eax - mov eax, 1 - shl eax, cl -.4: - mov [ntfs_data.iab_size], eax -; allocate space for buffers - add eax, [ntfs_data.frs_size] - push eax - call kernel_alloc - test eax, eax - jz problem_fat_dec_count - mov [ntfs_data.frs_buffer], eax - add eax, [ntfs_data.frs_size] - mov [ntfs_data.iab_buffer], eax -; read $MFT disposition - mov eax, [ntfs_data.mft_cluster] - mul [ntfs_data.sectors_per_cluster] - call ntfs_read_frs_sector - cmp [hd_error], 0 - jnz .usemirr - cmp dword [ebx], 'FILE' - jnz .usemirr - call ntfs_restore_usa_frs - jnc .mftok -.usemirr: - and [hd_error], 0 - mov eax, [ntfs_data.mftmirr_cluster] - mul [ntfs_data.sectors_per_cluster] - call ntfs_read_frs_sector - cmp [hd_error], 0 - jnz @f - cmp dword [ebx], 'FILE' - jnz @f - call ntfs_restore_usa_frs - jnc .mftok -@@: -; $MFT and $MFTMirr invalid! -.fail_free_frs: - push [ntfs_data.frs_buffer] - call kernel_free - jmp problem_fat_dec_count -.fail_free_mft: - push [ntfs_data.mft_retrieval] - call kernel_free - jmp .fail_free_frs -.mftok: -; read $MFT table retrieval information -; start with one page, increase if not enough (when MFT too fragmented) - push ebx - push 0x1000 - call kernel_alloc - pop ebx - test eax, eax - jz .fail_free_frs - mov [ntfs_data.mft_retrieval], eax - and [ntfs_data.mft_retrieval_size], 0 - mov [ntfs_data.mft_retrieval_alloc], 0x1000/8 -; $MFT base record must contain unnamed non-resident $DATA attribute - movzx eax, word [ebx+14h] - add eax, ebx -.scandata: - cmp dword [eax], -1 - jz .fail_free_mft - cmp dword [eax], 0x80 - jnz @f - cmp byte [eax+9], 0 - jz .founddata -@@: - add eax, [eax+4] - jmp .scandata -.founddata: - cmp byte [eax+8], 0 - jz .fail_free_mft -; load first portion of $DATA attribute retrieval information - mov edx, [eax+0x18] - mov [ntfs_data.mft_retrieval_end], edx - mov esi, eax - movzx eax, word [eax+0x20] - add esi, eax - sub esp, 10h -.scanmcb: - call ntfs_decode_mcb_entry - jnc .scanmcbend - call .get_mft_retrieval_ptr - mov edx, [esp] ; block length - mov [eax], edx - mov edx, [esp+8] ; block addr (relative) - mov [eax+4], edx - inc [ntfs_data.mft_retrieval_size] - jmp .scanmcb -.scanmcbend: - add esp, 10h -; there may be other portions of $DATA attribute in auxiliary records; -; if they will be needed, they will be loaded later - - mov [ntfs_data.cur_index_size], 0x1000/0x200 - push 0x1000 - call kernel_alloc - test eax, eax - jz .fail_free_mft - mov [ntfs_data.cur_index_buf], eax - - popad - call free_hd_channel - and [hd1_status], 0 - ret - -.get_mft_retrieval_ptr: - pushad - mov eax, [ntfs_data.mft_retrieval_size] - cmp eax, [ntfs_data.mft_retrieval_alloc] - jnz .ok - add eax, 0x1000/8 - mov [ntfs_data.mft_retrieval_alloc], eax - shl eax, 3 - push eax - call kernel_alloc - test eax, eax - jnz @f - popad - add esp, 14h - jmp .fail_free_mft -@@: - mov esi, [ntfs_data.mft_retrieval] - mov edi, eax - mov ecx, [ntfs_data.mft_retrieval_size] - add ecx, ecx - rep movsd - push [ntfs_data.mft_retrieval] - mov [ntfs_data.mft_retrieval], eax - call kernel_free - mov eax, [ntfs_data.mft_retrieval_size] -.ok: - shl eax, 3 - add eax, [ntfs_data.mft_retrieval] - mov [esp+28], eax - popad - ret - -ntfs_read_frs_sector: - push eax ecx - add eax, [PARTITION_START] - mov ecx, [ntfs_data.frs_size] - shr ecx, 9 - mov ebx, [ntfs_data.frs_buffer] - push ebx -@@: - call hd_read - cmp [hd_error], 0 - jnz .fail - add ebx, 0x200 - inc eax - loop @b -.fail: - pop ebx - pop ecx eax - ret - -uglobal -align 4 -ntfs_cur_attr dd ? -ntfs_cur_iRecord dd ? -ntfs_cur_offs dd ? ; in sectors -ntfs_cur_size dd ? ; in sectors -ntfs_cur_buf dd ? -ntfs_cur_read dd ? ; [output] -ntfs_bCanContinue db ? - rb 3 - -ntfs_attrlist_buf rb 0x400 -ntfs_attrlist_mft_buf rb 0x400 -ntfs_bitmap_buf rb 0x400 - -ntfs_attr_iRecord dd ? -ntfs_attr_iBaseRecord dd ? -ntfs_attr_offs dd ? -ntfs_attr_list dd ? -ntfs_attr_size dq ? -ntfs_cur_tail dd ? -endg - -ntfs_read_attr: -; in: global variables -; out: [ntfs_cur_read] - pushad - and [ntfs_cur_read], 0 - cmp [ntfs_cur_iRecord], 0 - jnz .nomft - cmp [ntfs_cur_attr], 0x80 - jnz .nomft - mov eax, [ntfs_data.mft_retrieval_end] - inc eax - mul [ntfs_data.sectors_per_cluster] - cmp eax, [ntfs_cur_offs] - jbe .nomft -; precalculated part of $Mft $DATA - mov esi, [ntfs_data.mft_retrieval] - mov eax, [ntfs_cur_offs] - xor edx, edx - div [ntfs_data.sectors_per_cluster] -; eax = VCN, edx = offset in sectors from beginning of cluster - xor ecx, ecx ; ecx will contain LCN -.mftscan: - add ecx, [esi+4] - sub eax, [esi] - jb @f - add esi, 8 - push eax - mov eax, [ntfs_data.mft_retrieval_end] - shl eax, 3 - add eax, [ntfs_data.mft_retrieval] - cmp eax, esi - pop eax - jnz .mftscan - jmp .nomft -@@: - push ecx - add ecx, eax - add ecx, [esi] - push eax - push edx - mov eax, [ntfs_data.sectors_per_cluster] - mul ecx -; eax = sector on partition - add eax, [PARTITION_START] - pop edx - add eax, edx - mov ebx, [ntfs_cur_buf] - pop ecx - neg ecx - imul ecx, [ntfs_data.sectors_per_cluster] - sub ecx, edx - cmp ecx, [ntfs_cur_size] - jb @f - mov ecx, [ntfs_cur_size] -@@: -; ecx = number of sequential sectors to read - call hd_read - cmp [hd_error], 0 - jnz .errread - add [ntfs_cur_read], 0x200 - dec [ntfs_cur_size] - inc [ntfs_cur_offs] - add ebx, 0x200 - mov [ntfs_cur_buf], ebx - inc eax - loop @b - pop ecx - xor eax, eax - xor edx, edx - cmp [ntfs_cur_size], eax - jz @f - add esi, 8 - push eax - mov eax, [ntfs_data.mft_retrieval_end] - shl eax, 3 - add eax, [ntfs_data.mft_retrieval] - cmp eax, esi - pop eax - jz .nomft - jmp .mftscan -@@: - popad - ret -.errread: - pop ecx -.errret: - stc - popad - ret -.nomft: -; 1. Read file record. -; N.B. This will do recursive call of read_attr for $MFT::$Data. - mov eax, [ntfs_cur_iRecord] - mov [ntfs_attr_iRecord], eax - and [ntfs_attr_list], 0 - or dword [ntfs_attr_size], -1 - or dword [ntfs_attr_size+4], -1 - or [ntfs_attr_iBaseRecord], -1 - call ntfs_read_file_record - test eax, eax - jz .errret -; 2. Find required attribute. - mov eax, [ntfs_data.frs_buffer] -; a) For auxiliary records, read base record -; N.B. If base record is present, -; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero - cmp dword [eax+24h], 0 - jz @f - mov eax, [eax+20h] -; test eax, eax -; jz @f -.beginfindattr: - mov [ntfs_attr_iRecord], eax - call ntfs_read_file_record - test eax, eax - jz .errret -@@: -; b) Scan for required attribute and for $ATTR_LIST - mov eax, [ntfs_data.frs_buffer] - movzx ecx, word [eax+14h] - add eax, ecx - mov ecx, [ntfs_cur_attr] - and [ntfs_attr_offs], 0 -.scanattr: - cmp dword [eax], -1 - jz .scandone - cmp dword [eax], ecx - jz .okattr - cmp [ntfs_attr_iBaseRecord], -1 - jnz .scancont - cmp dword [eax], 0x20 ; $ATTR_LIST - jnz .scancont - mov [ntfs_attr_list], eax - jmp .scancont -.okattr: -; ignore named $DATA attributes (aka NTFS streams) - cmp ecx, 0x80 - jnz @f - cmp byte [eax+9], 0 - jnz .scancont -@@: - mov [ntfs_attr_offs], eax -.scancont: - add eax, [eax+4] - jmp .scanattr -.continue: - pushad - and [ntfs_cur_read], 0 -.scandone: -; c) Check for required offset and length - mov ecx, [ntfs_attr_offs] - jecxz .noattr - push [ntfs_cur_size] - push [ntfs_cur_read] - call .doreadattr - pop edx - pop eax - jc @f - cmp [ntfs_bCanContinue], 0 - jz @f - sub edx, [ntfs_cur_read] - neg edx - shr edx, 9 - sub eax, edx - mov [ntfs_cur_size], eax - jnz .not_in_cur -@@: - popad - ret -.noattr: -.not_in_cur: - cmp [ntfs_cur_attr], 0x20 - jz @f - mov ecx, [ntfs_attr_list] - test ecx, ecx - jnz .lookattr -.ret_is_attr: - cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0 - popad - ret -.lookattr: -; required attribute or required offset was not found in base record; -; it may be present in auxiliary records; -; scan $ATTR_LIST - mov eax, [ntfs_attr_iBaseRecord] - cmp eax, -1 - jz @f - call ntfs_read_file_record - test eax, eax - jz .errret - or [ntfs_attr_iBaseRecord], -1 -@@: - push [ntfs_cur_offs] - push [ntfs_cur_size] - push [ntfs_cur_read] - push [ntfs_cur_buf] - push dword [ntfs_attr_size] - push dword [ntfs_attr_size+4] - or dword [ntfs_attr_size], -1 - or dword [ntfs_attr_size+4], -1 - and [ntfs_cur_offs], 0 - mov [ntfs_cur_size], 2 - and [ntfs_cur_read], 0 - mov eax, ntfs_attrlist_buf - cmp [ntfs_cur_iRecord], 0 - jnz @f - mov eax, ntfs_attrlist_mft_buf -@@: - mov [ntfs_cur_buf], eax - push eax - call .doreadattr - pop esi - mov edx, 1 - pop dword [ntfs_attr_size+4] - pop dword [ntfs_attr_size] - mov ebp, [ntfs_cur_read] - pop [ntfs_cur_buf] - pop [ntfs_cur_read] - pop [ntfs_cur_size] - pop [ntfs_cur_offs] - jc .errret - or edi, -1 - lea ebp, [ebp+esi-1Ah] -.scanliststart: - mov eax, [ntfs_cur_attr] -.scanlist: - cmp esi, ebp - jae .scanlistdone - cmp eax, [esi] - jz @f -.scanlistcont: - movzx ecx, word [esi+4] - add esi, ecx - jmp .scanlist -@@: -; ignore named $DATA attributes (aka NTFS streams) - cmp eax, 0x80 - jnz @f - cmp byte [esi+6], 0 - jnz .scanlistcont -@@: - push eax - mov eax, [esi+8] - test eax, eax - jnz .testf - mov eax, dword [ntfs_attr_size] - and eax, dword [ntfs_attr_size+4] - cmp eax, -1 - jnz .testfz -; if attribute is in auxiliary records, its size is defined only in first - mov eax, [esi+10h] - call ntfs_read_file_record - test eax, eax - jnz @f -.errret_pop: - pop eax - jmp .errret -@@: - mov eax, [ntfs_data.frs_buffer] - movzx ecx, word [eax+14h] - add eax, ecx - mov ecx, [ntfs_cur_attr] -@@: - cmp dword [eax], -1 - jz .errret_pop - cmp dword [eax], ecx - jz @f -.l1: - add eax, [eax+4] - jmp @b -@@: - cmp eax, 0x80 - jnz @f - cmp byte [eax+9], 0 - jnz .l1 -@@: - cmp byte [eax+8], 0 - jnz .sdnores - mov eax, [eax+10h] - mov dword [ntfs_attr_size], eax - and dword [ntfs_attr_size+4], 0 - jmp .testfz -.sdnores: - mov ecx, [eax+30h] - mov dword [ntfs_attr_size], ecx - mov ecx, [eax+34h] - mov dword [ntfs_attr_size+4], ecx -.testfz: - xor eax, eax -.testf: - imul eax, [ntfs_data.sectors_per_cluster] - cmp eax, [ntfs_cur_offs] - pop eax - ja @f - mov edi, [esi+10h] ; keep previous iRecord - jmp .scanlistcont -@@: -.scanlistfound: - cmp edi, -1 - jnz @f - popad - ret -@@: - mov eax, [ntfs_cur_iRecord] - mov [ntfs_attr_iBaseRecord], eax - mov eax, edi - jmp .beginfindattr -.sde: - popad - stc - ret -.scanlistdone: - sub ebp, ntfs_attrlist_buf-1Ah - cmp [ntfs_cur_iRecord], 0 - jnz @f - sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf -@@: - cmp ebp, 0x400 - jnz .scanlistfound - inc edx - push esi edi - mov esi, ntfs_attrlist_buf+0x200 - mov edi, ntfs_attrlist_buf - cmp [ntfs_cur_iRecord], 0 - jnz @f - mov esi, ntfs_attrlist_mft_buf+0x200 - mov edi, ntfs_attrlist_mft_buf -@@: - mov ecx, 0x200/4 - rep movsd - mov eax, edi - pop edi esi - sub esi, 0x200 - push [ntfs_cur_offs] - push [ntfs_cur_size] - push [ntfs_cur_read] - push [ntfs_cur_buf] - push dword [ntfs_attr_size] - push dword [ntfs_attr_size+4] - or dword [ntfs_attr_size], -1 - or dword [ntfs_attr_size+4], -1 - mov [ntfs_cur_offs], edx - mov [ntfs_cur_size], 1 - and [ntfs_cur_read], 0 - mov [ntfs_cur_buf], eax - mov ecx, [ntfs_attr_list] - push esi edx - call .doreadattr - pop edx esi - mov ebp, [ntfs_cur_read] - pop dword [ntfs_attr_size+4] - pop dword [ntfs_attr_size] - pop [ntfs_cur_buf] - pop [ntfs_cur_read] - pop [ntfs_cur_size] - pop [ntfs_cur_offs] - jc .errret - add ebp, ntfs_attrlist_buf+0x200-0x1A - cmp [ntfs_cur_iRecord], 0 - jnz .scanliststart - add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf - jmp .scanliststart - -.doreadattr: - mov [ntfs_bCanContinue], 0 - cmp byte [ecx+8], 0 - jnz .nonresident - mov eax, [ecx+10h] ; length - mov esi, eax - mov edx, [ntfs_cur_offs] - shr eax, 9 - cmp eax, edx - jb .okret - shl edx, 9 - sub esi, edx - movzx eax, word [ecx+14h] - add edx, eax - add edx, ecx ; edx -> data - mov eax, [ntfs_cur_size] - cmp eax, (0xFFFFFFFF shr 9)+1 - jbe @f - mov eax, (0xFFFFFFFF shr 9)+1 -@@: - shl eax, 9 - cmp eax, esi - jbe @f - mov eax, esi -@@: -; eax = length, edx -> data - mov [ntfs_cur_read], eax - mov ecx, eax - mov eax, edx - mov ebx, [ntfs_cur_buf] - call memmove - and [ntfs_cur_size], 0 ; CF=0 - ret -.nonresident: -; Not all auxiliary records contain correct FileSize info - mov eax, dword [ntfs_attr_size] - mov edx, dword [ntfs_attr_size+4] - push eax - and eax, edx - cmp eax, -1 - pop eax - jnz @f - mov eax, [ecx+30h] ; FileSize - mov edx, [ecx+34h] - mov dword [ntfs_attr_size], eax - mov dword [ntfs_attr_size+4], edx -@@: - add eax, 0x1FF - adc edx, 0 - shrd eax, edx, 9 - sub eax, [ntfs_cur_offs] - ja @f -; return with nothing read - and [ntfs_cur_size], 0 -.okret: - clc - ret -@@: -; reduce read length - and [ntfs_cur_tail], 0 - cmp [ntfs_cur_size], eax - jb @f - mov [ntfs_cur_size], eax - mov eax, dword [ntfs_attr_size] - and eax, 0x1FF - mov [ntfs_cur_tail], eax -@@: - cmp [ntfs_cur_size], 0 - jz .okret - mov eax, [ntfs_cur_offs] - xor edx, edx - div [ntfs_data.sectors_per_cluster] - sub eax, [ecx+10h] ; first_vbo - jb .okret -; eax = cluster, edx = starting sector - sub esp, 10h - movzx esi, word [ecx+20h] ; mcb_info_ofs - add esi, ecx - xor ebp, ebp -.readloop: - call ntfs_decode_mcb_entry - jnc .break - add ebp, [esp+8] - sub eax, [esp] - jae .readloop - push ecx - push eax - add eax, [esp+8] - add eax, ebp - imul eax, [ntfs_data.sectors_per_cluster] - add eax, edx - add eax, [PARTITION_START] - pop ecx - neg ecx - imul ecx, [ntfs_data.sectors_per_cluster] - sub ecx, edx - cmp ecx, [ntfs_cur_size] - jb @f - mov ecx, [ntfs_cur_size] -@@: - mov ebx, [ntfs_cur_buf] -@@: - call hd_read - cmp [hd_error], 0 - jnz .errread2 - add ebx, 0x200 - mov [ntfs_cur_buf], ebx - inc eax - add [ntfs_cur_read], 0x200 - dec [ntfs_cur_size] - inc [ntfs_cur_offs] - loop @b - pop ecx - xor eax, eax - xor edx, edx - cmp [ntfs_cur_size], 0 - jnz .readloop - add esp, 10h - mov eax, [ntfs_cur_tail] - test eax, eax - jz @f - sub eax, 0x200 - add [ntfs_cur_read], eax -@@: - clc - ret -.errread2: - pop ecx - add esp, 10h - stc - ret -.break: - add esp, 10h ; CF=0 - mov [ntfs_bCanContinue], 1 - ret - -ntfs_read_file_record: -; in: eax=iRecord -; out: [ntfs_data.frs_buffer] contains information -; eax=0 - failed, eax=1 - success -; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size] - push ecx edx - mov ecx, [ntfs_data.frs_size] - mul ecx - shrd eax, edx, 9 - shr edx, 9 - jnz .err - push [ntfs_attr_iRecord] - push [ntfs_attr_iBaseRecord] - push [ntfs_attr_offs] - push [ntfs_attr_list] - push dword [ntfs_attr_size+4] - push dword [ntfs_attr_size] - push [ntfs_cur_iRecord] - push [ntfs_cur_attr] - push [ntfs_cur_offs] - push [ntfs_cur_size] - push [ntfs_cur_buf] - push [ntfs_cur_read] - mov [ntfs_cur_attr], 0x80 ; $DATA - and [ntfs_cur_iRecord], 0 ; $Mft - mov [ntfs_cur_offs], eax - shr ecx, 9 - mov [ntfs_cur_size], ecx - mov eax, [ntfs_data.frs_buffer] - mov [ntfs_cur_buf], eax - call ntfs_read_attr - mov eax, [ntfs_cur_read] - pop [ntfs_cur_read] - pop [ntfs_cur_buf] - pop [ntfs_cur_size] - pop [ntfs_cur_offs] - pop [ntfs_cur_attr] - pop [ntfs_cur_iRecord] - pop dword [ntfs_attr_size] - pop dword [ntfs_attr_size+4] - pop [ntfs_attr_list] - pop [ntfs_attr_offs] - pop [ntfs_attr_iBaseRecord] - pop [ntfs_attr_iRecord] - pop edx ecx - jc .errret - cmp eax, [ntfs_data.frs_size] - jnz .errret - mov eax, [ntfs_data.frs_buffer] - cmp dword [eax], 'FILE' - jnz .errret - push ebx - mov ebx, eax - call ntfs_restore_usa_frs - pop ebx - setnc al - movzx eax, al -.ret: - ret -.err: - pop edx ecx -.errret: - xor eax, eax - ret - -ntfs_restore_usa_frs: - mov eax, [ntfs_data.frs_size] -ntfs_restore_usa: - pushad - shr eax, 9 - mov ecx, eax - inc eax - cmp [ebx+6], ax - jnz .err - movzx eax, word [ebx+4] - lea esi, [eax+ebx] - lodsw - mov edx, eax - lea edi, [ebx+0x1FE] -@@: - cmp [edi], dx - jnz .err - lodsw - stosw - add edi, 0x1FE - loop @b - popad - clc - ret -.err: - popad - stc - ret - -ntfs_decode_mcb_entry: - push eax ecx edi - lea edi, [esp+16] - xor eax, eax - lodsb - test al, al - jz .end - mov ecx, eax - and ecx, 0xF - cmp ecx, 8 - ja .end - push ecx - rep movsb - pop ecx - sub ecx, 8 - neg ecx - cmp byte [esi-1], 80h - jae .end - push eax - xor eax, eax - rep stosb - pop ecx - shr ecx, 4 - cmp ecx, 8 - ja .end - push ecx - rep movsb - pop ecx - sub ecx, 8 - neg ecx - cmp byte [esi-1], 80h - cmc - sbb eax, eax - rep stosb - stc -.end: - pop edi ecx eax - ret - -unichar_toupper: - push eax - call uni2ansi_char - cmp al, '_' - jz .unk - add esp, 4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +ntfs_test_bootsec: +; in: ebx->buffer, edx=size of partition +; out: CF set <=> invalid +; 1. Name=='NTFS ' + cmp dword [ebx+3], 'NTFS' + jnz .no + cmp dword [ebx+7], ' ' + jnz .no +; 2. Number of bytes per sector is the same as for physical device +; (that is, 0x200 for hard disk) + cmp word [ebx+11], 0x200 + jnz .no +; 3. Number of sectors per cluster must be power of 2 + movzx eax, byte [ebx+13] + dec eax + js .no + test al, [ebx+13] + jnz .no +; 4. FAT parameters must be zero + cmp word [ebx+14], 0 + jnz .no + cmp dword [ebx+16], 0 + jnz .no + cmp byte [ebx+20], 0 + jnz .no + cmp word [ebx+22], 0 + jnz .no + cmp dword [ebx+32], 0 + jnz .no +; 5. Number of sectors <= partition size + cmp dword [ebx+0x2C], 0 + ja .no + cmp [ebx+0x28], edx + ja .no +; 6. $MFT and $MFTMirr clusters must be within partition + cmp dword [ebx+0x34], 0 + ja .no + push edx + movzx eax, byte [ebx+13] + mul dword [ebx+0x30] + test edx, edx + pop edx + jnz .no + cmp eax, edx + ja .no + cmp dword [ebx+0x3C], 0 + ja .no + push edx + movzx eax, byte [ebx+13] + mul dword [ebx+0x38] + test edx, edx + pop edx + jnz .no + cmp eax, edx + ja .no +; 7. Clusters per FRS must be either negative and in [-31,-9] or positive and power of 2 + movsx eax, byte [ebx+0x40] + cmp al, -31 + jl .no + cmp al, -9 + jle @f + dec eax + js .no + test [ebx+0x40], al + jnz .no +@@: +; 8. Same for clusters per IndexAllocationBuffer + movsx eax, byte [ebx+0x44] + cmp al, -31 + jl .no + cmp al, -9 + jle @f + dec eax + js .no + test [ebx+0x44], al + jnz .no +@@: +; OK, this is correct NTFS bootsector + clc + ret +.no: +; No, this bootsector isn't NTFS + stc + ret + +ntfs_setup: ; CODE XREF: part_set.inc +; By given bootsector, initialize some NTFS variables +; call ntfs_test_bootsec ; checking boot sector was already +; jc problem_fat_dec_count + movzx eax, byte [ebx+13] + mov [ntfs_data.sectors_per_cluster], eax + mov eax, [ebx+0x28] + add eax, [PARTITION_START] + dec eax + mov [PARTITION_END], eax + mov [fs_type], 1 + mov eax, [ebx+0x30] + mov [ntfs_data.mft_cluster], eax + mov eax, [ebx+0x38] + mov [ntfs_data.mftmirr_cluster], eax + movsx eax, byte [ebx+0x40] + test eax, eax + js .1 + mul [ntfs_data.sectors_per_cluster] + shl eax, 9 + jmp .2 +.1: + neg eax + mov ecx, eax + mov eax, 1 + shl eax, cl +.2: + mov [ntfs_data.frs_size], eax + movsx eax, byte [ebx+0x44] + test eax, eax + js .3 + mul [ntfs_data.sectors_per_cluster] + shl eax, 9 + jmp .4 +.3: + neg eax + mov ecx, eax + mov eax, 1 + shl eax, cl +.4: + mov [ntfs_data.iab_size], eax +; allocate space for buffers + add eax, [ntfs_data.frs_size] + push eax + call kernel_alloc + test eax, eax + jz problem_fat_dec_count + mov [ntfs_data.frs_buffer], eax + add eax, [ntfs_data.frs_size] + mov [ntfs_data.iab_buffer], eax +; read $MFT disposition + mov eax, [ntfs_data.mft_cluster] + mul [ntfs_data.sectors_per_cluster] + call ntfs_read_frs_sector + cmp [hd_error], 0 + jnz .usemirr + cmp dword [ebx], 'FILE' + jnz .usemirr + call ntfs_restore_usa_frs + jnc .mftok +.usemirr: + and [hd_error], 0 + mov eax, [ntfs_data.mftmirr_cluster] + mul [ntfs_data.sectors_per_cluster] + call ntfs_read_frs_sector + cmp [hd_error], 0 + jnz @f + cmp dword [ebx], 'FILE' + jnz @f + call ntfs_restore_usa_frs + jnc .mftok +@@: +; $MFT and $MFTMirr invalid! +.fail_free_frs: + push [ntfs_data.frs_buffer] + call kernel_free + jmp problem_fat_dec_count +.fail_free_mft: + push [ntfs_data.mft_retrieval] + call kernel_free + jmp .fail_free_frs +.mftok: +; read $MFT table retrieval information +; start with one page, increase if not enough (when MFT too fragmented) + push ebx + push 0x1000 + call kernel_alloc + pop ebx + test eax, eax + jz .fail_free_frs + mov [ntfs_data.mft_retrieval], eax + and [ntfs_data.mft_retrieval_size], 0 + mov [ntfs_data.mft_retrieval_alloc], 0x1000/8 +; $MFT base record must contain unnamed non-resident $DATA attribute + movzx eax, word [ebx+14h] + add eax, ebx +.scandata: + cmp dword [eax], -1 + jz .fail_free_mft + cmp dword [eax], 0x80 + jnz @f + cmp byte [eax+9], 0 + jz .founddata +@@: + add eax, [eax+4] + jmp .scandata +.founddata: + cmp byte [eax+8], 0 + jz .fail_free_mft +; load first portion of $DATA attribute retrieval information + mov edx, [eax+0x18] + mov [ntfs_data.mft_retrieval_end], edx + mov esi, eax + movzx eax, word [eax+0x20] + add esi, eax + sub esp, 10h +.scanmcb: + call ntfs_decode_mcb_entry + jnc .scanmcbend + call .get_mft_retrieval_ptr + mov edx, [esp] ; block length + mov [eax], edx + mov edx, [esp+8] ; block addr (relative) + mov [eax+4], edx + inc [ntfs_data.mft_retrieval_size] + jmp .scanmcb +.scanmcbend: + add esp, 10h +; there may be other portions of $DATA attribute in auxiliary records; +; if they will be needed, they will be loaded later + + mov [ntfs_data.cur_index_size], 0x1000/0x200 + push 0x1000 + call kernel_alloc + test eax, eax + jz .fail_free_mft + mov [ntfs_data.cur_index_buf], eax + + popad + call free_hd_channel + and [hd1_status], 0 + ret + +.get_mft_retrieval_ptr: + pushad + mov eax, [ntfs_data.mft_retrieval_size] + cmp eax, [ntfs_data.mft_retrieval_alloc] + jnz .ok + add eax, 0x1000/8 + mov [ntfs_data.mft_retrieval_alloc], eax + shl eax, 3 + push eax + call kernel_alloc + test eax, eax + jnz @f + popad + add esp, 14h + jmp .fail_free_mft +@@: + mov esi, [ntfs_data.mft_retrieval] + mov edi, eax + mov ecx, [ntfs_data.mft_retrieval_size] + add ecx, ecx + rep movsd + push [ntfs_data.mft_retrieval] + mov [ntfs_data.mft_retrieval], eax + call kernel_free + mov eax, [ntfs_data.mft_retrieval_size] +.ok: + shl eax, 3 + add eax, [ntfs_data.mft_retrieval] + mov [esp+28], eax + popad + ret + +ntfs_read_frs_sector: + push eax ecx + add eax, [PARTITION_START] + mov ecx, [ntfs_data.frs_size] + shr ecx, 9 + mov ebx, [ntfs_data.frs_buffer] + push ebx +@@: + call hd_read + cmp [hd_error], 0 + jnz .fail + add ebx, 0x200 + inc eax + loop @b +.fail: + pop ebx + pop ecx eax + ret + +uglobal +align 4 +ntfs_cur_attr dd ? +ntfs_cur_iRecord dd ? +ntfs_cur_offs dd ? ; in sectors +ntfs_cur_size dd ? ; in sectors +ntfs_cur_buf dd ? +ntfs_cur_read dd ? ; [output] +ntfs_bCanContinue db ? + rb 3 + +ntfs_attrlist_buf rb 0x400 +ntfs_attrlist_mft_buf rb 0x400 +ntfs_bitmap_buf rb 0x400 + +ntfs_attr_iRecord dd ? +ntfs_attr_iBaseRecord dd ? +ntfs_attr_offs dd ? +ntfs_attr_list dd ? +ntfs_attr_size dq ? +ntfs_cur_tail dd ? +endg + +ntfs_read_attr: +; in: global variables +; out: [ntfs_cur_read] + pushad + and [ntfs_cur_read], 0 + cmp [ntfs_cur_iRecord], 0 + jnz .nomft + cmp [ntfs_cur_attr], 0x80 + jnz .nomft + mov eax, [ntfs_data.mft_retrieval_end] + inc eax + mul [ntfs_data.sectors_per_cluster] + cmp eax, [ntfs_cur_offs] + jbe .nomft +; precalculated part of $Mft $DATA + mov esi, [ntfs_data.mft_retrieval] + mov eax, [ntfs_cur_offs] + xor edx, edx + div [ntfs_data.sectors_per_cluster] +; eax = VCN, edx = offset in sectors from beginning of cluster + xor ecx, ecx ; ecx will contain LCN +.mftscan: + add ecx, [esi+4] + sub eax, [esi] + jb @f + add esi, 8 + push eax + mov eax, [ntfs_data.mft_retrieval_end] + shl eax, 3 + add eax, [ntfs_data.mft_retrieval] + cmp eax, esi + pop eax + jnz .mftscan + jmp .nomft +@@: + push ecx + add ecx, eax + add ecx, [esi] + push eax + push edx + mov eax, [ntfs_data.sectors_per_cluster] + mul ecx +; eax = sector on partition + add eax, [PARTITION_START] + pop edx + add eax, edx + mov ebx, [ntfs_cur_buf] + pop ecx + neg ecx + imul ecx, [ntfs_data.sectors_per_cluster] + sub ecx, edx + cmp ecx, [ntfs_cur_size] + jb @f + mov ecx, [ntfs_cur_size] +@@: +; ecx = number of sequential sectors to read + call hd_read + cmp [hd_error], 0 + jnz .errread + add [ntfs_cur_read], 0x200 + dec [ntfs_cur_size] + inc [ntfs_cur_offs] + add ebx, 0x200 + mov [ntfs_cur_buf], ebx + inc eax + loop @b + pop ecx + xor eax, eax + xor edx, edx + cmp [ntfs_cur_size], eax + jz @f + add esi, 8 + push eax + mov eax, [ntfs_data.mft_retrieval_end] + shl eax, 3 + add eax, [ntfs_data.mft_retrieval] + cmp eax, esi + pop eax + jz .nomft + jmp .mftscan +@@: + popad + ret +.errread: + pop ecx +.errret: + stc + popad + ret +.nomft: +; 1. Read file record. +; N.B. This will do recursive call of read_attr for $MFT::$Data. + mov eax, [ntfs_cur_iRecord] + mov [ntfs_attr_iRecord], eax + and [ntfs_attr_list], 0 + or dword [ntfs_attr_size], -1 + or dword [ntfs_attr_size+4], -1 + or [ntfs_attr_iBaseRecord], -1 + call ntfs_read_file_record + test eax, eax + jz .errret +; 2. Find required attribute. + mov eax, [ntfs_data.frs_buffer] +; a) For auxiliary records, read base record +; N.B. If base record is present, +; base iRecord may be 0 (for $Mft), but SequenceNumber is nonzero + cmp dword [eax+24h], 0 + jz @f + mov eax, [eax+20h] +; test eax, eax +; jz @f +.beginfindattr: + mov [ntfs_attr_iRecord], eax + call ntfs_read_file_record + test eax, eax + jz .errret +@@: +; b) Scan for required attribute and for $ATTR_LIST + mov eax, [ntfs_data.frs_buffer] + movzx ecx, word [eax+14h] + add eax, ecx + mov ecx, [ntfs_cur_attr] + and [ntfs_attr_offs], 0 +.scanattr: + cmp dword [eax], -1 + jz .scandone + cmp dword [eax], ecx + jz .okattr + cmp [ntfs_attr_iBaseRecord], -1 + jnz .scancont + cmp dword [eax], 0x20 ; $ATTR_LIST + jnz .scancont + mov [ntfs_attr_list], eax + jmp .scancont +.okattr: +; ignore named $DATA attributes (aka NTFS streams) + cmp ecx, 0x80 + jnz @f + cmp byte [eax+9], 0 + jnz .scancont +@@: + mov [ntfs_attr_offs], eax +.scancont: + add eax, [eax+4] + jmp .scanattr +.continue: + pushad + and [ntfs_cur_read], 0 +.scandone: +; c) Check for required offset and length + mov ecx, [ntfs_attr_offs] + jecxz .noattr + push [ntfs_cur_size] + push [ntfs_cur_read] + call .doreadattr + pop edx + pop eax + jc @f + cmp [ntfs_bCanContinue], 0 + jz @f + sub edx, [ntfs_cur_read] + neg edx + shr edx, 9 + sub eax, edx + mov [ntfs_cur_size], eax + jnz .not_in_cur +@@: + popad + ret +.noattr: +.not_in_cur: + cmp [ntfs_cur_attr], 0x20 + jz @f + mov ecx, [ntfs_attr_list] + test ecx, ecx + jnz .lookattr +.ret_is_attr: + cmp [ntfs_attr_offs], 1 ; CF set <=> ntfs_attr_offs == 0 + popad + ret +.lookattr: +; required attribute or required offset was not found in base record; +; it may be present in auxiliary records; +; scan $ATTR_LIST + mov eax, [ntfs_attr_iBaseRecord] + cmp eax, -1 + jz @f + call ntfs_read_file_record + test eax, eax + jz .errret + or [ntfs_attr_iBaseRecord], -1 +@@: + push [ntfs_cur_offs] + push [ntfs_cur_size] + push [ntfs_cur_read] + push [ntfs_cur_buf] + push dword [ntfs_attr_size] + push dword [ntfs_attr_size+4] + or dword [ntfs_attr_size], -1 + or dword [ntfs_attr_size+4], -1 + and [ntfs_cur_offs], 0 + mov [ntfs_cur_size], 2 + and [ntfs_cur_read], 0 + mov eax, ntfs_attrlist_buf + cmp [ntfs_cur_iRecord], 0 + jnz @f + mov eax, ntfs_attrlist_mft_buf +@@: + mov [ntfs_cur_buf], eax + push eax + call .doreadattr + pop esi + mov edx, 1 + pop dword [ntfs_attr_size+4] + pop dword [ntfs_attr_size] + mov ebp, [ntfs_cur_read] + pop [ntfs_cur_buf] + pop [ntfs_cur_read] + pop [ntfs_cur_size] + pop [ntfs_cur_offs] + jc .errret + or edi, -1 + lea ebp, [ebp+esi-1Ah] +.scanliststart: + mov eax, [ntfs_cur_attr] +.scanlist: + cmp esi, ebp + jae .scanlistdone + cmp eax, [esi] + jz @f +.scanlistcont: + movzx ecx, word [esi+4] + add esi, ecx + jmp .scanlist +@@: +; ignore named $DATA attributes (aka NTFS streams) + cmp eax, 0x80 + jnz @f + cmp byte [esi+6], 0 + jnz .scanlistcont +@@: + push eax + mov eax, [esi+8] + test eax, eax + jnz .testf + mov eax, dword [ntfs_attr_size] + and eax, dword [ntfs_attr_size+4] + cmp eax, -1 + jnz .testfz +; if attribute is in auxiliary records, its size is defined only in first + mov eax, [esi+10h] + call ntfs_read_file_record + test eax, eax + jnz @f +.errret_pop: + pop eax + jmp .errret +@@: + mov eax, [ntfs_data.frs_buffer] + movzx ecx, word [eax+14h] + add eax, ecx + mov ecx, [ntfs_cur_attr] +@@: + cmp dword [eax], -1 + jz .errret_pop + cmp dword [eax], ecx + jz @f +.l1: + add eax, [eax+4] + jmp @b +@@: + cmp eax, 0x80 + jnz @f + cmp byte [eax+9], 0 + jnz .l1 +@@: + cmp byte [eax+8], 0 + jnz .sdnores + mov eax, [eax+10h] + mov dword [ntfs_attr_size], eax + and dword [ntfs_attr_size+4], 0 + jmp .testfz +.sdnores: + mov ecx, [eax+30h] + mov dword [ntfs_attr_size], ecx + mov ecx, [eax+34h] + mov dword [ntfs_attr_size+4], ecx +.testfz: + xor eax, eax +.testf: + imul eax, [ntfs_data.sectors_per_cluster] + cmp eax, [ntfs_cur_offs] + pop eax + ja @f + mov edi, [esi+10h] ; keep previous iRecord + jmp .scanlistcont +@@: +.scanlistfound: + cmp edi, -1 + jnz @f + popad + ret +@@: + mov eax, [ntfs_cur_iRecord] + mov [ntfs_attr_iBaseRecord], eax + mov eax, edi + jmp .beginfindattr +.sde: + popad + stc + ret +.scanlistdone: + sub ebp, ntfs_attrlist_buf-1Ah + cmp [ntfs_cur_iRecord], 0 + jnz @f + sub ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf +@@: + cmp ebp, 0x400 + jnz .scanlistfound + inc edx + push esi edi + mov esi, ntfs_attrlist_buf+0x200 + mov edi, ntfs_attrlist_buf + cmp [ntfs_cur_iRecord], 0 + jnz @f + mov esi, ntfs_attrlist_mft_buf+0x200 + mov edi, ntfs_attrlist_mft_buf +@@: + mov ecx, 0x200/4 + rep movsd + mov eax, edi + pop edi esi + sub esi, 0x200 + push [ntfs_cur_offs] + push [ntfs_cur_size] + push [ntfs_cur_read] + push [ntfs_cur_buf] + push dword [ntfs_attr_size] + push dword [ntfs_attr_size+4] + or dword [ntfs_attr_size], -1 + or dword [ntfs_attr_size+4], -1 + mov [ntfs_cur_offs], edx + mov [ntfs_cur_size], 1 + and [ntfs_cur_read], 0 + mov [ntfs_cur_buf], eax + mov ecx, [ntfs_attr_list] + push esi edx + call .doreadattr + pop edx esi + mov ebp, [ntfs_cur_read] + pop dword [ntfs_attr_size+4] + pop dword [ntfs_attr_size] + pop [ntfs_cur_buf] + pop [ntfs_cur_read] + pop [ntfs_cur_size] + pop [ntfs_cur_offs] + jc .errret + add ebp, ntfs_attrlist_buf+0x200-0x1A + cmp [ntfs_cur_iRecord], 0 + jnz .scanliststart + add ebp, ntfs_attrlist_mft_buf-ntfs_attrlist_buf + jmp .scanliststart + +.doreadattr: + mov [ntfs_bCanContinue], 0 + cmp byte [ecx+8], 0 + jnz .nonresident + mov eax, [ecx+10h] ; length + mov esi, eax + mov edx, [ntfs_cur_offs] + shr eax, 9 + cmp eax, edx + jb .okret + shl edx, 9 + sub esi, edx + movzx eax, word [ecx+14h] + add edx, eax + add edx, ecx ; edx -> data + mov eax, [ntfs_cur_size] + cmp eax, (0xFFFFFFFF shr 9)+1 + jbe @f + mov eax, (0xFFFFFFFF shr 9)+1 +@@: + shl eax, 9 + cmp eax, esi + jbe @f + mov eax, esi +@@: +; eax = length, edx -> data + mov [ntfs_cur_read], eax + mov ecx, eax + mov eax, edx + mov ebx, [ntfs_cur_buf] + call memmove + and [ntfs_cur_size], 0 ; CF=0 + ret +.nonresident: +; Not all auxiliary records contain correct FileSize info + mov eax, dword [ntfs_attr_size] + mov edx, dword [ntfs_attr_size+4] + push eax + and eax, edx + cmp eax, -1 + pop eax + jnz @f + mov eax, [ecx+30h] ; FileSize + mov edx, [ecx+34h] + mov dword [ntfs_attr_size], eax + mov dword [ntfs_attr_size+4], edx +@@: + add eax, 0x1FF + adc edx, 0 + shrd eax, edx, 9 + sub eax, [ntfs_cur_offs] + ja @f +; return with nothing read + and [ntfs_cur_size], 0 +.okret: + clc + ret +@@: +; reduce read length + and [ntfs_cur_tail], 0 + cmp [ntfs_cur_size], eax + jb @f + mov [ntfs_cur_size], eax + mov eax, dword [ntfs_attr_size] + and eax, 0x1FF + mov [ntfs_cur_tail], eax +@@: + cmp [ntfs_cur_size], 0 + jz .okret + mov eax, [ntfs_cur_offs] + xor edx, edx + div [ntfs_data.sectors_per_cluster] + sub eax, [ecx+10h] ; first_vbo + jb .okret +; eax = cluster, edx = starting sector + sub esp, 10h + movzx esi, word [ecx+20h] ; mcb_info_ofs + add esi, ecx + xor ebp, ebp +.readloop: + call ntfs_decode_mcb_entry + jnc .break + add ebp, [esp+8] + sub eax, [esp] + jae .readloop + push ecx + push eax + add eax, [esp+8] + add eax, ebp + imul eax, [ntfs_data.sectors_per_cluster] + add eax, edx + add eax, [PARTITION_START] + pop ecx + neg ecx + imul ecx, [ntfs_data.sectors_per_cluster] + sub ecx, edx + cmp ecx, [ntfs_cur_size] + jb @f + mov ecx, [ntfs_cur_size] +@@: + mov ebx, [ntfs_cur_buf] +@@: + call hd_read + cmp [hd_error], 0 + jnz .errread2 + add ebx, 0x200 + mov [ntfs_cur_buf], ebx + inc eax + add [ntfs_cur_read], 0x200 + dec [ntfs_cur_size] + inc [ntfs_cur_offs] + loop @b + pop ecx + xor eax, eax + xor edx, edx + cmp [ntfs_cur_size], 0 + jnz .readloop + add esp, 10h + mov eax, [ntfs_cur_tail] + test eax, eax + jz @f + sub eax, 0x200 + add [ntfs_cur_read], eax +@@: + clc + ret +.errread2: + pop ecx + add esp, 10h + stc + ret +.break: + add esp, 10h ; CF=0 + mov [ntfs_bCanContinue], 1 + ret + +ntfs_read_file_record: +; in: eax=iRecord +; out: [ntfs_data.frs_buffer] contains information +; eax=0 - failed, eax=1 - success +; Read attr $DATA of $Mft, starting from eax*[ntfs_data.frs_size] + push ecx edx + mov ecx, [ntfs_data.frs_size] + mul ecx + shrd eax, edx, 9 + shr edx, 9 + jnz .err + push [ntfs_attr_iRecord] + push [ntfs_attr_iBaseRecord] + push [ntfs_attr_offs] + push [ntfs_attr_list] + push dword [ntfs_attr_size+4] + push dword [ntfs_attr_size] + push [ntfs_cur_iRecord] + push [ntfs_cur_attr] + push [ntfs_cur_offs] + push [ntfs_cur_size] + push [ntfs_cur_buf] + push [ntfs_cur_read] + mov [ntfs_cur_attr], 0x80 ; $DATA + and [ntfs_cur_iRecord], 0 ; $Mft + mov [ntfs_cur_offs], eax + shr ecx, 9 + mov [ntfs_cur_size], ecx + mov eax, [ntfs_data.frs_buffer] + mov [ntfs_cur_buf], eax + call ntfs_read_attr + mov eax, [ntfs_cur_read] + pop [ntfs_cur_read] + pop [ntfs_cur_buf] + pop [ntfs_cur_size] + pop [ntfs_cur_offs] + pop [ntfs_cur_attr] + pop [ntfs_cur_iRecord] + pop dword [ntfs_attr_size] + pop dword [ntfs_attr_size+4] + pop [ntfs_attr_list] + pop [ntfs_attr_offs] + pop [ntfs_attr_iBaseRecord] + pop [ntfs_attr_iRecord] + pop edx ecx + jc .errret + cmp eax, [ntfs_data.frs_size] + jnz .errret + mov eax, [ntfs_data.frs_buffer] + cmp dword [eax], 'FILE' + jnz .errret + push ebx + mov ebx, eax + call ntfs_restore_usa_frs + pop ebx + setnc al + movzx eax, al +.ret: + ret +.err: + pop edx ecx +.errret: + xor eax, eax + ret + +ntfs_restore_usa_frs: + mov eax, [ntfs_data.frs_size] +ntfs_restore_usa: + pushad + shr eax, 9 + mov ecx, eax + inc eax + cmp [ebx+6], ax + jnz .err + movzx eax, word [ebx+4] + lea esi, [eax+ebx] + lodsw + mov edx, eax + lea edi, [ebx+0x1FE] +@@: + cmp [edi], dx + jnz .err + lodsw + stosw + add edi, 0x1FE + loop @b + popad + clc + ret +.err: + popad + stc + ret + +ntfs_decode_mcb_entry: + push eax ecx edi + lea edi, [esp+16] + xor eax, eax + lodsb + test al, al + jz .end + mov ecx, eax + and ecx, 0xF + cmp ecx, 8 + ja .end + push ecx + rep movsb + pop ecx + sub ecx, 8 + neg ecx + cmp byte [esi-1], 80h + jae .end + push eax + xor eax, eax + rep stosb + pop ecx + shr ecx, 4 + cmp ecx, 8 + ja .end + push ecx + rep movsb + pop ecx + sub ecx, 8 + neg ecx + cmp byte [esi-1], 80h + cmc + sbb eax, eax + rep stosb + stc +.end: + pop edi ecx eax + ret + +unichar_toupper: + push eax + call uni2ansi_char + cmp al, '_' + jz .unk + add esp, 4 call char_toupper jmp ansi2uni_char .unk: pop eax ret - -ntfs_find_lfn: -; in: esi+ebp -> name -; out: CF=1 - file not found -; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory - mov [ntfs_cur_iRecord], 5 ; start parse from root cluster -.doit2: - mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT - and [ntfs_cur_offs], 0 - mov eax, [ntfs_data.cur_index_size] - mov [ntfs_cur_size], eax - mov eax, [ntfs_data.cur_index_buf] - mov [ntfs_cur_buf], eax - call ntfs_read_attr - jnc @f -.ret: - ret -@@: - cmp [ntfs_cur_read], 0x20 - jc .ret - pushad - mov esi, [ntfs_data.cur_index_buf] - mov eax, [esi+14h] - add eax, 10h - cmp [ntfs_cur_read], eax - jae .readok1 - add eax, 1FFh - shr eax, 9 - cmp eax, [ntfs_data.cur_index_size] - ja @f -.stc_ret: - popad - stc - ret -@@: -; reallocate - push eax - push [ntfs_data.cur_index_buf] - call kernel_free - pop eax - mov [ntfs_data.cur_index_size], eax - push eax - call kernel_alloc - test eax, eax - jnz @f - and [ntfs_data.cur_index_size], 0 - and [ntfs_data.cur_index_buf], 0 - jmp .stc_ret -@@: - mov [ntfs_data.cur_index_buf], eax - popad - jmp .doit2 -.readok1: - mov ebp, [esi+8] ; subnode_size - shr ebp, 9 - cmp ebp, [ntfs_data.cur_index_size] - jbe .ok2 - push esi ebp - push ebp - call kernel_alloc - pop ebp esi - test eax, eax - jz .stc_ret - mov edi, eax - mov ecx, [ntfs_data.cur_index_size] - shl ecx, 9-2 - rep movsd - mov esi, eax - mov [ntfs_data.cur_index_size], ebp - push esi ebp - push [ntfs_data.cur_index_buf] - call kernel_free - pop ebp esi - mov [ntfs_data.cur_index_buf], esi -.ok2: - add esi, 10h - mov edi, [esp+4] -; edi -> name, esi -> current index data, ebp = subnode size -.scanloop: - add esi, [esi] -.scanloopint: - test byte [esi+0Ch], 2 - jnz .subnode - push esi - add esi, 0x52 - movzx ecx, byte [esi-2] - push edi -@@: - lodsw - call unichar_toupper - push eax - mov al, [edi] - inc edi - cmp al, '/' - jz .slash - call char_toupper - call ansi2uni_char - cmp ax, [esp] - pop eax - loopz @b - jz .found - pop edi - pop esi - jb .subnode -.scanloopcont: - movzx eax, word [esi+8] - add esi, eax - jmp .scanloopint -.slash: - pop eax - pop edi - pop esi -.subnode: - test byte [esi+0Ch], 1 - jz .notfound - movzx eax, word [esi+8] - mov eax, [esi+eax-8] - mul [ntfs_data.sectors_per_cluster] - mov [ntfs_cur_offs], eax - mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION - mov [ntfs_cur_size], ebp - mov eax, [ntfs_data.cur_index_buf] - mov esi, eax - mov [ntfs_cur_buf], eax - call ntfs_read_attr - mov eax, ebp - shl eax, 9 - cmp [ntfs_cur_read], eax - jnz .notfound - cmp dword [esi], 'INDX' - jnz .notfound - mov ebx, esi - call ntfs_restore_usa - jc .notfound - add esi, 0x18 - jmp .scanloop -.notfound: - popad - stc - ret -.found: - cmp byte [edi], 0 - jz .done - cmp byte [edi], '/' - jz .next - pop edi - pop esi - jmp .scanloopcont -.done: -.next: - pop esi - pop esi - mov eax, [esi] - mov [ntfs_cur_iRecord], eax - mov [esp+1Ch], esi - mov [esp+4], edi - popad - inc esi - cmp byte [esi-1], 0 - jnz .doit2 - test ebp, ebp - jz @f - mov esi, ebp - xor ebp, ebp - jmp .doit2 -@@: - ret - -;---------------------------------------------------------------- -; -; ntfs_HdRead - read NTFS hard disk -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to read, 0+ -; edx mem location to return data -; -; ret ebx = bytes read or 0xffffffff file not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -ntfs_HdRead: - cmp byte [esi], 0 - jnz @f - or ebx, -1 - push ERROR_ACCESS_DENIED - pop eax - ret -@@: - call ntfs_find_lfn - jnc .found - or ebx, -1 - push ERROR_FILE_NOT_FOUND - pop eax - ret -.found: - mov [ntfs_cur_attr], 0x80 ; $DATA - and [ntfs_cur_offs], 0 - and [ntfs_cur_size], 0 - call ntfs_read_attr - jnc @f - or ebx, -1 - push ERROR_ACCESS_DENIED - pop eax - ret -@@: - pushad - and dword [esp+10h], 0 - xor eax, eax - test ebx, ebx - jz .zero1 - cmp dword [ebx+4], 0x200 - jb @f -.eof0: - popad - xor ebx, ebx -.eof: - push ERROR_END_OF_FILE - pop eax - ret -@@: - mov eax, [ebx] - test eax, 0x1FF - jz .alignedstart - push edx - mov edx, [ebx+4] - shrd eax, edx, 9 - pop edx - mov [ntfs_cur_offs], eax - mov [ntfs_cur_size], 1 - mov [ntfs_cur_buf], ntfs_bitmap_buf - call ntfs_read_attr.continue - mov eax, [ebx] - and eax, 0x1FF - lea esi, [ntfs_bitmap_buf+eax] - sub eax, [ntfs_cur_read] - jae .eof0 - neg eax - push ecx - cmp ecx, eax - jb @f - mov ecx, eax -@@: - mov [esp+10h+4], ecx - mov edi, edx - rep movsb - mov edx, edi - pop ecx - sub ecx, [esp+10h] - jnz @f -.retok: - popad - xor eax, eax - ret -@@: - cmp [ntfs_cur_read], 0x200 - jz .alignedstart -.eof_ebx: - popad - jmp .eof -.alignedstart: - mov eax, [ebx] - push edx - mov edx, [ebx+4] - add eax, 511 - adc edx, 0 - shrd eax, edx, 9 - pop edx -.zero1: - mov [ntfs_cur_offs], eax - mov [ntfs_cur_buf], edx - mov eax, ecx - shr eax, 9 - mov [ntfs_cur_size], eax - add eax, [ntfs_cur_offs] - push eax - call ntfs_read_attr.continue - pop [ntfs_cur_offs] - mov eax, [ntfs_cur_read] - add [esp+10h], eax - mov eax, ecx - and eax, not 0x1FF - cmp [ntfs_cur_read], eax - jnz .eof_ebx - and ecx, 0x1FF - jz .retok - add edx, [ntfs_cur_read] - mov [ntfs_cur_size], 1 - mov [ntfs_cur_buf], ntfs_bitmap_buf - call ntfs_read_attr.continue - cmp [ntfs_cur_read], ecx - jb @f - mov [ntfs_cur_read], ecx -@@: - xchg ecx, [ntfs_cur_read] - push ecx - mov edi, edx - mov esi, ntfs_bitmap_buf - add [esp+10h+4], ecx - rep movsb - pop ecx - xor eax, eax - cmp ecx, [ntfs_cur_read] - jz @f - mov al, ERROR_END_OF_FILE -@@: - mov [esp+1Ch], eax - popad - ret - -;---------------------------------------------------------------- -; -; ntfs_HdReadFolder - read NTFS hard disk folder -; -; esi points to filename -; ebx pointer to structure 32-bit number = first wanted block, 0+ -; & flags (bitfields) -; flags: bit 0: 0=ANSI names, 1=UNICODE names -; ecx number of blocks to read, 0+ -; edx mem location to return data -; -; ret ebx = blocks read or 0xffffffff folder not found -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -ntfs_HdReadFolder: - mov eax, 5 ; root cluster - cmp byte [esi], 0 - jz .doit - call ntfs_find_lfn - jnc .doit2 -.notfound: - or ebx, -1 - push ERROR_FILE_NOT_FOUND -.pop_ret: - pop eax - ret -.doit: - mov [ntfs_cur_iRecord], eax -.doit2: - mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION - and [ntfs_cur_offs], 0 - mov [ntfs_cur_size], 1 - mov [ntfs_cur_buf], ntfs_bitmap_buf - call ntfs_read_attr - jc .notfound - mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT - and [ntfs_cur_offs], 0 - mov eax, [ntfs_data.cur_index_size] - mov [ntfs_cur_size], eax - mov eax, [ntfs_data.cur_index_buf] - mov [ntfs_cur_buf], eax - call ntfs_read_attr - jnc .ok - cmp [hd_error], 0 - jz .notfound - or ebx, -1 - push 11 - jmp .pop_ret -.ok: - cmp [ntfs_cur_read], 0x20 - jae @f - or ebx, -1 -.fserr: - push ERROR_FAT_TABLE - jmp .pop_ret -@@: - pushad - mov esi, [ntfs_data.cur_index_buf] - mov eax, [esi+14h] - add eax, 10h - cmp [ntfs_cur_read], eax - jae .readok1 - add eax, 1FFh - shr eax, 9 - cmp eax, [ntfs_data.cur_index_size] - ja @f - popad - jmp .fserr -@@: -; reallocate - push eax - push [ntfs_data.cur_index_buf] - call kernel_free - pop eax - mov [ntfs_data.cur_index_size], eax - push eax - call kernel_alloc - test eax, eax - jnz @f - and [ntfs_data.cur_index_size], 0 - and [ntfs_data.cur_index_buf], 0 -.nomem: - popad - or ebx, -1 - push 12 - pop eax - ret -@@: - mov [ntfs_data.cur_index_buf], eax - popad - jmp .doit2 -.readok1: - mov ebp, [esi+8] ; subnode_size - shr ebp, 9 - cmp ebp, [ntfs_data.cur_index_size] - jbe .ok2 - push esi ebp - push ebp - call kernel_alloc - pop ebp esi - test eax, eax - jz .nomem - mov edi, eax - mov ecx, [ntfs_data.cur_index_size] - shl ecx, 9-2 - rep movsd - mov esi, eax - mov [ntfs_data.cur_index_size], ebp - push esi ebp - push [ntfs_data.cur_index_buf] - call kernel_free - pop ebp esi - mov [ntfs_data.cur_index_buf], esi -.ok2: - add esi, 10h - mov ebx, [esp+10h] - mov edx, [esp+14h] - push dword [ebx+4] ; read ANSI/UNICODE name - mov ebx, [ebx] -; init header - mov edi, edx - mov ecx, 32/4 - xor eax, eax - rep stosd - mov byte [edx], 1 ; version - mov ecx, [esp+4+18h] - push edx - mov edx, esp -; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block, -; ecx = number of blocks to read -; edx -> parameters block: dd , dd - cmp [ntfs_cur_iRecord], 5 - jz .skip_specials -; dot and dotdot entries - push esi - xor esi, esi - call .add_special_entry - inc esi - call .add_special_entry - pop esi -.skip_specials: -; at first, dump index root - add esi, [esi] -.dump_root: - test byte [esi+0Ch], 2 - jnz .dump_root_done - call .add_entry - movzx eax, word [esi+8] - add esi, eax - jmp .dump_root -.dump_root_done: -; now dump all subnodes - push ecx edi - mov edi, ntfs_bitmap_buf - mov [ntfs_cur_buf], edi - mov ecx, 0x400/4 - xor eax, eax - rep stosd - mov [ntfs_cur_attr], 0xB0 ; $BITMAP - and [ntfs_cur_offs], 0 - mov [ntfs_cur_size], 2 - call ntfs_read_attr - pop edi ecx - push 0 ; save offset in $BITMAP attribute - and [ntfs_cur_offs], 0 -.dumploop: - mov [ntfs_cur_attr], 0xA0 - mov [ntfs_cur_size], ebp - mov eax, [ntfs_data.cur_index_buf] - mov esi, eax - mov [ntfs_cur_buf], eax - push [ntfs_cur_offs] - mov eax, [ntfs_cur_offs] - imul eax, ebp - mov [ntfs_cur_offs], eax - call ntfs_read_attr - pop [ntfs_cur_offs] - mov eax, ebp - shl eax, 9 - cmp [ntfs_cur_read], eax - jnz .done - push eax - mov eax, [ntfs_cur_offs] - and eax, 0x400*8-1 - bt dword [ntfs_bitmap_buf], eax - pop eax - jnc .dump_subnode_done - cmp dword [esi], 'INDX' - jnz .dump_subnode_done - push ebx - mov ebx, esi - call ntfs_restore_usa - pop ebx - jc .dump_subnode_done - add esi, 0x18 - add esi, [esi] -.dump_subnode: - test byte [esi+0Ch], 2 - jnz .dump_subnode_done - call .add_entry - movzx eax, word [esi+8] - add esi, eax - jmp .dump_subnode -.dump_subnode_done: - inc [ntfs_cur_offs] - test [ntfs_cur_offs], 0x400*8-1 - jnz .dumploop - mov [ntfs_cur_attr], 0xB0 - push ecx edi - mov edi, ntfs_bitmap_buf - mov [ntfs_cur_buf], edi - mov ecx, 0x400/4 - xor eax, eax - rep stosd - pop edi ecx - pop eax - push [ntfs_cur_offs] - inc eax - mov [ntfs_cur_offs], eax - mov [ntfs_cur_size], 2 - push eax - call ntfs_read_attr - pop eax - pop [ntfs_cur_offs] - push eax - jmp .dumploop -.done: - pop eax - pop edx - mov ebx, [edx+4] - pop edx - xor eax, eax - dec ecx - js @f - mov al, ERROR_END_OF_FILE -@@: - mov [esp+1Ch], eax - mov [esp+10h], ebx - popad - ret - -.add_special_entry: - mov eax, [edx] - inc dword [eax+8] ; new file found - dec ebx - jns .ret - dec ecx - js .ret - inc dword [eax+4] ; new file block copied - mov eax, [edx+4] - mov [edi+4], eax -; mov eax, dword [ntfs_bitmap_buf+0x20] -; or al, 0x10 - mov eax, 0x10 - stosd - scasd - push edx - mov eax, dword [ntfs_bitmap_buf] - mov edx, dword [ntfs_bitmap_buf+4] - call ntfs_datetime_to_bdfe - mov eax, dword [ntfs_bitmap_buf+0x18] - mov edx, dword [ntfs_bitmap_buf+0x1C] - call ntfs_datetime_to_bdfe - mov eax, dword [ntfs_bitmap_buf+8] - mov edx, dword [ntfs_bitmap_buf+0xC] - call ntfs_datetime_to_bdfe - pop edx - xor eax, eax - stosd - stosd - mov al, '.' - push edi ecx - lea ecx, [esi+1] - test byte [edi-0x24], 1 - jz @f - rep stosw - pop ecx - xor eax, eax - stosw - pop edi - add edi, 520 - ret -@@: - rep stosb - pop ecx - xor eax, eax - stosb - pop edi - add edi, 264 -.ret: - ret - -.add_entry: -; do not return DOS 8.3 names - cmp byte [esi+0x51], 2 - jz .ret -; do not return system files -; ... note that there will be no bad effects if system files also were reported ... - cmp dword [esi], 0x10 - jb .ret - mov eax, [edx] - inc dword [eax+8] ; new file found - dec ebx - jns .ret - dec ecx - js .ret - inc dword [eax+4] ; new file block copied - mov eax, [edx+4] ; flags - call ntfs_direntry_to_bdfe - push ecx esi edi - movzx ecx, byte [esi+0x50] - add esi, 0x52 - test byte [edi-0x24], 1 - jz .ansi - shr ecx, 1 - rep movsd - adc ecx, ecx - rep movsw - and word [edi], 0 - pop edi - add edi, 520 - pop esi ecx - ret -.ansi: - jecxz .skip -@@: - lodsw - call uni2ansi_char - stosb - loop @b -.skip: - xor al, al - stosb - pop edi - add edi, 264 - pop esi ecx - ret - -ntfs_direntry_to_bdfe: - mov [edi+4], eax ; ANSI/UNICODE name - mov eax, [esi+48h] - test eax, 0x10000000 - jz @f - and eax, not 0x10000000 - or al, 0x10 -@@: - stosd - scasd - push edx - mov eax, [esi+0x18] - mov edx, [esi+0x1C] - call ntfs_datetime_to_bdfe - mov eax, [esi+0x30] - mov edx, [esi+0x34] - call ntfs_datetime_to_bdfe - mov eax, [esi+0x20] - mov edx, [esi+0x24] - call ntfs_datetime_to_bdfe - pop edx - mov eax, [esi+0x40] - stosd - mov eax, [esi+0x44] - stosd - ret - -iglobal -_24 dd 24 -_60 dd 60 -_10000000 dd 10000000 -days400year dd 365*400+100-4+1 -days100year dd 365*100+25-1 -days4year dd 365*4+1 -days1year dd 365 -months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -_400 dd 400 -_100 dd 100 -endg - -ntfs_datetime_to_bdfe: -; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC - push eax - mov eax, edx - xor edx, edx - div [_10000000] - xchg eax, [esp] - div [_10000000] - pop edx - .sec: -; edx:eax = number of seconds since January 1, 1601 - push eax - mov eax, edx - xor edx, edx - div [_60] - xchg eax, [esp] - div [_60] - mov [edi], dl - pop edx -; edx:eax = number of minutes - div [_60] - mov [edi+1], dl -; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32) - xor edx, edx - div [_24] - mov [edi+2], dl - mov [edi+3], byte 0 -; eax = number of days since January 1, 1601 - xor edx, edx - div [days400year] - imul eax, 400 - add eax, 1601 - mov [edi+6], ax - mov eax, edx - xor edx, edx - div [days100year] - cmp al, 4 - jnz @f - dec eax - add edx, [days100year] -@@: - imul eax, 100 - add [edi+6], ax - mov eax, edx - xor edx, edx - div [days4year] - shl eax, 2 - add [edi+6], ax - mov eax, edx - xor edx, edx - div [days1year] - cmp al, 4 - jnz @f - dec eax - add edx, [days1year] -@@: - add [edi+6], ax - push esi edx - mov esi, months - movzx eax, word [edi+6] - test al, 3 - jnz .noleap - xor edx, edx - push eax - div [_400] - pop eax - test edx, edx - jz .leap - xor edx, edx - div [_100] - test edx, edx - jz .noleap -.leap: - mov esi, months2 -.noleap: - pop edx - xor eax, eax - inc eax -@@: - sub edx, [esi] - jb @f - add esi, 4 - inc eax - jmp @b -@@: - add edx, [esi] - pop esi - inc edx - mov [edi+4], dl - mov [edi+5], al - add edi, 8 - ret - -;---------------------------------------------------------------- -; -; ntfs_HdRewrite - write to NTFS hard disk -; -; esi points to filename -; ebx ignored (reserved) -; ecx number of bytes to write, 0+ -; edx mem location to data -; -; ret ebx = number of written bytes -; eax = 0 ok read or other = errormsg -; -;-------------------------------------------------------------- -ntfs_HdRewrite: - xor ebx, ebx - mov eax, ERROR_UNSUPPORTED_FS - ret - -;---------------------------------------------------------------- -; -; ntfs_HdWrite - write to NTFS hard disk -; -; esi points to filename -; ebx pointer to 64-bit number = first wanted byte, 0+ -; may be ebx=0 - start from first byte -; ecx number of bytes to write, 0+ -; edx mem location to data -; -; ret ebx = bytes written (maybe 0) -; eax = 0 ok write or other = errormsg -; -;-------------------------------------------------------------- -ntfs_HdWrite: - xor ebx, ebx - mov eax, ERROR_UNSUPPORTED_FS - ret - -;---------------------------------------------------------------- -; -; ntfs_HdSetFileEnd - set end of file on NTFS hard disk -; -; esi points to filename -; ebx points to 64-bit number = new file size -; ecx ignored (reserved) -; edx ignored (reserved) -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -ntfs_HdSetFileEnd: -ntfs_HdSetFileInfo: -;---------------------------------------------------------------- -; -; ntfs_HdDelete - delete file or empty folder from NTFS hard disk -; -; esi points to filename -; -; ret eax = 0 ok or other = errormsg -; -;-------------------------------------------------------------- -ntfs_HdDelete: - mov eax, ERROR_UNSUPPORTED_FS - ret - -ntfs_HdGetFileInfo: - cmp byte [esi], 0 - jnz @f - push 2 - pop eax - ret -@@: - call ntfs_find_lfn - jnc .doit - push ERROR_FILE_NOT_FOUND - pop eax - cmp [hd_error], 0 - jz @f - mov al, 11 -@@: - ret -.doit: - push esi edi - mov esi, eax - mov edi, edx - xor eax, eax - call ntfs_direntry_to_bdfe - pop edi esi - xor eax, eax + +ntfs_find_lfn: +; in: esi+ebp -> name +; out: CF=1 - file not found +; else CF=0, [ntfs_cur_iRecord] valid, eax->record in parent directory + mov [ntfs_cur_iRecord], 5 ; start parse from root cluster +.doit2: + mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT + and [ntfs_cur_offs], 0 + mov eax, [ntfs_data.cur_index_size] + mov [ntfs_cur_size], eax + mov eax, [ntfs_data.cur_index_buf] + mov [ntfs_cur_buf], eax + call ntfs_read_attr + jnc @f +.ret: + ret +@@: + cmp [ntfs_cur_read], 0x20 + jc .ret + pushad + mov esi, [ntfs_data.cur_index_buf] + mov eax, [esi+14h] + add eax, 10h + cmp [ntfs_cur_read], eax + jae .readok1 + add eax, 1FFh + shr eax, 9 + cmp eax, [ntfs_data.cur_index_size] + ja @f +.stc_ret: + popad + stc + ret +@@: +; reallocate + push eax + push [ntfs_data.cur_index_buf] + call kernel_free + pop eax + mov [ntfs_data.cur_index_size], eax + push eax + call kernel_alloc + test eax, eax + jnz @f + and [ntfs_data.cur_index_size], 0 + and [ntfs_data.cur_index_buf], 0 + jmp .stc_ret +@@: + mov [ntfs_data.cur_index_buf], eax + popad + jmp .doit2 +.readok1: + mov ebp, [esi+8] ; subnode_size + shr ebp, 9 + cmp ebp, [ntfs_data.cur_index_size] + jbe .ok2 + push esi ebp + push ebp + call kernel_alloc + pop ebp esi + test eax, eax + jz .stc_ret + mov edi, eax + mov ecx, [ntfs_data.cur_index_size] + shl ecx, 9-2 + rep movsd + mov esi, eax + mov [ntfs_data.cur_index_size], ebp + push esi ebp + push [ntfs_data.cur_index_buf] + call kernel_free + pop ebp esi + mov [ntfs_data.cur_index_buf], esi +.ok2: + add esi, 10h + mov edi, [esp+4] +; edi -> name, esi -> current index data, ebp = subnode size +.scanloop: + add esi, [esi] +.scanloopint: + test byte [esi+0Ch], 2 + jnz .subnode + push esi + add esi, 0x52 + movzx ecx, byte [esi-2] + push edi +@@: + lodsw + call unichar_toupper + push eax + mov al, [edi] + inc edi + cmp al, '/' + jz .slash + call char_toupper + call ansi2uni_char + cmp ax, [esp] + pop eax + loopz @b + jz .found + pop edi + pop esi + jb .subnode +.scanloopcont: + movzx eax, word [esi+8] + add esi, eax + jmp .scanloopint +.slash: + pop eax + pop edi + pop esi +.subnode: + test byte [esi+0Ch], 1 + jz .notfound + movzx eax, word [esi+8] + mov eax, [esi+eax-8] + mul [ntfs_data.sectors_per_cluster] + mov [ntfs_cur_offs], eax + mov [ntfs_cur_attr], 0xA0 ; $INDEX_ALLOCATION + mov [ntfs_cur_size], ebp + mov eax, [ntfs_data.cur_index_buf] + mov esi, eax + mov [ntfs_cur_buf], eax + call ntfs_read_attr + mov eax, ebp + shl eax, 9 + cmp [ntfs_cur_read], eax + jnz .notfound + cmp dword [esi], 'INDX' + jnz .notfound + mov ebx, esi + call ntfs_restore_usa + jc .notfound + add esi, 0x18 + jmp .scanloop +.notfound: + popad + stc + ret +.found: + cmp byte [edi], 0 + jz .done + cmp byte [edi], '/' + jz .next + pop edi + pop esi + jmp .scanloopcont +.done: +.next: + pop esi + pop esi + mov eax, [esi] + mov [ntfs_cur_iRecord], eax + mov [esp+1Ch], esi + mov [esp+4], edi + popad + inc esi + cmp byte [esi-1], 0 + jnz .doit2 + test ebp, ebp + jz @f + mov esi, ebp + xor ebp, ebp + jmp .doit2 +@@: + ret + +;---------------------------------------------------------------- +; +; ntfs_HdRead - read NTFS hard disk +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to read, 0+ +; edx mem location to return data +; +; ret ebx = bytes read or 0xffffffff file not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +ntfs_HdRead: + cmp byte [esi], 0 + jnz @f + or ebx, -1 + push ERROR_ACCESS_DENIED + pop eax + ret +@@: + call ntfs_find_lfn + jnc .found + or ebx, -1 + push ERROR_FILE_NOT_FOUND + pop eax + ret +.found: + mov [ntfs_cur_attr], 0x80 ; $DATA + and [ntfs_cur_offs], 0 + and [ntfs_cur_size], 0 + call ntfs_read_attr + jnc @f + or ebx, -1 + push ERROR_ACCESS_DENIED + pop eax + ret +@@: + pushad + and dword [esp+10h], 0 + xor eax, eax + test ebx, ebx + jz .zero1 + cmp dword [ebx+4], 0x200 + jb @f +.eof0: + popad + xor ebx, ebx +.eof: + push ERROR_END_OF_FILE + pop eax + ret +@@: + mov eax, [ebx] + test eax, 0x1FF + jz .alignedstart + push edx + mov edx, [ebx+4] + shrd eax, edx, 9 + pop edx + mov [ntfs_cur_offs], eax + mov [ntfs_cur_size], 1 + mov [ntfs_cur_buf], ntfs_bitmap_buf + call ntfs_read_attr.continue + mov eax, [ebx] + and eax, 0x1FF + lea esi, [ntfs_bitmap_buf+eax] + sub eax, [ntfs_cur_read] + jae .eof0 + neg eax + push ecx + cmp ecx, eax + jb @f + mov ecx, eax +@@: + mov [esp+10h+4], ecx + mov edi, edx + rep movsb + mov edx, edi + pop ecx + sub ecx, [esp+10h] + jnz @f +.retok: + popad + xor eax, eax + ret +@@: + cmp [ntfs_cur_read], 0x200 + jz .alignedstart +.eof_ebx: + popad + jmp .eof +.alignedstart: + mov eax, [ebx] + push edx + mov edx, [ebx+4] + add eax, 511 + adc edx, 0 + shrd eax, edx, 9 + pop edx +.zero1: + mov [ntfs_cur_offs], eax + mov [ntfs_cur_buf], edx + mov eax, ecx + shr eax, 9 + mov [ntfs_cur_size], eax + add eax, [ntfs_cur_offs] + push eax + call ntfs_read_attr.continue + pop [ntfs_cur_offs] + mov eax, [ntfs_cur_read] + add [esp+10h], eax + mov eax, ecx + and eax, not 0x1FF + cmp [ntfs_cur_read], eax + jnz .eof_ebx + and ecx, 0x1FF + jz .retok + add edx, [ntfs_cur_read] + mov [ntfs_cur_size], 1 + mov [ntfs_cur_buf], ntfs_bitmap_buf + call ntfs_read_attr.continue + cmp [ntfs_cur_read], ecx + jb @f + mov [ntfs_cur_read], ecx +@@: + xchg ecx, [ntfs_cur_read] + push ecx + mov edi, edx + mov esi, ntfs_bitmap_buf + add [esp+10h+4], ecx + rep movsb + pop ecx + xor eax, eax + cmp ecx, [ntfs_cur_read] + jz @f + mov al, ERROR_END_OF_FILE +@@: + mov [esp+1Ch], eax + popad + ret + +;---------------------------------------------------------------- +; +; ntfs_HdReadFolder - read NTFS hard disk folder +; +; esi points to filename +; ebx pointer to structure 32-bit number = first wanted block, 0+ +; & flags (bitfields) +; flags: bit 0: 0=ANSI names, 1=UNICODE names +; ecx number of blocks to read, 0+ +; edx mem location to return data +; +; ret ebx = blocks read or 0xffffffff folder not found +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +ntfs_HdReadFolder: + mov eax, 5 ; root cluster + cmp byte [esi], 0 + jz .doit + call ntfs_find_lfn + jnc .doit2 +.notfound: + or ebx, -1 + push ERROR_FILE_NOT_FOUND +.pop_ret: + pop eax + ret +.doit: + mov [ntfs_cur_iRecord], eax +.doit2: + mov [ntfs_cur_attr], 0x10 ; $STANDARD_INFORMATION + and [ntfs_cur_offs], 0 + mov [ntfs_cur_size], 1 + mov [ntfs_cur_buf], ntfs_bitmap_buf + call ntfs_read_attr + jc .notfound + mov [ntfs_cur_attr], 0x90 ; $INDEX_ROOT + and [ntfs_cur_offs], 0 + mov eax, [ntfs_data.cur_index_size] + mov [ntfs_cur_size], eax + mov eax, [ntfs_data.cur_index_buf] + mov [ntfs_cur_buf], eax + call ntfs_read_attr + jnc .ok + cmp [hd_error], 0 + jz .notfound + or ebx, -1 + push 11 + jmp .pop_ret +.ok: + cmp [ntfs_cur_read], 0x20 + jae @f + or ebx, -1 +.fserr: + push ERROR_FAT_TABLE + jmp .pop_ret +@@: + pushad + mov esi, [ntfs_data.cur_index_buf] + mov eax, [esi+14h] + add eax, 10h + cmp [ntfs_cur_read], eax + jae .readok1 + add eax, 1FFh + shr eax, 9 + cmp eax, [ntfs_data.cur_index_size] + ja @f + popad + jmp .fserr +@@: +; reallocate + push eax + push [ntfs_data.cur_index_buf] + call kernel_free + pop eax + mov [ntfs_data.cur_index_size], eax + push eax + call kernel_alloc + test eax, eax + jnz @f + and [ntfs_data.cur_index_size], 0 + and [ntfs_data.cur_index_buf], 0 +.nomem: + popad + or ebx, -1 + push 12 + pop eax + ret +@@: + mov [ntfs_data.cur_index_buf], eax + popad + jmp .doit2 +.readok1: + mov ebp, [esi+8] ; subnode_size + shr ebp, 9 + cmp ebp, [ntfs_data.cur_index_size] + jbe .ok2 + push esi ebp + push ebp + call kernel_alloc + pop ebp esi + test eax, eax + jz .nomem + mov edi, eax + mov ecx, [ntfs_data.cur_index_size] + shl ecx, 9-2 + rep movsd + mov esi, eax + mov [ntfs_data.cur_index_size], ebp + push esi ebp + push [ntfs_data.cur_index_buf] + call kernel_free + pop ebp esi + mov [ntfs_data.cur_index_buf], esi +.ok2: + add esi, 10h + mov ebx, [esp+10h] + mov edx, [esp+14h] + push dword [ebx+4] ; read ANSI/UNICODE name + mov ebx, [ebx] +; init header + mov edi, edx + mov ecx, 32/4 + xor eax, eax + rep stosd + mov byte [edx], 1 ; version + mov ecx, [esp+4+18h] + push edx + mov edx, esp +; edi -> BDFE, esi -> current index data, ebp = subnode size, ebx = first wanted block, +; ecx = number of blocks to read +; edx -> parameters block: dd , dd + cmp [ntfs_cur_iRecord], 5 + jz .skip_specials +; dot and dotdot entries + push esi + xor esi, esi + call .add_special_entry + inc esi + call .add_special_entry + pop esi +.skip_specials: +; at first, dump index root + add esi, [esi] +.dump_root: + test byte [esi+0Ch], 2 + jnz .dump_root_done + call .add_entry + movzx eax, word [esi+8] + add esi, eax + jmp .dump_root +.dump_root_done: +; now dump all subnodes + push ecx edi + mov edi, ntfs_bitmap_buf + mov [ntfs_cur_buf], edi + mov ecx, 0x400/4 + xor eax, eax + rep stosd + mov [ntfs_cur_attr], 0xB0 ; $BITMAP + and [ntfs_cur_offs], 0 + mov [ntfs_cur_size], 2 + call ntfs_read_attr + pop edi ecx + push 0 ; save offset in $BITMAP attribute + and [ntfs_cur_offs], 0 +.dumploop: + mov [ntfs_cur_attr], 0xA0 + mov [ntfs_cur_size], ebp + mov eax, [ntfs_data.cur_index_buf] + mov esi, eax + mov [ntfs_cur_buf], eax + push [ntfs_cur_offs] + mov eax, [ntfs_cur_offs] + imul eax, ebp + mov [ntfs_cur_offs], eax + call ntfs_read_attr + pop [ntfs_cur_offs] + mov eax, ebp + shl eax, 9 + cmp [ntfs_cur_read], eax + jnz .done + push eax + mov eax, [ntfs_cur_offs] + and eax, 0x400*8-1 + bt dword [ntfs_bitmap_buf], eax + pop eax + jnc .dump_subnode_done + cmp dword [esi], 'INDX' + jnz .dump_subnode_done + push ebx + mov ebx, esi + call ntfs_restore_usa + pop ebx + jc .dump_subnode_done + add esi, 0x18 + add esi, [esi] +.dump_subnode: + test byte [esi+0Ch], 2 + jnz .dump_subnode_done + call .add_entry + movzx eax, word [esi+8] + add esi, eax + jmp .dump_subnode +.dump_subnode_done: + inc [ntfs_cur_offs] + test [ntfs_cur_offs], 0x400*8-1 + jnz .dumploop + mov [ntfs_cur_attr], 0xB0 + push ecx edi + mov edi, ntfs_bitmap_buf + mov [ntfs_cur_buf], edi + mov ecx, 0x400/4 + xor eax, eax + rep stosd + pop edi ecx + pop eax + push [ntfs_cur_offs] + inc eax + mov [ntfs_cur_offs], eax + mov [ntfs_cur_size], 2 + push eax + call ntfs_read_attr + pop eax + pop [ntfs_cur_offs] + push eax + jmp .dumploop +.done: + pop eax + pop edx + mov ebx, [edx+4] + pop edx + xor eax, eax + dec ecx + js @f + mov al, ERROR_END_OF_FILE +@@: + mov [esp+1Ch], eax + mov [esp+10h], ebx + popad + ret + +.add_special_entry: + mov eax, [edx] + inc dword [eax+8] ; new file found + dec ebx + jns .ret + dec ecx + js .ret + inc dword [eax+4] ; new file block copied + mov eax, [edx+4] + mov [edi+4], eax +; mov eax, dword [ntfs_bitmap_buf+0x20] +; or al, 0x10 + mov eax, 0x10 + stosd + scasd + push edx + mov eax, dword [ntfs_bitmap_buf] + mov edx, dword [ntfs_bitmap_buf+4] + call ntfs_datetime_to_bdfe + mov eax, dword [ntfs_bitmap_buf+0x18] + mov edx, dword [ntfs_bitmap_buf+0x1C] + call ntfs_datetime_to_bdfe + mov eax, dword [ntfs_bitmap_buf+8] + mov edx, dword [ntfs_bitmap_buf+0xC] + call ntfs_datetime_to_bdfe + pop edx + xor eax, eax + stosd + stosd + mov al, '.' + push edi ecx + lea ecx, [esi+1] + test byte [edi-0x24], 1 + jz @f + rep stosw + pop ecx + xor eax, eax + stosw + pop edi + add edi, 520 + ret +@@: + rep stosb + pop ecx + xor eax, eax + stosb + pop edi + add edi, 264 +.ret: + ret + +.add_entry: +; do not return DOS 8.3 names + cmp byte [esi+0x51], 2 + jz .ret +; do not return system files +; ... note that there will be no bad effects if system files also were reported ... + cmp dword [esi], 0x10 + jb .ret + mov eax, [edx] + inc dword [eax+8] ; new file found + dec ebx + jns .ret + dec ecx + js .ret + inc dword [eax+4] ; new file block copied + mov eax, [edx+4] ; flags + call ntfs_direntry_to_bdfe + push ecx esi edi + movzx ecx, byte [esi+0x50] + add esi, 0x52 + test byte [edi-0x24], 1 + jz .ansi + shr ecx, 1 + rep movsd + adc ecx, ecx + rep movsw + and word [edi], 0 + pop edi + add edi, 520 + pop esi ecx + ret +.ansi: + jecxz .skip +@@: + lodsw + call uni2ansi_char + stosb + loop @b +.skip: + xor al, al + stosb + pop edi + add edi, 264 + pop esi ecx + ret + +ntfs_direntry_to_bdfe: + mov [edi+4], eax ; ANSI/UNICODE name + mov eax, [esi+48h] + test eax, 0x10000000 + jz @f + and eax, not 0x10000000 + or al, 0x10 +@@: + stosd + scasd + push edx + mov eax, [esi+0x18] + mov edx, [esi+0x1C] + call ntfs_datetime_to_bdfe + mov eax, [esi+0x30] + mov edx, [esi+0x34] + call ntfs_datetime_to_bdfe + mov eax, [esi+0x20] + mov edx, [esi+0x24] + call ntfs_datetime_to_bdfe + pop edx + mov eax, [esi+0x40] + stosd + mov eax, [esi+0x44] + stosd + ret + +iglobal +_24 dd 24 +_60 dd 60 +_10000000 dd 10000000 +days400year dd 365*400+100-4+1 +days100year dd 365*100+25-1 +days4year dd 365*4+1 +days1year dd 365 +months dd 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +months2 dd 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +_400 dd 400 +_100 dd 100 +endg + +ntfs_datetime_to_bdfe: +; edx:eax = number of 100-nanosecond intervals since January 1, 1601, in UTC + push eax + mov eax, edx + xor edx, edx + div [_10000000] + xchg eax, [esp] + div [_10000000] + pop edx + .sec: +; edx:eax = number of seconds since January 1, 1601 + push eax + mov eax, edx + xor edx, edx + div [_60] + xchg eax, [esp] + div [_60] + mov [edi], dl + pop edx +; edx:eax = number of minutes + div [_60] + mov [edi+1], dl +; eax = number of hours (note that 2^64/(10^7*60*60) < 2^32) + xor edx, edx + div [_24] + mov [edi+2], dl + mov [edi+3], byte 0 +; eax = number of days since January 1, 1601 + xor edx, edx + div [days400year] + imul eax, 400 + add eax, 1601 + mov [edi+6], ax + mov eax, edx + xor edx, edx + div [days100year] + cmp al, 4 + jnz @f + dec eax + add edx, [days100year] +@@: + imul eax, 100 + add [edi+6], ax + mov eax, edx + xor edx, edx + div [days4year] + shl eax, 2 + add [edi+6], ax + mov eax, edx + xor edx, edx + div [days1year] + cmp al, 4 + jnz @f + dec eax + add edx, [days1year] +@@: + add [edi+6], ax + push esi edx + mov esi, months + movzx eax, word [edi+6] + test al, 3 + jnz .noleap + xor edx, edx + push eax + div [_400] + pop eax + test edx, edx + jz .leap + xor edx, edx + div [_100] + test edx, edx + jz .noleap +.leap: + mov esi, months2 +.noleap: + pop edx + xor eax, eax + inc eax +@@: + sub edx, [esi] + jb @f + add esi, 4 + inc eax + jmp @b +@@: + add edx, [esi] + pop esi + inc edx + mov [edi+4], dl + mov [edi+5], al + add edi, 8 + ret + +;---------------------------------------------------------------- +; +; ntfs_HdRewrite - write to NTFS hard disk +; +; esi points to filename +; ebx ignored (reserved) +; ecx number of bytes to write, 0+ +; edx mem location to data +; +; ret ebx = number of written bytes +; eax = 0 ok read or other = errormsg +; +;-------------------------------------------------------------- +ntfs_HdRewrite: + xor ebx, ebx + mov eax, ERROR_UNSUPPORTED_FS + ret + +;---------------------------------------------------------------- +; +; ntfs_HdWrite - write to NTFS hard disk +; +; esi points to filename +; ebx pointer to 64-bit number = first wanted byte, 0+ +; may be ebx=0 - start from first byte +; ecx number of bytes to write, 0+ +; edx mem location to data +; +; ret ebx = bytes written (maybe 0) +; eax = 0 ok write or other = errormsg +; +;-------------------------------------------------------------- +ntfs_HdWrite: + xor ebx, ebx + mov eax, ERROR_UNSUPPORTED_FS + ret + +;---------------------------------------------------------------- +; +; ntfs_HdSetFileEnd - set end of file on NTFS hard disk +; +; esi points to filename +; ebx points to 64-bit number = new file size +; ecx ignored (reserved) +; edx ignored (reserved) +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +ntfs_HdSetFileEnd: +ntfs_HdSetFileInfo: +;---------------------------------------------------------------- +; +; ntfs_HdDelete - delete file or empty folder from NTFS hard disk +; +; esi points to filename +; +; ret eax = 0 ok or other = errormsg +; +;-------------------------------------------------------------- +ntfs_HdDelete: + mov eax, ERROR_UNSUPPORTED_FS + ret + +ntfs_HdGetFileInfo: + cmp byte [esi], 0 + jnz @f + push 2 + pop eax + ret +@@: + call ntfs_find_lfn + jnc .doit + push ERROR_FILE_NOT_FOUND + pop eax + cmp [hd_error], 0 + jz @f + mov al, 11 +@@: + ret +.doit: + push esi edi + mov esi, eax + mov edi, edx + xor eax, eax + call ntfs_direntry_to_bdfe + pop edi esi + xor eax, eax ret diff --git a/kernel/trunk/fs/parse_fn.inc b/kernel/trunk/fs/parse_fn.inc index a1061ca93..e48850644 100644 --- a/kernel/trunk/fs/parse_fn.inc +++ b/kernel/trunk/fs/parse_fn.inc @@ -1,236 +1,236 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;------------------------------------------------------------------------- -; -; File path partial substitution (according to configuration) -; -; -; SPraid -; -;------------------------------------------------------------------------- - -$Revision$ - - -iglobal -; pointer to memory for path replace table, -; size of one record is 128 bytes: 64 bytes for search pattern + 64 bytes for replace string - -; start with one entry: sys -> -full_file_name_table dd sysdir_name -.size dd 1 - -tmp_file_name_size dd 1 -endg - -uglobal -; Parser_params will initialize: sysdir_name = "sys", sysdir_path = -sysdir_name rb 64 -sysdir_path rb 64 -tmp_file_name_table dd ? -endg - -; use bx_from_load and init system directory /sys -proc Parser_params -locals - buff db 4 dup(?) ; for test cd -endl - mov eax,[OS_BASE+0x10000+bx_from_load] - mov ecx,sysdir_path - mov [ecx-64],dword 'sys' - cmp al,'r' ; if ram disk - jnz @f - mov [ecx],dword 'RD/?' - mov [ecx+3],byte ah - mov [ecx+4],byte 0 - ret -@@: - cmp al,'m' ; if ram disk - jnz @f - mov [ecx],dword 'CD?/' ; if cd disk {m} - mov [ecx+4],byte '1' - mov [ecx+5],dword '/KOL' - mov [ecx+9],dword 'IBRI' - mov [ecx+13],byte 0 -.next_cd: - mov [ecx+2],byte ah - inc ah - cmp ah,'5' - je .not_found_cd - lea edx,[buff] - pushad - stdcall read_file,read_firstapp,edx,0,4 - popad - cmp [edx],dword 'MENU' - jne .next_cd - jmp .ok - -@@: - sub al,49 - mov [ecx],dword 'HD?/' ; if hard disk - mov [ecx+2],byte al - mov [ecx+4],byte ah - mov [ecx+5],dword '/KOL' - mov [ecx+9],dword 'IBRI' - mov [ecx+13],byte 0 -.ok: -.not_found_cd: - ret -endp - -proc load_file_parse_table - stdcall kernel_alloc,0x1000 - mov [tmp_file_name_table],eax - mov edi,eax - mov esi,sysdir_name - mov ecx,128/4 - rep movsd - - invoke ini.enum_keys,conf_fname,conf_path_sect,get_every_key - - mov eax,[tmp_file_name_table] - mov [full_file_name_table],eax - mov eax,[tmp_file_name_size] - mov [full_file_name_table.size],eax - ret -endp - -uglobal -def_val_1 db 0 -endg - -proc get_every_key stdcall, f_name, sec_name, key_name - mov esi, [key_name] - mov ecx, esi - cmp byte [esi], '/' - jnz @f - inc esi -@@: - mov edi, [tmp_file_name_size] - shl edi, 7 - cmp edi, 0x1000 - jae .stop_parse - add edi, [tmp_file_name_table] - lea ebx, [edi+64] -@@: - cmp edi, ebx - jae .skip_this_key - lodsb - test al, al - jz @f - or al, 20h - stosb - jmp @b -@@: - stosb - - invoke ini.get_str, [f_name],[sec_name],ecx,ebx,64,def_val_1 - - cmp byte [ebx], '/' - jnz @f - lea esi, [ebx+1] - mov edi, ebx - mov ecx, 63 - rep movsb -@@: - push ebp - mov ebp, [tmp_file_name_table] - mov ecx, [tmp_file_name_size] - jecxz .noreplace - mov eax, ecx - dec eax - shl eax, 7 - add ebp, eax -.replace_loop: - mov edi, ebx - mov esi, ebp -@@: - lodsb - test al, al - jz .doreplace - mov dl, [edi] - inc edi - test dl, dl - jz .replace_loop_cont - or dl, 20h - cmp al, dl - jz @b - jmp .replace_loop_cont -.doreplace: - cmp byte [edi], 0 - jz @f - cmp byte [edi], '/' - jnz .replace_loop_cont -@@: - lea esi, [ebp+64] - call .replace - jc .skip_this_key2 -.replace_loop_cont: - sub ebp, 128 - loop .replace_loop -.noreplace: - pop ebp - - inc [tmp_file_name_size] -.skip_this_key: - xor eax, eax - inc eax - ret -.skip_this_key2: - pop ebp - jmp .skip_this_key -.stop_parse: - xor eax, eax - ret -endp - -proc get_every_key.replace -; in: ebx->destination, esi->first part of name, edi->second part of name -; maximum length is 64 bytes -; out: CF=1 <=> overflow -; 1) allocate temporary buffer in stack - sub esp, 64 -; 2) save second part of name to temporary buffer - push esi - lea esi, [esp+4] ; esi->tmp buffer - xchg esi, edi ; edi->tmp buffer, esi->source -@@: - lodsb - stosb - test al, al - jnz @b -; 3) copy first part of name to destination - pop esi - mov edi, ebx -@@: - lodsb - test al, al - jz @f - stosb - jmp @b -@@: -; 4) restore second part of name from temporary buffer to destination -; (may cause overflow) - lea edx, [ebx+64] ; limit of destination - mov esi, esp -@@: - cmp edi, edx - jae .overflow - lodsb - stosb - test al, al - jnz @b -; all is OK - add esp, 64 ; CF is cleared - ret -.overflow: -; name is too long - add esp, 64 - stc - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;------------------------------------------------------------------------- +; +; File path partial substitution (according to configuration) +; +; +; SPraid +; +;------------------------------------------------------------------------- + +$Revision$ + + +iglobal +; pointer to memory for path replace table, +; size of one record is 128 bytes: 64 bytes for search pattern + 64 bytes for replace string + +; start with one entry: sys -> +full_file_name_table dd sysdir_name +.size dd 1 + +tmp_file_name_size dd 1 +endg + +uglobal +; Parser_params will initialize: sysdir_name = "sys", sysdir_path = +sysdir_name rb 64 +sysdir_path rb 64 +tmp_file_name_table dd ? +endg + +; use bx_from_load and init system directory /sys +proc Parser_params +locals + buff db 4 dup(?) ; for test cd +endl + mov eax, [OS_BASE+0x10000+bx_from_load] + mov ecx, sysdir_path + mov [ecx-64], dword 'sys' + cmp al, 'r'; if ram disk + jnz @f + mov [ecx], dword 'RD/?' + mov [ecx+3], byte ah + mov [ecx+4], byte 0 + ret +@@: + cmp al, 'm'; if ram disk + jnz @f + mov [ecx], dword 'CD?/'; if cd disk {m} + mov [ecx+4], byte '1' + mov [ecx+5], dword '/KOL' + mov [ecx+9], dword 'IBRI' + mov [ecx+13], byte 0 +.next_cd: + mov [ecx+2], byte ah + inc ah + cmp ah, '5' + je .not_found_cd + lea edx, [buff] + pushad + stdcall read_file, read_firstapp, edx, 0, 4 + popad + cmp [edx], dword 'MENU' + jne .next_cd + jmp .ok + +@@: + sub al, 49 + mov [ecx], dword 'HD?/'; if hard disk + mov [ecx+2], byte al + mov [ecx+4], byte ah + mov [ecx+5], dword '/KOL' + mov [ecx+9], dword 'IBRI' + mov [ecx+13], byte 0 +.ok: +.not_found_cd: + ret +endp + +proc load_file_parse_table + stdcall kernel_alloc, 0x1000 + mov [tmp_file_name_table], eax + mov edi, eax + mov esi, sysdir_name + mov ecx, 128/4 + rep movsd + + invoke ini.enum_keys, conf_fname, conf_path_sect, get_every_key + + mov eax, [tmp_file_name_table] + mov [full_file_name_table], eax + mov eax, [tmp_file_name_size] + mov [full_file_name_table.size], eax + ret +endp + +uglobal +def_val_1 db 0 +endg + +proc get_every_key stdcall, f_name, sec_name, key_name + mov esi, [key_name] + mov ecx, esi + cmp byte [esi], '/' + jnz @f + inc esi +@@: + mov edi, [tmp_file_name_size] + shl edi, 7 + cmp edi, 0x1000 + jae .stop_parse + add edi, [tmp_file_name_table] + lea ebx, [edi+64] +@@: + cmp edi, ebx + jae .skip_this_key + lodsb + test al, al + jz @f + or al, 20h + stosb + jmp @b +@@: + stosb + + invoke ini.get_str, [f_name], [sec_name], ecx, ebx, 64, def_val_1 + + cmp byte [ebx], '/' + jnz @f + lea esi, [ebx+1] + mov edi, ebx + mov ecx, 63 + rep movsb +@@: + push ebp + mov ebp, [tmp_file_name_table] + mov ecx, [tmp_file_name_size] + jecxz .noreplace + mov eax, ecx + dec eax + shl eax, 7 + add ebp, eax +.replace_loop: + mov edi, ebx + mov esi, ebp +@@: + lodsb + test al, al + jz .doreplace + mov dl, [edi] + inc edi + test dl, dl + jz .replace_loop_cont + or dl, 20h + cmp al, dl + jz @b + jmp .replace_loop_cont +.doreplace: + cmp byte [edi], 0 + jz @f + cmp byte [edi], '/' + jnz .replace_loop_cont +@@: + lea esi, [ebp+64] + call .replace + jc .skip_this_key2 +.replace_loop_cont: + sub ebp, 128 + loop .replace_loop +.noreplace: + pop ebp + + inc [tmp_file_name_size] +.skip_this_key: + xor eax, eax + inc eax + ret +.skip_this_key2: + pop ebp + jmp .skip_this_key +.stop_parse: + xor eax, eax + ret +endp + +proc get_every_key.replace +; in: ebx->destination, esi->first part of name, edi->second part of name +; maximum length is 64 bytes +; out: CF=1 <=> overflow +; 1) allocate temporary buffer in stack + sub esp, 64 +; 2) save second part of name to temporary buffer + push esi + lea esi, [esp+4] ; esi->tmp buffer + xchg esi, edi ; edi->tmp buffer, esi->source +@@: + lodsb + stosb + test al, al + jnz @b +; 3) copy first part of name to destination + pop esi + mov edi, ebx +@@: + lodsb + test al, al + jz @f + stosb + jmp @b +@@: +; 4) restore second part of name from temporary buffer to destination +; (may cause overflow) + lea edx, [ebx+64] ; limit of destination + mov esi, esp +@@: + cmp edi, edx + jae .overflow + lodsb + stosb + test al, al + jnz @b +; all is OK + add esp, 64 ; CF is cleared + ret +.overflow: +; name is too long + add esp, 64 + stc + ret +endp diff --git a/kernel/trunk/fs/part_set.inc b/kernel/trunk/fs/part_set.inc index 806be0fab..83b140691 100644 --- a/kernel/trunk/fs/part_set.inc +++ b/kernel/trunk/fs/part_set.inc @@ -1,531 +1,534 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + ;************************************************************* -;* 13.02.2010 Find all partition and check supported FS -;* 12.07.2007 Check all 4 entry of MBR and EMBR -;* 29.04.2006 Elimination of hangup after the -;* expiration hd_wait_timeout - Mario79 -;* 28.01.2006 find all Fat16/32 partition in all input point -;* to MBR - Mario79 -;************************************************************* - -uglobal -align 4 - -;****************************************************** -; Please do not change this place - variables in text -; Mario79 -; START place -;****************************************************** -PARTITION_START dd 0x3f -PARTITION_END dd 0 -fs_type db 0 ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32 -align 4 - -fs_dependent_data_start: -; FATxx data - -SECTORS_PER_FAT dd 0x1f3a -NUMBER_OF_FATS dd 0x2 -SECTORS_PER_CLUSTER dd 0x8 -BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes -ROOT_CLUSTER dd 2 ; first rootdir cluster -FAT_START dd 0 ; start of fat table -ROOT_START dd 0 ; start of rootdir (only fat16) -ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16) -DATA_START dd 0 ; start of data area (=first cluster 2) -LAST_CLUSTER dd 0 ; last availabe cluster -ADR_FSINFO dd 0 ; used only by fat32 - -fatRESERVED dd 0x0FFFFFF6 -fatBAD dd 0x0FFFFFF7 -fatEND dd 0x0FFFFFF8 -fatMASK dd 0x0FFFFFFF - -fatStartScan dd 2 - -fs_dependent_data_end: -file_system_data_size = $ - PARTITION_START -if file_system_data_size > 96 -ERROR: sizeof(file system data) too big! -end if - -virtual at fs_dependent_data_start -; NTFS data -ntfs_data: -.sectors_per_cluster dd ? -.mft_cluster dd ? -.mftmirr_cluster dd ? -.frs_size dd ? ; FRS size in bytes -.iab_size dd ? ; IndexAllocationBuffer size in bytes -.frs_buffer dd ? -.iab_buffer dd ? -.mft_retrieval dd ? -.mft_retrieval_size dd ? -.mft_retrieval_alloc dd ? -.mft_retrieval_end dd ? -.cur_index_size dd ? -.cur_index_buf dd ? -if $ > fs_dependent_data_end -ERROR: increase sizeof(fs_dependent_data)! -end if -end virtual - -virtual at fs_dependent_data_start -; EXT2 data -ext2_data: - .log_block_size dd ? - .block_size dd ? - .count_block_in_block dd ? - .blocks_per_group dd ? - .inodes_per_group dd ? - .global_desc_table dd ? - .root_inode dd ? ; pointer to root inode in memory - .inode_size dd ? - .count_pointer_in_block dd ? ; block_size / 4 - .count_pointer_in_block_square dd ? ; (block_size / 4)**2 - .ext2_save_block dd ? ; Ў«®Є ­  Ј«®Ў «м­го 1 Їа®жҐ¤гаг - .ext2_temp_block dd ? ; Ў«®Є ¤«п ¬Ґ«ЄЁе Їа®жҐ¤га - .ext2_save_inode dd ? ; inode ­  Ј«®Ў «м­го Їа®жҐ¤гаг +;* 13.02.2010 Find all partition and check supported FS +;* 12.07.2007 Check all 4 entry of MBR and EMBR +;* 29.04.2006 Elimination of hangup after the +;* expiration hd_wait_timeout - Mario79 +;* 28.01.2006 find all Fat16/32 partition in all input point +;* to MBR - Mario79 +;************************************************************* + +uglobal +align 4 + +;****************************************************** +; Please do not change this place - variables in text +; Mario79 +; START place +;****************************************************** +PARTITION_START dd 0x3f +PARTITION_END dd 0 +fs_type db 0 ; 1=NTFS, 2=EXT2/3, 16=FAT16, 32=FAT32 +align 4 + +fs_dependent_data_start: +; FATxx data + +SECTORS_PER_FAT dd 0x1f3a +NUMBER_OF_FATS dd 0x2 +SECTORS_PER_CLUSTER dd 0x8 +BYTES_PER_SECTOR dd 0x200 ; Note: if BPS <> 512 need lots of changes +ROOT_CLUSTER dd 2 ; first rootdir cluster +FAT_START dd 0 ; start of fat table +ROOT_START dd 0 ; start of rootdir (only fat16) +ROOT_SECTORS dd 0 ; count of rootdir sectors (only fat16) +DATA_START dd 0 ; start of data area (=first cluster 2) +LAST_CLUSTER dd 0 ; last availabe cluster +ADR_FSINFO dd 0 ; used only by fat32 + +fatRESERVED dd 0x0FFFFFF6 +fatBAD dd 0x0FFFFFF7 +fatEND dd 0x0FFFFFF8 +fatMASK dd 0x0FFFFFFF + +fatStartScan dd 2 + +fs_dependent_data_end: +file_system_data_size = $ - PARTITION_START +if file_system_data_size > 96 +ERROR: + sizeof(file system data) too big! +end if + +virtual at fs_dependent_data_start +; NTFS data +ntfs_data: +.sectors_per_cluster dd ? +.mft_cluster dd ? +.mftmirr_cluster dd ? +.frs_size dd ? ; FRS size in bytes +.iab_size dd ? ; IndexAllocationBuffer size in bytes +.frs_buffer dd ? +.iab_buffer dd ? +.mft_retrieval dd ? +.mft_retrieval_size dd ? +.mft_retrieval_alloc dd ? +.mft_retrieval_end dd ? +.cur_index_size dd ? +.cur_index_buf dd ? +if $ > fs_dependent_data_end +ERROR: + increase sizeof(fs_dependent_data)! +end if +end virtual + +virtual at fs_dependent_data_start +; EXT2 data +ext2_data: + .log_block_size dd ? + .block_size dd ? + .count_block_in_block dd ? + .blocks_per_group dd ? + .inodes_per_group dd ? + .global_desc_table dd ? + .root_inode dd ? ; pointer to root inode in memory + .inode_size dd ? + .count_pointer_in_block dd ? ; block_size / 4 + .count_pointer_in_block_square dd ? ; (block_size / 4)**2 + .ext2_save_block dd ? ; Ў«®Є ­  Ј«®Ў «м­го 1 Їа®жҐ¤гаг + .ext2_temp_block dd ? ; Ў«®Є ¤«п ¬Ґ«ЄЁе Їа®жҐ¤га + .ext2_save_inode dd ? ; inode ­  Ј«®Ў «м­го Їа®жҐ¤гаг .ext2_temp_inode dd ? ; inode ¤«п ¬Ґ«ЄЁе Їа®жҐ¤га .sb dd ? ; superblock - .groups_count dd ? -if $ > fs_dependent_data_end -ERROR: increase sizeof(fs_dependent_data)! -end if -end virtual - -;*************************************************************************** -; End place -; Mario79 -;*************************************************************************** -endg -iglobal - - partition_types: ; list of fat16/32 partitions - db 0x04 ; DOS: fat16 <32M - db 0x06 ; DOS: fat16 >32M - db 0x0b ; WIN95: fat32 - db 0x0c ; WIN95: fat32, LBA-mapped - db 0x0e ; WIN95: fat16, LBA-mapped - db 0x14 ; Hidden DOS: fat16 <32M - db 0x16 ; Hidden DOS: fat16 >32M - db 0x1b ; Hidden WIN95: fat32 - db 0x1c ; Hidden WIN95: fat32, LBA-mapped - db 0x1e ; Hidden WIN95: fat16, LBA-mapped - db 0xc4 ; DRDOS/secured: fat16 <32M - db 0xc6 ; DRDOS/secured: fat16 >32M - db 0xcb ; DRDOS/secured: fat32 - db 0xcc ; DRDOS/secured: fat32, LBA-mapped - db 0xce ; DRDOS/secured: fat16, LBA-mapped - db 0xd4 ; Old Multiuser DOS secured: fat16 <32M - db 0xd6 ; Old Multiuser DOS secured: fat16 >32M - db 0x07 ; NTFS - db 0x27 ; NTFS, hidden - db 0x83 ; Linux native file system (ext2fs) - partition_types_end: - - - extended_types: ; list of extended partitions - db 0x05 ; DOS: extended partition - db 0x0f ; WIN95: extended partition, LBA-mapped - db 0xc5 ; DRDOS/secured: extended partition - db 0xd5 ; Old Multiuser DOS secured: extended partition - extended_types_end: - -endg - -; Partition chain used: -; MBR <--------------------- -; | | -; |-> PARTITION1 | -; |-> EXTENDED PARTITION - ;not need be second partition -; |-> PARTITION3 -; |-> PARTITION4 - -set_PARTITION_variables: -set_FAT32_variables: ;deprecated - and [problem_partition], 0 - call reserve_hd1 - call reserve_hd_channel - - pushad - - cmp dword [hdpos],0 - je problem_hd - - xor ecx,ecx ; partition count - ;or edx,-1 ; flag for partition - xor eax,eax ; address MBR - xor ebp,ebp ; extended partition start - -new_mbr: - test ebp,ebp ; is there extended partition? (MBR or EMBR) - jnz extended_already_set ; yes - xchg ebp,eax ; no. set it now - -extended_already_set: - add eax,ebp ; mbr=mbr+0, ext_part=ext_start+relat_start - mov ebx,buffer - call hd_read - cmp [hd_error],0 - jne problem_hd - - cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? - jnz end_partition_chain - push eax ; push only one time - cmp dword [ebx+0x1be+0xc],0 ; skip over empty partition - jnz test_primary_partition_0 - cmp dword [ebx+0x1be+0xc+16],0 - jnz test_primary_partition_1 - cmp dword [ebx+0x1be+0xc+16+16],0 - jnz test_primary_partition_2 - cmp dword [ebx+0x1be+0xc+16+16+16],0 - jnz test_primary_partition_3 - pop eax - jmp end_partition_chain - -test_primary_partition_0: - mov al,[ebx+0x1be+4] ; get primary partition type - call scan_partition_types - jnz test_primary_partition_1 ; no. skip over - - inc ecx - cmp ecx,[known_part] ; is it wanted partition? - jnz test_primary_partition_1 ; no + .groups_count dd ? +if $ > fs_dependent_data_end +ERROR: + increase sizeof(fs_dependent_data)! +end if +end virtual - pop eax - ;mov edx, eax ; start sector +;*************************************************************************** +; End place +; Mario79 +;*************************************************************************** +endg +iglobal + + partition_types: ; list of fat16/32 partitions + db 0x04 ; DOS: fat16 <32M + db 0x06 ; DOS: fat16 >32M + db 0x0b ; WIN95: fat32 + db 0x0c ; WIN95: fat32, LBA-mapped + db 0x0e ; WIN95: fat16, LBA-mapped + db 0x14 ; Hidden DOS: fat16 <32M + db 0x16 ; Hidden DOS: fat16 >32M + db 0x1b ; Hidden WIN95: fat32 + db 0x1c ; Hidden WIN95: fat32, LBA-mapped + db 0x1e ; Hidden WIN95: fat16, LBA-mapped + db 0xc4 ; DRDOS/secured: fat16 <32M + db 0xc6 ; DRDOS/secured: fat16 >32M + db 0xcb ; DRDOS/secured: fat32 + db 0xcc ; DRDOS/secured: fat32, LBA-mapped + db 0xce ; DRDOS/secured: fat16, LBA-mapped + db 0xd4 ; Old Multiuser DOS secured: fat16 <32M + db 0xd6 ; Old Multiuser DOS secured: fat16 >32M + db 0x07 ; NTFS + db 0x27 ; NTFS, hidden + db 0x83 ; Linux native file system (ext2fs) + partition_types_end: + + + extended_types: ; list of extended partitions + db 0x05 ; DOS: extended partition + db 0x0f ; WIN95: extended partition, LBA-mapped + db 0xc5 ; DRDOS/secured: extended partition + db 0xd5 ; Old Multiuser DOS secured: extended partition + extended_types_end: + +endg + +; Partition chain used: +; MBR <--------------------- +; | | +; |-> PARTITION1 | +; |-> EXTENDED PARTITION - ;not need be second partition +; |-> PARTITION3 +; |-> PARTITION4 + +set_PARTITION_variables: +set_FAT32_variables: ;deprecated + and [problem_partition], 0 + call reserve_hd1 + call reserve_hd_channel + + pushad + + cmp dword [hdpos], 0 + je problem_hd + + xor ecx, ecx ; partition count + ;or edx,-1 ; flag for partition + xor eax, eax ; address MBR + xor ebp, ebp ; extended partition start + +new_mbr: + test ebp, ebp ; is there extended partition? (MBR or EMBR) + jnz extended_already_set; yes + xchg ebp, eax ; no. set it now + +extended_already_set: + add eax, ebp ; mbr=mbr+0, ext_part=ext_start+relat_start + mov ebx, buffer + call hd_read + cmp [hd_error], 0 + jne problem_hd + + cmp word [ebx+0x1fe], 0xaa55; is it valid boot sector? + jnz end_partition_chain + push eax ; push only one time + cmp dword [ebx+0x1be+0xc], 0; skip over empty partition + jnz test_primary_partition_0 + cmp dword [ebx+0x1be+0xc+16], 0 + jnz test_primary_partition_1 + cmp dword [ebx+0x1be+0xc+16+16], 0 + jnz test_primary_partition_2 + cmp dword [ebx+0x1be+0xc+16+16+16], 0 + jnz test_primary_partition_3 + pop eax + jmp end_partition_chain + +test_primary_partition_0: + mov al, [ebx+0x1be+4]; get primary partition type + call scan_partition_types + jnz test_primary_partition_1; no. skip over + + inc ecx + cmp ecx, [known_part]; is it wanted partition? + jnz test_primary_partition_1; no + + pop eax + ;mov edx, eax ; start sector add eax, [ebx+0x1be+8] ; add relative start - ;mov [PARTITON_START],edx + ;mov [PARTITON_START],edx ;push edx - mov edx, [ebx+0x1be+12] ; length - ;add edx, eax ; add length - ;dec edx ; PARTITION_END is inclusive - ;mov [PARTITION_END], edx ; note that this can be changed - ; when file system data will be available - mov cl, [ebx+0x1be+4] ; fs_type - ;mov [fs_type], dl ; save for FS recognizer (separate FAT vs NTFS) + mov edx, [ebx+0x1be+12] ; length + ;add edx, eax ; add length + ;dec edx ; PARTITION_END is inclusive + ;mov [PARTITION_END], edx ; note that this can be changed + ; when file system data will be available + mov cl, [ebx+0x1be+4] ; fs_type + ;mov [fs_type], dl ; save for FS recognizer (separate FAT vs NTFS) ;pop edx - jmp hd_and_partition_ok - -test_primary_partition_1: - mov al,[ebx+0x1be+4+16] ; get primary partition type - call scan_partition_types - jnz test_primary_partition_2 ; no. skip over - - inc ecx - cmp ecx,[known_part] ; is it wanted partition? - jnz test_primary_partition_2 ; no + jmp hd_and_partition_ok + +test_primary_partition_1: + mov al, [ebx+0x1be+4+16]; get primary partition type + call scan_partition_types + jnz test_primary_partition_2 ; no. skip over + + inc ecx + cmp ecx, [known_part]; is it wanted partition? + jnz test_primary_partition_2 ; no pop eax add eax, [ebx+0x1be+8+16] mov edx, [ebx+0x1be+12+16] mov cl, [ebx+0x1be+4+16] jmp hd_and_partition_ok - - ;mov edx, eax - ;add edx, [ebx+0x1be+8+16] - ;push edx - ;add edx, [ebx+0x1be+12+16] - ;dec edx - ;mov [PARTITION_END], edx - ;mov al, [ebx+0x1be+4+16] - ;mov [fs_type], dl - ;pop edx - -test_primary_partition_2: - mov al,[ebx+0x1be+4+16+16] ; get primary partition type - call scan_partition_types - jnz test_primary_partition_3 ; no. skip over - - inc ecx - cmp ecx,[known_part] ; is it wanted partition? - jnz test_primary_partition_3 ; no + + ;mov edx, eax + ;add edx, [ebx+0x1be+8+16] + ;push edx + ;add edx, [ebx+0x1be+12+16] + ;dec edx + ;mov [PARTITION_END], edx + ;mov al, [ebx+0x1be+4+16] + ;mov [fs_type], dl + ;pop edx + +test_primary_partition_2: + mov al, [ebx+0x1be+4+16+16]; get primary partition type + call scan_partition_types + jnz test_primary_partition_3 ; no. skip over + + inc ecx + cmp ecx, [known_part]; is it wanted partition? + jnz test_primary_partition_3 ; no pop eax add eax, [ebx+0x1be+8+16+16] mov edx, [ebx+0x1be+12+16+16] mov cl, [ebx+0x1be+4+16+16] - jmp hd_and_partition_ok - ;mov edx, eax - ;add edx, [ebx+0x1be+8+16+16] - ;push edx - ;add edx, [ebx+0x1be+12+16+16] - ;dec edx - ;mov [PARTITION_END], edx - ;mov al, [ebx+0x1be+4+16+16] - ;mov [fs_type], dl - ;pop edx - -test_primary_partition_3: - mov al,[ebx+0x1be+4+16+16+16] ; get primary partition type - call scan_partition_types - jnz test_ext_partition_0 ; no. skip over - - inc ecx - cmp ecx,[known_part] ; is it wanted partition? - jnz test_ext_partition_0 ; no + jmp hd_and_partition_ok + ;mov edx, eax + ;add edx, [ebx+0x1be+8+16+16] + ;push edx + ;add edx, [ebx+0x1be+12+16+16] + ;dec edx + ;mov [PARTITION_END], edx + ;mov al, [ebx+0x1be+4+16+16] + ;mov [fs_type], dl + ;pop edx + +test_primary_partition_3: + mov al, [ebx+0x1be+4+16+16+16]; get primary partition type + call scan_partition_types + jnz test_ext_partition_0 ; no. skip over + + inc ecx + cmp ecx, [known_part]; is it wanted partition? + jnz test_ext_partition_0; no pop eax add eax, [ebx+0x1be+8+16+16+16] mov edx, [ebx+0x1be+12+16+16+16] mov cl, [ebx+0x1be+4+16+16+16] jmp hd_and_partition_ok - - ;mov edx, eax - ;add edx, [ebx+0x1be+8+16+16+16] - ;push edx - ;add edx, [ebx+0x1be+12+16+16+16] - ;dec edx - ;mov [PARTITION_END], edx - ;mov al, [ebx+0x1be+4+16+16+16] - ;mov [fs_type], dl - ;pop edx - + + ;mov edx, eax + ;add edx, [ebx+0x1be+8+16+16+16] + ;push edx + ;add edx, [ebx+0x1be+12+16+16+16] + ;dec edx + ;mov [PARTITION_END], edx + ;mov al, [ebx+0x1be+4+16+16+16] + ;mov [fs_type], dl + ;pop edx + test_ext_partition_0: - pop eax ; Їа®бв® ўлЄЁ¤лў Ґ¬ Ё§ б⥪  - mov al,[ebx+0x1be+4] ; get extended partition type - call scan_extended_types - jnz test_ext_partition_1 - - mov eax,[ebx+0x1be+8] ; add relative start - test eax,eax ; is there extended partition? - jnz new_mbr ; yes. read it - -test_ext_partition_1: - mov al,[ebx+0x1be+4+16] ; get extended partition type - call scan_extended_types - jnz test_ext_partition_2 - - mov eax,[ebx+0x1be+8+16] ; add relative start - test eax,eax ; is there extended partition? - jnz new_mbr ; yes. read it - -test_ext_partition_2: - mov al,[ebx+0x1be+4+16+16] ; get extended partition type - call scan_extended_types - jnz test_ext_partition_3 - - mov eax,[ebx+0x1be+8+16+16] ; add relative start - test eax,eax ; is there extended partition? - jnz new_mbr ; yes. read it - -test_ext_partition_3: - mov al,[ebx+0x1be+4+16+16+16] ; get extended partition type - call scan_extended_types - jnz end_partition_chain ; no. end chain - - mov eax,[ebx+0x1be+8+16+16+16] ; get start of extended partition - test eax,eax ; is there extended partition? - jnz new_mbr ; yes. read it - -end_partition_chain: - ;mov [partition_count],ecx - - ;cmp edx,-1 ; found wanted partition? - ;jnz hd_and_partition_ok ; yes. install it + pop eax ; Їа®бв® ўлЄЁ¤лў Ґ¬ Ё§ б⥪  + mov al, [ebx+0x1be+4]; get extended partition type + call scan_extended_types + jnz test_ext_partition_1 + + mov eax, [ebx+0x1be+8]; add relative start + test eax, eax ; is there extended partition? + jnz new_mbr ; yes. read it + +test_ext_partition_1: + mov al, [ebx+0x1be+4+16]; get extended partition type + call scan_extended_types + jnz test_ext_partition_2 + + mov eax, [ebx+0x1be+8+16]; add relative start + test eax, eax ; is there extended partition? + jnz new_mbr ; yes. read it + +test_ext_partition_2: + mov al, [ebx+0x1be+4+16+16]; get extended partition type + call scan_extended_types + jnz test_ext_partition_3 + + mov eax, [ebx+0x1be+8+16+16]; add relative start + test eax, eax ; is there extended partition? + jnz new_mbr ; yes. read it + +test_ext_partition_3: + mov al, [ebx+0x1be+4+16+16+16]; get extended partition type + call scan_extended_types + jnz end_partition_chain; no. end chain + + mov eax, [ebx+0x1be+8+16+16+16]; get start of extended partition + test eax, eax ; is there extended partition? + jnz new_mbr ; yes. read it + +end_partition_chain: + ;mov [partition_count],ecx + + ;cmp edx,-1 ; found wanted partition? + ;jnz hd_and_partition_ok ; yes. install it ;jmp problem_partition_or_fat problem_hd: - or [problem_partition], 2 - jmp return_from_part_set - - -scan_partition_types: - push ecx - mov edi,partition_types - mov ecx,partition_types_end-partition_types - cld - repne scasb ; is partition type ok? - pop ecx - ret - -scan_extended_types: - push ecx - mov edi,extended_types - mov ecx,extended_types_end-extended_types - cld - repne scasb ; is it extended partition? - pop ecx - ret - -problem_fat_dec_count: ; bootsector is missing or another problem -; dec [partition_count] ; remove it from partition_count - -problem_partition_or_fat: - or [problem_partition],1 + or [problem_partition], 2 + jmp return_from_part_set + + +scan_partition_types: + push ecx + mov edi, partition_types + mov ecx, partition_types_end-partition_types + cld + repne scasb ; is partition type ok? + pop ecx + ret + +scan_extended_types: + push ecx + mov edi, extended_types + mov ecx, extended_types_end-extended_types + cld + repne scasb ; is it extended partition? + pop ecx + ret + +problem_fat_dec_count: ; bootsector is missing or another problem +; dec [partition_count] ; remove it from partition_count + +problem_partition_or_fat: + or [problem_partition], 1 + +return_from_part_set: + popad + ;mov [fs_type],0 + call free_hd_channel + mov [hd1_status], 0 ; free + ret -return_from_part_set: - popad - ;mov [fs_type],0 - call free_hd_channel - mov [hd1_status],0 ; free - ret - hd_and_partition_ok: ;eax = PARTITION_START edx=PARTITION_LENGTH cl=fs_type - mov [fs_type], cl - ;mov eax,edx - mov [PARTITION_START],eax - add edx, eax - dec edx - mov [PARTITION_END], edx - - ; mov edx, [PARTITION_END] - ; sub edx, eax - ; inc edx ; edx = length of partition § зҐ¬ ®­® ­ ¬?? - -; mov [hd_setup],1 - mov ebx,buffer - call hd_read ; read boot sector of partition - cmp [hd_error], 0 - jz boot_read_ok - cmp [fs_type], 7 - jnz problem_fat_dec_count -; NTFS duplicates bootsector: -; NT4/2k/XP+ saves bootsector copy in the end of disk -; NT 3.51 saves bootsector copy in the middle of disk - and [hd_error], 0 - mov eax, [PARTITION_END] - call hd_read - cmp [hd_error], 0 - jnz @f - call ntfs_test_bootsec - jnc boot_read_ok -@@: - and [hd_error], 0 - mov eax, edx - shr eax, 1 - add eax, [PARTITION_START] - call hd_read - cmp [hd_error], 0 - jnz problem_fat_dec_count ; no chance... -boot_read_ok: - -; if we are running on NTFS, check bootsector - - call ntfs_test_bootsec ; test ntfs - jnc ntfs_setup - - call ext2_test_superblock ; test ext2fs - jnc ext2_setup - - mov eax, [PARTITION_START] ;ext2 test changes [buffer] - call hd_read - cmp [hd_error], 0 - jnz problem_fat_dec_count - - cmp word [ebx+0x1fe],0xaa55 ; is it valid boot sector? - jnz problem_fat_dec_count - - movzx eax,word [ebx+0xe] ; sectors reserved - add eax,[PARTITION_START] - mov [FAT_START],eax ; fat_start = partition_start + reserved - - movzx eax,byte [ebx+0xd] ; sectors per cluster - test eax,eax - jz problem_fat_dec_count - mov [SECTORS_PER_CLUSTER],eax - - movzx ecx,word [ebx+0xb] ; bytes per sector - cmp ecx,0x200 - jnz problem_fat_dec_count - mov [BYTES_PER_SECTOR],ecx - - movzx eax,word [ebx+0x11] ; count of rootdir entries (=0 fat32) - mov edx,32 - mul edx - dec ecx - add eax,ecx ; round up if not equal count - inc ecx ; bytes per sector - div ecx - mov [ROOT_SECTORS],eax ; count of rootdir sectors - - movzx eax,word [ebx+0x16] ; sectors per fat <65536 - test eax,eax - jnz fat16_fatsize - mov eax,[ebx+0x24] ; sectors per fat - fat16_fatsize: - mov [SECTORS_PER_FAT],eax - - movzx eax,byte [ebx+0x10] ; number of fats - test eax,eax ; if 0 it's not fat partition - jz problem_fat_dec_count - mov [NUMBER_OF_FATS],eax - imul eax,[SECTORS_PER_FAT] - add eax,[FAT_START] - mov [ROOT_START],eax ; rootdir = fat_start + fat_size * fat_count - add eax,[ROOT_SECTORS] ; rootdir sectors should be 0 on fat32 - mov [DATA_START],eax ; data area = rootdir + rootdir_size - - movzx eax,word [ebx+0x13] ; total sector count <65536 - test eax,eax - jnz fat16_total - mov eax,[ebx+0x20] ; total sector count - fat16_total: - add eax,[PARTITION_START] - dec eax - mov [PARTITION_END],eax - inc eax - sub eax,[DATA_START] ; eax = count of data sectors - xor edx,edx - div dword [SECTORS_PER_CLUSTER] - inc eax - mov [LAST_CLUSTER],eax - dec eax ; cluster count - mov [fatStartScan],2 - - ; limits by Microsoft Hardware White Paper v1.03 - cmp eax,4085 ; 0xff5 - jb problem_fat_dec_count ; fat12 not supported - cmp eax,65525 ; 0xfff5 - jb fat16_partition - -fat32_partition: - mov eax,[ebx+0x2c] ; rootdir cluster - mov [ROOT_CLUSTER],eax - movzx eax,word [ebx+0x30] ; fs info sector - add eax,[PARTITION_START] - mov [ADR_FSINFO],eax - call hd_read - mov eax,[ebx+0x1ec] - cmp eax,-1 - jz @f - mov [fatStartScan],eax -@@: - - popad - - mov [fatRESERVED],0x0FFFFFF6 - mov [fatBAD],0x0FFFFFF7 - mov [fatEND],0x0FFFFFF8 - mov [fatMASK],0x0FFFFFFF - mov [fs_type],32 ; Fat32 - call free_hd_channel - mov [hd1_status],0 ; free - ret - -fat16_partition: - xor eax,eax - mov [ROOT_CLUSTER],eax - - popad - - mov [fatRESERVED],0x0000FFF6 - mov [fatBAD],0x0000FFF7 - mov [fatEND],0x0000FFF8 - mov [fatMASK],0x0000FFFF - mov [fs_type],16 ; Fat16 - call free_hd_channel - mov [hd1_status],0 ; free - ret + mov [fs_type], cl + ;mov eax,edx + mov [PARTITION_START], eax + add edx, eax + dec edx + mov [PARTITION_END], edx + + ; mov edx, [PARTITION_END] + ; sub edx, eax + ; inc edx ; edx = length of partition § зҐ¬ ®­® ­ ¬?? + +; mov [hd_setup],1 + mov ebx, buffer + call hd_read ; read boot sector of partition + cmp [hd_error], 0 + jz boot_read_ok + cmp [fs_type], 7 + jnz problem_fat_dec_count +; NTFS duplicates bootsector: +; NT4/2k/XP+ saves bootsector copy in the end of disk +; NT 3.51 saves bootsector copy in the middle of disk + and [hd_error], 0 + mov eax, [PARTITION_END] + call hd_read + cmp [hd_error], 0 + jnz @f + call ntfs_test_bootsec + jnc boot_read_ok +@@: + and [hd_error], 0 + mov eax, edx + shr eax, 1 + add eax, [PARTITION_START] + call hd_read + cmp [hd_error], 0 + jnz problem_fat_dec_count ; no chance... +boot_read_ok: + +; if we are running on NTFS, check bootsector + + call ntfs_test_bootsec ; test ntfs + jnc ntfs_setup + + call ext2_test_superblock ; test ext2fs + jnc ext2_setup + + mov eax, [PARTITION_START] ;ext2 test changes [buffer] + call hd_read + cmp [hd_error], 0 + jnz problem_fat_dec_count + + cmp word [ebx+0x1fe], 0xaa55; is it valid boot sector? + jnz problem_fat_dec_count + + movzx eax, word [ebx+0xe]; sectors reserved + add eax, [PARTITION_START] + mov [FAT_START], eax; fat_start = partition_start + reserved + + movzx eax, byte [ebx+0xd]; sectors per cluster + test eax, eax + jz problem_fat_dec_count + mov [SECTORS_PER_CLUSTER], eax + + movzx ecx, word [ebx+0xb]; bytes per sector + cmp ecx, 0x200 + jnz problem_fat_dec_count + mov [BYTES_PER_SECTOR], ecx + + movzx eax, word [ebx+0x11]; count of rootdir entries (=0 fat32) + mov edx, 32 + mul edx + dec ecx + add eax, ecx ; round up if not equal count + inc ecx ; bytes per sector + div ecx + mov [ROOT_SECTORS], eax; count of rootdir sectors + + movzx eax, word [ebx+0x16]; sectors per fat <65536 + test eax, eax + jnz fat16_fatsize + mov eax, [ebx+0x24] ; sectors per fat + fat16_fatsize: + mov [SECTORS_PER_FAT], eax + + movzx eax, byte [ebx+0x10]; number of fats + test eax, eax ; if 0 it's not fat partition + jz problem_fat_dec_count + mov [NUMBER_OF_FATS], eax + imul eax, [SECTORS_PER_FAT] + add eax, [FAT_START] + mov [ROOT_START], eax; rootdir = fat_start + fat_size * fat_count + add eax, [ROOT_SECTORS]; rootdir sectors should be 0 on fat32 + mov [DATA_START], eax; data area = rootdir + rootdir_size + + movzx eax, word [ebx+0x13]; total sector count <65536 + test eax, eax + jnz fat16_total + mov eax, [ebx+0x20] ; total sector count + fat16_total: + add eax, [PARTITION_START] + dec eax + mov [PARTITION_END], eax + inc eax + sub eax, [DATA_START]; eax = count of data sectors + xor edx, edx + div dword [SECTORS_PER_CLUSTER] + inc eax + mov [LAST_CLUSTER], eax + dec eax ; cluster count + mov [fatStartScan], 2 + + ; limits by Microsoft Hardware White Paper v1.03 + cmp eax, 4085 ; 0xff5 + jb problem_fat_dec_count; fat12 not supported + cmp eax, 65525 ; 0xfff5 + jb fat16_partition + +fat32_partition: + mov eax, [ebx+0x2c] ; rootdir cluster + mov [ROOT_CLUSTER], eax + movzx eax, word [ebx+0x30]; fs info sector + add eax, [PARTITION_START] + mov [ADR_FSINFO], eax + call hd_read + mov eax, [ebx+0x1ec] + cmp eax, -1 + jz @f + mov [fatStartScan], eax +@@: + + popad + + mov [fatRESERVED], 0x0FFFFFF6 + mov [fatBAD], 0x0FFFFFF7 + mov [fatEND], 0x0FFFFFF8 + mov [fatMASK], 0x0FFFFFFF + mov [fs_type], 32 ; Fat32 + call free_hd_channel + mov [hd1_status], 0 ; free + ret + +fat16_partition: + xor eax, eax + mov [ROOT_CLUSTER], eax + + popad + + mov [fatRESERVED], 0x0000FFF6 + mov [fatBAD], 0x0000FFF7 + mov [fatEND], 0x0000FFF8 + mov [fatMASK], 0x0000FFFF + mov [fs_type], 16 ; Fat16 + call free_hd_channel + mov [hd1_status], 0 ; free + ret diff --git a/kernel/trunk/gui/button.inc b/kernel/trunk/gui/button.inc index e474696e8..243179dc2 100644 --- a/kernel/trunk/gui/button.inc +++ b/kernel/trunk/gui/button.inc @@ -131,7 +131,8 @@ syscall_button: ;///// system function 8 ////////////////////////////////////// call button._.incecx2 ; set button height counter - @@: mov edx, edi + @@: + mov edx, edi .next_line: call button._.button_dececx @@ -380,14 +381,17 @@ button._.dececx: ;///////////////////////////////////////////////////////////// sub cl, 0x20 jnc @f xor cl, cl - @@: sub ch, 0x20 + @@: + sub ch, 0x20 jnc @f xor ch, ch - @@: rol ecx, 16 + @@: + rol ecx, 16 sub cl, 0x20 jnc @f xor cl, cl - @@: rol ecx, 16 + @@: + rol ecx, 16 ret ;------------------------------------------------------------------------------ @@ -398,14 +402,17 @@ button._.incecx: ;///////////////////////////////////////////////////////////// add cl, 0x20 jnc @f or cl, -1 - @@: add ch, 0x20 + @@: + add ch, 0x20 jnc @f or ch, -1 - @@: rol ecx, 16 + @@: + rol ecx, 16 add cl, 0x20 jnc @f or cl, -1 - @@: rol ecx, 16 + @@: + rol ecx, 16 ret ;------------------------------------------------------------------------------ @@ -416,14 +423,17 @@ button._.incecx2: ;//////////////////////////////////////////////////////////// add cl, 0x14 jnc @f or cl, -1 - @@: add ch, 0x14 + @@: + add ch, 0x14 jnc @f or ch, -1 - @@: rol ecx, 16 + @@: + rol ecx, 16 add cl, 0x14 jnc @f or cl, -1 - @@: rol ecx, 16 + @@: + rol ecx, 16 ret ;------------------------------------------------------------------------------ @@ -440,17 +450,21 @@ button._.button_dececx: ;////////////////////////////////////////////////////// jg @f mov al, 2 - @@: sub cl, al - jnc @f - xor cl, cl - @@: sub ch, al - jnc @f - xor ch, ch - @@: rol ecx, 16 + @@: sub cl, al jnc @f xor cl, cl - @@: rol ecx, 16 + @@: + sub ch, al + jnc @f + xor ch, ch + @@: + rol ecx, 16 + sub cl, al + jnc @f + xor cl, cl + @@: + rol ecx, 16 pop eax diff --git a/kernel/trunk/gui/event.inc b/kernel/trunk/gui/event.inc index 8a46d81c2..63f50949c 100644 --- a/kernel/trunk/gui/event.inc +++ b/kernel/trunk/gui/event.inc @@ -1,497 +1,510 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -WINDOW_MOVE_AND_RESIZE_FLAGS = \ - mouse.WINDOW_RESIZE_N_FLAG + \ - mouse.WINDOW_RESIZE_W_FLAG + \ - mouse.WINDOW_RESIZE_S_FLAG + \ - mouse.WINDOW_RESIZE_E_FLAG + \ - mouse.WINDOW_MOVE_FLAG - -uglobal -align 4 - event_start dd ? - event_end dd ? - event_uid dd 0 -endg -EV_SPACE = 512 -FreeEvents = event_start-EVENT.fd ; "виртуальный" event, используются только поля: - ; FreeEvents.fd=event_start и FreeEvents.bk=event_end -align 4 -init_events: ;; used from kernel.asm - stdcall kernel_alloc,EV_SPACE*EVENT.size - or eax,eax - jz .fail - ; eax - current event, ebx - previos event below - mov ecx,EV_SPACE ; current - in allocated space - mov ebx,FreeEvents ; previos - начало списка - push ebx ; оно же и конец потом будет - @@: mov [ebx+EVENT.fd],eax - mov [eax+EVENT.bk],ebx - mov ebx,eax ; previos <- current - add eax,EVENT.size ; new current - loop @b - pop eax ; вот оно концом и стало - mov [ebx+EVENT.fd],eax - mov [eax+EVENT.bk],ebx -.fail: ret - -EVENT_WATCHED equ 0x10000000 ;бит 28 -EVENT_SIGNALED equ 0x20000000 ;бит 29 -MANUAL_RESET equ 0x40000000 ;бит 30 -MANUAL_DESTROY equ 0x80000000 ;бит 31 - -align 4 -create_event: ;; EXPORT use -;info: -; Переносим EVENT из списка FreeEvents в список ObjList текущего слота -; EVENT.state устанавливаем из ecx, EVENT.code косвенно из esi (если esi<>0) -;param: -; esi - event data -; ecx - flags -;retval: -; eax - event (=0 => fail) -; edx - uid -;scratched: ebx,ecx,esi,edi - mov ebx,[current_slot] - add ebx,APP_OBJ_OFFSET - mov edx,[TASK_BASE] - mov edx,[edx+TASKDATA.pid] - pushfd - cli - -set_event: ;; INTERNAL use !!! don't use for Call -;info: -; Берем новый event из FreeEvents, заполняем его поля, как указано в ecx,edx,esi -; и устанавливаем в список, указанный в ebx. -; Возвращаем сам event (в eax), и его uid (в edx) -;param: -; ebx - start-chain "virtual" event for entry new event Right of him -; ecx - flags (copied to EVENT.state) -; edx - pid (copied to EVENT.pid) -; esi - event data (copied to EVENT.code indirect, =0 => skip) -;retval: -; eax - event (=0 => fail) -; edx - uid -;scratched: ebx,ecx,esi,edi - mov eax,FreeEvents - cmp eax,[eax+EVENT.fd] - jne @f ; not empty ??? - pushad - call init_events - popad - jz RemoveEventTo.break ; POPF+RET - @@: mov eax,[eax+EVENT.fd] - mov [eax+EVENT.magic],'EVNT' - mov [eax+EVENT.destroy],destroy_event.internal - mov [eax+EVENT.state],ecx - mov [eax+EVENT.pid],edx - inc [event_uid] - Mov [eax+EVENT.id],edx,[event_uid] - or esi,esi - jz RemoveEventTo - lea edi,[eax+EVENT.code] - mov ecx,EVENT.codesize/4 - cld - rep movsd - -RemoveEventTo: ;; INTERNAL use !!! don't use for Call -;param: -; eax - указатель на event, КОТОРЫЙ вставляем -; ebx - указатель на event, ПОСЛЕ которого вставляем -;scratched: ebx,ecx - mov ecx,eax ; ecx=eax=Self, ebx=NewLeft - xchg ecx,[ebx+EVENT.fd] ; NewLeft.fd=Self, ecx=NewRight - cmp eax,ecx ; стоп, себе думаю... - je .break ; - а не дурак ли я? - mov [ecx+EVENT.bk],eax ; NewRight.bk=Self - xchg ebx,[eax+EVENT.bk] ; Self.bk=NewLeft, ebx=OldLeft - xchg ecx,[eax+EVENT.fd] ; Self.fd=NewRight, ecx=OldRight - mov [ebx+EVENT.fd],ecx ; OldLeft.fd=OldRight - mov [ecx+EVENT.bk],ebx ; OldRight.bk=OldLeft -.break: popfd - ret - -align 4 -NotDummyTest: ;; INTERNAL use (not returned for fail !!!) - pop edi - call DummyTest ; not returned for fail !!! - mov ebx,eax - mov eax,[ebx+EVENT.pid] - push edi -.small: ; криво как-то... - pop edi - pushfd - cli - call pid_to_slot ; saved all registers (eax - retval) - shl eax,8 - jz RemoveEventTo.break ; POPF+RET - jmp edi ; штатный возврат - -align 4 -raise_event: ;; EXPORT use -;info: -; Устанавливаем данные EVENT.code -; Если там флаг EVENT_SIGNALED уже активен - больше ничего -; Иначе: этот флаг взводится, за исключением случая наличия флага EVENT_WATCHED в edx -; В этом случае EVENT_SIGNALED взводится лишь при наличие EVENT_WATCHED в самом событии -;param: -; eax - event -; ebx - uid (for Dummy testing) -; edx - flags -; esi - event data (=0 => skip) -;scratched: ebx,ecx,esi,edi - call NotDummyTest ; not returned for fail !!! - or esi,esi - jz @f - lea edi,[ebx+EVENT.code] - mov ecx,EVENT.codesize/4 - cld - rep movsd - @@: - test byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 - jnz RemoveEventTo.break ; POPF+RET - bt edx, 28 ;EVENT_WATCHED - jnc @f - test byte[ebx+EVENT.state+3], EVENT_WATCHED shr 24 - jz RemoveEventTo.break ; POPF+RET - @@: - or byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 - add eax,SLOT_BASE+APP_EV_OFFSET - xchg eax,ebx - jmp RemoveEventTo - -align 4 -clear_event: ;; EXPORT use -;info: -; -;param: -; eax - event -; ebx - uid (for Dummy testing) -;scratched: ebx,ecx - call NotDummyTest ; not returned for fail !!! - add eax,SLOT_BASE+APP_OBJ_OFFSET - and byte[ebx+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) - xchg eax,ebx - jmp RemoveEventTo - -align 4 -send_event: ;; EXPORT use -;info: -; Создает новый EVENT (вытаскивает из списка FreeEvents) в списке EventList -; целевого слота (eax=pid), с данными из esi косвенно, и state=EVENT_SIGNALED -;param: -; eax - slots pid, to sending new event -; esi - pointer to sending data (in code field of new event) -;retval: -; eax - event (=0 => fail) -; edx - uid -;warning: -; may be used as CDECL with such prefix... -; mov esi,[esp+8] -; mov eax,[esp+4] -; but not as STDCALL :( -;scratched: ebx,ecx,esi,edi - mov edx,eax - call NotDummyTest.small ; not returned for fail !!! - lea ebx,[eax+SLOT_BASE+APP_EV_OFFSET] - mov ecx,EVENT_SIGNALED - jmp set_event - -align 4 -DummyTest: ;; INTERNAL use (not returned for fail !!!) -;param: -; eax - event -; ebx - uid (for Dummy testing) - cmp [eax+EVENT.magic],'EVNT' - jne @f - cmp [eax+EVENT.id],ebx - je .ret - @@: pop eax - xor eax,eax -.ret: ret - - -align 4 -Wait_events: - or ebx,-1 ; infinite timeout -Wait_events_ex: -;info: -; Ожидание "абстрактного" события через перевод слота в 5-ю позицию. -; Абстрактность заключена в том, что факт события определяется функцией APPDATA.wait_test, -; которая задается клиентом и может быть фактически любой. -; Это позволяет shed-у надежно определить факт события, и не совершать "холостых" переключений, -; предназначенных для разборок типа "свой/чужой" внутри задачи. -;param: -; edx - wait_test, клиентская ф-я тестирования (адрес кода) -; ecx - wait_param, дополнительный параметр, возможно необходимый для [wait_test] -; ebx - wait_timeout -;retval: -; eax - результат вызова [wait_test] (=0 => timeout) -;scratched: esi - mov esi,[current_slot] - mov [esi+APPDATA.wait_param],ecx - pushad - mov ebx,esi;пока это вопрос, чего куды сувать.......... - pushfd ; это следствие общей концепции: пусть ф-я тестирования имеет - cli ; право рассчитывать на закрытые прерывания, как при вызове из shed - call edx - popfd - mov [esp+28],eax - popad - or eax,eax - jnz @f ;RET - mov [esi+APPDATA.wait_test],edx - mov [esi+APPDATA.wait_timeout],ebx - Mov [esi+APPDATA.wait_begin],eax,[timer_ticks] - mov eax,[TASK_BASE] - mov [eax+TASKDATA.state], 5 - call change_task - mov eax,[esi+APPDATA.wait_param] - @@: ret - -align 4 -wait_event: ;; EXPORT use -;info: -; Ожидание флага EVENT_SIGNALED в совершенно конкретном Event -; (устанавливаемого, надо полагать, через raise_event) -; При активном флаге MANUAL_RESET - больше ничего -; Иначе: флаги EVENT_SIGNALED и EVENT_WATCHED у полученного события сбрасываются, -; и, при активном MANUAL_DESTROY - перемещается в список ObjList текущего слота, -; а при не активном - уничтожается штатно (destroy_event.internal) -;param: -; eax - event -; ebx - uid (for Dummy testing) -;scratched: ecx,edx,esi - call DummyTest - mov ecx,eax ; wait_param - mov edx, get_event_alone ; wait_test - call Wait_events ; timeout ignored - jmp wait_finish - -align 4 -get_event_ex: ;; f68:14 -;info: -; Ожидание любого события в очереди EventList текущего слота -; Данные события code - копируются в память приложения (косвенно по edi) -; При активном флаге MANUAL_RESET - больше ничего -; Иначе: флаги EVENT_SIGNALED и EVENT_WATCHED у полученного события сбрасываются, -; и, при активном MANUAL_DESTROY - перемещается в список ObjList текущего слота, -; а при не активном - уничтожается штатно (destroy_event.internal) -;param: -; edi - адрес в коде приложения для копирования данных из EVENT.code -;retval: -; eax - собственно EVENT (будем называть это его хэндлом) -;scratched: ebx,ecx,edx,esi,edi - mov edx, get_event_queue ; wait_test - call Wait_events ; timeout ignored - lea esi,[eax+EVENT.code] - mov ecx,EVENT.codesize/4 - cld - rep movsd - mov [edi-EVENT.codesize+2],cl ;clear priority field -wait_finish: - test byte[eax+EVENT.state+3], MANUAL_RESET shr 24 - jnz get_event_queue.ret ; RET - and byte[eax+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) - test byte[eax+EVENT.state+3], MANUAL_DESTROY shr 24 - jz destroy_event.internal - mov ebx,[current_slot] - add ebx,APP_OBJ_OFFSET - pushfd - cli - jmp RemoveEventTo - -align 4 -destroy_event: ;; EXPORT use -;info: -; Переносим EVENT в список FreeEvents, чистим поля magic,destroy,pid,id -;param: -; eax - event -; ebx - uid (for Dummy testing) -;retval: -; eax - адрес объекта EVENT (=0 => fail) -;scratched: ebx,ecx - call DummyTest ; not returned for fail !!! -.internal: - xor ecx,ecx ; clear common header - pushfd - cli - mov [eax+EVENT.magic],ecx - mov [eax+EVENT.destroy],ecx - mov [eax+EVENT.pid],ecx - mov [eax+EVENT.id],ecx - mov ebx,FreeEvents - jmp RemoveEventTo - -align 4 -get_event_queue: -;info: -; клиентская ф-я тестирования для get_event_ex -;warning: -; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot -; -may be assumed, that interrupt are disabled -; -it is not restriction for scratched registers -;param: -; ebx - адрес APPDATA слота тестирования -;retval: -; eax - адрес объекта EVENT (=0 => fail) - add ebx,APP_EV_OFFSET - mov eax,[ebx+APPOBJ.bk] ; выбираем с конца, по принципу FIFO - cmp eax,ebx ; empty ??? - je get_event_alone.ret0 -.ret: ret - -align 4 -get_event_alone: -;info: -; клиентская ф-я тестирования для wait_event -;warning: -; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot -; -may be assumed, that interrupt are disabled -; -it is not restriction for scratched registers -;param: -; ebx - адрес APPDATA слота тестирования -;retval: -; eax - адрес объекта EVENT (=0 => fail) - mov eax,[ebx+APPDATA.wait_param] - test byte[eax+EVENT.state+3], EVENT_SIGNALED shr 24 - jnz .ret - or byte[eax+EVENT.state+3], EVENT_WATCHED shr 24 -.ret0: xor eax,eax ; NO event!!! -.ret: ret - -align 4 -sys_sendwindowmsg: ;; f72 - dec ebx - jnz .ret ;subfunction==1 ? - ;pushfd ;а нафига? - cli - sub ecx,2 - je .sendkey - dec ecx - jnz .retf -.sendbtn: - cmp byte[BTN_COUNT],1 - jae .result ;overflow - inc byte[BTN_COUNT] - shl edx, 8 - mov [BTN_BUFF],edx - jmp .result -.sendkey: - movzx eax,byte[KEY_COUNT] - cmp al,120 - jae .result ;overflow - inc byte[KEY_COUNT] - mov [KEY_COUNT+1+eax],dl -.result: - setae byte[esp+32] ;считаем, что исходно: dword[esp+32]==72 -.retf: ;popfd -.ret: ret - -align 4 -sys_getevent: ;; f11 - mov ebx,[current_slot] ;пока это вопрос, чего куды сувать.......... - pushfd ; это следствие общей концепции: пусть ф-я тестирования имеет - cli ; право рассчитывать на закрытые прерывания, как при вызове из shed - call get_event_for_app - popfd - mov [esp+32],eax - ret - -align 4 -sys_waitforevent: ;; f10 - or ebx,-1 ; infinite timeout -sys_wait_event_timeout: ;; f23 - mov edx,get_event_for_app ; wait_test - call Wait_events_ex ; ebx - timeout - mov [esp+32],eax - ret - -align 4 -get_event_for_app: ;; used from f10,f11,f23 -;info: -; клиентская ф-я тестирования для приложений (f10,f23) -;warning: -; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot -; -may be assumed, that interrupt are disabled -; -it is not restriction for scratched registers -;param: -; ebx - адрес APPDATA слота тестирования -;retval: -; eax - номер события (=0 => no events) - movzx edi,bh ; bh is assumed as [CURRENT_TASK] - shl edi,5 - add edi,CURRENT_TASK ; edi is assumed as [TASK_BASE] - mov ecx,[edi+TASKDATA.event_mask] -.loop: ; пока не исчерпаем все биты маски - bsr eax,ecx ; находим ненулевой бит маски (31 -> 0) - jz .no_events ; исчерпали все биты маски, но ничего не нашли ??? - btr ecx,eax ; сбрасываем проверяемый бит маски - ; переходим на обработчик этого (eax) бита - cmp eax,9 - jae .loop ; eax=[9..31], ignored - cmp eax,3 - je .loop ; eax=3, ignored - ja .FlagAutoReset ; eax=[4..8], retvals=eax+1 - cmp eax,1 - jae .BtKy ; eax=[1,2], retvals=eax+1 -.WndRedraw: ; eax=0, retval WndRedraw=1 - cmp [edi-twdw+WDATA.fl_redraw],al ;al==0 - jne .result - jmp .loop - .no_events: - xor eax,eax - ret - -.FlagAutoReset: ; retvals: BgrRedraw=5, Mouse=6, IPC=7, Stack=8, Debug=9 - cmp eax,5 ; Mouse 5+1=6 - jne @f - push eax -; If the window is captured and moved by the user, then no mouse events!!! - mov al,[mouse.active_sys_window.action] - and al,WINDOW_MOVE_AND_RESIZE_FLAGS - test al,al - pop eax - jnz .loop -@@: - btr [ebx+APPDATA.event_mask],eax - jnc .loop - .result: ; retval = eax+1 - inc eax - ret - .BtKy: - movzx edx,bh - movzx edx, word[WIN_STACK+edx*2] - je .Keys ; eax=1, retval Keys=2 -.Buttons: ; eax=2, retval Buttons=3 - cmp byte[BTN_COUNT],0 - je .loop ; empty ??? - cmp edx,[TASK_COUNT] - jne .loop ; not Top ??? - mov edx, [BTN_BUFF] - shr edx, 8 - cmp edx, 0xFFFF ;-ID for Minimize-Button of Form - jne .result - mov [window_minimize],1 - dec byte[BTN_COUNT] - jmp .loop -.Keys: ; eax==1 - cmp edx,[TASK_COUNT] - jne @f ; not Top ??? - cmp [KEY_COUNT],al ; al==1 - jae .result ; not empty ??? - @@: mov edx, hotkey_buffer - @@: cmp [edx],bh ; bh - slot for testing - je .result - add edx,8 - cmp edx, hotkey_buffer+120*8 - jb @b - jmp .loop -;end. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +WINDOW_MOVE_AND_RESIZE_FLAGS = \ + mouse.WINDOW_RESIZE_N_FLAG + \ + mouse.WINDOW_RESIZE_W_FLAG + \ + mouse.WINDOW_RESIZE_S_FLAG + \ + mouse.WINDOW_RESIZE_E_FLAG + \ + mouse.WINDOW_MOVE_FLAG + +uglobal +align 4 + event_start dd ? + event_end dd ? + event_uid dd 0 +endg +EV_SPACE = 512 +FreeEvents = event_start-EVENT.fd ; "виртуальный" event, используются только поля: + ; FreeEvents.fd=event_start и FreeEvents.bk=event_end +align 4 +init_events: ;; used from kernel.asm + stdcall kernel_alloc, EV_SPACE*EVENT.size + or eax, eax + jz .fail + ; eax - current event, ebx - previos event below + mov ecx, EV_SPACE ; current - in allocated space + mov ebx, FreeEvents ; previos - начало списка + push ebx ; оно же и конец потом будет + @@: + mov [ebx+EVENT.fd], eax + mov [eax+EVENT.bk], ebx + mov ebx, eax ; previos <- current + add eax, EVENT.size ; new current + loop @b + pop eax ; вот оно концом и стало + mov [ebx+EVENT.fd], eax + mov [eax+EVENT.bk], ebx +.fail: + ret + +EVENT_WATCHED equ 0x10000000 ;бит 28 +EVENT_SIGNALED equ 0x20000000 ;бит 29 +MANUAL_RESET equ 0x40000000 ;бит 30 +MANUAL_DESTROY equ 0x80000000 ;бит 31 + +align 4 +create_event: ;; EXPORT use +;info: +; Переносим EVENT из списка FreeEvents в список ObjList текущего слота +; EVENT.state устанавливаем из ecx, EVENT.code косвенно из esi (если esi<>0) +;param: +; esi - event data +; ecx - flags +;retval: +; eax - event (=0 => fail) +; edx - uid +;scratched: ebx,ecx,esi,edi + mov ebx, [current_slot] + add ebx, APP_OBJ_OFFSET + mov edx, [TASK_BASE] + mov edx, [edx+TASKDATA.pid] + pushfd + cli + +set_event: ;; INTERNAL use !!! don't use for Call +;info: +; Берем новый event из FreeEvents, заполняем его поля, как указано в ecx,edx,esi +; и устанавливаем в список, указанный в ebx. +; Возвращаем сам event (в eax), и его uid (в edx) +;param: +; ebx - start-chain "virtual" event for entry new event Right of him +; ecx - flags (copied to EVENT.state) +; edx - pid (copied to EVENT.pid) +; esi - event data (copied to EVENT.code indirect, =0 => skip) +;retval: +; eax - event (=0 => fail) +; edx - uid +;scratched: ebx,ecx,esi,edi + mov eax, FreeEvents + cmp eax, [eax+EVENT.fd] + jne @f ; not empty ??? + pushad + call init_events + popad + jz RemoveEventTo.break ; POPF+RET + @@: + mov eax, [eax+EVENT.fd] + mov [eax+EVENT.magic], 'EVNT' + mov [eax+EVENT.destroy], destroy_event.internal + mov [eax+EVENT.state], ecx + mov [eax+EVENT.pid], edx + inc [event_uid] + Mov [eax+EVENT.id],edx,[event_uid] + or esi, esi + jz RemoveEventTo + lea edi, [eax+EVENT.code] + mov ecx, EVENT.codesize/4 + cld + rep movsd + +RemoveEventTo: ;; INTERNAL use !!! don't use for Call +;param: +; eax - указатель на event, КОТОРЫЙ вставляем +; ebx - указатель на event, ПОСЛЕ которого вставляем +;scratched: ebx,ecx + mov ecx, eax ; ecx=eax=Self, ebx=NewLeft + xchg ecx, [ebx+EVENT.fd] ; NewLeft.fd=Self, ecx=NewRight + cmp eax, ecx ; стоп, себе думаю... + je .break ; - а не дурак ли я? + mov [ecx+EVENT.bk], eax ; NewRight.bk=Self + xchg ebx, [eax+EVENT.bk] ; Self.bk=NewLeft, ebx=OldLeft + xchg ecx, [eax+EVENT.fd] ; Self.fd=NewRight, ecx=OldRight + mov [ebx+EVENT.fd], ecx ; OldLeft.fd=OldRight + mov [ecx+EVENT.bk], ebx ; OldRight.bk=OldLeft +.break: + popfd + ret + +align 4 +NotDummyTest: ;; INTERNAL use (not returned for fail !!!) + pop edi + call DummyTest ; not returned for fail !!! + mov ebx, eax + mov eax, [ebx+EVENT.pid] + push edi +.small: ; криво как-то... + pop edi + pushfd + cli + call pid_to_slot ; saved all registers (eax - retval) + shl eax, 8 + jz RemoveEventTo.break ; POPF+RET + jmp edi ; штатный возврат + +align 4 +raise_event: ;; EXPORT use +;info: +; Устанавливаем данные EVENT.code +; Если там флаг EVENT_SIGNALED уже активен - больше ничего +; Иначе: этот флаг взводится, за исключением случая наличия флага EVENT_WATCHED в edx +; В этом случае EVENT_SIGNALED взводится лишь при наличие EVENT_WATCHED в самом событии +;param: +; eax - event +; ebx - uid (for Dummy testing) +; edx - flags +; esi - event data (=0 => skip) +;scratched: ebx,ecx,esi,edi + call NotDummyTest ; not returned for fail !!! + or esi, esi + jz @f + lea edi, [ebx+EVENT.code] + mov ecx, EVENT.codesize/4 + cld + rep movsd + @@: + test byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 + jnz RemoveEventTo.break ; POPF+RET + bt edx, 28 ;EVENT_WATCHED + jnc @f + test byte[ebx+EVENT.state+3], EVENT_WATCHED shr 24 + jz RemoveEventTo.break ; POPF+RET + @@: + or byte[ebx+EVENT.state+3], EVENT_SIGNALED shr 24 + add eax, SLOT_BASE+APP_EV_OFFSET + xchg eax, ebx + jmp RemoveEventTo + +align 4 +clear_event: ;; EXPORT use +;info: +; +;param: +; eax - event +; ebx - uid (for Dummy testing) +;scratched: ebx,ecx + call NotDummyTest ; not returned for fail !!! + add eax, SLOT_BASE+APP_OBJ_OFFSET + and byte[ebx+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) + xchg eax, ebx + jmp RemoveEventTo + +align 4 +send_event: ;; EXPORT use +;info: +; Создает новый EVENT (вытаскивает из списка FreeEvents) в списке EventList +; целевого слота (eax=pid), с данными из esi косвенно, и state=EVENT_SIGNALED +;param: +; eax - slots pid, to sending new event +; esi - pointer to sending data (in code field of new event) +;retval: +; eax - event (=0 => fail) +; edx - uid +;warning: +; may be used as CDECL with such prefix... +; mov esi,[esp+8] +; mov eax,[esp+4] +; but not as STDCALL :( +;scratched: ebx,ecx,esi,edi + mov edx, eax + call NotDummyTest.small ; not returned for fail !!! + lea ebx, [eax+SLOT_BASE+APP_EV_OFFSET] + mov ecx, EVENT_SIGNALED + jmp set_event + +align 4 +DummyTest: ;; INTERNAL use (not returned for fail !!!) +;param: +; eax - event +; ebx - uid (for Dummy testing) + cmp [eax+EVENT.magic], 'EVNT' + jne @f + cmp [eax+EVENT.id], ebx + je .ret + @@: + pop eax + xor eax, eax +.ret: + ret + + +align 4 +Wait_events: + or ebx, -1; infinite timeout +Wait_events_ex: +;info: +; Ожидание "абстрактного" события через перевод слота в 5-ю позицию. +; Абстрактность заключена в том, что факт события определяется функцией APPDATA.wait_test, +; которая задается клиентом и может быть фактически любой. +; Это позволяет shed-у надежно определить факт события, и не совершать "холостых" переключений, +; предназначенных для разборок типа "свой/чужой" внутри задачи. +;param: +; edx - wait_test, клиентская ф-я тестирования (адрес кода) +; ecx - wait_param, дополнительный параметр, возможно необходимый для [wait_test] +; ebx - wait_timeout +;retval: +; eax - результат вызова [wait_test] (=0 => timeout) +;scratched: esi + mov esi, [current_slot] + mov [esi+APPDATA.wait_param], ecx + pushad + mov ebx, esi;пока это вопрос, чего куды сувать.......... + pushfd ; это следствие общей концепции: пусть ф-я тестирования имеет + cli ; право рассчитывать на закрытые прерывания, как при вызове из shed + call edx + popfd + mov [esp+28], eax + popad + or eax, eax + jnz @f ;RET + mov [esi+APPDATA.wait_test], edx + mov [esi+APPDATA.wait_timeout], ebx + Mov [esi+APPDATA.wait_begin],eax,[timer_ticks] + mov eax, [TASK_BASE] + mov [eax+TASKDATA.state], 5 + call change_task + mov eax, [esi+APPDATA.wait_param] + @@: + ret + +align 4 +wait_event: ;; EXPORT use +;info: +; Ожидание флага EVENT_SIGNALED в совершенно конкретном Event +; (устанавливаемого, надо полагать, через raise_event) +; При активном флаге MANUAL_RESET - больше ничего +; Иначе: флаги EVENT_SIGNALED и EVENT_WATCHED у полученного события сбрасываются, +; и, при активном MANUAL_DESTROY - перемещается в список ObjList текущего слота, +; а при не активном - уничтожается штатно (destroy_event.internal) +;param: +; eax - event +; ebx - uid (for Dummy testing) +;scratched: ecx,edx,esi + call DummyTest + mov ecx, eax ; wait_param + mov edx, get_event_alone ; wait_test + call Wait_events ; timeout ignored + jmp wait_finish + +align 4 +get_event_ex: ;; f68:14 +;info: +; Ожидание любого события в очереди EventList текущего слота +; Данные события code - копируются в память приложения (косвенно по edi) +; При активном флаге MANUAL_RESET - больше ничего +; Иначе: флаги EVENT_SIGNALED и EVENT_WATCHED у полученного события сбрасываются, +; и, при активном MANUAL_DESTROY - перемещается в список ObjList текущего слота, +; а при не активном - уничтожается штатно (destroy_event.internal) +;param: +; edi - адрес в коде приложения для копирования данных из EVENT.code +;retval: +; eax - собственно EVENT (будем называть это его хэндлом) +;scratched: ebx,ecx,edx,esi,edi + mov edx, get_event_queue ; wait_test + call Wait_events ; timeout ignored + lea esi, [eax+EVENT.code] + mov ecx, EVENT.codesize/4 + cld + rep movsd + mov [edi-EVENT.codesize+2], cl;clear priority field +wait_finish: + test byte[eax+EVENT.state+3], MANUAL_RESET shr 24 + jnz get_event_queue.ret ; RET + and byte[eax+EVENT.state+3], not((EVENT_SIGNALED+EVENT_WATCHED)shr 24) + test byte[eax+EVENT.state+3], MANUAL_DESTROY shr 24 + jz destroy_event.internal + mov ebx, [current_slot] + add ebx, APP_OBJ_OFFSET + pushfd + cli + jmp RemoveEventTo + +align 4 +destroy_event: ;; EXPORT use +;info: +; Переносим EVENT в список FreeEvents, чистим поля magic,destroy,pid,id +;param: +; eax - event +; ebx - uid (for Dummy testing) +;retval: +; eax - адрес объекта EVENT (=0 => fail) +;scratched: ebx,ecx + call DummyTest ; not returned for fail !!! +.internal: + xor ecx, ecx ; clear common header + pushfd + cli + mov [eax+EVENT.magic], ecx + mov [eax+EVENT.destroy], ecx + mov [eax+EVENT.pid], ecx + mov [eax+EVENT.id], ecx + mov ebx, FreeEvents + jmp RemoveEventTo + +align 4 +get_event_queue: +;info: +; клиентская ф-я тестирования для get_event_ex +;warning: +; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot +; -may be assumed, that interrupt are disabled +; -it is not restriction for scratched registers +;param: +; ebx - адрес APPDATA слота тестирования +;retval: +; eax - адрес объекта EVENT (=0 => fail) + add ebx, APP_EV_OFFSET + mov eax, [ebx+APPOBJ.bk] ; выбираем с конца, по принципу FIFO + cmp eax, ebx ; empty ??? + je get_event_alone.ret0 +.ret: + ret + +align 4 +get_event_alone: +;info: +; клиентская ф-я тестирования для wait_event +;warning: +; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot +; -may be assumed, that interrupt are disabled +; -it is not restriction for scratched registers +;param: +; ebx - адрес APPDATA слота тестирования +;retval: +; eax - адрес объекта EVENT (=0 => fail) + mov eax, [ebx+APPDATA.wait_param] + test byte[eax+EVENT.state+3], EVENT_SIGNALED shr 24 + jnz .ret + or byte[eax+EVENT.state+3], EVENT_WATCHED shr 24 +.ret0: + xor eax, eax; NO event!!! +.ret: + ret + +align 4 +sys_sendwindowmsg: ;; f72 + dec ebx + jnz .ret ;subfunction==1 ? + ;pushfd ;а нафига? + cli + sub ecx, 2 + je .sendkey + dec ecx + jnz .retf +.sendbtn: + cmp byte[BTN_COUNT], 1 + jae .result ;overflow + inc byte[BTN_COUNT] + shl edx, 8 + mov [BTN_BUFF], edx + jmp .result +.sendkey: + movzx eax, byte[KEY_COUNT] + cmp al, 120 + jae .result ;overflow + inc byte[KEY_COUNT] + mov [KEY_COUNT+1+eax], dl +.result: + setae byte[esp+32] ;считаем, что исходно: dword[esp+32]==72 +.retf: ;popfd +.ret: + ret + +align 4 +sys_getevent: ;; f11 + mov ebx, [current_slot];пока это вопрос, чего куды сувать.......... + pushfd ; это следствие общей концепции: пусть ф-я тестирования имеет + cli ; право рассчитывать на закрытые прерывания, как при вызове из shed + call get_event_for_app + popfd + mov [esp+32], eax + ret + +align 4 +sys_waitforevent: ;; f10 + or ebx, -1; infinite timeout +sys_wait_event_timeout: ;; f23 + mov edx, get_event_for_app; wait_test + call Wait_events_ex ; ebx - timeout + mov [esp+32], eax + ret + +align 4 +get_event_for_app: ;; used from f10,f11,f23 +;info: +; клиентская ф-я тестирования для приложений (f10,f23) +;warning: +; -don't use [TASK_BASE],[current_slot],[CURRENT_TASK] - it is not for your slot +; -may be assumed, that interrupt are disabled +; -it is not restriction for scratched registers +;param: +; ebx - адрес APPDATA слота тестирования +;retval: +; eax - номер события (=0 => no events) + movzx edi, bh ; bh is assumed as [CURRENT_TASK] + shl edi, 5 + add edi, CURRENT_TASK ; edi is assumed as [TASK_BASE] + mov ecx, [edi+TASKDATA.event_mask] +.loop: ; пока не исчерпаем все биты маски + bsr eax, ecx ; находим ненулевой бит маски (31 -> 0) + jz .no_events ; исчерпали все биты маски, но ничего не нашли ??? + btr ecx, eax ; сбрасываем проверяемый бит маски + ; переходим на обработчик этого (eax) бита + cmp eax, 9 + jae .loop ; eax=[9..31], ignored + cmp eax, 3 + je .loop ; eax=3, ignored + ja .FlagAutoReset ; eax=[4..8], retvals=eax+1 + cmp eax, 1 + jae .BtKy ; eax=[1,2], retvals=eax+1 +.WndRedraw: ; eax=0, retval WndRedraw=1 + cmp [edi-twdw+WDATA.fl_redraw], al;al==0 + jne .result + jmp .loop + .no_events: + xor eax, eax + ret + +.FlagAutoReset: ; retvals: BgrRedraw=5, Mouse=6, IPC=7, Stack=8, Debug=9 + cmp eax, 5; Mouse 5+1=6 + jne @f + push eax +; If the window is captured and moved by the user, then no mouse events!!! + mov al, [mouse.active_sys_window.action] + and al, WINDOW_MOVE_AND_RESIZE_FLAGS + test al, al + pop eax + jnz .loop +@@: + btr [ebx+APPDATA.event_mask], eax + jnc .loop + .result: ; retval = eax+1 + inc eax + ret + .BtKy: + movzx edx, bh + movzx edx, word[WIN_STACK+edx*2] + je .Keys ; eax=1, retval Keys=2 +.Buttons: ; eax=2, retval Buttons=3 + cmp byte[BTN_COUNT], 0 + je .loop ; empty ??? + cmp edx, [TASK_COUNT] + jne .loop ; not Top ??? + mov edx, [BTN_BUFF] + shr edx, 8 + cmp edx, 0xFFFF ;-ID for Minimize-Button of Form + jne .result + mov [window_minimize], 1 + dec byte[BTN_COUNT] + jmp .loop +.Keys: ; eax==1 + cmp edx, [TASK_COUNT] + jne @f ; not Top ??? + cmp [KEY_COUNT], al; al==1 + jae .result ; not empty ??? + @@: + mov edx, hotkey_buffer + @@: + cmp [edx], bh ; bh - slot for testing + je .result + add edx, 8 + cmp edx, hotkey_buffer+120*8 + jb @b + jmp .loop +;end. diff --git a/kernel/trunk/gui/font.inc b/kernel/trunk/gui/font.inc index b5fbbab45..216e2060e 100644 --- a/kernel/trunk/gui/font.inc +++ b/kernel/trunk/gui/font.inc @@ -1,132 +1,132 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; // Alver 22.06.2008 // { -align 4 -dtext_asciiz_esi: ; for skins title out - push eax - xor eax, eax - inc eax - jmp dtext.1 -; } \\ Alver \\ - -align 4 -dtext: ; Text String Output (rw by Johnny_B[john@kolibrios.org]) - ; ebx x & y - ; ecx style ( 0xX0000000 ) & color ( 0x00RRGGBB ) - ; X = ABnnb: - ; nn = font - ; A = 0 <=> output esi characters; otherwise output ASCIIZ string - ; B = 1 <=> fill background with color eax - ; edx start of text - ; edi 1 force - -; // Alver 22.06.2008 // { - push eax - xor eax, eax -.1: -; } \\ Alver \\ - pushad - call [_display.disable_mouse] - - movsx eax, bx ; eax=y - sar ebx, 16 ; ebx=x - xchg eax, ebx ; eax=x, ebx=y - cmp esi, 255 - jb .loop - mov esi, 255 -.loop: - test ecx, ecx - js .test_asciiz - dec esi - js .end - jmp @f -.test_asciiz: - cmp byte [edx], 0 - jz .end -; // Alver 22.06.2008 // { - cmp byte [esp+28], 1 - jne @f - dec esi - js .end -; } \\ Alver \\ -@@: - inc edx - pushad - movzx edx, byte [edx-1] - test ecx, 0x10000000 - jnz .font2 - mov esi, 9 - lea ebp, [FONT_I+8*edx+edx] -.symloop1: - mov dl, byte [ebp] - or dl, 1 shl 6 -.pixloop1: - shr dl, 1 - jz .pixloop1end - jnc .nopix - call [putpixel] - jmp .pixloop1cont -.nopix: - test ecx, 0x40000000 - jz .pixloop1cont - push ecx - mov ecx, [esp+4+20h+20h] - call [putpixel] - pop ecx -.pixloop1cont: - inc eax - jmp .pixloop1 -.pixloop1end: - sub eax, 6 - inc ebx - inc ebp - dec esi - jnz .symloop1 - popad - add eax, 6 - jmp .loop -.font2: - add edx, edx - lea ebp, [FONT_II+4*edx+edx+1] - push 9 - movzx esi, byte [ebp-1] -.symloop2: - mov dl, byte [ebp] - push esi -.pixloop2: - shr dl, 1 - jnc .nopix2 - call [putpixel] - jmp .pixloop2cont -.nopix2: - test ecx, 0x40000000 - jz .pixloop2cont - push ecx - mov ecx, [esp+12+20h+20h] - call [putpixel] - pop ecx -.pixloop2cont: - inc eax - dec esi - jnz .pixloop2 - pop esi - sub eax, esi - inc ebx - inc ebp - dec dword [esp] - jnz .symloop2 - pop eax - add dword [esp+28], esi - popad - jmp .loop -.end: - popad - pop eax ; << // Alver 22.06.2008 // << - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; // Alver 22.06.2008 // { +align 4 +dtext_asciiz_esi: ; for skins title out + push eax + xor eax, eax + inc eax + jmp dtext.1 +; } \\ Alver \\ + +align 4 +dtext: ; Text String Output (rw by Johnny_B[john@kolibrios.org]) + ; ebx x & y + ; ecx style ( 0xX0000000 ) & color ( 0x00RRGGBB ) + ; X = ABnnb: + ; nn = font + ; A = 0 <=> output esi characters; otherwise output ASCIIZ string + ; B = 1 <=> fill background with color eax + ; edx start of text + ; edi 1 force + +; // Alver 22.06.2008 // { + push eax + xor eax, eax +.1: +; } \\ Alver \\ + pushad + call [_display.disable_mouse] + + movsx eax, bx ; eax=y + sar ebx, 16 ; ebx=x + xchg eax, ebx ; eax=x, ebx=y + cmp esi, 255 + jb .loop + mov esi, 255 +.loop: + test ecx, ecx + js .test_asciiz + dec esi + js .end + jmp @f +.test_asciiz: + cmp byte [edx], 0 + jz .end +; // Alver 22.06.2008 // { + cmp byte [esp+28], 1 + jne @f + dec esi + js .end +; } \\ Alver \\ +@@: + inc edx + pushad + movzx edx, byte [edx-1] + test ecx, 0x10000000 + jnz .font2 + mov esi, 9 + lea ebp, [FONT_I+8*edx+edx] +.symloop1: + mov dl, byte [ebp] + or dl, 1 shl 6 +.pixloop1: + shr dl, 1 + jz .pixloop1end + jnc .nopix + call [putpixel] + jmp .pixloop1cont +.nopix: + test ecx, 0x40000000 + jz .pixloop1cont + push ecx + mov ecx, [esp+4+20h+20h] + call [putpixel] + pop ecx +.pixloop1cont: + inc eax + jmp .pixloop1 +.pixloop1end: + sub eax, 6 + inc ebx + inc ebp + dec esi + jnz .symloop1 + popad + add eax, 6 + jmp .loop +.font2: + add edx, edx + lea ebp, [FONT_II+4*edx+edx+1] + push 9 + movzx esi, byte [ebp-1] +.symloop2: + mov dl, byte [ebp] + push esi +.pixloop2: + shr dl, 1 + jnc .nopix2 + call [putpixel] + jmp .pixloop2cont +.nopix2: + test ecx, 0x40000000 + jz .pixloop2cont + push ecx + mov ecx, [esp+12+20h+20h] + call [putpixel] + pop ecx +.pixloop2cont: + inc eax + dec esi + jnz .pixloop2 + pop esi + sub eax, esi + inc ebx + inc ebp + dec dword [esp] + jnz .symloop2 + pop eax + add dword [esp+28], esi + popad + jmp .loop +.end: + popad + pop eax ; << // Alver 22.06.2008 // << + ret diff --git a/kernel/trunk/gui/mouse.inc b/kernel/trunk/gui/mouse.inc index ddac7cd88..b8a915ad3 100644 --- a/kernel/trunk/gui/mouse.inc +++ b/kernel/trunk/gui/mouse.inc @@ -72,7 +72,8 @@ mouse_check_events: ;////////////////////////////////////////////////////////// jmp .exit ; is there any system button under cursor? - @@: call mouse._.find_sys_button_under_cursor + @@: + call mouse._.find_sys_button_under_cursor or eax, eax jz .check_buttons_released @@ -119,12 +120,14 @@ mouse_check_events: ;////////////////////////////////////////////////////////// mov eax, [esp + 4] call .call_left_button_handler - @@: test byte[esp], mouse.RIGHT_BUTTON_FLAG + @@: + test byte[esp], mouse.RIGHT_BUTTON_FLAG jz @f mov eax, [esp + 4] call .call_right_button_handler - @@: test byte[esp], mouse.MIDDLE_BUTTON_FLAG + @@: + test byte[esp], mouse.MIDDLE_BUTTON_FLAG jz .check_position mov eax, [esp + 4] call .call_middle_button_handler @@ -222,7 +225,8 @@ mouse._.left_button_press_handler: ;/////////////////////////////////////////// call sys_window_maximize_handler jmp .exit - @@: test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED + @@: + test [edi + WDATA.fl_wstate], WSTATE_MAXIMIZED jnz .exit mov [mouse.active_sys_window.pslot], esi lea eax, [edi + WDATA.box] @@ -238,15 +242,18 @@ mouse._.left_button_press_handler: ;/////////////////////////////////////////// call .calculate_w_delta jmp .call_window_handler - @@: test dl, mouse.WINDOW_RESIZE_W_FLAG + @@: + test dl, mouse.WINDOW_RESIZE_W_FLAG jz @f call .calculate_w_delta - @@: test dl, mouse.WINDOW_RESIZE_S_FLAG + @@: + test dl, mouse.WINDOW_RESIZE_S_FLAG jz @f call .calculate_s_delta - @@: test dl, mouse.WINDOW_RESIZE_E_FLAG + @@: + test dl, mouse.WINDOW_RESIZE_E_FLAG jz .call_window_handler call .calculate_e_delta @@ -389,17 +396,20 @@ mouse._.move_handler: ;//////////////////////////////////////////////////////// jge @f xor eax, eax mov [mouse.active_sys_window.new_box.left], eax - @@: add eax, [mouse.active_sys_window.new_box.width] + @@: + add eax, [mouse.active_sys_window.new_box.width] cmp eax, [Screen_Max_X] jl @f sub eax, [Screen_Max_X] sub [mouse.active_sys_window.new_box.left], eax - @@: mov eax, [mouse.active_sys_window.new_box.top] + @@: + mov eax, [mouse.active_sys_window.new_box.top] or eax, eax jge @f xor eax, eax mov [mouse.active_sys_window.new_box.top], eax - @@: add eax, [mouse.active_sys_window.new_box.height] + @@: + add eax, [mouse.active_sys_window.new_box.height] cmp eax, [Screen_Max_Y] jle .call_window_handler sub eax, [Screen_Max_Y] @@ -421,7 +431,8 @@ mouse._.move_handler: ;//////////////////////////////////////////////////////// jge @f add [mouse.active_sys_window.new_box.left], eax mov [mouse.active_sys_window.new_box.width], 127 - @@: mov eax, [mouse.active_sys_window.new_box.left] + @@: + mov eax, [mouse.active_sys_window.new_box.left] or eax, eax jge .check_resize_s add [mouse.active_sys_window.new_box.width], eax @@ -449,7 +460,8 @@ mouse._.move_handler: ;//////////////////////////////////////////////////////// jge @f mov eax, ecx mov [mouse.active_sys_window.new_box.height], eax - @@: add eax, [mouse.active_sys_window.new_box.top] + @@: + add eax, [mouse.active_sys_window.new_box.top] cmp eax, [Screen_Max_Y] jle .check_resize_e sub eax, [Screen_Max_Y] @@ -474,7 +486,8 @@ mouse._.move_handler: ;//////////////////////////////////////////////////////// jge @f mov eax, 127 mov [mouse.active_sys_window.new_box.width], eax - @@: add eax, [mouse.active_sys_window.new_box.left] + @@: + add eax, [mouse.active_sys_window.new_box.left] cmp eax, [Screen_Max_X] jle .call_window_handler sub eax, [Screen_Max_X] diff --git a/kernel/trunk/gui/mousepointer.inc b/kernel/trunk/gui/mousepointer.inc index 98b38f88c..305c93a61 100644 --- a/kernel/trunk/gui/mousepointer.inc +++ b/kernel/trunk/gui/mousepointer.inc @@ -1,250 +1,250 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -iglobal - -align 4 -mousepointer: -db 0x00,0x00,0x00,0x74,0x74,0x74,0x6e,0x6e,0x6e,0x6f -db 0x6f,0x6f,0x71,0x71,0x71,0x75,0x75,0x75,0x79,0x79 -db 0x79,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63 -db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 -db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0 -db 0xc0,0xc0,0x00,0x00,0x00,0x54,0x54,0x54,0x57,0x57 -db 0x57,0x5f,0x5f,0x5f,0x68,0x68,0x68,0x71,0x71,0x71 -db 0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x47,0x47,0x47,0x50 -db 0x50,0x50,0x5b,0x5b,0x5b,0x67,0x67,0x67,0x70,0x70 -db 0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3f,0x3f,0x3f -db 0x4b,0x4b,0x4b,0x59,0x59,0x59,0x66,0x66,0x66,0x70 -db 0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e -db 0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3a,0x3a -db 0x3a,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66,0x66 -db 0x70,0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e -db 0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x39 -db 0x39,0x39,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66 -db 0x66,0x71,0x71,0x71,0x78,0x78,0x78,0x7c,0x7c,0x7c -db 0x7e,0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0xff -db 0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00 -db 0x39,0x39,0x39,0x4a,0x4a,0x4a,0x5a,0x5a,0x5a,0x68 -db 0x68,0x68,0x72,0x72,0x72,0x79,0x79,0x79,0x7d,0x7d -db 0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00 -db 0x00,0x3c,0x3c,0x3c,0x4e,0x4e,0x4e,0x5e,0x5e,0x5e -db 0x6b,0x6b,0x6b,0x75,0x75,0x75,0x7a,0x7a,0x7a,0x7e -db 0x7e,0x7e,0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00 -db 0x00,0x00,0x43,0x43,0x43,0x55,0x55,0x55,0x64,0x64 -db 0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d -db 0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0 -db 0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x4e,0x4e,0x4e,0x5f,0x5f,0x5f,0x6d -db 0x6d,0x6d,0x76,0x76,0x76,0x7c,0x7c,0x7c,0x80,0x80 -db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 -db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x14 -db 0x14,0x14,0x1b,0x1b,0x1b,0x29,0x29,0x29,0x3a,0x3a -db 0x3a,0x4c,0x4c,0x4c,0x5d,0x5d,0x5d,0x6c,0x6c,0x6c -db 0x75,0x75,0x75,0x7b,0x7b,0x7b,0x80,0x80,0x80,0xc0 -db 0xc0,0xc0,0x00,0x00,0x00,0x2f,0x2f,0x2f,0x80,0x80 -db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 -db 0x21,0x21,0x21,0x2e,0x2e,0x2e,0x40,0x40,0x40,0x52 -db 0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f,0x77,0x77 -db 0x77,0x7c,0x7c,0x7c,0x80,0x80,0x80,0x00,0x00,0x00 -db 0x47,0x47,0x47,0x3b,0x3b,0x3b,0x80,0x80,0x80,0xff -db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x25,0x25 -db 0x25,0x30,0x30,0x30,0x42,0x42,0x42,0x54,0x54,0x54 -db 0x64,0x64,0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d -db 0x7d,0x7d,0x00,0x00,0x00,0x62,0x62,0x62,0x52,0x52 -db 0x52,0x4a,0x4a,0x4a,0x43,0x43,0x43,0x80,0x80,0x80 -db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x33 -db 0x33,0x33,0x42,0x42,0x42,0x54,0x54,0x54,0x64,0x64 -db 0x64,0x71,0x71,0x71,0x79,0x79,0x79,0x7d,0x7d,0x7d -db 0x72,0x72,0x72,0x6b,0x6b,0x6b,0x5f,0x5f,0x5f,0x5a -db 0x5a,0x5a,0x54,0x54,0x54,0x80,0x80,0x80,0xff,0xff -db 0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x35,0x35,0x35 -db 0x41,0x41,0x41,0x53,0x53,0x53,0x63,0x63,0x63,0x70 -db 0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d,0x77,0x77 -db 0x77,0x73,0x73,0x73,0x6c,0x6c,0x6c,0x68,0x68,0x68 -db 0x62,0x62,0x62,0x5a,0x5a,0x5a,0x80,0x80,0x80,0xff -db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x41,0x41 -db 0x41,0x52,0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f -db 0x78,0x78,0x78,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x79 -db 0x79,0x79,0x74,0x74,0x74,0x72,0x72,0x72,0x6e,0x6e -db 0x6e,0x66,0x66,0x66,0x80,0x80,0x80,0xc0,0xc0,0xc0 -db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x44,0x44,0x44,0x52 -db 0x52,0x52,0x62,0x62,0x62,0x6e,0x6e,0x6e,0x77,0x77 -db 0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7c,0x7c,0x7c -db 0x7a,0x7a,0x7a,0x79,0x79,0x79,0x75,0x75,0x75,0x6f -db 0x6f,0x6f,0x65,0x65,0x65,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x48,0x48,0x48,0x4b,0x4b,0x4b,0x56,0x56,0x56 -db 0x65,0x65,0x65,0x70,0x70,0x70,0x78,0x78,0x78,0x7d -db 0x7d,0x7d,0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e -db 0x7e,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76,0x76 -db 0x6f,0x6f,0x6f,0x65,0x65,0x65,0x5c,0x5c,0x5c,0x56 -db 0x56,0x56,0x58,0x58,0x58,0x60,0x60,0x60,0x6b,0x6b -db 0x6b,0x73,0x73,0x73,0x7a,0x7a,0x7a,0x7d,0x7d,0x7d -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7f -db 0x7f,0x7f,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76 -db 0x76,0x70,0x70,0x70,0x6a,0x6a,0x6a,0x66,0x66,0x66 -db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 -db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x77 -db 0x77,0x77,0x73,0x73,0x73,0x71,0x71,0x71,0x71,0x71 -db 0x71,0x74,0x74,0x74,0x78,0x78,0x78,0x7b,0x7b,0x7b -db 0x7d,0x7d,0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7c,0x7c,0x7c -db 0x7a,0x7a,0x7a,0x78,0x78,0x78,0x78,0x78,0x78,0x7a -db 0x7a,0x7a,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7f,0x7f -db 0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 -db 0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7e,0x7e -db 0x7e,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e -db 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 -db 0x80,0x80 - -mousepointer1: -db 0xff,0xff,0xff,0x06,0x06,0x06,0x0a,0x0a -db 0x0a,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x19,0x16 -db 0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2e,0x2e,0x2e -db 0x23,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f -db 0x3f,0x29,0x29,0x29,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x47 -db 0x47,0x47,0x2c,0x2c,0x2c,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0x47,0x47,0x47,0x29,0x29,0x29 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0x40,0x40,0x40,0x23,0x23 -db 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xaa,0xaa,0xaa,0x9f,0x9f,0x9f,0x8c,0x8c,0x8c -db 0x70,0x70,0x70,0x4f,0x4f,0x4f,0x30,0x30,0x30,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x8f,0x8f -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0xff,0x9c,0x9c,0x9c,0x87,0x87,0x87,0x6c,0x6c -db 0x6c,0x4f,0x4f,0x4f,0x32,0x32,0x32,0x19,0x19,0x19 -db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff -db 0xff,0xff,0x69,0x69,0x69,0x84,0x84,0x84,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0x92,0x92,0x92,0x79,0x79,0x79,0x59,0x59,0x59,0x3c -db 0x3c,0x3c,0x24,0x24,0x24,0x11,0x11,0x11,0x00,0x00 -db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x37,0x37,0x37 -db 0x5d,0x5d,0x5d,0x70,0x70,0x70,0x76,0x76,0x76,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0xff,0x75,0x75,0x75,0x51,0x51,0x51,0x31,0x31,0x31 -db 0x19,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x16,0x16,0x16,0x2d,0x2d,0x2d,0x49,0x49 -db 0x49,0x53,0x53,0x53,0x54,0x54,0x54,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x78 -db 0x78,0x78,0x54,0x54,0x54,0x30,0x30,0x30,0x16,0x16 -db 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x0f,0x0f,0x0f,0x1f,0x1f,0x1f,0x30,0x30,0x30,0x33 -db 0x33,0x33,0x33,0x33,0x33,0x3b,0x3b,0x3b,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff -db 0x62,0x62,0x62,0x3b,0x3b,0x3b,0x1c,0x1c,0x1c,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08 -db 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x24,0x24,0x24,0xff,0xff,0xff,0xff -db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6e,0x6e -db 0x6e,0x48,0x48,0x48,0x25,0x25,0x25,0x0e,0x0e,0x0e -db 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00 -db 0x00,0x00,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x29,0x29,0x29,0xff,0xff,0xff -db 0xff,0xff,0xff,0x7c,0x7c,0x7c,0x71,0x71,0x71,0x50 -db 0x50,0x50,0x2b,0x2b,0x2b,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x02,0x02,0x02,0x04,0x04,0x04,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x56,0x56 -db 0x56,0x69,0x69,0x69,0x64,0x64,0x64,0x4a,0x4a,0x4a -db 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x05,0x05,0x05 -db 0x00,0x00,0x00,0x21,0x21,0x21,0x39,0x39,0x39,0x49 -db 0x49,0x49,0x48,0x48,0x48,0x35,0x35,0x35,0x1d,0x1d -db 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x1d,0x1d,0x1d,0x27,0x27,0x27 -db 0x27,0x27,0x27,0x1d,0x1d,0x1d,0x0f,0x0f,0x0f,0x06 -db 0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -db 0x00,0x00,0x00,0x00 - -endg +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +iglobal + +align 4 +mousepointer: +db 0x00,0x00,0x00,0x74,0x74,0x74,0x6e,0x6e,0x6e,0x6f +db 0x6f,0x6f,0x71,0x71,0x71,0x75,0x75,0x75,0x79,0x79 +db 0x79,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63 +db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 +db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0 +db 0xc0,0xc0,0x00,0x00,0x00,0x54,0x54,0x54,0x57,0x57 +db 0x57,0x5f,0x5f,0x5f,0x68,0x68,0x68,0x71,0x71,0x71 +db 0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x47,0x47,0x47,0x50 +db 0x50,0x50,0x5b,0x5b,0x5b,0x67,0x67,0x67,0x70,0x70 +db 0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3f,0x3f,0x3f +db 0x4b,0x4b,0x4b,0x59,0x59,0x59,0x66,0x66,0x66,0x70 +db 0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e,0x7e +db 0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x3a,0x3a +db 0x3a,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66,0x66 +db 0x70,0x70,0x70,0x77,0x77,0x77,0x7c,0x7c,0x7c,0x7e +db 0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x39 +db 0x39,0x39,0x49,0x49,0x49,0x59,0x59,0x59,0x66,0x66 +db 0x66,0x71,0x71,0x71,0x78,0x78,0x78,0x7c,0x7c,0x7c +db 0x7e,0x7e,0x7e,0x80,0x80,0x80,0x80,0x80,0x80,0xff +db 0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00 +db 0x39,0x39,0x39,0x4a,0x4a,0x4a,0x5a,0x5a,0x5a,0x68 +db 0x68,0x68,0x72,0x72,0x72,0x79,0x79,0x79,0x7d,0x7d +db 0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00 +db 0x00,0x3c,0x3c,0x3c,0x4e,0x4e,0x4e,0x5e,0x5e,0x5e +db 0x6b,0x6b,0x6b,0x75,0x75,0x75,0x7a,0x7a,0x7a,0x7e +db 0x7e,0x7e,0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00 +db 0x00,0x00,0x43,0x43,0x43,0x55,0x55,0x55,0x64,0x64 +db 0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d +db 0x80,0x80,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xc0 +db 0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x4e,0x4e,0x4e,0x5f,0x5f,0x5f,0x6d +db 0x6d,0x6d,0x76,0x76,0x76,0x7c,0x7c,0x7c,0x80,0x80 +db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x14 +db 0x14,0x14,0x1b,0x1b,0x1b,0x29,0x29,0x29,0x3a,0x3a +db 0x3a,0x4c,0x4c,0x4c,0x5d,0x5d,0x5d,0x6c,0x6c,0x6c +db 0x75,0x75,0x75,0x7b,0x7b,0x7b,0x80,0x80,0x80,0xc0 +db 0xc0,0xc0,0x00,0x00,0x00,0x2f,0x2f,0x2f,0x80,0x80 +db 0x80,0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00 +db 0x21,0x21,0x21,0x2e,0x2e,0x2e,0x40,0x40,0x40,0x52 +db 0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f,0x77,0x77 +db 0x77,0x7c,0x7c,0x7c,0x80,0x80,0x80,0x00,0x00,0x00 +db 0x47,0x47,0x47,0x3b,0x3b,0x3b,0x80,0x80,0x80,0xff +db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x25,0x25 +db 0x25,0x30,0x30,0x30,0x42,0x42,0x42,0x54,0x54,0x54 +db 0x64,0x64,0x64,0x70,0x70,0x70,0x78,0x78,0x78,0x7d +db 0x7d,0x7d,0x00,0x00,0x00,0x62,0x62,0x62,0x52,0x52 +db 0x52,0x4a,0x4a,0x4a,0x43,0x43,0x43,0x80,0x80,0x80 +db 0xff,0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x33 +db 0x33,0x33,0x42,0x42,0x42,0x54,0x54,0x54,0x64,0x64 +db 0x64,0x71,0x71,0x71,0x79,0x79,0x79,0x7d,0x7d,0x7d +db 0x72,0x72,0x72,0x6b,0x6b,0x6b,0x5f,0x5f,0x5f,0x5a +db 0x5a,0x5a,0x54,0x54,0x54,0x80,0x80,0x80,0xff,0xff +db 0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x35,0x35,0x35 +db 0x41,0x41,0x41,0x53,0x53,0x53,0x63,0x63,0x63,0x70 +db 0x70,0x70,0x78,0x78,0x78,0x7d,0x7d,0x7d,0x77,0x77 +db 0x77,0x73,0x73,0x73,0x6c,0x6c,0x6c,0x68,0x68,0x68 +db 0x62,0x62,0x62,0x5a,0x5a,0x5a,0x80,0x80,0x80,0xff +db 0xff,0xff,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x41,0x41 +db 0x41,0x52,0x52,0x52,0x62,0x62,0x62,0x6f,0x6f,0x6f +db 0x78,0x78,0x78,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x79 +db 0x79,0x79,0x74,0x74,0x74,0x72,0x72,0x72,0x6e,0x6e +db 0x6e,0x66,0x66,0x66,0x80,0x80,0x80,0xc0,0xc0,0xc0 +db 0xc0,0xc0,0xc0,0x00,0x00,0x00,0x44,0x44,0x44,0x52 +db 0x52,0x52,0x62,0x62,0x62,0x6e,0x6e,0x6e,0x77,0x77 +db 0x77,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7c,0x7c,0x7c +db 0x7a,0x7a,0x7a,0x79,0x79,0x79,0x75,0x75,0x75,0x6f +db 0x6f,0x6f,0x65,0x65,0x65,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x48,0x48,0x48,0x4b,0x4b,0x4b,0x56,0x56,0x56 +db 0x65,0x65,0x65,0x70,0x70,0x70,0x78,0x78,0x78,0x7d +db 0x7d,0x7d,0x80,0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e +db 0x7e,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76,0x76 +db 0x6f,0x6f,0x6f,0x65,0x65,0x65,0x5c,0x5c,0x5c,0x56 +db 0x56,0x56,0x58,0x58,0x58,0x60,0x60,0x60,0x6b,0x6b +db 0x6b,0x73,0x73,0x73,0x7a,0x7a,0x7a,0x7d,0x7d,0x7d +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7f +db 0x7f,0x7f,0x7d,0x7d,0x7d,0x7a,0x7a,0x7a,0x76,0x76 +db 0x76,0x70,0x70,0x70,0x6a,0x6a,0x6a,0x66,0x66,0x66 +db 0x66,0x66,0x66,0x6c,0x6c,0x6c,0x72,0x72,0x72,0x78 +db 0x78,0x78,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7b,0x7b,0x7b,0x77 +db 0x77,0x77,0x73,0x73,0x73,0x71,0x71,0x71,0x71,0x71 +db 0x71,0x74,0x74,0x74,0x78,0x78,0x78,0x7b,0x7b,0x7b +db 0x7d,0x7d,0x7d,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x7f,0x7f,0x7f,0x7d,0x7d,0x7d,0x7c,0x7c,0x7c +db 0x7a,0x7a,0x7a,0x78,0x78,0x78,0x78,0x78,0x78,0x7a +db 0x7a,0x7a,0x7c,0x7c,0x7c,0x7e,0x7e,0x7e,0x7f,0x7f +db 0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 +db 0x80,0x80,0x7f,0x7f,0x7f,0x7e,0x7e,0x7e,0x7e,0x7e +db 0x7e,0x7d,0x7d,0x7d,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e +db 0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,0x80 +db 0x80,0x80 + +mousepointer1: +db 0xff,0xff,0xff,0x06,0x06,0x06,0x0a,0x0a +db 0x0a,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x19,0x16 +db 0x16,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2e,0x2e,0x2e +db 0x23,0x23,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x3f +db 0x3f,0x29,0x29,0x29,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x47 +db 0x47,0x47,0x2c,0x2c,0x2c,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x16,0x16,0x16 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0x48,0x48,0x48,0x2c,0x2c,0x2c,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0x47,0x47,0x47,0x29,0x29,0x29 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0x40,0x40,0x40,0x23,0x23 +db 0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xaa,0xaa,0xaa,0x9f,0x9f,0x9f,0x8c,0x8c,0x8c +db 0x70,0x70,0x70,0x4f,0x4f,0x4f,0x30,0x30,0x30,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x8f,0x8f,0x8f +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0xff,0x9c,0x9c,0x9c,0x87,0x87,0x87,0x6c,0x6c +db 0x6c,0x4f,0x4f,0x4f,0x32,0x32,0x32,0x19,0x19,0x19 +db 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff +db 0xff,0xff,0x69,0x69,0x69,0x84,0x84,0x84,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0x92,0x92,0x92,0x79,0x79,0x79,0x59,0x59,0x59,0x3c +db 0x3c,0x3c,0x24,0x24,0x24,0x11,0x11,0x11,0x00,0x00 +db 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x37,0x37,0x37 +db 0x5d,0x5d,0x5d,0x70,0x70,0x70,0x76,0x76,0x76,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0xff,0x75,0x75,0x75,0x51,0x51,0x51,0x31,0x31,0x31 +db 0x19,0x19,0x19,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x16,0x16,0x16,0x2d,0x2d,0x2d,0x49,0x49 +db 0x49,0x53,0x53,0x53,0x54,0x54,0x54,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x78 +db 0x78,0x78,0x54,0x54,0x54,0x30,0x30,0x30,0x16,0x16 +db 0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x0f,0x0f,0x0f,0x1f,0x1f,0x1f,0x30,0x30,0x30,0x33 +db 0x33,0x33,0x33,0x33,0x33,0x3b,0x3b,0x3b,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +db 0x62,0x62,0x62,0x3b,0x3b,0x3b,0x1c,0x1c,0x1c,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08 +db 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x24,0x24,0x24,0xff,0xff,0xff,0xff +db 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x6e,0x6e +db 0x6e,0x48,0x48,0x48,0x25,0x25,0x25,0x0e,0x0e,0x0e +db 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x00 +db 0x00,0x00,0x0a,0x0a,0x0a,0x09,0x09,0x09,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x29,0x29,0x29,0xff,0xff,0xff +db 0xff,0xff,0xff,0x7c,0x7c,0x7c,0x71,0x71,0x71,0x50 +db 0x50,0x50,0x2b,0x2b,0x2b,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x02,0x02,0x02,0x04,0x04,0x04,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x56,0x56 +db 0x56,0x69,0x69,0x69,0x64,0x64,0x64,0x4a,0x4a,0x4a +db 0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x05,0x05,0x05 +db 0x00,0x00,0x00,0x21,0x21,0x21,0x39,0x39,0x39,0x49 +db 0x49,0x49,0x48,0x48,0x48,0x35,0x35,0x35,0x1d,0x1d +db 0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x1d,0x1d,0x1d,0x27,0x27,0x27 +db 0x27,0x27,0x27,0x1d,0x1d,0x1d,0x0f,0x0f,0x0f,0x06 +db 0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +db 0x00,0x00,0x00,0x00 + +endg diff --git a/kernel/trunk/gui/skincode.inc b/kernel/trunk/gui/skincode.inc index 7012f74b9..aec547c99 100644 --- a/kernel/trunk/gui/skincode.inc +++ b/kernel/trunk/gui/skincode.inc @@ -1,460 +1,466 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -include "skindata.inc" - -;skin_data = 0x00778000 - -read_skin_file: - stdcall load_file, ebx - test eax, eax - jz .notfound - cmp dword [eax], 'SKIN' - jnz .noskin - cmp ebx, 32*1024 - jb @f - mov ebx, 32*1024 -@@: - lea ecx, [ebx+3] - shr ecx, 2 - mov esi, eax - mov edi, skin_data - rep movsd - stdcall kernel_free, eax - - call parse_skin_data - xor eax, eax - ret -.notfound: - xor eax, eax - inc eax - ret -.noskin: - stdcall kernel_free, eax - push 2 - pop eax - ret - -struct SKIN_HEADER - .ident dd ? - .version dd ? - .params dd ? - .buttons dd ? - .bitmaps dd ? -ends - -struct SKIN_PARAMS - .skin_height dd ? - .margin.right dw ? - .margin.left dw ? - .margin.bottom dw ? - .margin.top dw ? - .colors.inner dd ? - .colors.outer dd ? - .colors.frame dd ? - .colors_1.inner dd ? - .colors_1.outer dd ? - .colors_1.frame dd ? - .dtp.size dd ? - .dtp.data db 40 dup (?) -ends - -struct SKIN_BUTTONS - .type dd ? +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +include "skindata.inc" + +;skin_data = 0x00778000 + +read_skin_file: + stdcall load_file, ebx + test eax, eax + jz .notfound + cmp dword [eax], 'SKIN' + jnz .noskin + cmp ebx, 32*1024 + jb @f + mov ebx, 32*1024 +@@: + lea ecx, [ebx+3] + shr ecx, 2 + mov esi, eax + mov edi, skin_data + rep movsd + stdcall kernel_free, eax + + call parse_skin_data + xor eax, eax + ret +.notfound: + xor eax, eax + inc eax + ret +.noskin: + stdcall kernel_free, eax + push 2 + pop eax + ret + +struct SKIN_HEADER + .ident dd ? + .version dd ? + .params dd ? + .buttons dd ? + .bitmaps dd ? +ends + +struct SKIN_PARAMS + .skin_height dd ? + .margin.right dw ? + .margin.left dw ? + .margin.bottom dw ? + .margin.top dw ? + .colors.inner dd ? + .colors.outer dd ? + .colors.frame dd ? + .colors_1.inner dd ? + .colors_1.outer dd ? + .colors_1.frame dd ? + .dtp.size dd ? + .dtp.data db 40 dup (?) +ends + +struct SKIN_BUTTONS + .type dd ? .pos: - .left dw ? - .top dw ? + .left dw ? + .top dw ? .size: - .width dw ? - .height dw ? -ends - -struct SKIN_BITMAPS - .kind dw ? - .type dw ? - .data dd ? -ends - -load_default_skin: - mov [_skinh],22 - mov ebx,_skin_file_default - call read_skin_file - ret - -parse_skin_data: - mov ebp,skin_data - cmp [ebp+SKIN_HEADER.ident],'SKIN' - jne .exit - - mov edi,skin_udata - mov ecx,(skin_udata.end-skin_udata)/4 - xor eax,eax - cld - rep stosd - - mov ebx,[ebp+SKIN_HEADER.params] - add ebx,skin_data - mov eax,[ebx+SKIN_PARAMS.skin_height] - mov [_skinh],eax - mov eax,[ebx+SKIN_PARAMS.colors.inner] - mov [skin_active.colors.inner],eax - mov eax,[ebx+SKIN_PARAMS.colors.outer] - mov [skin_active.colors.outer],eax - mov eax,[ebx+SKIN_PARAMS.colors.frame] - mov [skin_active.colors.frame],eax - mov eax,[ebx+SKIN_PARAMS.colors_1.inner] - mov [skin_inactive.colors.inner],eax - mov eax,[ebx+SKIN_PARAMS.colors_1.outer] - mov [skin_inactive.colors.outer],eax - mov eax,[ebx+SKIN_PARAMS.colors_1.frame] - mov [skin_inactive.colors.frame],eax - lea esi,[ebx+SKIN_PARAMS.dtp.data] - mov edi,common_colours - mov ecx,[ebx+SKIN_PARAMS.dtp.size] - and ecx,127 - rep movsb - mov eax,dword[ebx+SKIN_PARAMS.margin.right] - mov dword[_skinmargins+0],eax - mov eax,dword[ebx+SKIN_PARAMS.margin.bottom] - mov dword[_skinmargins+4],eax - - mov ebx,[ebp+SKIN_HEADER.bitmaps] - add ebx,skin_data - .lp1: cmp dword[ebx],0 - je .end_bitmaps - movzx eax,[ebx+SKIN_BITMAPS.kind] - movzx ecx,[ebx+SKIN_BITMAPS.type] - dec eax - jnz .not_left - xor eax,eax - mov edx,skin_active.left.data - or ecx,ecx - jnz @f - mov edx,skin_inactive.left.data - @@: jmp .next_bitmap - .not_left: - dec eax - jnz .not_oper - mov esi,[ebx+SKIN_BITMAPS.data] - add esi,skin_data - mov eax,[esi+0] - neg eax - mov edx,skin_active.oper.data - or ecx,ecx - jnz @f - mov edx,skin_inactive.oper.data - @@: jmp .next_bitmap - .not_oper: - dec eax - jnz .not_base - mov eax,[skin_active.left.width] - mov edx,skin_active.base.data - or ecx,ecx - jnz @f - mov eax,[skin_inactive.left.width] - mov edx,skin_inactive.base.data - @@: jmp .next_bitmap - .not_base: - add ebx,8 - jmp .lp1 - .next_bitmap: - mov ecx,[ebx+SKIN_BITMAPS.data] - add ecx,skin_data - mov [edx+4],eax - mov eax,[ecx+0] - mov [edx+8],eax - add ecx,8 - mov [edx+0],ecx - add ebx,8 - jmp .lp1 - .end_bitmaps: - - mov ebx,[ebp+SKIN_HEADER.buttons] - add ebx,skin_data - .lp2: cmp dword[ebx],0 - je .end_buttons - mov eax,[ebx+SKIN_BUTTONS.type] - dec eax - jnz .not_close - mov edx,skin_btn_close - jmp .next_button - .not_close: - dec eax - jnz .not_minimize - mov edx,skin_btn_minimize - jmp .next_button - .not_minimize: - add ebx,12 - jmp .lp2 - .next_button: - movsx eax,[ebx+SKIN_BUTTONS.left] - mov [edx+SKIN_BUTTON.left],eax - movsx eax,[ebx+SKIN_BUTTONS.top] - mov [edx+SKIN_BUTTON.top],eax - movsx eax,[ebx+SKIN_BUTTONS.width] - mov [edx+SKIN_BUTTON.width],eax - movsx eax,[ebx+SKIN_BUTTONS.height] - mov [edx+SKIN_BUTTON.height],eax - add ebx,12 - jmp .lp2 - .end_buttons: - - .exit: - ret - -sys_putimage_with_check: - or ebx,ebx - jz @f - call sys_putimage.forced - @@: ret - -drawwindow_IV_caption: - - mov ebp,skin_active - or al,al - jnz @f - mov ebp,skin_inactive - @@: - - mov esi,[esp+4] - mov eax,[esi+WDATA.box.width] ; window width - mov edx,[ebp+SKIN_DATA.left.left] - shl edx,16 - mov ecx,[ebp+SKIN_DATA.left.width] - shl ecx,16 - add ecx,[_skinh] - - mov ebx, [ebp+SKIN_DATA.left.data] - call sys_putimage_with_check - - mov esi,[esp+4] - mov eax,[esi+WDATA.box.width] - sub eax,[ebp+SKIN_DATA.left.width] - sub eax,[ebp+SKIN_DATA.oper.width] - cmp eax,[ebp+SKIN_DATA.base.left] - jng .non_base - xor edx,edx - mov ecx,[ebp+SKIN_DATA.base.width] - jecxz .non_base - div ecx - - inc eax - - mov ebx,[ebp+SKIN_DATA.base.data] - mov ecx,[ebp+SKIN_DATA.base.width] - shl ecx,16 - add ecx,[_skinh] - mov edx,[ebp+SKIN_DATA.base.left] - sub edx,[ebp+SKIN_DATA.base.width] - shl edx,16 - .baseskinloop: - shr edx,16 - add edx,[ebp+SKIN_DATA.base.width] - shl edx,16 - - push eax ebx ecx edx - call sys_putimage_with_check - pop edx ecx ebx eax - - dec eax - jnz .baseskinloop - .non_base: - - mov esi,[esp+4] - mov edx,[esi+WDATA.box.width] - sub edx,[ebp+SKIN_DATA.oper.width] - inc edx - shl edx,16 - mov ebx,[ebp+SKIN_DATA.oper.data] - - mov ecx,[ebp+SKIN_DATA.oper.width] - shl ecx,16 - add ecx,[_skinh] - call sys_putimage_with_check - - ret - -;//mike.dld, 2006-08-02 ] - - -drawwindow_IV: -;param1 - aw_yes - - pusha - - push edx - - mov edi,edx - - mov ebp,skin_active - cmp byte [esp+32+4+4],0 - jne @f - mov ebp,skin_inactive - @@: - - mov eax,[edi+WDATA.box.left] - shl eax,16 - mov ax,word [edi+WDATA.box.left] - add ax,word [edi+WDATA.box.width] - mov ebx,[edi+WDATA.box.top] - shl ebx,16 - mov bx,word [edi+WDATA.box.top] - add bx,word [edi+WDATA.box.height] -; mov esi,[edi+24] -; shr esi,1 -; and esi,0x007f7f7f - mov esi,[ebp+SKIN_DATA.colors.outer] - call draw_rectangle - mov ecx,3 - _dw3l: - add eax,1*65536-1 - add ebx,1*65536-1 - test ax,ax - js no_skin_add_button - test bx,bx - js no_skin_add_button - mov esi,[ebp+SKIN_DATA.colors.frame] ;[edi+24] - call draw_rectangle - dec ecx - jnz _dw3l - mov esi,[ebp+SKIN_DATA.colors.inner] - add eax,1*65536-1 - add ebx,1*65536-1 - test ax,ax - js no_skin_add_button - test bx,bx - js no_skin_add_button - call draw_rectangle - - cmp dword[skin_data],'SKIN' - je @f - xor eax,eax - xor ebx,ebx - mov esi,[esp] - mov ecx,[esi+WDATA.box.width] - inc ecx - mov edx,[_skinh] - mov edi,[common_colours+4] ; standard grab color - call [drawbar] - jmp draw_clientbar - @@: - - mov al,[esp+32+4+4] - call drawwindow_IV_caption - - draw_clientbar: - - mov esi,[esp] - - mov edx,[esi+WDATA.box.top] ; WORK AREA - add edx,21+5 - mov ebx,[esi+WDATA.box.top] - add ebx,[esi+WDATA.box.height] - cmp edx,ebx - jg _noinside2 - mov eax,5 - mov ebx,[_skinh] - mov ecx,[esi+WDATA.box.width] - mov edx,[esi+WDATA.box.height] - sub ecx,4 - sub edx,4 - mov edi,[esi+WDATA.cl_workarea] - test edi,0x40000000 - jnz _noinside2 - call [drawbar] - _noinside2: - - cmp dword[skin_data],'SKIN' - jne no_skin_add_button - -;* close button - mov edi,[BTN_ADDR] - movzx eax,word [edi] - cmp eax,1000 - jge no_skin_add_button - inc eax - mov [edi],ax - - shl eax,4 - add eax,edi - - mov bx,[CURRENT_TASK] - mov [eax],bx - - add eax,2 ; save button id number - mov bx,1 - mov [eax],bx - add eax,2 ; x start - xor ebx,ebx - cmp [skin_btn_close.left],0 - jge _bCx_at_right - mov ebx,[esp] - mov ebx,[ebx+WDATA.box.width] - inc ebx - _bCx_at_right: - add ebx,[skin_btn_close.left] - mov [eax],bx - add eax,2 ; x size - mov ebx,[skin_btn_close.width] - dec ebx - mov [eax],bx - add eax,2 ; y start - mov ebx,[skin_btn_close.top] - mov [eax],bx - add eax,2 ; y size - mov ebx,[skin_btn_close.height] - dec ebx - mov [eax],bx - -;* minimize button - mov edi,[BTN_ADDR] - movzx eax,word [edi] - cmp eax,1000 - jge no_skin_add_button - inc eax - mov [edi],ax - - shl eax,4 - add eax,edi - - mov bx,[CURRENT_TASK] - mov [eax],bx - - add eax,2 ; save button id number - mov bx,65535 ;999 - mov [eax],bx - add eax,2 ; x start - xor ebx,ebx - cmp [skin_btn_minimize.left],0 - jge _bMx_at_right - mov ebx,[esp] - mov ebx,[ebx+WDATA.box.width] - inc ebx - _bMx_at_right: - add ebx,[skin_btn_minimize.left] - mov [eax],bx - add eax,2 ; x size - mov ebx,[skin_btn_minimize.width] - dec ebx - mov [eax],bx - add eax,2 ; y start - mov ebx,[skin_btn_minimize.top] - mov [eax],bx - add eax,2 ; y size - mov ebx,[skin_btn_minimize.height] - dec ebx - mov [eax],bx - - no_skin_add_button: - pop edi - popa - - ret 4 - + .width dw ? + .height dw ? +ends + +struct SKIN_BITMAPS + .kind dw ? + .type dw ? + .data dd ? +ends + +load_default_skin: + mov [_skinh], 22 + mov ebx, _skin_file_default + call read_skin_file + ret + +parse_skin_data: + mov ebp, skin_data + cmp [ebp+SKIN_HEADER.ident], 'SKIN' + jne .exit + + mov edi, skin_udata + mov ecx, (skin_udata.end-skin_udata)/4 + xor eax, eax + cld + rep stosd + + mov ebx, [ebp+SKIN_HEADER.params] + add ebx, skin_data + mov eax, [ebx+SKIN_PARAMS.skin_height] + mov [_skinh], eax + mov eax, [ebx+SKIN_PARAMS.colors.inner] + mov [skin_active.colors.inner], eax + mov eax, [ebx+SKIN_PARAMS.colors.outer] + mov [skin_active.colors.outer], eax + mov eax, [ebx+SKIN_PARAMS.colors.frame] + mov [skin_active.colors.frame], eax + mov eax, [ebx+SKIN_PARAMS.colors_1.inner] + mov [skin_inactive.colors.inner], eax + mov eax, [ebx+SKIN_PARAMS.colors_1.outer] + mov [skin_inactive.colors.outer], eax + mov eax, [ebx+SKIN_PARAMS.colors_1.frame] + mov [skin_inactive.colors.frame], eax + lea esi, [ebx+SKIN_PARAMS.dtp.data] + mov edi, common_colours + mov ecx, [ebx+SKIN_PARAMS.dtp.size] + and ecx, 127 + rep movsb + mov eax, dword[ebx+SKIN_PARAMS.margin.right] + mov dword[_skinmargins+0], eax + mov eax, dword[ebx+SKIN_PARAMS.margin.bottom] + mov dword[_skinmargins+4], eax + + mov ebx, [ebp+SKIN_HEADER.bitmaps] + add ebx, skin_data + .lp1: + cmp dword[ebx], 0 + je .end_bitmaps + movzx eax, [ebx+SKIN_BITMAPS.kind] + movzx ecx, [ebx+SKIN_BITMAPS.type] + dec eax + jnz .not_left + xor eax, eax + mov edx, skin_active.left.data + or ecx, ecx + jnz @f + mov edx, skin_inactive.left.data + @@: + jmp .next_bitmap + .not_left: + dec eax + jnz .not_oper + mov esi, [ebx+SKIN_BITMAPS.data] + add esi, skin_data + mov eax, [esi+0] + neg eax + mov edx, skin_active.oper.data + or ecx, ecx + jnz @f + mov edx, skin_inactive.oper.data + @@: + jmp .next_bitmap + .not_oper: + dec eax + jnz .not_base + mov eax, [skin_active.left.width] + mov edx, skin_active.base.data + or ecx, ecx + jnz @f + mov eax, [skin_inactive.left.width] + mov edx, skin_inactive.base.data + @@: + jmp .next_bitmap + .not_base: + add ebx, 8 + jmp .lp1 + .next_bitmap: + mov ecx, [ebx+SKIN_BITMAPS.data] + add ecx, skin_data + mov [edx+4], eax + mov eax, [ecx+0] + mov [edx+8], eax + add ecx, 8 + mov [edx+0], ecx + add ebx, 8 + jmp .lp1 + .end_bitmaps: + + mov ebx, [ebp+SKIN_HEADER.buttons] + add ebx, skin_data + .lp2: + cmp dword[ebx], 0 + je .end_buttons + mov eax, [ebx+SKIN_BUTTONS.type] + dec eax + jnz .not_close + mov edx, skin_btn_close + jmp .next_button + .not_close: + dec eax + jnz .not_minimize + mov edx, skin_btn_minimize + jmp .next_button + .not_minimize: + add ebx, 12 + jmp .lp2 + .next_button: + movsx eax, [ebx+SKIN_BUTTONS.left] + mov [edx+SKIN_BUTTON.left], eax + movsx eax, [ebx+SKIN_BUTTONS.top] + mov [edx+SKIN_BUTTON.top], eax + movsx eax, [ebx+SKIN_BUTTONS.width] + mov [edx+SKIN_BUTTON.width], eax + movsx eax, [ebx+SKIN_BUTTONS.height] + mov [edx+SKIN_BUTTON.height], eax + add ebx, 12 + jmp .lp2 + .end_buttons: + + .exit: + ret + +sys_putimage_with_check: + or ebx, ebx + jz @f + call sys_putimage.forced + @@: + ret + +drawwindow_IV_caption: + + mov ebp, skin_active + or al, al + jnz @f + mov ebp, skin_inactive + @@: + + mov esi, [esp+4] + mov eax, [esi+WDATA.box.width] ; window width + mov edx, [ebp+SKIN_DATA.left.left] + shl edx, 16 + mov ecx, [ebp+SKIN_DATA.left.width] + shl ecx, 16 + add ecx, [_skinh] + + mov ebx, [ebp+SKIN_DATA.left.data] + call sys_putimage_with_check + + mov esi, [esp+4] + mov eax, [esi+WDATA.box.width] + sub eax, [ebp+SKIN_DATA.left.width] + sub eax, [ebp+SKIN_DATA.oper.width] + cmp eax, [ebp+SKIN_DATA.base.left] + jng .non_base + xor edx, edx + mov ecx, [ebp+SKIN_DATA.base.width] + jecxz .non_base + div ecx + + inc eax + + mov ebx, [ebp+SKIN_DATA.base.data] + mov ecx, [ebp+SKIN_DATA.base.width] + shl ecx, 16 + add ecx, [_skinh] + mov edx, [ebp+SKIN_DATA.base.left] + sub edx, [ebp+SKIN_DATA.base.width] + shl edx, 16 + .baseskinloop: + shr edx, 16 + add edx, [ebp+SKIN_DATA.base.width] + shl edx, 16 + + push eax ebx ecx edx + call sys_putimage_with_check + pop edx ecx ebx eax + + dec eax + jnz .baseskinloop + .non_base: + + mov esi, [esp+4] + mov edx, [esi+WDATA.box.width] + sub edx, [ebp+SKIN_DATA.oper.width] + inc edx + shl edx, 16 + mov ebx, [ebp+SKIN_DATA.oper.data] + + mov ecx, [ebp+SKIN_DATA.oper.width] + shl ecx, 16 + add ecx, [_skinh] + call sys_putimage_with_check + + ret + +;//mike.dld, 2006-08-02 ] + + +drawwindow_IV: +;param1 - aw_yes + + pusha + + push edx + + mov edi, edx + + mov ebp, skin_active + cmp byte [esp+32+4+4], 0 + jne @f + mov ebp, skin_inactive + @@: + + mov eax, [edi+WDATA.box.left] + shl eax, 16 + mov ax, word [edi+WDATA.box.left] + add ax, word [edi+WDATA.box.width] + mov ebx, [edi+WDATA.box.top] + shl ebx, 16 + mov bx, word [edi+WDATA.box.top] + add bx, word [edi+WDATA.box.height] +; mov esi,[edi+24] +; shr esi,1 +; and esi,0x007f7f7f + mov esi, [ebp+SKIN_DATA.colors.outer] + call draw_rectangle + mov ecx, 3 + _dw3l: + add eax, 1*65536-1 + add ebx, 1*65536-1 + test ax, ax + js no_skin_add_button + test bx, bx + js no_skin_add_button + mov esi, [ebp+SKIN_DATA.colors.frame];[edi+24] + call draw_rectangle + dec ecx + jnz _dw3l + mov esi, [ebp+SKIN_DATA.colors.inner] + add eax, 1*65536-1 + add ebx, 1*65536-1 + test ax, ax + js no_skin_add_button + test bx, bx + js no_skin_add_button + call draw_rectangle + + cmp dword[skin_data], 'SKIN' + je @f + xor eax, eax + xor ebx, ebx + mov esi, [esp] + mov ecx, [esi+WDATA.box.width] + inc ecx + mov edx, [_skinh] + mov edi, [common_colours+4]; standard grab color + call [drawbar] + jmp draw_clientbar + @@: + + mov al, [esp+32+4+4] + call drawwindow_IV_caption + + draw_clientbar: + + mov esi, [esp] + + mov edx, [esi+WDATA.box.top] ; WORK AREA + add edx, 21+5 + mov ebx, [esi+WDATA.box.top] + add ebx, [esi+WDATA.box.height] + cmp edx, ebx + jg _noinside2 + mov eax, 5 + mov ebx, [_skinh] + mov ecx, [esi+WDATA.box.width] + mov edx, [esi+WDATA.box.height] + sub ecx, 4 + sub edx, 4 + mov edi, [esi+WDATA.cl_workarea] + test edi, 0x40000000 + jnz _noinside2 + call [drawbar] + _noinside2: + + cmp dword[skin_data], 'SKIN' + jne no_skin_add_button + +;* close button + mov edi, [BTN_ADDR] + movzx eax, word [edi] + cmp eax, 1000 + jge no_skin_add_button + inc eax + mov [edi], ax + + shl eax, 4 + add eax, edi + + mov bx, [CURRENT_TASK] + mov [eax], bx + + add eax, 2 ; save button id number + mov bx, 1 + mov [eax], bx + add eax, 2 ; x start + xor ebx, ebx + cmp [skin_btn_close.left], 0 + jge _bCx_at_right + mov ebx, [esp] + mov ebx, [ebx+WDATA.box.width] + inc ebx + _bCx_at_right: + add ebx, [skin_btn_close.left] + mov [eax], bx + add eax, 2 ; x size + mov ebx, [skin_btn_close.width] + dec ebx + mov [eax], bx + add eax, 2 ; y start + mov ebx, [skin_btn_close.top] + mov [eax], bx + add eax, 2 ; y size + mov ebx, [skin_btn_close.height] + dec ebx + mov [eax], bx + +;* minimize button + mov edi, [BTN_ADDR] + movzx eax, word [edi] + cmp eax, 1000 + jge no_skin_add_button + inc eax + mov [edi], ax + + shl eax, 4 + add eax, edi + + mov bx, [CURRENT_TASK] + mov [eax], bx + + add eax, 2 ; save button id number + mov bx, 65535;999 + mov [eax], bx + add eax, 2 ; x start + xor ebx, ebx + cmp [skin_btn_minimize.left], 0 + jge _bMx_at_right + mov ebx, [esp] + mov ebx, [ebx+WDATA.box.width] + inc ebx + _bMx_at_right: + add ebx, [skin_btn_minimize.left] + mov [eax], bx + add eax, 2 ; x size + mov ebx, [skin_btn_minimize.width] + dec ebx + mov [eax], bx + add eax, 2 ; y start + mov ebx, [skin_btn_minimize.top] + mov [eax], bx + add eax, 2 ; y size + mov ebx, [skin_btn_minimize.height] + dec ebx + mov [eax], bx + + no_skin_add_button: + pop edi + popa + + ret 4 + diff --git a/kernel/trunk/gui/skindata.inc b/kernel/trunk/gui/skindata.inc index b2e3c1244..c5e80dc64 100644 --- a/kernel/trunk/gui/skindata.inc +++ b/kernel/trunk/gui/skindata.inc @@ -1,64 +1,64 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; -; WINDOW SKIN DATA -; - -iglobal - _skin_file_default db '/sys/DEFAULT.SKN',0 -endg - -struct SKIN_DATA - .colors.inner dd ? - .colors.outer dd ? - .colors.frame dd ? - .left.data dd ? - .left.left dd ? - .left.width dd ? - .oper.data dd ? - .oper.left dd ? - .oper.width dd ? - .base.data dd ? - .base.left dd ? - .base.width dd ? -ends - -struct SKIN_BUTTON - .left dd ? - .top dd ? - .width dd ? - .height dd ? -ends - -uglobal - -align 4 - -skin_udata: - _skinh dd ? - - _skinmargins: ; rw 4 - .right dw ? - .left dw ? - .bottom dw ? - .top dw ? - - skin_btn_close SKIN_BUTTON - skin_btn_minimize SKIN_BUTTON - - skin_active SKIN_DATA - skin_inactive SKIN_DATA - -align 4 - -skin_udata.end: - -endg +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; +; WINDOW SKIN DATA +; + +iglobal + _skin_file_default db '/sys/DEFAULT.SKN',0 +endg + +struct SKIN_DATA + .colors.inner dd ? + .colors.outer dd ? + .colors.frame dd ? + .left.data dd ? + .left.left dd ? + .left.width dd ? + .oper.data dd ? + .oper.left dd ? + .oper.width dd ? + .base.data dd ? + .base.left dd ? + .base.width dd ? +ends + +struct SKIN_BUTTON + .left dd ? + .top dd ? + .width dd ? + .height dd ? +ends + +uglobal + +align 4 + +skin_udata: + _skinh dd ? + + _skinmargins: ; rw 4 + .right dw ? + .left dw ? + .bottom dw ? + .top dw ? + + skin_btn_close SKIN_BUTTON + skin_btn_minimize SKIN_BUTTON + + skin_active SKIN_DATA + skin_inactive SKIN_DATA + +align 4 + +skin_udata.end: + +endg diff --git a/kernel/trunk/gui/window.inc b/kernel/trunk/gui/window.inc index 8bfc01ca4..8b376ae6c 100644 --- a/kernel/trunk/gui/window.inc +++ b/kernel/trunk/gui/window.inc @@ -56,7 +56,8 @@ syscall_draw_window: ;///// system function 0 ///////////////////////////////// call drawwindow_I jmp window._.draw_window_caption.2 - @@: dec al + @@: + dec al jnz @f ; type II - only reserve area, no draw @@ -65,7 +66,8 @@ syscall_draw_window: ;///// system function 0 ///////////////////////////////// call [draw_pointer] jmp .exit - @@: dec al + @@: + dec al jnz @f ; type III - new style @@ -73,7 +75,8 @@ syscall_draw_window: ;///// system function 0 ///////////////////////////////// jmp window._.draw_window_caption.2 ; type IV & V - skinned window (resizable & not) - @@: mov eax, [TASK_COUNT] + @@: + mov eax, [TASK_COUNT] movzx eax, word[WIN_POS + eax * 2] cmp eax, [CURRENT_TASK] setz al @@ -133,7 +136,8 @@ syscall_display_settings: ;///// system function 48 /////////////////////////// cmp ebx, .sizeof.ftable / 4 ja @f jmp [.ftable + ebx * 4] - @@: ret + @@: + ret align 4 @@ -167,7 +171,7 @@ syscall_display_settings.02: and edx, 127 mov edi, common_colours mov ecx, edx - rep movsb + rep movsb mov [windowtypechanged], ebx ret @@ -177,7 +181,7 @@ syscall_display_settings.03: and edx, 127 mov esi, common_colours mov ecx, edx - rep movsb + rep movsb ret align 4 @@ -210,11 +214,13 @@ syscall_display_settings.06: or eax, eax jge @f xor eax, eax - @@: mov [screen_workarea.left], eax + @@: + mov [screen_workarea.left], eax cmp ebx, edi jle @f mov ebx, edi - @@: mov [screen_workarea.right], ebx + @@: + mov [screen_workarea.right], ebx .check_horizontal: mov edi, [Screen_Max_Y] @@ -227,11 +233,13 @@ syscall_display_settings.06: or eax, eax jge @f xor eax, eax - @@: mov [screen_workarea.top], eax + @@: + mov [screen_workarea.top], eax cmp ebx, edi jle @f mov ebx, edi - @@: mov [screen_workarea.bottom], ebx + @@: + mov [screen_workarea.bottom], ebx .check_if_redraw_needed: or esi, esi @@ -328,17 +336,21 @@ syscall_move_window: ;///// system function 67 //////////////////////////////// cmp ebx, -1 jne @f mov ebx, [edi + WDATA.box.left] - @@: cmp ecx, -1 + @@: + cmp ecx, -1 jne @f mov ecx, [edi + WDATA.box.top] - @@: cmp edx, -1 + @@: + cmp edx, -1 jne @f mov edx, [edi + WDATA.box.width] - @@: cmp esi, -1 + @@: + cmp esi, -1 jne @f mov esi, [edi + WDATA.box.height] - @@: push esi edx ecx ebx + @@: + push esi edx ecx ebx mov eax, esp mov bl, [edi + WDATA.fl_wstate] call window._.set_window_box @@ -399,7 +411,8 @@ set_window_defaults: ;///////////////////////////////////////////////////////// push eax ecx xor eax, eax mov ecx, WIN_STACK - @@: inc eax + @@: + inc eax add ecx, 2 ; process no mov [ecx + 0x000], ax @@ -466,17 +479,21 @@ calculatescreen: ;///////////////////////////////////////////////////////////// cmp eax, [esp + RECT.left] jae @f mov eax, [esp + RECT.left] - @@: cmp ebx, [esp + RECT.top] + @@: + cmp ebx, [esp + RECT.top] jae @f mov ebx, [esp + RECT.top] - @@: cmp ecx, [esp + RECT.right] + @@: + cmp ecx, [esp + RECT.right] jbe @f mov ecx, [esp + RECT.right] - @@: cmp edx, [esp + RECT.bottom] + @@: + cmp edx, [esp + RECT.bottom] jbe @f mov edx, [esp + RECT.bottom] - @@: push esi + @@: + push esi movzx esi, word[WIN_POS + esi * 2] call window._.set_screen pop esi @@ -520,7 +537,8 @@ repos_windows: ;/////////////////////////////////////////////////////////////// sub eax, ebx jle @f mov [edi + WDATA.box.width], ebx - @@: sub ebx, [edi + WDATA.box.width] + @@: + sub ebx, [edi + WDATA.box.width] mov [edi + WDATA.box.left], ebx .fix_vertical: @@ -533,7 +551,8 @@ repos_windows: ;/////////////////////////////////////////////////////////////// sub eax, ebx jle @f mov [edi + WDATA.box.height], ebx - @@: sub ebx, [edi + WDATA.box.height] + @@: + sub ebx, [edi + WDATA.box.height] mov [edi + WDATA.box.top], ebx jmp .fix_client_box @@ -655,7 +674,8 @@ drawwindow_I_caption: ;//////////////////////////////////////////////////////// cmp ebx, eax jbe @f mov ebx, eax - @@: push ebx + @@: + push ebx xor edi, edi @@ -674,7 +694,8 @@ drawwindow_I_caption: ;//////////////////////////////////////////////////////// jz @f sub ecx, 0x00040404 mov [esi + WDATA.cl_titlebar], ecx - @@: and ecx, 0x00ffffff + @@: + and ecx, 0x00ffffff call [draw_line] inc edx cmp edx, [esp] @@ -753,7 +774,8 @@ drawwindow_III_caption: ;///////////////////////////////////////////////////// cmp ebx, eax jb @f mov ebx, eax - @@: push ebx + @@: + push ebx xor edi, edi @@ -770,10 +792,12 @@ drawwindow_III_caption: ;///////////////////////////////////////////////////// test ecx, 0x40000000 jz @f add ecx, 0x00040404 - @@: test ecx, 0x80000000 + @@: + test ecx, 0x80000000 jz @f sub ecx, 0x00040404 - @@: mov [esi + WDATA.cl_titlebar], ecx + @@: + mov [esi + WDATA.cl_titlebar], ecx and ecx, 0x00ffffff call [draw_line] inc edx @@ -987,7 +1011,8 @@ restore_minimized_window: ;//////////////////////////////////////////////////// cmp eax, [TASK_COUNT] jz @f mov ebp, calculatescreen - @@: mov eax, [edi + WDATA.box.left] + @@: + mov eax, [edi + WDATA.box.left] mov ebx, [edi + WDATA.box.top] mov ecx, [edi + WDATA.box.width] mov edx, [edi + WDATA.box.height] @@ -1022,7 +1047,8 @@ window_check_events: ;///////////////////////////////////////////////////////// call minimize_window jmp .exit - @@: call restore_minimized_window + @@: + call restore_minimized_window .exit: ret @@ -1083,7 +1109,8 @@ sys_window_maximize_handler: ;///////////////////////////////////////////////// mov [ecx + BOX.height], eax xchg eax, ecx - @@: call window._.set_window_box + @@: + call window._.set_window_box add esp, BOX.sizeof .exit: @@ -1124,7 +1151,8 @@ sys_window_rollup_handler: ;/////////////////////////////////////////////////// lea eax, [edx + APPDATA.saved_box] jmp .set_box - @@: mov eax, [screen_workarea.top] + @@: + mov eax, [screen_workarea.top] push [screen_workarea.bottom] \ [edi + WDATA.box.width] \ eax \ @@ -1232,27 +1260,31 @@ window._.invalidate_screen: ;////////////////////////////////////////////////// cmp ecx, edx jle @f mov ecx, edx - @@: mov [draw_limits.left], ecx + @@: + mov [draw_limits.left], ecx mov ecx, [eax + BOX.left] add ecx, [eax + BOX.width] add edx, [ebx + BOX.width] cmp ecx, edx jae @f mov ecx, edx - @@: mov [draw_limits.right], ecx + @@: + mov [draw_limits.right], ecx mov ecx, [eax + BOX.top] mov edx, [ebx + BOX.top] cmp ecx, edx jle @f mov ecx, edx - @@: mov [draw_limits.top], ecx + @@: + mov [draw_limits.top], ecx mov ecx, [eax + BOX.top] add ecx, [eax + BOX.height] add edx, [ebx + BOX.height] cmp ecx, edx jae @f mov ecx, edx - @@: mov [draw_limits.bottom], ecx + @@: + mov [draw_limits.bottom], ecx ; recalculate screen buffer at old position push ebx @@ -1296,17 +1328,17 @@ window._.set_window_box: ;///////////////////////////////////////////////////// push eax ebx esi ; don't do anything if the new box is identical to the old - cmp bl, [edi + WDATA.fl_wstate] - jnz @f - mov esi, eax - push edi + cmp bl, [edi + WDATA.fl_wstate] + jnz @f + mov esi, eax + push edi if WDATA.box - add edi, WDATA.box + add edi, WDATA.box end if - mov ecx, 4 - repz cmpsd - pop edi - jz .exit + mov ecx, 4 + repz cmpsd + pop edi + jz .exit @@: add esp, -BOX.sizeof @@ -1315,7 +1347,7 @@ end if if WDATA.box lea esi, [edi + WDATA.box] else - mov esi, edi ; optimization for WDATA.box = 0 + mov esi, edi ; optimization for WDATA.box = 0 end if xchg eax, esi mov ecx, BOX.sizeof @@ -1477,7 +1509,8 @@ window._.sys_set_window: ;///////////////////////////////////////////////////// xor eax, eax - @@: mov [edi + APPDATA.wnd_caption], eax + @@: + mov [edi + APPDATA.wnd_caption], eax mov esi, [esp] add edi, APPDATA.saved_box @@ -1601,7 +1634,8 @@ window._.get_titlebar_height: ;//////////////////////////////////////////////// jne @f mov eax, [_skinh] ret - @@: mov eax, 21 + @@: + mov eax, 21 ret align 4 @@ -1619,11 +1653,13 @@ window._.get_rolledup_height: ;//////////////////////////////////////////////// mov eax, [_skinh] add eax, 3 ret - @@: or al, al + @@: + or al, al jnz @f mov eax, 21 ret - @@: mov eax, 21 + 2 + @@: + mov eax, 21 + 2 ret align 4 @@ -1688,10 +1724,10 @@ end virtual .next_line: push ecx shr ecx, 2 - rep stosd + rep stosd mov ecx, [esp] and ecx, 3 - rep stosb + rep stosb pop ecx add edi, esi sub edi, ecx @@ -1765,12 +1801,13 @@ end virtual pop edx ebx add eax, edi call .read_byte - test al,al + test al, al jz @f mov eax, esi mov [ebp], al ; -- end body -- - @@: inc ebp + @@: + inc ebp inc edx cmp edx, [ff_xsz] jb .ff_new_x @@ -1812,9 +1849,9 @@ window._.window_activate: ;//////////////////////////////////////////////////// ; if type of current active window is 3 or 4, it must be redrawn mov ebx, [TASK_COUNT] - -; DEBUGF 1, "K : TASK_COUNT (0x%x)\n", ebx - + +; DEBUGF 1, "K : TASK_COUNT (0x%x)\n", ebx + movzx ebx, word[WIN_POS + ebx * 2] shl ebx, 5 add eax, window_data @@ -1841,13 +1878,13 @@ window._.window_activate: ;//////////////////////////////////////////////////// cmp eax, [TASK_COUNT] jae .move_self_up inc eax - -; push ebx -; xor ebx,ebx -; mov bx,[WIN_STACK + eax * 2] -; DEBUGF 1, "K : DEC WIN_STACK (0x%x)\n",ebx -; pop ebx - + +; push ebx +; xor ebx,ebx +; mov bx,[WIN_STACK + eax * 2] +; DEBUGF 1, "K : DEC WIN_STACK (0x%x)\n",ebx +; pop ebx + cmp [WIN_STACK + eax * 2], bx jbe .next_stack_window dec word[WIN_STACK + eax * 2] @@ -1887,46 +1924,46 @@ window._.window_deactivate: ;/////////////////////////////////////////////////// ;------------------------------------------------------------------------------ ;> esi = pointer to WIN_POS+ window data ;------------------------------------------------------------------------------ - push eax ebx + push eax ebx ;------------------------------------------------------------------------------ .move_others_up: - ; ax <- process no - movzx ebx, word[esi] - ; ax <- position in window stack - movzx ebx, word[WIN_STACK + ebx * 2] - ; up others - xor eax, eax + ; ax <- process no + movzx ebx, word[esi] + ; ax <- position in window stack + movzx ebx, word[WIN_STACK + ebx * 2] + ; up others + xor eax, eax .next_stack_window: - cmp eax, [TASK_COUNT] - jae .move_self_down - inc eax - cmp [WIN_STACK + eax * 2], bx - jae .next_stack_window - inc word[WIN_STACK + eax * 2] - jmp .next_stack_window + cmp eax, [TASK_COUNT] + jae .move_self_down + inc eax + cmp [WIN_STACK + eax * 2], bx + jae .next_stack_window + inc word[WIN_STACK + eax * 2] + jmp .next_stack_window ;---------------------------------------------- .move_self_down: - movzx ebx, word[esi] - ; this is the last (and the low) - mov [WIN_STACK + ebx * 2], word 1 - ; update on screen - window stack - xor eax, eax + movzx ebx, word[esi] + ; this is the last (and the low) + mov [WIN_STACK + ebx * 2], word 1 + ; update on screen - window stack + xor eax, eax .next_window_pos: - cmp eax, [TASK_COUNT] - jae .reset_vars - inc eax - movzx ebx, word[WIN_STACK + eax * 2] - mov [WIN_POS + ebx * 2], ax - jmp .next_window_pos + cmp eax, [TASK_COUNT] + jae .reset_vars + inc eax + movzx ebx, word[WIN_STACK + eax * 2] + mov [WIN_POS + ebx * 2], ax + jmp .next_window_pos ;----------------------------------------------- .reset_vars: - mov byte[KEY_COUNT], 0 - mov byte[BTN_COUNT], 0 - mov word[MOUSE_SCROLL_H], 0 - mov word[MOUSE_SCROLL_V], 0 - pop ebx eax - ret -;------------------------------------------------------------------------------ + mov byte[KEY_COUNT], 0 + mov byte[BTN_COUNT], 0 + mov word[MOUSE_SCROLL_H], 0 + mov word[MOUSE_SCROLL_V], 0 + pop ebx eax + ret +;------------------------------------------------------------------------------ align 4 ;------------------------------------------------------------------------------ window._.check_window_draw: ;////////////////////////////////////////////////// @@ -2014,7 +2051,8 @@ window._.draw_window_caption: ;//////////////////////////////////////////////// cmp edx, [CURRENT_TASK] jne @f inc eax - @@: mov edx, [CURRENT_TASK] + @@: + mov edx, [CURRENT_TASK] shl edx, 5 add edx, window_data movzx ebx, [edx + WDATA.fl_wstyle] @@ -2045,7 +2083,8 @@ window._.draw_window_caption: ;//////////////////////////////////////////////// call drawwindow_I_caption - .2: mov edi, [CURRENT_TASK] + .2: + mov edi, [CURRENT_TASK] shl edi, 5 test [edi + window_data + WDATA.fl_wstyle], WSTYLE_HASCAPTION jz .exit @@ -2149,5 +2188,5 @@ window._.end_moving__box: ;////////////////////////////////////////////////// ;> edi = pointer to BOX struct ;------------------------------------------------------------------------------ push eax ebx esi - xor esi,esi - jmp window._.draw_negative_box.1 \ No newline at end of file + xor esi, esi + jmp window._.draw_negative_box.1 diff --git a/kernel/trunk/hid/keyboard.inc b/kernel/trunk/hid/keyboard.inc index f5b65d6ec..9946487c7 100644 --- a/kernel/trunk/hid/keyboard.inc +++ b/kernel/trunk/hid/keyboard.inc @@ -1,407 +1,407 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -VKEY_LSHIFT = 0000000000000001b -VKEY_RSHIFT = 0000000000000010b -VKEY_LCONTROL = 0000000000000100b -VKEY_RCONTROL = 0000000000001000b -VKEY_LALT = 0000000000010000b -VKEY_RALT = 0000000000100000b -VKEY_CAPSLOCK = 0000000001000000b -VKEY_NUMLOCK = 0000000010000000b -VKEY_SCRLOCK = 0000000100000000b - -VKEY_SHIFT = 0000000000000011b -VKEY_CONTROL = 0000000000001100b -VKEY_ALT = 0000000000110000b - -uglobal - align 4 - kb_state dd 0 - ext_code db 0 - - keyboard_mode db 0 - keyboard_data db 0 - - altmouseb db 0 - ctrl_alt_del db 0 - - kb_lights db 0 - -align 4 - hotkey_scancodes rd 256 ; we have 256 scancodes - hotkey_list rd 256*4 ; max 256 defined hotkeys - hotkey_buffer rd 120*2 ; buffer for 120 hotkeys -endg - -iglobal -hotkey_tests dd hotkey_test0 - dd hotkey_test1 - dd hotkey_test2 - dd hotkey_test3 - dd hotkey_test4 -hotkey_tests_num = 5 -endg -;--------------------------------------------------------------------- -hotkey_test0: - test al,al - setz al - ret -;--------------------------------------------------------------------- -hotkey_test1: - test al,al - setnp al - ret -;--------------------------------------------------------------------- -hotkey_test2: - cmp al,3 - setz al - ret -;--------------------------------------------------------------------- -hotkey_test3: - cmp al,1 - setz al - ret -;--------------------------------------------------------------------- -hotkey_test4: - cmp al,2 - setz al - ret -;--------------------------------------------------------------------- -hotkey_do_test: - push eax - mov edx,[kb_state] - shr edx,cl - add cl,cl - mov eax,[eax+4] - shr eax,cl - and eax,15 - cmp al,hotkey_tests_num - jae .fail - - xchg eax,edx - and al,3 - call [hotkey_tests + edx*4] - cmp al,1 - pop eax - ret -;-------------------------------------- -.fail: - stc - pop eax - ret -;--------------------------------------------------------------------- -align 4 -set_keyboard_data: - movzx eax,word[TASK_COUNT] ; top window process - movzx eax,word[WIN_POS+eax*2] - shl eax,8 - mov al,[SLOT_BASE+eax+APPDATA.keyboard_mode] - mov [keyboard_mode],al - - mov eax,ecx - - push ebx esi edi ebp - call send_scancode - pop ebp edi esi ebx - ret -;--------------------------------------------------------------------- -align 4 -irq1: - movzx eax,word[TASK_COUNT] ; top window process - movzx eax,word[WIN_POS+eax*2] - shl eax,8 - mov al,[SLOT_BASE+eax+APPDATA.keyboard_mode] - mov [keyboard_mode],al - - in al,0x60 -;-------------------------------------- -send_scancode: - mov [keyboard_data],al -; ch = scancode -; cl = ext_code -; bh = 0 - normal key -; bh = 1 - modifier (Shift/Ctrl/Alt) -; bh = 2 - extended code - mov ch,al - cmp al,0xE0 - je @f - - cmp al,0xE1 - jne .normal_code -@@: - mov bh,2 - mov [ext_code],al - jmp .writekey -;-------------------------------------- -.normal_code: - mov cl,0 - xchg cl,[ext_code] - and al,0x7F - mov bh,1 -@@: - cmp al,0x2A - jne @f - - cmp cl,0xE0 - je .writekey - - mov eax,VKEY_LSHIFT - jmp .modifier -;-------------------------------------- -@@: - cmp al,0x36 - jne @f - - cmp cl,0xE0 - je .writekey - - mov eax,VKEY_RSHIFT - jmp .modifier -;-------------------------------------- -@@: - cmp al,0x38 - jne @f - - mov eax,VKEY_LALT - test cl,cl - jz .modifier - - mov al,VKEY_RALT - jmp .modifier -;-------------------------------------- -@@: - cmp al,0x1D - jne @f - - mov eax,VKEY_LCONTROL - test cl,cl - jz .modifier - - mov al,VKEY_RCONTROL - cmp cl,0xE0 - jz .modifier - - mov [ext_code],cl - jmp .writekey -;-------------------------------------- -@@: - cmp al,0x3A - jne @f - - mov bl,4 - mov eax,VKEY_CAPSLOCK - jmp .no_key.xor -;-------------------------------------- -@@: - cmp al,0x45 - jne @f - test cl,cl - jnz .writekey - - mov bl,2 - mov eax,VKEY_NUMLOCK - jmp .no_key.xor -;-------------------------------------- -@@: - cmp al,0x46 - jne @f - - mov bl,1 - mov eax,VKEY_SCRLOCK - jmp .no_key.xor -;-------------------------------------- -@@: - xor ebx,ebx - test ch,ch - js .writekey - - movzx eax,ch ; plain key - mov bl,[keymap+eax] - mov edx,[kb_state] - test dl,VKEY_CONTROL ; ctrl alt del - jz .noctrlaltdel - - test dl,VKEY_ALT - jz .noctrlaltdel - - cmp ch,53h - jne .noctrlaltdel - - mov [ctrl_alt_del],1 -.noctrlaltdel: - test dl,VKEY_CONTROL ; ctrl on ? - jz @f - - sub bl,0x60 -@@: - test dl,VKEY_CAPSLOCK ; caps lock on ? - jz .no_caps_lock - - test dl,VKEY_SHIFT ; shift on ? - jz .keymap_shif - - jmp @f -;-------------------------------------- -.no_caps_lock: - test dl,VKEY_SHIFT ; shift on ? - jz @f -.keymap_shif: - mov bl,[keymap_shift+eax] -@@: - test dl,VKEY_ALT ; alt on ? - jz @f - - mov bl,[keymap_alt+eax] -@@: - jmp .writekey -;-------------------------------------- -.modifier: - test ch, ch - js .modifier.up - or [kb_state],eax - jmp .writekey -;-------------------------------------- -.modifier.up: - not eax - and [kb_state],eax - jmp .writekey -;-------------------------------------- -.no_key.xor: - mov bh,0 - test ch,ch - js .writekey - - xor [kb_state],eax - xor [kb_lights],bl - call set_lights -.writekey: -; test for system hotkeys - movzx eax,ch - cmp bh,1 - ja .nohotkey - jb @f - - xor eax,eax -@@: - mov eax, [hotkey_scancodes + eax*4] -.hotkey_loop: - test eax, eax - jz .nohotkey - - mov cl,0 - call hotkey_do_test - jc .hotkey_cont - - mov cl,2 - call hotkey_do_test - jc .hotkey_cont - - mov cl,4 - call hotkey_do_test - jnc .hotkey_found -.hotkey_cont: - mov eax,[eax] - jmp .hotkey_loop -;-------------------------------------- -.hotkey_found: - mov eax,[eax+8] -; put key in buffer for process in slot eax - mov edi,hotkey_buffer -@@: - cmp dword [edi],0 - jz .found_free - - add edi,8 - cmp edi,hotkey_buffer+120*8 - jb @b -; no free space - replace first entry - mov edi,hotkey_buffer -.found_free: - mov [edi],eax - movzx eax,ch - cmp bh,1 - jnz @f - - xor eax, eax -@@: - mov [edi+4],ax - mov eax,[kb_state] - mov [edi+6],ax - jmp .exit.irq1 -;-------------------------------------- -.nohotkey: - cmp [keyboard_mode],0 ; return from keymap - jne .scancode - - test bh,bh - jnz .exit.irq1 - - test bl,bl - jz .exit.irq1 - - test [kb_state],VKEY_NUMLOCK - jz .dowrite - - cmp cl,0xE0 - jz .dowrite - - cmp ch,55 - jnz @f - - mov bl,0x2A ;* - jmp .dowrite -;-------------------------------------- -@@: - cmp ch,71 - jb .dowrite - - cmp ch,83 - ja .dowrite - - movzx eax, ch - mov bl,[numlock_map + eax - 71] - jmp .dowrite -;-------------------------------------- -.scancode: - mov bl,ch -.dowrite: - movzx eax,byte[KEY_COUNT] - cmp al,120 - jae .exit.irq1 - inc eax - mov [KEY_COUNT],al - mov [KEY_COUNT+eax],bl -.exit.irq1: - mov [check_idle_semaphore],5 - ret -;--------------------------------------------------------------------- -set_lights: - mov al,0xED - call kb_write - mov al,[kb_lights] - call kb_write - ret -;--------------------------------------------------------------------- -numlock_map: - db 0x37 ;Num 7 - db 0x38 ;Num 8 - db 0x39 ;Num 9 - db 0x2D ;Num - - db 0x34 ;Num 4 - db 0x35 ;Num 5 - db 0x36 ;Num 6 - db 0x2B ;Num + - db 0x31 ;Num 1 - db 0x32 ;Num 2 - db 0x33 ;Num 3 - db 0x30 ;Num 0 - db 0x2E ;Num . -;--------------------------------------------------------------------- +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +VKEY_LSHIFT = 0000000000000001b +VKEY_RSHIFT = 0000000000000010b +VKEY_LCONTROL = 0000000000000100b +VKEY_RCONTROL = 0000000000001000b +VKEY_LALT = 0000000000010000b +VKEY_RALT = 0000000000100000b +VKEY_CAPSLOCK = 0000000001000000b +VKEY_NUMLOCK = 0000000010000000b +VKEY_SCRLOCK = 0000000100000000b + +VKEY_SHIFT = 0000000000000011b +VKEY_CONTROL = 0000000000001100b +VKEY_ALT = 0000000000110000b + +uglobal + align 4 + kb_state dd 0 + ext_code db 0 + + keyboard_mode db 0 + keyboard_data db 0 + + altmouseb db 0 + ctrl_alt_del db 0 + + kb_lights db 0 + +align 4 + hotkey_scancodes rd 256 ; we have 256 scancodes + hotkey_list rd 256*4 ; max 256 defined hotkeys + hotkey_buffer rd 120*2 ; buffer for 120 hotkeys +endg + +iglobal +hotkey_tests dd hotkey_test0 + dd hotkey_test1 + dd hotkey_test2 + dd hotkey_test3 + dd hotkey_test4 +hotkey_tests_num = 5 +endg +;--------------------------------------------------------------------- +hotkey_test0: + test al, al + setz al + ret +;--------------------------------------------------------------------- +hotkey_test1: + test al, al + setnp al + ret +;--------------------------------------------------------------------- +hotkey_test2: + cmp al, 3 + setz al + ret +;--------------------------------------------------------------------- +hotkey_test3: + cmp al, 1 + setz al + ret +;--------------------------------------------------------------------- +hotkey_test4: + cmp al, 2 + setz al + ret +;--------------------------------------------------------------------- +hotkey_do_test: + push eax + mov edx, [kb_state] + shr edx, cl + add cl, cl + mov eax, [eax+4] + shr eax, cl + and eax, 15 + cmp al, hotkey_tests_num + jae .fail + + xchg eax, edx + and al, 3 + call [hotkey_tests + edx*4] + cmp al, 1 + pop eax + ret +;-------------------------------------- +.fail: + stc + pop eax + ret +;--------------------------------------------------------------------- +align 4 +set_keyboard_data: + movzx eax, word[TASK_COUNT]; top window process + movzx eax, word[WIN_POS+eax*2] + shl eax, 8 + mov al, [SLOT_BASE+eax+APPDATA.keyboard_mode] + mov [keyboard_mode], al + + mov eax, ecx + + push ebx esi edi ebp + call send_scancode + pop ebp edi esi ebx + ret +;--------------------------------------------------------------------- +align 4 +irq1: + movzx eax, word[TASK_COUNT]; top window process + movzx eax, word[WIN_POS+eax*2] + shl eax, 8 + mov al, [SLOT_BASE+eax+APPDATA.keyboard_mode] + mov [keyboard_mode], al + + in al, 0x60 +;-------------------------------------- +send_scancode: + mov [keyboard_data], al +; ch = scancode +; cl = ext_code +; bh = 0 - normal key +; bh = 1 - modifier (Shift/Ctrl/Alt) +; bh = 2 - extended code + mov ch, al + cmp al, 0xE0 + je @f + + cmp al, 0xE1 + jne .normal_code +@@: + mov bh, 2 + mov [ext_code], al + jmp .writekey +;-------------------------------------- +.normal_code: + mov cl, 0 + xchg cl, [ext_code] + and al, 0x7F + mov bh, 1 +@@: + cmp al, 0x2A + jne @f + + cmp cl, 0xE0 + je .writekey + + mov eax, VKEY_LSHIFT + jmp .modifier +;-------------------------------------- +@@: + cmp al, 0x36 + jne @f + + cmp cl, 0xE0 + je .writekey + + mov eax, VKEY_RSHIFT + jmp .modifier +;-------------------------------------- +@@: + cmp al, 0x38 + jne @f + + mov eax, VKEY_LALT + test cl, cl + jz .modifier + + mov al, VKEY_RALT + jmp .modifier +;-------------------------------------- +@@: + cmp al, 0x1D + jne @f + + mov eax, VKEY_LCONTROL + test cl, cl + jz .modifier + + mov al, VKEY_RCONTROL + cmp cl, 0xE0 + jz .modifier + + mov [ext_code], cl + jmp .writekey +;-------------------------------------- +@@: + cmp al, 0x3A + jne @f + + mov bl, 4 + mov eax, VKEY_CAPSLOCK + jmp .no_key.xor +;-------------------------------------- +@@: + cmp al, 0x45 + jne @f + test cl, cl + jnz .writekey + + mov bl, 2 + mov eax, VKEY_NUMLOCK + jmp .no_key.xor +;-------------------------------------- +@@: + cmp al, 0x46 + jne @f + + mov bl, 1 + mov eax, VKEY_SCRLOCK + jmp .no_key.xor +;-------------------------------------- +@@: + xor ebx, ebx + test ch, ch + js .writekey + + movzx eax, ch ; plain key + mov bl, [keymap+eax] + mov edx, [kb_state] + test dl, VKEY_CONTROL ; ctrl alt del + jz .noctrlaltdel + + test dl, VKEY_ALT + jz .noctrlaltdel + + cmp ch, 53h + jne .noctrlaltdel + + mov [ctrl_alt_del], 1 +.noctrlaltdel: + test dl, VKEY_CONTROL ; ctrl on ? + jz @f + + sub bl, 0x60 +@@: + test dl, VKEY_CAPSLOCK ; caps lock on ? + jz .no_caps_lock + + test dl, VKEY_SHIFT ; shift on ? + jz .keymap_shif + + jmp @f +;-------------------------------------- +.no_caps_lock: + test dl, VKEY_SHIFT ; shift on ? + jz @f +.keymap_shif: + mov bl, [keymap_shift+eax] +@@: + test dl, VKEY_ALT ; alt on ? + jz @f + + mov bl, [keymap_alt+eax] +@@: + jmp .writekey +;-------------------------------------- +.modifier: + test ch, ch + js .modifier.up + or [kb_state], eax + jmp .writekey +;-------------------------------------- +.modifier.up: + not eax + and [kb_state], eax + jmp .writekey +;-------------------------------------- +.no_key.xor: + mov bh, 0 + test ch, ch + js .writekey + + xor [kb_state], eax + xor [kb_lights], bl + call set_lights +.writekey: +; test for system hotkeys + movzx eax, ch + cmp bh, 1 + ja .nohotkey + jb @f + + xor eax, eax +@@: + mov eax, [hotkey_scancodes + eax*4] +.hotkey_loop: + test eax, eax + jz .nohotkey + + mov cl, 0 + call hotkey_do_test + jc .hotkey_cont + + mov cl, 2 + call hotkey_do_test + jc .hotkey_cont + + mov cl, 4 + call hotkey_do_test + jnc .hotkey_found +.hotkey_cont: + mov eax, [eax] + jmp .hotkey_loop +;-------------------------------------- +.hotkey_found: + mov eax, [eax+8] +; put key in buffer for process in slot eax + mov edi, hotkey_buffer +@@: + cmp dword [edi], 0 + jz .found_free + + add edi, 8 + cmp edi, hotkey_buffer+120*8 + jb @b +; no free space - replace first entry + mov edi, hotkey_buffer +.found_free: + mov [edi], eax + movzx eax, ch + cmp bh, 1 + jnz @f + + xor eax, eax +@@: + mov [edi+4], ax + mov eax, [kb_state] + mov [edi+6], ax + jmp .exit.irq1 +;-------------------------------------- +.nohotkey: + cmp [keyboard_mode], 0; return from keymap + jne .scancode + + test bh, bh + jnz .exit.irq1 + + test bl, bl + jz .exit.irq1 + + test [kb_state], VKEY_NUMLOCK + jz .dowrite + + cmp cl, 0xE0 + jz .dowrite + + cmp ch, 55 + jnz @f + + mov bl, 0x2A ;* + jmp .dowrite +;-------------------------------------- +@@: + cmp ch, 71 + jb .dowrite + + cmp ch, 83 + ja .dowrite + + movzx eax, ch + mov bl, [numlock_map + eax - 71] + jmp .dowrite +;-------------------------------------- +.scancode: + mov bl, ch +.dowrite: + movzx eax, byte[KEY_COUNT] + cmp al, 120 + jae .exit.irq1 + inc eax + mov [KEY_COUNT], al + mov [KEY_COUNT+eax], bl +.exit.irq1: + mov [check_idle_semaphore], 5 + ret +;--------------------------------------------------------------------- +set_lights: + mov al, 0xED + call kb_write + mov al, [kb_lights] + call kb_write + ret +;--------------------------------------------------------------------- +numlock_map: + db 0x37 ;Num 7 + db 0x38 ;Num 8 + db 0x39 ;Num 9 + db 0x2D ;Num - + db 0x34 ;Num 4 + db 0x35 ;Num 5 + db 0x36 ;Num 6 + db 0x2B ;Num + + db 0x31 ;Num 1 + db 0x32 ;Num 2 + db 0x33 ;Num 3 + db 0x30 ;Num 0 + db 0x2E ;Num . +;--------------------------------------------------------------------- diff --git a/kernel/trunk/hid/mousedrv.inc b/kernel/trunk/hid/mousedrv.inc index f13442cfe..f2e70ab24 100644 --- a/kernel/trunk/hid/mousedrv.inc +++ b/kernel/trunk/hid/mousedrv.inc @@ -1,455 +1,456 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; check mouse -; -; -; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y -; FB10 -> FB17 mouse color mem -; FB21 x move -; FB22 y move -; FB30 color temp -; FB28 high bits temp -; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under -; FC00 -> FCFE com1/ps2 buffer -; FCFF com1/ps2 buffer count starting from FC00 - -uglobal - mousecount dd 0x0 - mousedata dd 0x0 -endg - -iglobal -mouse_delay dd 10 -mouse_speed_factor: dd 3 -mouse_timer_ticks dd 0 -endg - -;include 'm_com.inc' - - -;test_mario79: -; push esi -; push eax -; mov [write_error_to],process_test_m79+43 -; movzx eax,al ;[DevErrorCode] -; call writehex -; mov esi,process_test_m79 -; call sys_msg_board_str -; pop eax -; pop esi -; ret -;process_test_m79 db 'K : Process - test Mario79 error 00000000',13,10,0 - -draw_mouse_under: - ; return old picture - - cmp [_display.restore_cursor], 0 - je @F - - pushad - movzx eax,word [X_UNDER] - movzx ebx,word [Y_UNDER] - stdcall [_display.restore_cursor], eax, ebx - popad - ret -@@: - pushad - xor ecx,ecx - xor edx,edx - align 4 -mres: - movzx eax,word [X_UNDER] - movzx ebx,word [Y_UNDER] - add eax,ecx - add ebx,edx - push ecx - push edx - push eax - push ebx - mov eax,edx - shl eax,6 - shl ecx,2 - add eax,ecx - add eax,mouseunder - mov ecx,[eax] - pop ebx - pop eax - mov edi, 1 ;force - call [putpixel] - pop edx - pop ecx - inc ecx - cmp ecx, 16 - jnz mres - xor ecx, ecx - inc edx - cmp edx, 24 - jnz mres - popad - ret - -save_draw_mouse: - - cmp [_display.move_cursor], 0 - je .no_hw_cursor - pushad - - mov [X_UNDER],ax - mov [Y_UNDER],bx - movzx eax,word [MOUSE_Y] - movzx ebx,word [MOUSE_X] - push eax - push ebx - - mov ecx, [Screen_Max_X] - inc ecx - mul ecx - add eax, [_WinMapAddress] - movzx edx, byte [ebx+eax] - shl edx, 8 - mov esi, [edx+SLOT_BASE+APPDATA.cursor] - - cmp esi, [current_cursor] - je .draw - - push esi - call [_display.select_cursor] - mov [current_cursor], esi -.draw: - stdcall [_display.move_cursor], esi - popad - ret -.fail: - mov ecx, [def_cursor] - mov [edx+SLOT_BASE+APPDATA.cursor], ecx - stdcall [_display.move_cursor], ecx ; stdcall: [esp]=ebx,eax - popad - ret - -.no_hw_cursor: - pushad - ; save & draw - mov [X_UNDER],ax - mov [Y_UNDER],bx - push eax - push ebx - mov ecx,0 - mov edx,0 - align 4 -drm: - push eax - push ebx - push ecx - push edx - ; helloworld - push ecx - add eax,ecx ; save picture under mouse - add ebx,edx - push ecx - call getpixel - mov [COLOR_TEMP],ecx - pop ecx - mov eax,edx - shl eax,6 - shl ecx,2 - add eax,ecx - add eax,mouseunder - mov ebx,[COLOR_TEMP] - mov [eax],ebx - pop ecx - mov edi,edx ; y cycle - shl edi,4 ; *16 bytes per row - add edi,ecx ; x cycle - mov esi, edi - add edi, esi - add edi, esi ; *3 - add edi,[MOUSE_PICTURE] ; we have our str address - mov esi, edi - add esi, 16*24*3 - push ecx - mov ecx, [COLOR_TEMP] - call combine_colors - mov [MOUSE_COLOR_MEM], ecx - pop ecx - pop edx - pop ecx - pop ebx - pop eax - add eax,ecx ; we have x coord+cycle - add ebx,edx ; and y coord+cycle - push ecx - mov ecx, [MOUSE_COLOR_MEM] - mov edi, 1 - call [putpixel] - pop ecx - mov ebx,[esp+0] ; pure y coord again - mov eax,[esp+4] ; and x - inc ecx ; +1 cycle - cmp ecx,16 ; if more than 16 - jnz drm - xor ecx, ecx - inc edx - cmp edx,24 - jnz drm - add esp,8 - popad - ret - - -combine_colors: - ; in - ; ecx - color ( 00 RR GG BB ) - ; edi - ref to new color byte - ; esi - ref to alpha byte - ; - ; out - ; ecx - new color ( roughly (ecx*[esi]>>8)+([edi]*[esi]>>8) ) - push eax - push ebx - push edx - push ecx - xor ecx, ecx - ; byte 2 - mov eax, 0xff - sub al, [esi+0] - mov ebx, [esp] - shr ebx, 16 - and ebx, 0xff - mul ebx - shr eax, 8 - add ecx, eax - xor eax, eax - xor ebx, ebx - mov al, [edi+0] - mov bl, [esi+0] - mul ebx - shr eax, 8 - add ecx, eax - shl ecx, 8 - ; byte 1 - mov eax, 0xff - sub al, [esi+1] - mov ebx, [esp] - shr ebx, 8 - and ebx, 0xff - mul ebx - shr eax, 8 - add ecx, eax - xor eax, eax - xor ebx, ebx - mov al, [edi+1] - mov bl, [esi+1] - mul ebx - shr eax, 8 - add ecx, eax - shl ecx, 8 - ; byte 2 - mov eax, 0xff - sub al, [esi+2] - mov ebx, [esp] - and ebx, 0xff - mul ebx - shr eax, 8 - add ecx, eax - xor eax, eax - xor ebx, ebx - mov al, [edi+2] - mov bl, [esi+2] - mul ebx - shr eax, 8 - add ecx, eax - pop eax - pop edx - pop ebx - pop eax - ret - - -__sys_disable_mouse: - cmp dword [MOUSE_VISIBLE],dword 0 - je @f - ret -@@: - pushad - cmp [CURRENT_TASK],dword 1 - je disable_m - mov edx,[CURRENT_TASK] - shl edx,5 - add edx,window_data - movzx eax, word [MOUSE_X] - movzx ebx, word [MOUSE_Y] - mov ecx,[Screen_Max_X] - inc ecx - imul ecx,ebx - add ecx,eax - add ecx, [_WinMapAddress] - mov eax, [CURRENT_TASK] - cmp al, [ecx] - je yes_mouse_disable - cmp al, [ecx+16] - je yes_mouse_disable - add ebx, 10 - cmp ebx, [Screen_Max_Y] - jae no_mouse_disable - mov ebx,[Screen_Max_X] - inc ebx - imul ebx,10 - add ecx,ebx - cmp al, [ecx] - je yes_mouse_disable - cmp al, [ecx+16] - je yes_mouse_disable - jmp no_mouse_disable -yes_mouse_disable: - mov edx,[CURRENT_TASK] - shl edx,5 - add edx,window_data - movzx eax, word [MOUSE_X] - movzx ebx, word [MOUSE_Y] - mov ecx,[edx+0] ; mouse inside the area ? - add eax,10 - cmp eax,ecx - jb no_mouse_disable - sub eax,10 - add ecx,[edx+8] - cmp eax,ecx - jg no_mouse_disable - mov ecx,[edx+4] - add ebx,14 - cmp ebx,ecx - jb no_mouse_disable - sub ebx,14 - add ecx,[edx+12] - cmp ebx,ecx - jg no_mouse_disable -disable_m: - cmp dword [MOUSE_VISIBLE],dword 0 - jne no_mouse_disable - pushf - cli - call draw_mouse_under - popf - mov [MOUSE_VISIBLE],dword 1 -no_mouse_disable: - popad - ret - -__sys_draw_pointer: - cmp [mouse_pause],0 - je @f - ret -@@: - push eax - mov eax,[timer_ticks] - sub eax,[MouseTickCounter] - cmp eax,1 - ja @f - pop eax - ret -@@: - mov eax,[timer_ticks] - mov [MouseTickCounter],eax - pop eax - pushad - cmp dword [MOUSE_VISIBLE],dword 0 ; mouse visible ? - je chms00 - mov [MOUSE_VISIBLE], dword 0 - movzx ebx,word [MOUSE_Y] - movzx eax,word [MOUSE_X] - pushfd - cli - call save_draw_mouse - popfd -nodmu2: - popad - ret -chms00: - movzx ecx,word [X_UNDER] - movzx edx,word [Y_UNDER] - movzx ebx,word [MOUSE_Y] - movzx eax,word [MOUSE_X] - cmp eax,ecx - jne redrawmouse - cmp ebx,edx - jne redrawmouse - jmp nodmp -redrawmouse: - pushfd - cli - call draw_mouse_under - call save_draw_mouse - popfd -nodmp: - popad - ret - -proc set_mouse_data stdcall, BtnState:dword, XMoving:dword, YMoving:dword, VScroll:dword, HScroll:dword - - mov eax,[BtnState] - mov [BTN_DOWN],eax - - mov eax,[XMoving] - call mouse_acceleration - add ax,[MOUSE_X] ;[XCoordinate] - cmp ax,0 - jge @@M1 - mov eax,0 - jmp @@M2 -@@M1: - cmp ax,[Screen_Max_X] ;ScreenLength - jl @@M2 - mov ax,[Screen_Max_X] ;ScreenLength-1 - -@@M2: - mov [MOUSE_X],ax ;[XCoordinate] - - mov eax,[YMoving] - neg eax - call mouse_acceleration - - add ax,[MOUSE_Y] ;[YCoordinate] - cmp ax,0 - jge @@M3 - mov ax,0 - jmp @@M4 -@@M3: - cmp ax,[Screen_Max_Y] ;ScreenHeigth - jl @@M4 - mov ax,[Screen_Max_Y] ;ScreenHeigth-1 - -@@M4: - mov [MOUSE_Y],ax ;[YCoordinate] - - mov eax,[VScroll] - add [MOUSE_SCROLL_V],ax - - mov eax,[HScroll] - add [MOUSE_SCROLL_H],ax - - mov [mouse_active],1 - mov eax,[timer_ticks] - mov [mouse_timer_ticks],eax - ret -endp - -mouse_acceleration: - push eax - mov eax,[timer_ticks] - sub eax,[mouse_timer_ticks] - cmp eax,[mouse_delay] - pop eax - ja @f - ;push edx - imul eax,[mouse_speed_factor] - ;pop edx -@@: - ret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; check mouse +; +; +; FB00 -> FB0F mouse memory 00 chunk count - FB0A-B x - FB0C-D y +; FB10 -> FB17 mouse color mem +; FB21 x move +; FB22 y move +; FB30 color temp +; FB28 high bits temp +; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under +; FC00 -> FCFE com1/ps2 buffer +; FCFF com1/ps2 buffer count starting from FC00 + +uglobal + mousecount dd 0x0 + mousedata dd 0x0 +endg + +iglobal +mouse_delay dd 10 +mouse_speed_factor: + dd 3 +mouse_timer_ticks dd 0 +endg + +;include 'm_com.inc' + + +;test_mario79: +; push esi +; push eax +; mov [write_error_to],process_test_m79+43 +; movzx eax,al ;[DevErrorCode] +; call writehex +; mov esi,process_test_m79 +; call sys_msg_board_str +; pop eax +; pop esi +; ret +;process_test_m79 db 'K : Process - test Mario79 error 00000000',13,10,0 + +draw_mouse_under: + ; return old picture + + cmp [_display.restore_cursor], 0 + je @F + + pushad + movzx eax, word [X_UNDER] + movzx ebx, word [Y_UNDER] + stdcall [_display.restore_cursor], eax, ebx + popad + ret +@@: + pushad + xor ecx, ecx + xor edx, edx + align 4 +mres: + movzx eax, word [X_UNDER] + movzx ebx, word [Y_UNDER] + add eax, ecx + add ebx, edx + push ecx + push edx + push eax + push ebx + mov eax, edx + shl eax, 6 + shl ecx, 2 + add eax, ecx + add eax, mouseunder + mov ecx, [eax] + pop ebx + pop eax + mov edi, 1;force + call [putpixel] + pop edx + pop ecx + inc ecx + cmp ecx, 16 + jnz mres + xor ecx, ecx + inc edx + cmp edx, 24 + jnz mres + popad + ret + +save_draw_mouse: + + cmp [_display.move_cursor], 0 + je .no_hw_cursor + pushad + + mov [X_UNDER], ax + mov [Y_UNDER], bx + movzx eax, word [MOUSE_Y] + movzx ebx, word [MOUSE_X] + push eax + push ebx + + mov ecx, [Screen_Max_X] + inc ecx + mul ecx + add eax, [_WinMapAddress] + movzx edx, byte [ebx+eax] + shl edx, 8 + mov esi, [edx+SLOT_BASE+APPDATA.cursor] + + cmp esi, [current_cursor] + je .draw + + push esi + call [_display.select_cursor] + mov [current_cursor], esi +.draw: + stdcall [_display.move_cursor], esi + popad + ret +.fail: + mov ecx, [def_cursor] + mov [edx+SLOT_BASE+APPDATA.cursor], ecx + stdcall [_display.move_cursor], ecx ; stdcall: [esp]=ebx,eax + popad + ret + +.no_hw_cursor: + pushad + ; save & draw + mov [X_UNDER], ax + mov [Y_UNDER], bx + push eax + push ebx + mov ecx, 0 + mov edx, 0 + align 4 +drm: + push eax + push ebx + push ecx + push edx + ; helloworld + push ecx + add eax, ecx; save picture under mouse + add ebx, edx + push ecx + call getpixel + mov [COLOR_TEMP], ecx + pop ecx + mov eax, edx + shl eax, 6 + shl ecx, 2 + add eax, ecx + add eax, mouseunder + mov ebx, [COLOR_TEMP] + mov [eax], ebx + pop ecx + mov edi, edx ; y cycle + shl edi, 4 ; *16 bytes per row + add edi, ecx ; x cycle + mov esi, edi + add edi, esi + add edi, esi ; *3 + add edi, [MOUSE_PICTURE] ; we have our str address + mov esi, edi + add esi, 16*24*3 + push ecx + mov ecx, [COLOR_TEMP] + call combine_colors + mov [MOUSE_COLOR_MEM], ecx + pop ecx + pop edx + pop ecx + pop ebx + pop eax + add eax, ecx ; we have x coord+cycle + add ebx, edx ; and y coord+cycle + push ecx + mov ecx, [MOUSE_COLOR_MEM] + mov edi, 1 + call [putpixel] + pop ecx + mov ebx, [esp+0] ; pure y coord again + mov eax, [esp+4] ; and x + inc ecx ; +1 cycle + cmp ecx, 16 ; if more than 16 + jnz drm + xor ecx, ecx + inc edx + cmp edx, 24 + jnz drm + add esp, 8 + popad + ret + + +combine_colors: + ; in + ; ecx - color ( 00 RR GG BB ) + ; edi - ref to new color byte + ; esi - ref to alpha byte + ; + ; out + ; ecx - new color ( roughly (ecx*[esi]>>8)+([edi]*[esi]>>8) ) + push eax + push ebx + push edx + push ecx + xor ecx, ecx + ; byte 2 + mov eax, 0xff + sub al, [esi+0] + mov ebx, [esp] + shr ebx, 16 + and ebx, 0xff + mul ebx + shr eax, 8 + add ecx, eax + xor eax, eax + xor ebx, ebx + mov al, [edi+0] + mov bl, [esi+0] + mul ebx + shr eax, 8 + add ecx, eax + shl ecx, 8 + ; byte 1 + mov eax, 0xff + sub al, [esi+1] + mov ebx, [esp] + shr ebx, 8 + and ebx, 0xff + mul ebx + shr eax, 8 + add ecx, eax + xor eax, eax + xor ebx, ebx + mov al, [edi+1] + mov bl, [esi+1] + mul ebx + shr eax, 8 + add ecx, eax + shl ecx, 8 + ; byte 2 + mov eax, 0xff + sub al, [esi+2] + mov ebx, [esp] + and ebx, 0xff + mul ebx + shr eax, 8 + add ecx, eax + xor eax, eax + xor ebx, ebx + mov al, [edi+2] + mov bl, [esi+2] + mul ebx + shr eax, 8 + add ecx, eax + pop eax + pop edx + pop ebx + pop eax + ret + + +__sys_disable_mouse: + cmp dword [MOUSE_VISIBLE], dword 0 + je @f + ret +@@: + pushad + cmp [CURRENT_TASK], dword 1 + je disable_m + mov edx, [CURRENT_TASK] + shl edx, 5 + add edx, window_data + movzx eax, word [MOUSE_X] + movzx ebx, word [MOUSE_Y] + mov ecx, [Screen_Max_X] + inc ecx + imul ecx, ebx + add ecx, eax + add ecx, [_WinMapAddress] + mov eax, [CURRENT_TASK] + cmp al, [ecx] + je yes_mouse_disable + cmp al, [ecx+16] + je yes_mouse_disable + add ebx, 10 + cmp ebx, [Screen_Max_Y] + jae no_mouse_disable + mov ebx, [Screen_Max_X] + inc ebx + imul ebx, 10 + add ecx, ebx + cmp al, [ecx] + je yes_mouse_disable + cmp al, [ecx+16] + je yes_mouse_disable + jmp no_mouse_disable +yes_mouse_disable: + mov edx, [CURRENT_TASK] + shl edx, 5 + add edx, window_data + movzx eax, word [MOUSE_X] + movzx ebx, word [MOUSE_Y] + mov ecx, [edx+0]; mouse inside the area ? + add eax, 10 + cmp eax, ecx + jb no_mouse_disable + sub eax, 10 + add ecx, [edx+8] + cmp eax, ecx + jg no_mouse_disable + mov ecx, [edx+4] + add ebx, 14 + cmp ebx, ecx + jb no_mouse_disable + sub ebx, 14 + add ecx, [edx+12] + cmp ebx, ecx + jg no_mouse_disable +disable_m: + cmp dword [MOUSE_VISIBLE], dword 0 + jne no_mouse_disable + pushf + cli + call draw_mouse_under + popf + mov [MOUSE_VISIBLE], dword 1 +no_mouse_disable: + popad + ret + +__sys_draw_pointer: + cmp [mouse_pause], 0 + je @f + ret +@@: + push eax + mov eax, [timer_ticks] + sub eax, [MouseTickCounter] + cmp eax, 1 + ja @f + pop eax + ret +@@: + mov eax, [timer_ticks] + mov [MouseTickCounter], eax + pop eax + pushad + cmp dword [MOUSE_VISIBLE], dword 0; mouse visible ? + je chms00 + mov [MOUSE_VISIBLE], dword 0 + movzx ebx, word [MOUSE_Y] + movzx eax, word [MOUSE_X] + pushfd + cli + call save_draw_mouse + popfd +nodmu2: + popad + ret +chms00: + movzx ecx, word [X_UNDER] + movzx edx, word [Y_UNDER] + movzx ebx, word [MOUSE_Y] + movzx eax, word [MOUSE_X] + cmp eax, ecx + jne redrawmouse + cmp ebx, edx + jne redrawmouse + jmp nodmp +redrawmouse: + pushfd + cli + call draw_mouse_under + call save_draw_mouse + popfd +nodmp: + popad + ret + +proc set_mouse_data stdcall, BtnState:dword, XMoving:dword, YMoving:dword, VScroll:dword, HScroll:dword + + mov eax, [BtnState] + mov [BTN_DOWN], eax + + mov eax, [XMoving] + call mouse_acceleration + add ax, [MOUSE_X];[XCoordinate] + cmp ax, 0 + jge @@M1 + mov eax, 0 + jmp @@M2 +@@M1: + cmp ax, [Screen_Max_X];ScreenLength + jl @@M2 + mov ax, [Screen_Max_X];ScreenLength-1 + +@@M2: + mov [MOUSE_X], ax;[XCoordinate] + + mov eax, [YMoving] + neg eax + call mouse_acceleration + + add ax, [MOUSE_Y];[YCoordinate] + cmp ax, 0 + jge @@M3 + mov ax, 0 + jmp @@M4 +@@M3: + cmp ax, [Screen_Max_Y];ScreenHeigth + jl @@M4 + mov ax, [Screen_Max_Y];ScreenHeigth-1 + +@@M4: + mov [MOUSE_Y], ax;[YCoordinate] + + mov eax, [VScroll] + add [MOUSE_SCROLL_V], ax + + mov eax, [HScroll] + add [MOUSE_SCROLL_H], ax + + mov [mouse_active], 1 + mov eax, [timer_ticks] + mov [mouse_timer_ticks], eax + ret +endp + +mouse_acceleration: + push eax + mov eax, [timer_ticks] + sub eax, [mouse_timer_ticks] + cmp eax, [mouse_delay] + pop eax + ja @f + ;push edx + imul eax, [mouse_speed_factor] + ;pop edx +@@: + ret + diff --git a/kernel/trunk/hid/set_dtc.inc b/kernel/trunk/hid/set_dtc.inc index abaa3eddf..f32922814 100644 --- a/kernel/trunk/hid/set_dtc.inc +++ b/kernel/trunk/hid/set_dtc.inc @@ -1,203 +1,203 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;setting date,time,clock and alarm-clock -;add sys_settime at servetable as for ex. 22 fcn: -; 22 - SETTING DATE TIME, CLOCK AND ALARM-CLOCK -; ebx =0 - set time ecx - 00SSMMHH -; ebx =1 - set date ecx=00DDMMYY -; ebx =2 - set day of week ecx- 1-7 -; ebx =3 - set alarm-clock ecx - 00SSMMHH -; out: 0 -Ok 1 -wrong format 2 -battery low -sys_settime: - - cli - mov al,0x0d - out 0x70,al - in al,0x71 - bt ax,7 - jnc bat_low - cmp ebx,2 ;day of week - jne nosetweek - test ecx,ecx ;test day of week - je wrongtime - cmp ecx,7 - ja wrongtime - mov edx,0x70 - call startstopclk - dec edx - mov al,6 - out dx,al - inc edx - mov al,cl - out dx,al - jmp endsettime - nosetweek: ;set date - cmp ebx,1 - jne nosetdate - cmp cl,0x99 ;test year - ja wrongtime - shl ecx,4 - cmp cl,0x90 - ja wrongtime - cmp ch,0x99 ;test month - ja wrongtime - shr ecx,4 - test ch,ch - je wrongtime - cmp ch,0x12 - ja wrongtime - shl ecx,8 - bswap ecx ;ebx=00YYMMDD - test cl,cl ;test day - je wrongtime - shl ecx,4 - cmp cl,0x90 - ja wrongtime - shr ecx,4 - cmp ch,2 ;February - jne testday - cmp cl,0x29 - ja wrongtime - jmp setdate - testday: - cmp ch,8 - jb testday1 ;Aug-Dec - bt cx,8 - jnc days31 - jmp days30 - testday1: - bt cx,8 ;Jan-Jul ex.Feb - jnc days30 - days31: - cmp cl,0x31 - ja wrongtime - jmp setdate - days30: - cmp cl,0x30 - ja wrongtime - setdate: - mov edx,0x70 - call startstopclk - dec edx - mov al,7 ;set days - out dx,al - inc edx - mov al,cl - out dx,al - dec edx - mov al,8 ;set months - out dx,al - inc edx - mov al,ch - out dx,al - dec edx - mov al,9 ;set years - out dx,al - inc edx - shr ecx,8 - mov al,ch - out dx,al - jmp endsettime - nosetdate: ;set time or alarm-clock - cmp ebx,3 - ja wrongtime - cmp cl,0x23 - ja wrongtime - cmp ch,0x59 - ja wrongtime - shl ecx,4 - cmp cl,0x90 - ja wrongtime - cmp ch,0x92 - ja wrongtime - shl ecx,4 - bswap ecx ;00HHMMSS - cmp cl,0x59 - ja wrongtime - shl ecx,4 - cmp cl,0x90 - ja wrongtime - shr ecx,4 - - mov edx,0x70 - call startstopclk - dec edx - cmp ebx,3 - - je setalarm - xor eax,eax ;al=0-set seconds - out dx,al - inc edx - mov al,cl - out dx,al - dec edx - mov al,2 ;set minutes - out dx,al - inc edx - mov al,ch - out dx,al - dec edx - mov al,4 ;set hours - out dx,al - inc edx - shr ecx,8 - mov al,ch - out dx,al - jmp endsettime - setalarm: - mov al,1 ;set seconds for al. - out dx,al - inc edx - mov al,cl - out dx,al - dec edx - mov al,3 ;set minutes for al. - out dx,al - inc edx - mov al,ch - out dx,al - dec edx - mov al,5 ;set hours for al. - out dx,al - inc edx - shr ecx,8 - mov al,ch - out dx,al - dec edx - mov al,0x0b ;enable irq's - out dx,al - inc dx - in al,dx - bts ax,5 ;set bit 5 - out dx,al - endsettime: - dec edx - call startstopclk - sti - and [esp+36-4],dword 0 - ret - bat_low: - sti - mov [esp+36-4],dword 2 - ret - wrongtime: - sti - mov [esp+36-4],dword 1 - ret - -startstopclk: - mov al,0x0b - out dx,al - inc dx - in al,dx - btc ax,7 - out dx,al - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;setting date,time,clock and alarm-clock +;add sys_settime at servetable as for ex. 22 fcn: +; 22 - SETTING DATE TIME, CLOCK AND ALARM-CLOCK +; ebx =0 - set time ecx - 00SSMMHH +; ebx =1 - set date ecx=00DDMMYY +; ebx =2 - set day of week ecx- 1-7 +; ebx =3 - set alarm-clock ecx - 00SSMMHH +; out: 0 -Ok 1 -wrong format 2 -battery low +sys_settime: + + cli + mov al, 0x0d + out 0x70, al + in al, 0x71 + bt ax, 7 + jnc bat_low + cmp ebx, 2;day of week + jne nosetweek + test ecx, ecx ;test day of week + je wrongtime + cmp ecx, 7 + ja wrongtime + mov edx, 0x70 + call startstopclk + dec edx + mov al, 6 + out dx, al + inc edx + mov al, cl + out dx, al + jmp endsettime + nosetweek: ;set date + cmp ebx, 1 + jne nosetdate + cmp cl, 0x99;test year + ja wrongtime + shl ecx, 4 + cmp cl, 0x90 + ja wrongtime + cmp ch, 0x99;test month + ja wrongtime + shr ecx, 4 + test ch, ch + je wrongtime + cmp ch, 0x12 + ja wrongtime + shl ecx, 8 + bswap ecx ;ebx=00YYMMDD + test cl, cl ;test day + je wrongtime + shl ecx, 4 + cmp cl, 0x90 + ja wrongtime + shr ecx, 4 + cmp ch, 2 ;February + jne testday + cmp cl, 0x29 + ja wrongtime + jmp setdate + testday: + cmp ch, 8 + jb testday1;Aug-Dec + bt cx, 8 + jnc days31 + jmp days30 + testday1: + bt cx, 8 ;Jan-Jul ex.Feb + jnc days30 + days31: + cmp cl, 0x31 + ja wrongtime + jmp setdate + days30: + cmp cl, 0x30 + ja wrongtime + setdate: + mov edx, 0x70 + call startstopclk + dec edx + mov al, 7 ;set days + out dx, al + inc edx + mov al, cl + out dx, al + dec edx + mov al, 8 ;set months + out dx, al + inc edx + mov al, ch + out dx, al + dec edx + mov al, 9 ;set years + out dx, al + inc edx + shr ecx, 8 + mov al, ch + out dx, al + jmp endsettime + nosetdate: ;set time or alarm-clock + cmp ebx, 3 + ja wrongtime + cmp cl, 0x23 + ja wrongtime + cmp ch, 0x59 + ja wrongtime + shl ecx, 4 + cmp cl, 0x90 + ja wrongtime + cmp ch, 0x92 + ja wrongtime + shl ecx, 4 + bswap ecx ;00HHMMSS + cmp cl, 0x59 + ja wrongtime + shl ecx, 4 + cmp cl, 0x90 + ja wrongtime + shr ecx, 4 + + mov edx, 0x70 + call startstopclk + dec edx + cmp ebx, 3 + + je setalarm + xor eax, eax;al=0-set seconds + out dx, al + inc edx + mov al, cl + out dx, al + dec edx + mov al, 2 ;set minutes + out dx, al + inc edx + mov al, ch + out dx, al + dec edx + mov al, 4 ;set hours + out dx, al + inc edx + shr ecx, 8 + mov al, ch + out dx, al + jmp endsettime + setalarm: + mov al, 1;set seconds for al. + out dx, al + inc edx + mov al, cl + out dx, al + dec edx + mov al, 3;set minutes for al. + out dx, al + inc edx + mov al, ch + out dx, al + dec edx + mov al, 5;set hours for al. + out dx, al + inc edx + shr ecx, 8 + mov al, ch + out dx, al + dec edx + mov al, 0x0b;enable irq's + out dx, al + inc dx + in al, dx + bts ax, 5;set bit 5 + out dx, al + endsettime: + dec edx + call startstopclk + sti + and [esp+36-4], dword 0 + ret + bat_low: + sti + mov [esp+36-4], dword 2 + ret + wrongtime: + sti + mov [esp+36-4], dword 1 + ret + +startstopclk: + mov al, 0x0b + out dx, al + inc dx + in al, dx + btc ax, 7 + out dx, al + ret diff --git a/kernel/trunk/imports.inc b/kernel/trunk/imports.inc index 3d94b67a1..18b4ff70c 100644 --- a/kernel/trunk/imports.inc +++ b/kernel/trunk/imports.inc @@ -1,27 +1,27 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;============================================================================ -; -; External kernel dependencies -; -;============================================================================ - -$Revision$ - - -align 4 -@IMPORT: - -library \ - libini,'libini.obj' - -import libini, \ - ini.lib_init,'lib_init',\ - ini.get_str,'ini.get_str',\ - ini.enum_keys,'ini.enum_keys',\ - ini.get_int,'ini.get_int' +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;============================================================================ +; +; External kernel dependencies +; +;============================================================================ + +$Revision$ + + +align 4 +@IMPORT: + +library \ + libini,'libini.obj' + +import libini, \ + ini.lib_init,'lib_init',\ + ini.get_str,'ini.get_str',\ + ini.enum_keys,'ini.enum_keys',\ + ini.get_int,'ini.get_int' diff --git a/kernel/trunk/init.inc b/kernel/trunk/init.inc index 80a070b2b..8f9627778 100644 --- a/kernel/trunk/init.inc +++ b/kernel/trunk/init.inc @@ -1,553 +1,554 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -MEM_WB equ 6 ;write-back memory -MEM_WC equ 1 ;write combined memory -MEM_UC equ 0 ;uncached memory - -align 4 -proc mem_test -; if we have BIOS with fn E820, skip the test - cmp dword [BOOT_VAR-OS_BASE + 0x9100], 0 - jnz .ret - - mov eax, cr0 - and eax, not (CR0_CD+CR0_NW) - or eax, CR0_CD ;disable caching - mov cr0, eax - wbinvd ;invalidate cache - - xor edi, edi - mov ebx, 'TEST' -@@: - add edi, 0x100000 - xchg ebx, dword [edi] - cmp dword [edi], 'TEST' - xchg ebx, dword [edi] - je @b - - and eax, not (CR0_CD+CR0_NW) ;enable caching - mov cr0, eax - inc dword [BOOT_VAR-OS_BASE + 0x9100] - xor eax, eax - mov [BOOT_VAR-OS_BASE + 0x9104], eax - mov [BOOT_VAR-OS_BASE + 0x9108], eax - mov [BOOT_VAR-OS_BASE + 0x910C], edi - mov [BOOT_VAR-OS_BASE + 0x9110], eax -.ret: - ret -endp - -align 4 -proc init_mem -; calculate maximum allocatable address and number of allocatable pages - mov edi, BOOT_VAR-OS_BASE + 0x9104 - mov ecx, [edi-4] - xor esi, esi ; esi will hold total amount of memory - xor edx, edx ; edx will hold maximum allocatable address -.calcmax: -; round all to pages - mov eax, [edi] - test eax, 0xFFF - jz @f - neg eax - and eax, 0xFFF - add [edi], eax - adc dword [edi+4], 0 - sub [edi+8], eax - sbb dword [edi+12], 0 - jc .unusable -@@: - and dword [edi+8], not 0xFFF - jz .unusable -; ignore memory after 4 Gb - cmp dword [edi+4], 0 - jnz .unusable - mov eax, [edi] - cmp dword [edi+12], 0 - jnz .overflow - add eax, [edi+8] - jnc @f -.overflow: - mov eax, 0xFFFFF000 -@@: - cmp edx, eax - jae @f - mov edx, eax -@@: - sub eax, [edi] - mov [edi+8], eax - add esi, eax - jmp .usable -.unusable: - and dword [edi+8], 0 -.usable: - add edi, 20 - loop .calcmax -.calculated: - mov [MEM_AMOUNT-OS_BASE], esi - mov [pg_data.mem_amount-OS_BASE], esi - shr esi, 12 - mov [pg_data.pages_count-OS_BASE], esi - - shr edx, 12 - add edx, 31 - and edx, not 31 - shr edx, 3 - mov [pg_data.pagemap_size-OS_BASE], edx - - add edx, (sys_pgmap-OS_BASE)+4095 - and edx, not 4095 - mov [tmp_page_tabs], edx - - mov edx, esi - and edx, -1024 - cmp edx, (OS_BASE/4096) - jbe @F - mov edx, (OS_BASE/4096) - jmp .set -@@: - cmp edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 - jae .set - mov edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 -.set: - mov [pg_data.kernel_pages-OS_BASE], edx - shr edx, 10 - mov [pg_data.kernel_tables-OS_BASE], edx - - xor eax, eax - mov edi, sys_pgdir-OS_BASE - mov ecx, 4096/4 - cld - rep stosd - - mov edx, (sys_pgdir-OS_BASE)+ 0x800; (OS_BASE shr 20) - bt [cpu_caps-OS_BASE], CAPS_PSE - jnc .no_PSE - - mov ebx, cr4 - or ebx, CR4_PSE - mov eax, PG_LARGE+PG_SW - mov cr4, ebx - dec [pg_data.kernel_tables-OS_BASE] - - mov [edx], eax - add edx, 4 - - mov edi, [tmp_page_tabs] - jmp .map_kernel_heap ; new kernel fits to the first 4Mb - nothing to do with ".map_low" -.no_PSE: - mov eax, PG_SW - mov ecx, [tmp_page_tabs] - shr ecx, 12 -.map_low: - mov edi, [tmp_page_tabs] -@@: ; - stosd - add eax, 0x1000 - dec ecx - jnz @B - -.map_kernel_heap: - mov ecx, [pg_data.kernel_tables-OS_BASE] - shl ecx, 10 - xor eax, eax - rep stosd - - mov ecx, [pg_data.kernel_tables-OS_BASE] - mov eax, [tmp_page_tabs] - or eax, PG_SW - mov edi, edx - -.map_kernel_tabs: - stosd - add eax, 0x1000 - dec ecx - jnz .map_kernel_tabs - - mov dword [sys_pgdir-OS_BASE+(page_tabs shr 20)], sys_pgdir+PG_SW-OS_BASE - - mov edi, (sys_pgdir-OS_BASE) - lea esi, [edi+(OS_BASE shr 20)] - movsd - movsd - ret -endp - -align 4 -proc init_page_map -; mark all memory as unavailable - mov edi, sys_pgmap-OS_BASE - mov ecx, [pg_data.pagemap_size-OS_BASE] - shr ecx, 2 - xor eax, eax - cld - rep stosd - -; scan through memory map and mark free areas as available - mov ebx, BOOT_VAR-OS_BASE + 0x9104 - mov edx, [ebx-4] -.scanmap: - mov ecx, [ebx+8] - shr ecx, 12 ; ecx = number of pages - jz .next - mov edi, [ebx] - shr edi, 12 ; edi = first page - mov eax, edi - shr edi, 5 - shl edi, 2 - add edi, sys_pgmap-OS_BASE - and eax, 31 - jz .startok - add ecx, eax - sub ecx, 32 - jbe .onedword - push ecx - mov ecx, eax - or eax, -1 - shl eax, cl - or [edi], eax - add edi, 4 - pop ecx -.startok: - push ecx - shr ecx, 5 - or eax, -1 - rep stosd - pop ecx - and ecx, 31 - neg eax - shl eax, cl - dec eax - or [edi], eax - jmp .next -.onedword: - add ecx, 32 - sub ecx, eax -@@: - bts [edi], eax - inc eax - loop @b -.next: - add ebx, 20 - dec edx - jnz .scanmap - -; mark kernel memory as allocated (unavailable) - mov ecx, [tmp_page_tabs] - mov edx, [pg_data.pages_count-OS_BASE] - shr ecx, 12 - add ecx, [pg_data.kernel_tables-OS_BASE] - sub edx, ecx - mov [pg_data.pages_free-OS_BASE], edx - - mov edi, sys_pgmap-OS_BASE - mov ebx, ecx - shr ecx, 5 - xor eax, eax - rep stosd - - not eax - mov ecx, ebx - and ecx, 31 - shl eax, cl - and [edi], eax - add edi, OS_BASE - mov [page_start-OS_BASE], edi; - - mov ebx, sys_pgmap - add ebx, [pg_data.pagemap_size-OS_BASE] - mov [page_end-OS_BASE], ebx - - ret -endp - -align 4 - -init_BIOS32: - mov edi, 0xE0000 -.pcibios_nxt: - cmp dword[edi], '_32_' ; "magic" word - je .BIOS32_found -.pcibios_nxt2: - add edi, 0x10 - cmp edi, 0xFFFF0 - je .BIOS32_not_found - jmp .pcibios_nxt -.BIOS32_found: ; magic word found, check control summ - - movzx ecx, byte[edi + 9] - shl ecx, 4 - mov esi, edi - xor eax, eax - cld ; paranoia -@@: lodsb - add ah, al - loop @b - jnz .pcibios_nxt2 ; control summ must be zero - ; BIOS32 service found ! - mov ebp, [edi + 4] - mov [bios32_entry], ebp - ; check PCI BIOS present - mov eax, '$PCI' - xor ebx, ebx - push cs ; special for 'ret far' from BIOS - call ebp - test al, al - jnz .PCI_BIOS32_not_found - - ; здесь создаются дискрипторы для PCI BIOS - - add ebx, OS_BASE - dec ecx - mov [(pci_code_32-OS_BASE)], cx ;limit 0-15 - mov [(pci_data_32-OS_BASE)], cx ;limit 0-15 - - mov [(pci_code_32-OS_BASE)+2], bx ;base 0-15 - mov [(pci_data_32-OS_BASE)+2], bx ;base 0-15 - - shr ebx, 16 - mov [(pci_code_32-OS_BASE)+4], bl ;base 16-23 - mov [(pci_data_32-OS_BASE)+4], bl ;base 16-23 - - shr ecx, 16 - and cl, 0x0F - mov ch, bh - add cx, D32 - mov [(pci_code_32-OS_BASE)+6], cx ;lim 16-19 & - mov [(pci_data_32-OS_BASE)+6], cx ;base 24-31 - - mov [(pci_bios_entry-OS_BASE)], edx - ; jmp .end -.PCI_BIOS32_not_found: - ; здесь должна заполнятся pci_emu_dat -.BIOS32_not_found: -.end: - ret - -align 4 -proc test_cpu - locals - cpu_type dd ? - cpu_id dd ? - cpu_Intel dd ? - cpu_AMD dd ? - endl - - xor eax, eax - mov [cpu_type], eax - mov [cpu_caps-OS_BASE], eax - mov [cpu_caps+4-OS_BASE], eax - - pushfd - pop eax - mov ecx, eax - xor eax, 0x40000 - push eax - popfd - pushfd - pop eax - xor eax, ecx - mov [cpu_type], CPU_386 - jz .end_cpuid - push ecx - popfd - - mov [cpu_type], CPU_486 - mov eax, ecx - xor eax, 0x200000 - push eax - popfd - pushfd - pop eax - xor eax, ecx - je .end_cpuid - mov [cpu_id], 1 - - xor eax, eax - cpuid - - mov [cpu_vendor-OS_BASE], ebx - mov [cpu_vendor+4-OS_BASE], edx - mov [cpu_vendor+8-OS_BASE], ecx - cmp ebx, dword [intel_str-OS_BASE] - jne .check_AMD - cmp edx, dword [intel_str+4-OS_BASE] - jne .check_AMD - cmp ecx, dword [intel_str+8-OS_BASE] - jne .check_AMD - mov [cpu_Intel], 1 - cmp eax, 1 - jl .end_cpuid - mov eax, 1 - cpuid - mov [cpu_sign-OS_BASE], eax - mov [cpu_info-OS_BASE], ebx - mov [cpu_caps-OS_BASE], edx - mov [cpu_caps+4-OS_BASE],ecx - - shr eax, 8 - and eax, 0x0f - ret -.end_cpuid: - mov eax, [cpu_type] - ret - -.check_AMD: - cmp ebx, dword [AMD_str-OS_BASE] - jne .unknown - cmp edx, dword [AMD_str+4-OS_BASE] - jne .unknown - cmp ecx, dword [AMD_str+8-OS_BASE] - jne .unknown - mov [cpu_AMD], 1 - cmp eax, 1 - jl .unknown - mov eax, 1 - cpuid - mov [cpu_sign-OS_BASE], eax - mov [cpu_info-OS_BASE], ebx - mov [cpu_caps-OS_BASE], edx - mov [cpu_caps+4-OS_BASE],ecx - shr eax, 8 - and eax, 0x0f - ret -.unknown: - mov eax, 1 - cpuid - mov [cpu_sign-OS_BASE], eax - mov [cpu_info-OS_BASE], ebx - mov [cpu_caps-OS_BASE], edx - mov [cpu_caps+4-OS_BASE],ecx - shr eax, 8 - and eax, 0x0f - ret -endp - -uglobal -align 4 -acpi_rsdp rd 1 -acpi_rsdt rd 1 -acpi_madt rd 1 - -acpi_dev_data rd 1 -acpi_dev_size rd 1 - -acpi_rsdt_base rd 1 -acpi_madt_base rd 1 -acpi_lapic_base rd 1 -acpi_ioapic_base rd 1 -endg - -ACPI_HI_RSDP_WINDOW_START equ 0x000E0000 -ACPI_HI_RSDP_WINDOW_END equ 0x00100000 -ACPI_RSDP_CHECKSUM_LENGTH equ 20 -ACPI_MADT_SIGN equ 0x43495041 - - -acpi_locate: - push ebx - mov ebx, ACPI_HI_RSDP_WINDOW_START -.check: - cmp [ebx], dword 0x20445352 - jne .next - cmp [ebx+4], dword 0x20525450 - jne .next - - mov edx, ebx - mov ecx, ACPI_RSDP_CHECKSUM_LENGTH - xor eax, eax -.sum: - add al, [edx] - inc edx - loop .sum - - test al, al - jnz .next - - mov eax, ebx - pop ebx - ret -.next: - add ebx, 16 - cmp ebx, ACPI_HI_RSDP_WINDOW_END - jb .check - - pop ebx - xor eax, eax - ret - -align 4 -rsdt_find: ;ecx= rsdt edx= SIG - push ebx - push esi - - lea ebx, [ecx+36] - mov esi, [ecx+4] - add esi, ecx -.next: - mov eax, [ebx] - cmp [eax], edx - je .done - - add ebx, 4 - cmp ebx, esi - jb .next - - xor eax, eax - pop esi - pop ebx - ret - -.done: - mov eax, [ebx] - pop esi - pop ebx - ret - - -align 4 - -check_acpi: - - call acpi_locate - test eax, eax - jz .done - - mov ecx, [eax+16] - mov edx, ACPI_MADT_SIGN - mov [acpi_rsdt_base-OS_BASE], ecx - call rsdt_find - test eax, eax - jz .done - - mov [acpi_madt_base-OS_BASE], eax - mov ecx, [eax+36] - mov [acpi_lapic_base-OS_BASE], ecx - - lea edx, [eax+44] - mov ecx, [eax+4] - add ecx, eax -.check: - mov eax, [edx] - cmp al, 1 - je .ioapic - -.next: - movzx eax, ah - add edx, eax - cmp edx, ecx - jb .check -.done: - ret -.ioapic: - mov eax, [edx+4] - mov [acpi_ioapic_base-OS_BASE], eax - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +MEM_WB equ 6 ;write-back memory +MEM_WC equ 1 ;write combined memory +MEM_UC equ 0 ;uncached memory + +align 4 +proc mem_test +; if we have BIOS with fn E820, skip the test + cmp dword [BOOT_VAR-OS_BASE + 0x9100], 0 + jnz .ret + + mov eax, cr0 + and eax, not (CR0_CD+CR0_NW) + or eax, CR0_CD ;disable caching + mov cr0, eax + wbinvd ;invalidate cache + + xor edi, edi + mov ebx, 'TEST' +@@: + add edi, 0x100000 + xchg ebx, dword [edi] + cmp dword [edi], 'TEST' + xchg ebx, dword [edi] + je @b + + and eax, not (CR0_CD+CR0_NW) ;enable caching + mov cr0, eax + inc dword [BOOT_VAR-OS_BASE + 0x9100] + xor eax, eax + mov [BOOT_VAR-OS_BASE + 0x9104], eax + mov [BOOT_VAR-OS_BASE + 0x9108], eax + mov [BOOT_VAR-OS_BASE + 0x910C], edi + mov [BOOT_VAR-OS_BASE + 0x9110], eax +.ret: + ret +endp + +align 4 +proc init_mem +; calculate maximum allocatable address and number of allocatable pages + mov edi, BOOT_VAR-OS_BASE + 0x9104 + mov ecx, [edi-4] + xor esi, esi; esi will hold total amount of memory + xor edx, edx; edx will hold maximum allocatable address +.calcmax: +; round all to pages + mov eax, [edi] + test eax, 0xFFF + jz @f + neg eax + and eax, 0xFFF + add [edi], eax + adc dword [edi+4], 0 + sub [edi+8], eax + sbb dword [edi+12], 0 + jc .unusable +@@: + and dword [edi+8], not 0xFFF + jz .unusable +; ignore memory after 4 Gb + cmp dword [edi+4], 0 + jnz .unusable + mov eax, [edi] + cmp dword [edi+12], 0 + jnz .overflow + add eax, [edi+8] + jnc @f +.overflow: + mov eax, 0xFFFFF000 +@@: + cmp edx, eax + jae @f + mov edx, eax +@@: + sub eax, [edi] + mov [edi+8], eax + add esi, eax + jmp .usable +.unusable: + and dword [edi+8], 0 +.usable: + add edi, 20 + loop .calcmax +.calculated: + mov [MEM_AMOUNT-OS_BASE], esi + mov [pg_data.mem_amount-OS_BASE], esi + shr esi, 12 + mov [pg_data.pages_count-OS_BASE], esi + + shr edx, 12 + add edx, 31 + and edx, not 31 + shr edx, 3 + mov [pg_data.pagemap_size-OS_BASE], edx + + add edx, (sys_pgmap-OS_BASE)+4095 + and edx, not 4095 + mov [tmp_page_tabs], edx + + mov edx, esi + and edx, -1024 + cmp edx, (OS_BASE/4096) + jbe @F + mov edx, (OS_BASE/4096) + jmp .set +@@: + cmp edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 + jae .set + mov edx, (HEAP_BASE-OS_BASE+HEAP_MIN_SIZE)/4096 +.set: + mov [pg_data.kernel_pages-OS_BASE], edx + shr edx, 10 + mov [pg_data.kernel_tables-OS_BASE], edx + + xor eax, eax + mov edi, sys_pgdir-OS_BASE + mov ecx, 4096/4 + cld + rep stosd + + mov edx, (sys_pgdir-OS_BASE)+ 0x800; (OS_BASE shr 20) + bt [cpu_caps-OS_BASE], CAPS_PSE + jnc .no_PSE + + mov ebx, cr4 + or ebx, CR4_PSE + mov eax, PG_LARGE+PG_SW + mov cr4, ebx + dec [pg_data.kernel_tables-OS_BASE] + + mov [edx], eax + add edx, 4 + + mov edi, [tmp_page_tabs] + jmp .map_kernel_heap ; new kernel fits to the first 4Mb - nothing to do with ".map_low" +.no_PSE: + mov eax, PG_SW + mov ecx, [tmp_page_tabs] + shr ecx, 12 +.map_low: + mov edi, [tmp_page_tabs] +@@: ; + stosd + add eax, 0x1000 + dec ecx + jnz @B + +.map_kernel_heap: + mov ecx, [pg_data.kernel_tables-OS_BASE] + shl ecx, 10 + xor eax, eax + rep stosd + + mov ecx, [pg_data.kernel_tables-OS_BASE] + mov eax, [tmp_page_tabs] + or eax, PG_SW + mov edi, edx + +.map_kernel_tabs: + stosd + add eax, 0x1000 + dec ecx + jnz .map_kernel_tabs + + mov dword [sys_pgdir-OS_BASE+(page_tabs shr 20)], sys_pgdir+PG_SW-OS_BASE + + mov edi, (sys_pgdir-OS_BASE) + lea esi, [edi+(OS_BASE shr 20)] + movsd + movsd + ret +endp + +align 4 +proc init_page_map +; mark all memory as unavailable + mov edi, sys_pgmap-OS_BASE + mov ecx, [pg_data.pagemap_size-OS_BASE] + shr ecx, 2 + xor eax, eax + cld + rep stosd + +; scan through memory map and mark free areas as available + mov ebx, BOOT_VAR-OS_BASE + 0x9104 + mov edx, [ebx-4] +.scanmap: + mov ecx, [ebx+8] + shr ecx, 12; ecx = number of pages + jz .next + mov edi, [ebx] + shr edi, 12; edi = first page + mov eax, edi + shr edi, 5 + shl edi, 2 + add edi, sys_pgmap-OS_BASE + and eax, 31 + jz .startok + add ecx, eax + sub ecx, 32 + jbe .onedword + push ecx + mov ecx, eax + or eax, -1 + shl eax, cl + or [edi], eax + add edi, 4 + pop ecx +.startok: + push ecx + shr ecx, 5 + or eax, -1 + rep stosd + pop ecx + and ecx, 31 + neg eax + shl eax, cl + dec eax + or [edi], eax + jmp .next +.onedword: + add ecx, 32 + sub ecx, eax +@@: + bts [edi], eax + inc eax + loop @b +.next: + add ebx, 20 + dec edx + jnz .scanmap + +; mark kernel memory as allocated (unavailable) + mov ecx, [tmp_page_tabs] + mov edx, [pg_data.pages_count-OS_BASE] + shr ecx, 12 + add ecx, [pg_data.kernel_tables-OS_BASE] + sub edx, ecx + mov [pg_data.pages_free-OS_BASE], edx + + mov edi, sys_pgmap-OS_BASE + mov ebx, ecx + shr ecx, 5 + xor eax, eax + rep stosd + + not eax + mov ecx, ebx + and ecx, 31 + shl eax, cl + and [edi], eax + add edi, OS_BASE + mov [page_start-OS_BASE], edi; + + mov ebx, sys_pgmap + add ebx, [pg_data.pagemap_size-OS_BASE] + mov [page_end-OS_BASE], ebx + + ret +endp + +align 4 + +init_BIOS32: + mov edi, 0xE0000 +.pcibios_nxt: + cmp dword[edi], '_32_'; "magic" word + je .BIOS32_found +.pcibios_nxt2: + add edi, 0x10 + cmp edi, 0xFFFF0 + je .BIOS32_not_found + jmp .pcibios_nxt +.BIOS32_found: ; magic word found, check control summ + + movzx ecx, byte[edi + 9] + shl ecx, 4 + mov esi, edi + xor eax, eax + cld ; paranoia +@@: + lodsb + add ah, al + loop @b + jnz .pcibios_nxt2; control summ must be zero + ; BIOS32 service found ! + mov ebp, [edi + 4] + mov [bios32_entry], ebp + ; check PCI BIOS present + mov eax, '$PCI' + xor ebx, ebx + push cs ; special for 'ret far' from BIOS + call ebp + test al, al + jnz .PCI_BIOS32_not_found + + ; здесь создаются дискрипторы для PCI BIOS + + add ebx, OS_BASE + dec ecx + mov [(pci_code_32-OS_BASE)], cx ;limit 0-15 + mov [(pci_data_32-OS_BASE)], cx ;limit 0-15 + + mov [(pci_code_32-OS_BASE)+2], bx ;base 0-15 + mov [(pci_data_32-OS_BASE)+2], bx ;base 0-15 + + shr ebx, 16 + mov [(pci_code_32-OS_BASE)+4], bl ;base 16-23 + mov [(pci_data_32-OS_BASE)+4], bl ;base 16-23 + + shr ecx, 16 + and cl, 0x0F + mov ch, bh + add cx, D32 + mov [(pci_code_32-OS_BASE)+6], cx ;lim 16-19 & + mov [(pci_data_32-OS_BASE)+6], cx ;base 24-31 + + mov [(pci_bios_entry-OS_BASE)], edx + ; jmp .end +.PCI_BIOS32_not_found: + ; здесь должна заполнятся pci_emu_dat +.BIOS32_not_found: +.end: + ret + +align 4 +proc test_cpu + locals + cpu_type dd ? + cpu_id dd ? + cpu_Intel dd ? + cpu_AMD dd ? + endl + + xor eax, eax + mov [cpu_type], eax + mov [cpu_caps-OS_BASE], eax + mov [cpu_caps+4-OS_BASE], eax + + pushfd + pop eax + mov ecx, eax + xor eax, 0x40000 + push eax + popfd + pushfd + pop eax + xor eax, ecx + mov [cpu_type], CPU_386 + jz .end_cpuid + push ecx + popfd + + mov [cpu_type], CPU_486 + mov eax, ecx + xor eax, 0x200000 + push eax + popfd + pushfd + pop eax + xor eax, ecx + je .end_cpuid + mov [cpu_id], 1 + + xor eax, eax + cpuid + + mov [cpu_vendor-OS_BASE], ebx + mov [cpu_vendor+4-OS_BASE], edx + mov [cpu_vendor+8-OS_BASE], ecx + cmp ebx, dword [intel_str-OS_BASE] + jne .check_AMD + cmp edx, dword [intel_str+4-OS_BASE] + jne .check_AMD + cmp ecx, dword [intel_str+8-OS_BASE] + jne .check_AMD + mov [cpu_Intel], 1 + cmp eax, 1 + jl .end_cpuid + mov eax, 1 + cpuid + mov [cpu_sign-OS_BASE], eax + mov [cpu_info-OS_BASE], ebx + mov [cpu_caps-OS_BASE], edx + mov [cpu_caps+4-OS_BASE], ecx + + shr eax, 8 + and eax, 0x0f + ret +.end_cpuid: + mov eax, [cpu_type] + ret + +.check_AMD: + cmp ebx, dword [AMD_str-OS_BASE] + jne .unknown + cmp edx, dword [AMD_str+4-OS_BASE] + jne .unknown + cmp ecx, dword [AMD_str+8-OS_BASE] + jne .unknown + mov [cpu_AMD], 1 + cmp eax, 1 + jl .unknown + mov eax, 1 + cpuid + mov [cpu_sign-OS_BASE], eax + mov [cpu_info-OS_BASE], ebx + mov [cpu_caps-OS_BASE], edx + mov [cpu_caps+4-OS_BASE], ecx + shr eax, 8 + and eax, 0x0f + ret +.unknown: + mov eax, 1 + cpuid + mov [cpu_sign-OS_BASE], eax + mov [cpu_info-OS_BASE], ebx + mov [cpu_caps-OS_BASE], edx + mov [cpu_caps+4-OS_BASE], ecx + shr eax, 8 + and eax, 0x0f + ret +endp + +uglobal +align 4 +acpi_rsdp rd 1 +acpi_rsdt rd 1 +acpi_madt rd 1 + +acpi_dev_data rd 1 +acpi_dev_size rd 1 + +acpi_rsdt_base rd 1 +acpi_madt_base rd 1 +acpi_lapic_base rd 1 +acpi_ioapic_base rd 1 +endg + +ACPI_HI_RSDP_WINDOW_START equ 0x000E0000 +ACPI_HI_RSDP_WINDOW_END equ 0x00100000 +ACPI_RSDP_CHECKSUM_LENGTH equ 20 +ACPI_MADT_SIGN equ 0x43495041 + + +acpi_locate: + push ebx + mov ebx, ACPI_HI_RSDP_WINDOW_START +.check: + cmp [ebx], dword 0x20445352 + jne .next + cmp [ebx+4], dword 0x20525450 + jne .next + + mov edx, ebx + mov ecx, ACPI_RSDP_CHECKSUM_LENGTH + xor eax, eax +.sum: + add al, [edx] + inc edx + loop .sum + + test al, al + jnz .next + + mov eax, ebx + pop ebx + ret +.next: + add ebx, 16 + cmp ebx, ACPI_HI_RSDP_WINDOW_END + jb .check + + pop ebx + xor eax, eax + ret + +align 4 +rsdt_find: ;ecx= rsdt edx= SIG + push ebx + push esi + + lea ebx, [ecx+36] + mov esi, [ecx+4] + add esi, ecx +.next: + mov eax, [ebx] + cmp [eax], edx + je .done + + add ebx, 4 + cmp ebx, esi + jb .next + + xor eax, eax + pop esi + pop ebx + ret + +.done: + mov eax, [ebx] + pop esi + pop ebx + ret + + +align 4 + +check_acpi: + + call acpi_locate + test eax, eax + jz .done + + mov ecx, [eax+16] + mov edx, ACPI_MADT_SIGN + mov [acpi_rsdt_base-OS_BASE], ecx + call rsdt_find + test eax, eax + jz .done + + mov [acpi_madt_base-OS_BASE], eax + mov ecx, [eax+36] + mov [acpi_lapic_base-OS_BASE], ecx + + lea edx, [eax+44] + mov ecx, [eax+4] + add ecx, eax +.check: + mov eax, [edx] + cmp al, 1 + je .ioapic + +.next: + movzx eax, ah + add edx, eax + cmp edx, ecx + jb .check +.done: + ret +.ioapic: + mov eax, [edx+4] + mov [acpi_ioapic_base-OS_BASE], eax + ret diff --git a/kernel/trunk/kernel.asm b/kernel/trunk/kernel.asm index ad27957cb..65206b176 100644 --- a/kernel/trunk/kernel.asm +++ b/kernel/trunk/kernel.asm @@ -1,5088 +1,5097 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. -;; PROGRAMMING: -;; Ivan Poddubny -;; Marat Zakiyanov (Mario79) -;; VaStaNi -;; Trans -;; Mihail Semenyako (mike.dld) -;; Sergey Kuzmin (Wildwest) -;; Andrey Halyavin (halyavin) -;; Mihail Lisovin (Mihasik) -;; Andrey Ignatiev (andrew_programmer) -;; NoName -;; Evgeny Grechnikov (Diamond) -;; Iliya Mihailov (Ghost) -;; Sergey Semyonov (Serge) -;; Johnny_B -;; SPraid (simba) -;; Hidnplayr -;; Alexey Teplov () -;; Rus -;; Nable -;; shurf -;; Alver -;; Maxis -;; Galkov -;; CleverMouse -;; tsdima -;; turbanoff -;; Asper -;; art_zh -;; -;; Data in this file was originally part of MenuetOS project which is -;; distributed under the terms of GNU GPL. It is modified and redistributed as -;; part of KolibriOS project under the terms of GNU GPL. -;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa -;; PROGRAMMING: -;; -;; Ville Mikael Turjanmaa, villemt@itu.jyu.fi -;; - main os coding/design -;; Jan-Michael Brummer, BUZZ2@gmx.de -;; Felix Kaiser, info@felix-kaiser.de -;; Paolo Minazzi, paolo.minazzi@inwind.it -;; quickcode@mail.ru -;; Alexey, kgaz@crosswinds.net -;; Juan M. Caravaca, bitrider@wanadoo.es -;; kristol@nic.fi -;; Mike Hibbett, mikeh@oceanfree.net -;; Lasse Kuusijarvi, kuusijar@lut.fi -;; Jarek Pelczar, jarekp3@wp.pl -;; -;; KolibriOS is distributed in the hope that it will be useful, but WITHOUT ANY -;; WARRANTY. No author or distributor accepts responsibility to anyone for the -;; consequences of using it or for whether it serves any particular purpose or -;; works at all, unless he says so in writing. Refer to the GNU General Public -;; License (the "GPL") for full details. -; -;; Everyone is granted permission to copy, modify and redistribute KolibriOS, -;; but only under the conditions described in the GPL. A copy of this license -;; is supposed to have been given to you along with KolibriOS so you can know -;; your rights and responsibilities. It should be in a file named COPYING. -;; Among other things, the copyright notice and this notice must be preserved -;; on all copies. -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -include 'macros.inc' - -$Revision$ - - -USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices - -; Enabling the next line will enable serial output console -;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used - -include "proc32.inc" -include "kglobals.inc" -include "lang.inc" - -include "const.inc" -max_processes equ 255 -tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4 - - -os_stack equ (os_data_l-gdts) ; GDTs -os_code equ (os_code_l-gdts) -graph_data equ (3+graph_data_l-gdts) -tss0 equ (tss0_l-gdts) -app_code equ (3+app_code_l-gdts) -app_data equ (3+app_data_l-gdts) -app_tls equ (3+tls_data_l-gdts) -pci_code_sel equ (pci_code_32-gdts) -pci_data_sel equ (pci_data_32-gdts) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; Included files: -;; -;; Kernel16.inc -;; - Booteng.inc English text for bootup -;; - Bootcode.inc Hardware setup -;; - Pci16.inc PCI functions -;; -;; Kernel32.inc -;; - Sys32.inc Process management -;; - Shutdown.inc Shutdown and restart -;; - Fat32.inc Read / write hd -;; - Vesa12.inc Vesa 1.2 driver -;; - Vesa20.inc Vesa 2.0 driver -;; - Vga.inc VGA driver -;; - Stack.inc Network interface -;; - Mouse.inc Mouse pointer -;; - Scincode.inc Window skinning -;; - Pci32.inc PCI functions -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; 16 BIT ENTRY FROM BOOTSECTOR ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -use16 - org 0x0 - jmp start_of_code - -version db 'Kolibri OS version 0.7.7.0+ ',13,10,13,10,0 - -include "boot/bootstr.inc" ; language-independent boot messages -include "boot/preboot.inc" - -if lang eq en -include "boot/booteng.inc" ; english system boot messages -else if lang eq ru -include "boot/bootru.inc" ; russian system boot messages -include "boot/ru.inc" ; Russian font -else if lang eq et -include "boot/bootet.inc" ; estonian system boot messages -include "boot/et.inc" ; Estonian font -else -include "boot/bootge.inc" ; german system boot messages -end if - -include "boot/bootcode.inc" ; 16 bit system boot code -include "bus/pci/pci16.inc" -include "detect/biosdisk.inc" - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; SWITCH TO 32 BIT PROTECTED MODE ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -; CR0 Flags - Protected mode and Paging - - mov ecx, CR0_PE - -; Enabling 32 bit protected mode - - sidt [cs:old_ints_h] - - cli ; disable all irqs - cld - mov al,255 ; mask all irqs - out 0xa1,al - out 0x21,al - l.5: in al, 0x64 ; Enable A20 - test al, 2 - jnz l.5 - mov al, 0xD1 - out 0x64, al - l.6: in al, 0x64 - test al, 2 - jnz l.6 - mov al, 0xDF - out 0x60, al - l.7: in al, 0x64 - test al, 2 - jnz l.7 - mov al, 0xFF - out 0x64, al - - lgdt [cs:tmp_gdt] ; Load GDT - mov eax, cr0 ; protected mode - or eax, ecx - and eax, 10011111b *65536*256 + 0xffffff ; caching enabled - mov cr0, eax - jmp pword os_code:B32 ; jmp to enable 32 bit mode - -align 8 -tmp_gdt: - - dw 23 - dd tmp_gdt+0x10000 - dw 0 - - dw 0xffff - dw 0x0000 - db 0x00 - dw 11011111b *256 +10011010b - db 0x00 - - dw 0xffff - dw 0x0000 - db 0x00 - dw 11011111b *256 +10010010b - db 0x00 - -include "data16.inc" - -use32 -org $+0x10000 - -align 4 -B32: - mov ax,os_stack ; Selector for os - mov ds,ax - mov es,ax - mov fs,ax - mov gs,ax - mov ss,ax - mov esp,0x006CC00 ; Set stack - -; CLEAR 0x280000 - HEAP_BASE - - xor eax,eax - mov edi,CLEAN_ZONE - mov ecx,(HEAP_BASE-OS_BASE-CLEAN_ZONE) / 4 - cld - rep stosd - -; CLEAR KERNEL UNDEFINED GLOBALS - mov edi, endofcode-OS_BASE - mov ecx, 0x90000 - sub ecx, edi - shr ecx, 2 - rep stosd - -; SAVE & CLEAR 0-0xffff - - xor esi, esi - mov edi,(BOOT_VAR-OS_BASE) - mov ecx,0x10000 / 4 - rep movsd - mov edi,0x1000 - mov ecx,0xf000 / 4 - rep stosd - - call test_cpu - bts [cpu_caps-OS_BASE], CAPS_TSC ;force use rdtsc - - call check_acpi - call init_BIOS32 -; MEMORY MODEL - call mem_test - call init_mem - call init_page_map - -; ENABLE PAGING - - mov eax, sys_pgdir-OS_BASE - mov cr3, eax - - mov eax,cr0 - or eax,CR0_PG+CR0_WP - mov cr0,eax - - lgdt [gdts] - jmp pword os_code:high_code - -align 4 -bios32_entry dd ? -tmp_page_tabs dd ? - -use16 -org $-0x10000 -include "boot/shutdown.inc" ; shutdown or restart -org $+0x10000 -use32 - -__DEBUG__ fix 1 -__DEBUG_LEVEL__ fix 1 -include 'init.inc' - -org OS_BASE+$ - -align 4 -high_code: - mov ax, os_stack - mov bx, app_data - mov cx, app_tls - mov ss, ax - add esp, OS_BASE - - mov ds, bx - mov es, bx - mov fs, cx - mov gs, bx - - bt [cpu_caps], CAPS_PGE - jnc @F - - or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL - - mov ebx, cr4 - or ebx, CR4_PGE - mov cr4, ebx -@@: - xor eax, eax - mov dword [sys_pgdir], eax - mov dword [sys_pgdir+4], eax - - mov eax, cr3 - mov cr3, eax ; flush TLB - - mov ecx, pg_data.mutex - call mutex_init - - mov ecx, disk_list_mutex - call mutex_init - -; SAVE REAL MODE VARIABLES - mov ax, [BOOT_VAR + 0x9031] - mov [IDEContrRegsBaseAddr], ax -; --------------- APM --------------------- - -; init selectors - mov ebx,[BOOT_VAR+0x9040] ; offset of APM entry point - movzx eax,word [BOOT_VAR+0x9050] ; real-mode segment base address of - ; protected-mode 32-bit code segment - movzx ecx,word [BOOT_VAR+0x9052] ; real-mode segment base address of - ; protected-mode 16-bit code segment - movzx edx,word [BOOT_VAR+0x9054] ; real-mode segment base address of - ; protected-mode 16-bit data segment - - shl eax, 4 - mov [dword apm_code_32 + 2], ax - shr eax, 16 - mov [dword apm_code_32 + 4], al - - shl ecx, 4 - mov [dword apm_code_16 + 2], cx - shr ecx, 16 - mov [dword apm_code_16 + 4], cl - - shl edx, 4 - mov [dword apm_data_16 + 2], dx - shr edx, 16 - mov [dword apm_data_16 + 4], dl - - mov dword[apm_entry], ebx - mov word [apm_entry + 4], apm_code_32 - gdts - - mov eax, [BOOT_VAR + 0x9044] ; version & flags - mov [apm_vf], eax -; ----------------------------------------- -; movzx eax,byte [BOOT_VAR+0x9010] ; mouse port -; mov [0xF604],byte 1 ;al - mov al, [BOOT_VAR+0x901F] ; DMA access - mov [allow_dma_access], al - movzx eax, byte [BOOT_VAR+0x9000] ; bpp - mov [ScreenBPP],al - - mov [_display.bpp], eax - mov [_display.vrefresh], 60 - mov [_display.disable_mouse], __sys_disable_mouse - - movzx eax,word [BOOT_VAR+0x900A] ; X max - mov [_display.width], eax - dec eax - mov [Screen_Max_X],eax - mov [screen_workarea.right],eax - movzx eax,word [BOOT_VAR+0x900C] ; Y max - mov [_display.height], eax - dec eax - mov [Screen_Max_Y],eax - mov [screen_workarea.bottom],eax - movzx eax,word [BOOT_VAR+0x9008] ; screen mode - mov [SCR_MODE],eax - mov eax,[BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add - mov [BANK_SWITCH],eax - mov [BytesPerScanLine],word 640*4 ; Bytes PerScanLine - cmp [SCR_MODE],word 0x13 ; 320x200 - je @f - cmp [SCR_MODE],word 0x12 ; VGA 640x480 - je @f - movzx eax, word[BOOT_VAR+0x9001] ; for other modes - mov [BytesPerScanLine],ax - mov [_display.pitch], eax -@@: - mov eax, [_display.width] - mul [_display.height] - mov [_WinMapSize], eax - - mov esi, BOOT_VAR+0x9080 - movzx ecx, byte [esi-1] - mov [NumBiosDisks], ecx - mov edi, BiosDisksData - rep movsd - -; GRAPHICS ADDRESSES - - and byte [BOOT_VAR+0x901e],0x0 - mov eax,[BOOT_VAR+0x9018] - mov [LFBAddress],eax - - cmp [SCR_MODE],word 0100000000000000b - jge setvesa20 - cmp [SCR_MODE],word 0x13 - je v20ga32 - mov [PUTPIXEL],dword Vesa12_putpixel24 ; Vesa 1.2 - mov [GETPIXEL],dword Vesa12_getpixel24 - cmp [ScreenBPP],byte 24 - jz ga24 - mov [PUTPIXEL],dword Vesa12_putpixel32 - mov [GETPIXEL],dword Vesa12_getpixel32 - ga24: - jmp v20ga24 - setvesa20: - mov [PUTPIXEL],dword Vesa20_putpixel24 ; Vesa 2.0 - mov [GETPIXEL],dword Vesa20_getpixel24 - cmp [ScreenBPP],byte 24 - jz v20ga24 - v20ga32: - mov [PUTPIXEL],dword Vesa20_putpixel32 - mov [GETPIXEL],dword Vesa20_getpixel32 - v20ga24: - cmp [SCR_MODE],word 0x12 ; 16 C VGA 640x480 - jne no_mode_0x12 - mov [PUTPIXEL],dword VGA_putpixel - mov [GETPIXEL],dword Vesa20_getpixel32 - no_mode_0x12: - -; -------- Fast System Call init ---------- -; Intel SYSENTER/SYSEXIT (AMD CPU support it too) - bt [cpu_caps], CAPS_SEP - jnc .SEnP ; SysEnter not Present - xor edx, edx - mov ecx, MSR_SYSENTER_CS - mov eax, os_code - wrmsr - mov ecx, MSR_SYSENTER_ESP -; mov eax, sysenter_stack ; Check it - xor eax, eax - wrmsr - mov ecx, MSR_SYSENTER_EIP - mov eax, sysenter_entry - wrmsr -.SEnP: -; AMD SYSCALL/SYSRET - cmp byte[cpu_vendor], 'A' - jne .noSYSCALL - mov eax, 0x80000001 - cpuid - test edx, 0x800 ; bit_11 - SYSCALL/SYSRET support - jz .noSYSCALL - mov ecx, MSR_AMD_EFER - rdmsr - or eax, 1 ; bit_0 - System Call Extension (SCE) - wrmsr - - ; !!!! It`s dirty hack, fix it !!! - ; Bits of EDX : - ; Bit 31–16 During the SYSRET instruction, this field is copied into the CS register - ; and the contents of this field, plus 8, are copied into the SS register. - ; Bit 15–0 During the SYSCALL instruction, this field is copied into the CS register - ; and the contents of this field, plus 8, are copied into the SS register. - - ; mov edx, (os_code + 16) * 65536 + os_code - mov edx, 0x1B0008 - - mov eax, syscall_entry - mov ecx, MSR_AMD_STAR - wrmsr -.noSYSCALL: -; ----------------------------------------- - stdcall alloc_page - stdcall map_page, tss-0xF80, eax, PG_SW - stdcall alloc_page - inc eax - mov [SLOT_BASE+256+APPDATA.io_map], eax - stdcall map_page, tss+0x80, eax, PG_SW - stdcall alloc_page - inc eax - mov dword [SLOT_BASE+256+APPDATA.io_map+4], eax - stdcall map_page, tss+0x1080, eax, PG_SW - -; LOAD IDT - - call build_interrupt_table ;lidt is executed - ;lidt [idtreg] - - call init_kernel_heap - stdcall kernel_alloc, RING0_STACK_SIZE+512 - mov [os_stack_seg], eax - - lea esp, [eax+RING0_STACK_SIZE] - - mov [tss._ss0], os_stack - mov [tss._esp0], esp - mov [tss._esp], esp - mov [tss._cs],os_code - mov [tss._ss],os_stack - mov [tss._ds],app_data - mov [tss._es],app_data - mov [tss._fs],app_data - mov [tss._gs],app_data - mov [tss._io],128 -;Add IO access table - bit array of permitted ports - mov edi, tss._io_map_0 - xor eax, eax - not eax - mov ecx, 8192/4 - rep stosd ; access to 4096*8=65536 ports - - mov ax,tss0 - ltr ax - - mov [LFBSize], 0x800000 - call init_LFB - call init_fpu - call init_malloc - - stdcall alloc_kernel_space, 0x51000 - mov [default_io_map], eax - - add eax, 0x2000 - mov [ipc_tmp], eax - mov ebx, 0x1000 - - add eax, 0x40000 - mov [proc_mem_map], eax - - add eax, 0x8000 - mov [proc_mem_pdir], eax - - add eax, ebx - mov [proc_mem_tab], eax - - add eax, ebx - mov [tmp_task_pdir], eax - - add eax, ebx - mov [tmp_task_ptab], eax - - add eax, ebx - mov [ipc_pdir], eax - - add eax, ebx - mov [ipc_ptab], eax - - stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \ - (unpack.lc+unpack.lp)))*4 - - mov [unpack.p], eax - - call init_events - mov eax, srv.fd-SRV_FD_OFFSET - mov [srv.fd], eax - mov [srv.bk], eax - -;Set base of graphic segment to linear address of LFB - mov eax,[LFBAddress] ; set for gs - mov [graph_data_l+2],ax - shr eax,16 - mov [graph_data_l+4],al - mov [graph_data_l+7],ah - - stdcall kernel_alloc, [_WinMapSize] - mov [_WinMapAddress], eax - - xor eax,eax - inc eax - mov [CURRENT_TASK],eax ;dword 1 - mov [TASK_COUNT],eax ;dword 1 - mov [TASK_BASE],dword TASK_DATA - mov [current_slot], SLOT_BASE+256 - -; set background - - mov [BgrDrawMode],eax - mov [BgrDataWidth],eax - mov [BgrDataHeight],eax - mov [mem_BACKGROUND], 4 - mov [img_background], static_background_data - - mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE - - stdcall kernel_alloc, 0x10000/8 - mov edi, eax - mov [network_free_ports], eax - or eax, -1 - mov ecx, 0x10000/32 - rep stosd - -; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f - - call init_irqs - call PIC_init - -; Initialize system V86 machine - call init_sys_v86 - -; Initialize system timer (IRQ0) - call PIT_init - -; Try to Initialize APIC - call APIC_init - -; Enable timer IRQ (IRQ0) and hard drives IRQs (IRQ14, IRQ15) -; they are used: when partitions are scanned, hd_read relies on timer - call unmask_timer - stdcall enable_irq, 2 ; @#$%! PIC - stdcall enable_irq, 6 ; FDD - stdcall enable_irq, 13 ; co-processor - stdcall enable_irq, 14 - stdcall enable_irq, 15 - -; Enable interrupts in IDE controller - mov al, 0 - mov dx, 0x3F6 - out dx, al - mov dl, 0x76 - out dx, al - -;!!!!!!!!!!!!!!!!!!!!!!!!!! -include 'detect/disks.inc' -;!!!!!!!!!!!!!!!!!!!!!!!!!! - - call Parser_params - -if ~ defined extended_primary_loader -; ramdisk image should be loaded by extended primary loader if it exists -; READ RAMDISK IMAGE FROM HD - -;!!!!!!!!!!!!!!!!!!!!!!! -include 'boot/rdload.inc' -;!!!!!!!!!!!!!!!!!!!!!!! -end if -; mov [dma_hdd],1 -; CALCULATE FAT CHAIN FOR RAMDISK - - call calculatefatchain - -if 0 - mov ax,[OS_BASE+0x10000+bx_from_load] - cmp ax,'r1' ; if using not ram disk, then load librares and parameters {SPraid.simba} - je no_lib_load -; LOADING LIBRARES - stdcall dll.Load,@IMPORT ; loading librares for kernel (.obj files) - call load_file_parse_table ; prepare file parse table - call set_kernel_conf ; configure devices and gui -no_lib_load: -end if - -; LOAD FONTS I and II - - stdcall read_file, char, FONT_I, 0, 2304 - stdcall read_file, char2, FONT_II, 0, 2560 - - mov esi,boot_fonts - call boot_log - -; Display APIC status - mov esi, boot_APIC_found - cmp [irq_mode], IRQ_APIC - je @f - mov esi, boot_APIC_nfound -@@: - -; PRINT AMOUNT OF MEMORY - mov esi, boot_memdetect - call boot_log - - movzx ecx, word [boot_y] - if lang eq ru - or ecx, (10+30*6) shl 16 - else - or ecx, (10+29*6) shl 16 - end if - sub ecx, 10 - mov edx, 0xFFFFFF - mov ebx, [MEM_AMOUNT] - shr ebx, 20 - xor edi,edi - mov eax, 0x00040000 - inc edi - call display_number_force - -; BUILD SCHEDULER - - call build_scheduler ; sys32.inc - - mov esi,boot_devices - call boot_log - - mov [pci_access_enabled],1 - - -; SET PRELIMINARY WINDOW STACK AND POSITIONS - - mov esi,boot_windefs - call boot_log - call set_window_defaults - -; SET BACKGROUND DEFAULTS - - mov esi,boot_bgr - call boot_log - call init_background - call calculatebackground - -; RESERVE SYSTEM IRQ'S JA PORT'S - - mov esi,boot_resirqports - call boot_log - call reserve_irqs_ports - -; SET UP OS TASK - - mov esi,boot_setostask - call boot_log - - xor eax, eax - mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data - mov dword [SLOT_BASE+APPDATA.exc_handler], eax - mov dword [SLOT_BASE+APPDATA.except_mask], eax - - ; name for OS/IDLE process - - mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I' - mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE ' - mov edi, [os_stack_seg] - mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi - add edi, 0x2000-512 - mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi - mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi ; just for case - ; [SLOT_BASE+256+APPDATA.io_map] was set earlier - - mov esi, fpu_data - mov ecx, 512/4 - cld - rep movsd - - mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax - mov dword [SLOT_BASE+256+APPDATA.except_mask], eax - - mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET - mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx - mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx - - mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path - mov dword [SLOT_BASE+256+APPDATA.tls_base], eax - - ; task list - mov dword [TASK_DATA+TASKDATA.mem_start],eax ; process base address - inc eax - mov dword [CURRENT_TASK],eax - mov dword [TASK_COUNT],eax - mov [current_slot], SLOT_BASE+256 - mov [TASK_BASE],dword TASK_DATA - mov byte[TASK_DATA+TASKDATA.wnd_number],al ; on screen number - mov dword [TASK_DATA+TASKDATA.pid], eax ; process id number - - call init_display - mov eax, [def_cursor] - mov [SLOT_BASE+APPDATA.cursor],eax - mov [SLOT_BASE+APPDATA.cursor+256],eax - - ; READ TSC / SECOND - - mov esi,boot_tsc - call boot_log - cli - rdtsc ;call _rdtsc - mov ecx,eax - mov esi,250 ; wait 1/4 a second - call delay_ms - rdtsc ;call _rdtsc - sti - sub eax,ecx - shl eax,2 - mov [CPU_FREQ],eax ; save tsc / sec -; mov ebx, 1000000 -; div ebx -; ў®®ЎйҐ-в® Їа®Ё§ў®¤ЁвҐ«м­®бвм ў ¤ ­­®¬ Є®­ЄаҐв­®¬ ¬Ґб⥠-; б®ўҐа襭­® ­ҐЄаЁвЁз­ , ­® зв®Ўл § вЄ­гвм «оЎЁвҐ«Ґ© -; ®ЇвЁ¬Ё§ЁагойЁе Є®¬ЇЁ«пв®а®ў џ‚“... - mov edx, 2251799814 - mul edx - shr edx, 19 - mov [stall_mcs], edx -; PRINT CPU FREQUENCY - mov esi, boot_cpufreq - call boot_log - - mov ebx, edx - movzx ecx, word [boot_y] - if lang eq ru - add ecx, (10+19*6) shl 16 - 10; 'Determining amount of memory' - else - add ecx, (10+17*6) shl 16 - 10; 'Determining amount of memory' - end if - mov edx, 0xFFFFFF - xor edi,edi - mov eax, 0x00040000 - inc edi - call display_number_force - -; SET VARIABLES - - call set_variables - -; STACK AND FDC - - call stack_init - call fdc_init - -; PALETTE FOR 320x200 and 640x480 16 col - - cmp [SCR_MODE],word 0x12 - jne no_pal_vga - mov esi,boot_pal_vga - call boot_log - call paletteVGA - no_pal_vga: - - cmp [SCR_MODE],word 0x13 - jne no_pal_ega - mov esi,boot_pal_ega - call boot_log - call palette320x200 - no_pal_ega: - -; LOAD DEFAULT SKIN - - call load_default_skin - -;protect io permission map - - mov esi, [default_io_map] - stdcall map_page,esi,[SLOT_BASE+256+APPDATA.io_map], PG_MAP - add esi, 0x1000 - stdcall map_page,esi,[SLOT_BASE+256+APPDATA.io_map+4], PG_MAP - - stdcall map_page,tss._io_map_0,\ - [SLOT_BASE+256+APPDATA.io_map], PG_MAP - stdcall map_page,tss._io_map_1,\ - [SLOT_BASE+256+APPDATA.io_map+4], PG_MAP - - mov ax,[OS_BASE+0x10000+bx_from_load] - cmp ax,'r1' ; if not rused ram disk - load network configuration from files {SPraid.simba} - je no_st_network - call set_network_conf - no_st_network: - -; LOAD FIRST APPLICATION - cli - -; cmp byte [BOOT_VAR+0x9030],1 -; jne no_load_vrr_m - -; mov ebp, vrr_m -; call fs_execute_from_sysdir -; -;; cmp eax,2 ; if vrr_m app found (PID=2) -; sub eax,2 -; jz first_app_found -; -;no_load_vrr_m: - - mov ebp, firstapp - call fs_execute_from_sysdir - -; cmp eax,2 ; continue if a process has been loaded - sub eax,2 - jz first_app_found - - mov esi, boot_failed - call boot_log - - mov eax, 0xDEADBEEF ; otherwise halt - hlt - -first_app_found: - - cli - - ;mov [TASK_COUNT],dword 2 - push 1 - pop dword [CURRENT_TASK] ; set OS task fisrt - -; SET KEYBOARD PARAMETERS - mov al, 0xf6 ; reset keyboard, scan enabled - call kb_write - - ; wait until 8042 is ready - xor ecx,ecx - @@: - in al,64h - and al,00000010b - loopnz @b - - ; mov al, 0xED ; Keyboard LEDs - only for testing! - ; call kb_write - ; call kb_read - ; mov al, 111b - ; call kb_write - ; call kb_read - - mov al, 0xF3 ; set repeat rate & delay - call kb_write -; call kb_read - mov al, 0 ; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500 - call kb_write -; call kb_read - ;// mike.dld [ - call set_lights - ;// mike.dld ] - stdcall attach_int_handler, 1, irq1, 0 - -; SET MOUSE - - stdcall load_driver, szPS2MDriver -; stdcall load_driver, szCOM_MDriver - - mov esi,boot_setmouse - call boot_log - call setmouse - -; Setup serial output console (if enabled) - -if defined debug_com_base - - ; enable Divisor latch - - mov dx, debug_com_base+3 - mov al, 1 shl 7 - out dx, al - - ; Set speed to 115200 baud (max speed) - - mov dx, debug_com_base - mov al, 0x01 - out dx, al - - mov dx, debug_com_base+1 - mov al, 0x00 - out dx, al - - ; No parity, 8bits words, one stop bit, dlab bit back to 0 - - mov dx, debug_com_base+3 - mov al, 3 - out dx, al - - ; disable interrupts - - mov dx, debug_com_base+1 - mov al, 0 - out dx, al - - ; clear + enable fifo (64 bits) - - mov dx, debug_com_base+2 - mov al, 0x7 + 1 shl 5 - out dx, al - - -end if - -; START MULTITASKING - -; A 'All set - press ESC to start' messages if need -if preboot_blogesc - mov esi, boot_tasking - call boot_log -.bll1: in al, 0x60 ; wait for ESC key press - cmp al, 129 - jne .bll1 -end if - - cmp [IDEContrRegsBaseAddr], 0 - setnz [dma_hdd] - mov [timer_ticks_enable],1 ; for cd driver - - sti - call change_task - - jmp osloop - - - ; Fly :) - -include 'unpacker.inc' -include 'fdo.inc' - -align 4 -boot_log: - pushad - - mov ebx,10*65536 - mov bx,word [boot_y] - add [boot_y],dword 10 - mov ecx,0x80ffffff ; ASCIIZ string with white color - xor edi,edi - mov edx,esi - inc edi - call dtext - - mov [novesachecksum],1000 - call checkVga_N13 - - popad - - ret - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; ; -; MAIN OS LOOP START ; -; ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -align 32 -osloop: - call [draw_pointer] - call window_check_events - call mouse_check_events - call checkmisc - call checkVga_N13 - call stack_handler - call checkidle - call check_fdd_motor_status - call check_ATAPI_device_event - call check_timers - jmp osloop -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; ; -; MAIN OS LOOP END ; -; ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -align 4 -checkidle: - pushad - call change_task - jmp idle_loop_entry - idle_loop: - cmp eax,[idlemem] ; eax == [timer_ticks] - jne idle_exit - rdtsc ;call _rdtsc - mov ecx,eax - hlt - rdtsc ;call _rdtsc - sub eax,ecx - add [idleuse],eax - idle_loop_entry: - mov eax,[timer_ticks] ; eax = [timer_ticks] - cmp [check_idle_semaphore],0 - je idle_loop - dec [check_idle_semaphore] - idle_exit: - mov [idlemem],eax ; eax == [timer_ticks] - popad - ret - -uglobal - idlemem dd 0x0 - idleuse dd 0x0 - idleusesec dd 0x0 - check_idle_semaphore dd 0x0 -endg - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; ; -; INCLUDED SYSTEM FILES ; -; ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -include "kernel32.inc" - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; ; -; KERNEL FUNCTIONS ; -; ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -reserve_irqs_ports: - - -; RESERVE PORTS - mov eax, RESERVED_PORTS - mov ecx, 1 - - mov [eax], dword 4 - - mov [eax+16], ecx - mov [eax+16+4], dword 0 - mov [eax+16+4], dword 0x2D - - mov [eax+32], ecx - mov [eax+32+4], dword 0x30 - mov [eax+32+8], dword 0x4D - - mov [eax+48], ecx - mov [eax+48+4], dword 0x50 - mov [eax+28+8], dword 0xDF - - mov [eax+64], ecx - mov [eax+64+4], dword 0xE5 - mov [eax+64+8], dword 0xFF - - ret - - -iglobal - process_number dd 0x1 -endg - -set_variables: - - mov ecx,0x16 ; flush port 0x60 -.fl60: - in al,0x60 - loop .fl60 - push eax - - mov ax,[BOOT_VAR+0x900c] - shr ax,1 - shl eax,16 - mov ax,[BOOT_VAR+0x900A] - shr ax,1 - mov [MOUSE_X],eax - - xor eax,eax - mov [BTN_ADDR],dword BUTTON_INFO ; address of button list - - mov byte [MOUSE_BUFF_COUNT],al ; mouse buffer - mov byte [KEY_COUNT],al ; keyboard buffer - mov byte [BTN_COUNT],al ; button buffer -; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y - - ;!! IP 04.02.2005: - mov byte [DONT_SWITCH],al ; change task if possible - pop eax - ret - -align 4 -;input eax=43,bl-byte of output, ecx - number of port -sys_outport: - - mov edi,ecx ; separate flag for read / write - and ecx,65535 - - mov eax,[RESERVED_PORTS] - test eax,eax - jnz .sopl8 - inc eax - mov [esp+32],eax - ret - - .sopl8: - mov edx,[TASK_BASE] - mov edx,[edx+0x4] - ;and ecx,65535 - ;cld - set on interrupt 0x40 - .sopl1: - - mov esi,eax - shl esi,4 - add esi,RESERVED_PORTS - cmp edx,[esi+0] - jne .sopl2 - cmp ecx,[esi+4] - jb .sopl2 - cmp ecx,[esi+8] - jg .sopl2 -.sopl3: - - test edi,0x80000000 ; read ? - jnz .sopl4 - - mov eax,ebx - mov dx,cx ; write - out dx,al - and [esp+32],dword 0 - ret - - .sopl2: - - dec eax - jnz .sopl1 - inc eax - mov [esp+32],eax - ret - - - .sopl4: - - mov dx,cx ; read - in al,dx - and eax,0xff - and [esp+32],dword 0 - mov [esp+20],eax - ret - -display_number: -;It is not optimization - mov eax, ebx - mov ebx, ecx - mov ecx, edx - mov edx, esi - mov esi, edi -; eax = print type, al=0 -> ebx is number -; al=1 -> ebx is pointer -; ah=0 -> display decimal -; ah=1 -> display hexadecimal -; ah=2 -> display binary -; eax bits 16-21 = number of digits to display (0-32) -; eax bits 22-31 = reserved -; -; ebx = number or pointer -; ecx = x shl 16 + y -; edx = color - xor edi, edi -display_number_force: - push eax - and eax,0x3fffffff - cmp eax,0xffff ; length > 0 ? - pop eax - jge cont_displ - ret - cont_displ: - push eax - and eax,0x3fffffff - cmp eax,61*0x10000 ; length <= 60 ? - pop eax - jb cont_displ2 - ret - cont_displ2: - - pushad - - cmp al,1 ; ecx is a pointer ? - jne displnl1 - mov ebp,ebx - add ebp,4 - mov ebp,[ebp+std_application_base_address] - mov ebx,[ebx+std_application_base_address] - displnl1: - sub esp,64 - - test ah,ah ; DECIMAL - jnz no_display_desnum - shr eax,16 - and eax,0xC03f -; and eax,0x3f - push eax - and eax,0x3f - mov edi,esp - add edi,4+64-1 - mov ecx,eax - mov eax,ebx - mov ebx,10 - d_desnum: - xor edx,edx - call division_64_bits - div ebx - add dl,48 - mov [edi],dl - dec edi - loop d_desnum - pop eax - call normalize_number - call draw_num_text - add esp,64 - popad - ret - no_display_desnum: - - cmp ah,0x01 ; HEXADECIMAL - jne no_display_hexnum - shr eax,16 - and eax,0xC03f -; and eax,0x3f - push eax - and eax,0x3f - mov edi,esp - add edi,4+64-1 - mov ecx,eax - mov eax,ebx - mov ebx,16 - d_hexnum: - xor edx,edx - call division_64_bits - div ebx - hexletters = __fdo_hexdigits - add edx,hexletters - mov dl,[edx] - mov [edi],dl - dec edi - loop d_hexnum - pop eax - call normalize_number - call draw_num_text - add esp,64 - popad - ret - no_display_hexnum: - - cmp ah,0x02 ; BINARY - jne no_display_binnum - shr eax,16 - and eax,0xC03f -; and eax,0x3f - push eax - and eax,0x3f - mov edi,esp - add edi,4+64-1 - mov ecx,eax - mov eax,ebx - mov ebx,2 - d_binnum: - xor edx,edx - call division_64_bits - div ebx - add dl,48 - mov [edi],dl - dec edi - loop d_binnum - pop eax - call normalize_number - call draw_num_text - add esp,64 - popad - ret - no_display_binnum: - - add esp,64 - popad - ret - -normalize_number: - test ah,0x80 - jz .continue - mov ecx,48 - and eax,0x3f -@@: - inc edi - cmp [edi],cl - jne .continue - dec eax - cmp eax,1 - ja @r - mov al,1 -.continue: - and eax,0x3f - ret - -division_64_bits: - test [esp+1+4],byte 0x40 - jz .continue - push eax - mov eax,ebp - div ebx - mov ebp,eax - pop eax -.continue: - ret - -draw_num_text: - mov esi,eax - mov edx,64+4 - sub edx,eax - add edx,esp - mov ebx,[esp+64+32-8+4] -; add window start x & y - mov ecx,[TASK_BASE] - - mov edi,[CURRENT_TASK] - shl edi,8 - - mov eax,[ecx-twdw+WDATA.box.left] - add eax,[edi+SLOT_BASE+APPDATA.wnd_clientbox.left] - shl eax,16 - add eax,[ecx-twdw+WDATA.box.top] - add eax,[edi+SLOT_BASE+APPDATA.wnd_clientbox.top] - add ebx,eax - mov ecx,[esp+64+32-12+4] - and ecx, not 0x80000000 ; force counted string - mov eax, [esp+64+8] ; background color (if given) - mov edi, [esp+64+4] - jmp dtext - -align 4 - -sys_setup: - -; 1=roland mpu midi base , base io address -; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus -; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave -; 5=system language, 1eng 2fi 3ger 4rus -; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave -; 8=fat32 partition in hd -; 9 -; 10 = sound dma channel -; 11 = enable lba read -; 12 = enable pci access - - - and [esp+32],dword 0 - dec ebx ; MIDI - jnz nsyse1 - cmp ecx,0x100 - - jb nsyse1 - mov esi,65535 - cmp esi,ecx - - jb nsyse1 - mov [midi_base],cx ;bx - mov word [mididp],cx ;bx - inc cx ;bx - mov word [midisp],cx ;bx - ret - -iglobal -midi_base dw 0 -endg - - nsyse1: - dec ebx ; KEYBOARD - jnz nsyse2 - mov edi,[TASK_BASE] - mov eax,[edi+TASKDATA.mem_start] - add eax,edx - - dec ecx - jnz kbnobase - mov ebx,keymap - mov ecx,128 - call memmove - ret - kbnobase: - dec ecx - jnz kbnoshift - - mov ebx,keymap_shift - mov ecx,128 - call memmove - ret - kbnoshift: - dec ecx - jnz kbnoalt - mov ebx,keymap_alt - mov ecx,128 - call memmove - ret - kbnoalt: - sub ecx,6 - jnz kbnocountry - mov word [keyboard],dx - ret - kbnocountry: - mov [esp+32],dword 1 - ret - nsyse2: - dec ebx ; CD - jnz nsyse4 - - test ecx,ecx - jz nosesl - - cmp ecx, 4 - ja nosesl - mov [cd_base],cl - - dec ecx - jnz noprma - mov [cdbase],0x1f0 - mov [cdid],0xa0 - noprma: - - dec ecx - jnz noprsl - mov [cdbase],0x1f0 - mov [cdid],0xb0 - noprsl: - dec ecx - jnz nosema - mov [cdbase],0x170 - mov [cdid],0xa0 - nosema: - dec ecx - jnz nosesl - mov [cdbase],0x170 - mov [cdid],0xb0 - nosesl: - ret - -iglobal -cd_base db 0 - -endg - nsyse4: - - sub ebx,2 ; SYSTEM LANGUAGE - jnz nsyse5 - mov [syslang],ecx - ret - nsyse5: - - sub ebx,2 ; HD BASE - jnz nsyse7 - - test ecx,ecx - jz nosethd - - cmp ecx,4 - ja nosethd - mov [hd_base],cl - - cmp ecx,1 - jnz noprmahd - mov [hdbase],0x1f0 - and dword [hdid],0x0 - mov dword [hdpos],ecx -; call set_FAT32_variables - noprmahd: - - cmp ecx,2 - jnz noprslhd - mov [hdbase],0x1f0 - mov [hdid],0x10 - mov dword [hdpos],ecx -; call set_FAT32_variables - noprslhd: - - cmp ecx,3 - jnz nosemahd - mov [hdbase],0x170 - and dword [hdid],0x0 - mov dword [hdpos],ecx -; call set_FAT32_variables - nosemahd: - - cmp ecx,4 - jnz noseslhd - mov [hdbase],0x170 - mov [hdid],0x10 - mov dword [hdpos],ecx -; call set_FAT32_variables - noseslhd: - call reserve_hd1 - call reserve_hd_channel - call free_hd_channel - and dword [hd1_status],0 ; free - nosethd: - ret - -iglobal -hd_base db 0 -endg - -nsyse7: - -; cmp eax,8 ; HD PARTITION - dec ebx - jnz nsyse8 - mov [fat32part],ecx -; call set_FAT32_variables - call reserve_hd1 - call reserve_hd_channel - call free_hd_channel -; pusha - call choice_necessity_partition_1 -; popa - and dword [hd1_status],0 ; free - ret - -nsyse8: -; cmp eax,11 ; ENABLE LBA READ - and ecx,1 - sub ebx,3 - jnz no_set_lba_read - mov [lba_read_enabled],ecx - ret - -no_set_lba_read: -; cmp eax,12 ; ENABLE PCI ACCESS - dec ebx - jnz sys_setup_err - mov [pci_access_enabled],ecx - ret - -sys_setup_err: - or [esp+32],dword -1 - ret - -align 4 - -sys_getsetup: - -; 1=roland mpu midi base , base io address -; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus -; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave -; 5=system language, 1eng 2fi 3ger 4rus -; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave -; 8=fat32 partition in hd -; 9=get hs timer tic - -; cmp eax,1 - dec ebx - jnz ngsyse1 - movzx eax,[midi_base] - mov [esp+32],eax - ret -ngsyse1: -; cmp eax,2 - dec ebx - jnz ngsyse2 - - mov edi,[TASK_BASE] - mov ebx,[edi+TASKDATA.mem_start] - add ebx,edx - -; cmp ebx,1 - dec ecx - jnz kbnobaseret - mov eax,keymap - mov ecx,128 - call memmove - ret -kbnobaseret: -; cmp ebx,2 - dec ecx - jnz kbnoshiftret - - mov eax,keymap_shift - mov ecx,128 - call memmove - ret -kbnoshiftret: -; cmp ebx,3 - dec ecx - jne kbnoaltret - - mov eax,keymap_alt - mov ecx,128 - call memmove - ret -kbnoaltret: -; cmp ebx,9 - sub ecx,6 - jnz ngsyse2 - movzx eax,word [keyboard] - mov [esp+32],eax - ret - - -ngsyse2: -; cmp eax,3 - dec ebx - jnz ngsyse3 - movzx eax,[cd_base] - mov [esp+32],eax - ret -ngsyse3: -; cmp eax,5 - sub ebx,2 - jnz ngsyse5 - mov eax,[syslang] - mov [esp+32],eax - ret -ngsyse5: -; cmp eax,7 - sub ebx,2 - jnz ngsyse7 - movzx eax,[hd_base] - mov [esp+32],eax - ret -ngsyse7: -; cmp eax,8 - dec ebx - jnz ngsyse8 - mov eax,[fat32part] - mov [esp+32],eax - ret -ngsyse8: -; cmp eax,9 - dec ebx - jnz ngsyse9 - mov eax,[timer_ticks] ;[0xfdf0] - mov [esp+32],eax - ret -ngsyse9: -; cmp eax,11 - sub ebx,2 - jnz ngsyse11 - mov eax,[lba_read_enabled] - mov [esp+32],eax - ret -ngsyse11: -; cmp eax,12 - dec ebx - jnz ngsyse12 - mov eax,[pci_access_enabled] - mov [esp+32],eax - ret -ngsyse12: - mov [esp+32],dword 1 - ret - - -get_timer_ticks: - mov eax,[timer_ticks] - ret - -iglobal -align 4 -mousefn dd msscreen, mswin, msbutton, msset - dd app_load_cursor - dd app_set_cursor - dd app_delete_cursor - dd msz -endg - -readmousepos: - -; eax=0 screen relative -; eax=1 window relative -; eax=2 buttons pressed -; eax=3 set mouse pos ; reserved -; eax=4 load cursor -; eax=5 set cursor -; eax=6 delete cursor ; reserved -; eax=7 get mouse_z - - cmp ebx, 7 - ja msset - jmp [mousefn+ebx*4] -msscreen: - mov eax,[MOUSE_X] - shl eax,16 - mov ax,[MOUSE_Y] - mov [esp+36-4],eax - ret -mswin: - mov eax,[MOUSE_X] - shl eax,16 - mov ax,[MOUSE_Y] - mov esi,[TASK_BASE] - mov bx, word [esi-twdw+WDATA.box.left] - shl ebx,16 - mov bx, word [esi-twdw+WDATA.box.top] - sub eax,ebx - - mov edi,[CURRENT_TASK] - shl edi,8 - sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.top] - rol eax,16 - sub ax,word[edi+SLOT_BASE+APPDATA.wnd_clientbox.left] - rol eax,16 - mov [esp+36-4],eax - ret -msbutton: - movzx eax,byte [BTN_DOWN] - mov [esp+36-4],eax - ret -msz: - mov edi, [TASK_COUNT] - movzx edi, word [WIN_POS + edi*2] - cmp edi, [CURRENT_TASK] - jne @f - mov ax,[MOUSE_SCROLL_H] - shl eax,16 - mov ax,[MOUSE_SCROLL_V] - mov [esp+36-4],eax - and [MOUSE_SCROLL_H],word 0 - and [MOUSE_SCROLL_V],word 0 - ret - @@: - and [esp+36-4],dword 0 -; ret -msset: - ret - -app_load_cursor: - cmp ecx, OS_BASE - jae msset - stdcall load_cursor, ecx, edx - mov [esp+36-4], eax - ret - -app_set_cursor: - stdcall set_cursor, ecx - mov [esp+36-4], eax - ret - -app_delete_cursor: - stdcall delete_cursor, ecx - mov [esp+36-4], eax - ret - -is_input: - - push edx - mov dx,word [midisp] - in al,dx - and al,0x80 - pop edx - ret - -is_output: - - push edx - mov dx,word [midisp] - in al,dx - and al,0x40 - pop edx - ret - - -get_mpu_in: - - push edx - mov dx,word [mididp] - in al,dx - pop edx - ret - - -put_mpu_out: - - push edx - mov dx,word [mididp] - out dx,al - pop edx - ret - - - -align 4 - -sys_midi: - cmp [mididp],0 - jnz sm0 - mov [esp+36],dword 1 - ret -sm0: - and [esp+36],dword 0 - dec ebx - jnz smn1 - ; call setuart -su1: - call is_output - test al,al - jnz su1 - mov dx,word [midisp] - mov al,0xff - out dx,al -su2: - mov dx,word [midisp] - mov al,0xff - out dx,al - call is_input - test al,al - jnz su2 - call get_mpu_in - cmp al,0xfe - jnz su2 -su3: - call is_output - test al,al - jnz su3 - mov dx,word [midisp] - mov al,0x3f - out dx,al - ret -smn1: - dec ebx - jnz smn2 -sm10: - call get_mpu_in - call is_output - test al,al - jnz sm10 - mov al,bl - call put_mpu_out - smn2: - ret - -detect_devices: -;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -;include 'detect/commouse.inc' -;include 'detect/ps2mouse.inc' -;include 'detect/dev_fd.inc' -;include 'detect/dev_hdcd.inc' -;include 'detect/sear_par.inc' -;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ret - -sys_end: - - mov ecx, [current_slot] - mov eax, [ecx+APPDATA.tls_base] - test eax, eax - jz @F - - stdcall user_free, eax -@@: - - mov eax,[TASK_BASE] - mov [eax+TASKDATA.state], 3 ; terminate this program - - waitterm: ; wait here for termination - mov ebx,100 - call delay_hs - jmp waitterm - -iglobal -align 4 -sys_system_table: - dd sysfn_deactivate ; 1 = deactivate window - dd sysfn_terminate ; 2 = terminate thread - dd sysfn_activate ; 3 = activate window - dd sysfn_getidletime ; 4 = get idle time - dd sysfn_getcpuclock ; 5 = get cpu clock - dd sysfn_saveramdisk ; 6 = save ramdisk - dd sysfn_getactive ; 7 = get active window - dd sysfn_sound_flag ; 8 = get/set sound_flag - dd sysfn_shutdown ; 9 = shutdown with parameter - dd sysfn_minimize ; 10 = minimize window - dd sysfn_getdiskinfo ; 11 = get disk subsystem info - dd sysfn_lastkey ; 12 = get last pressed key - dd sysfn_getversion ; 13 = get kernel version - dd sysfn_waitretrace ; 14 = wait retrace - dd sysfn_centermouse ; 15 = center mouse cursor - dd sysfn_getfreemem ; 16 = get free memory size - dd sysfn_getallmem ; 17 = get total memory size - dd sysfn_terminate2 ; 18 = terminate thread using PID - ; instead of slot - dd sysfn_mouse_acceleration; 19 = set/get mouse acceleration - dd sysfn_meminfo ; 20 = get extended memory info - dd sysfn_pid_to_slot ; 21 = get slot number for pid - dd sysfn_min_rest_window ; 22 = minimize and restore any window -sysfn_num = ($ - sys_system_table)/4 -endg -;------------------------------------------------------------------------------ -sys_system: - dec ebx - cmp ebx, sysfn_num - jae @f - jmp dword [sys_system_table + ebx*4] -@@: - ret -;------------------------------------------------------------------------------ -sysfn_shutdown: ; 18.9 = system shutdown - cmp ecx,1 - jl exit_for_anyone - cmp ecx,4 - jg exit_for_anyone - mov [BOOT_VAR+0x9030],cl - - mov eax,[TASK_COUNT] - mov [SYS_SHUTDOWN],al - mov [shutdown_processes],eax - and dword [esp+32], 0 - exit_for_anyone: - ret - uglobal - shutdown_processes: dd 0x0 - endg -;------------------------------------------------------------------------------ -sysfn_terminate: ; 18.2 = TERMINATE - cmp ecx,2 - jb noprocessterminate - mov edx,[TASK_COUNT] - cmp ecx,edx - ja noprocessterminate - mov eax,[TASK_COUNT] - shl ecx,5 - mov edx,[ecx+CURRENT_TASK+TASKDATA.pid] - add ecx,CURRENT_TASK+TASKDATA.state - cmp byte [ecx], 9 - jz noprocessterminate - - ;call MEM_Heap_Lock ;guarantee that process isn't working with heap - mov [ecx],byte 3 ; clear possible i40's - ;call MEM_Heap_UnLock - - cmp edx,[application_table_status] ; clear app table stat - jne noatsc - and [application_table_status],0 - noatsc: - noprocessterminate: - ret -;------------------------------------------------------------------------------ -sysfn_terminate2: -;lock application_table_status mutex -.table_status: - cli - cmp [application_table_status],0 - je .stf - sti - call change_task - jmp .table_status -.stf: - call set_application_table_status - mov eax,ecx - call pid_to_slot - test eax,eax - jz .not_found - mov ecx,eax - cli - call sysfn_terminate - and [application_table_status],0 - sti - and dword [esp+32],0 - ret -.not_found: - mov [application_table_status],0 - or dword [esp+32],-1 - ret -;------------------------------------------------------------------------------ -sysfn_deactivate: ; 18.1 = DEACTIVATE WINDOW - cmp ecx,2 - jb .nowindowdeactivate - cmp ecx,[TASK_COUNT] - ja .nowindowdeactivate - - movzx esi, word [WIN_STACK + ecx*2] - cmp esi, 1 - je .nowindowdeactivate ; already deactive - - mov edi, ecx - shl edi, 5 - add edi, window_data - movzx esi, word [WIN_STACK + ecx * 2] - lea esi, [WIN_POS + esi * 2] - call window._.window_deactivate - - xor eax, eax - mov byte[MOUSE_BACKGROUND], al - mov byte[DONT_DRAW_MOUSE], al - mov byte[MOUSE_DOWN], 0 - - call syscall_display_settings._.calculate_whole_screen - call syscall_display_settings._.redraw_whole_screen -.nowindowdeactivate: - ret - ;------------------------------------------------------------------------------ -sysfn_activate: ; 18.3 = ACTIVATE WINDOW - cmp ecx,2 - jb .nowindowactivate - cmp ecx,[TASK_COUNT] - ja .nowindowactivate - - mov [window_minimize], 2 ; restore window if minimized - - movzx esi, word [WIN_STACK + ecx*2] - cmp esi, [TASK_COUNT] - je .nowindowactivate ; already active - - mov edi, ecx - shl edi, 5 - add edi, window_data - movzx esi, word [WIN_STACK + ecx * 2] - lea esi, [WIN_POS + esi * 2] - call waredraw -.nowindowactivate: - ret -;------------------------------------------------------------------------------ -sysfn_getidletime: ; 18.4 = GET IDLETIME - mov eax,[idleusesec] - mov [esp+32], eax - ret -;------------------------------------------------------------------------------ -sysfn_getcpuclock: ; 18.5 = GET TSC/SEC - mov eax,[CPU_FREQ] - mov [esp+32], eax - ret -;------------------------------------------------------------------------------ -; SAVE ramdisk to /hd/1/menuet.img -;!!!!!!!!!!!!!!!!!!!!!!!! - include 'blkdev/rdsave.inc' -;!!!!!!!!!!!!!!!!!!!!!!!! -;------------------------------------------------------------------------------ -align 4 -sysfn_getactive: ; 18.7 = get active window - mov eax, [TASK_COUNT] - movzx eax, word [WIN_POS + eax*2] - mov [esp+32],eax - ret -;------------------------------------------------------------------------------ -sysfn_sound_flag: ; 18.8 = get/set sound_flag -; cmp ecx,1 - dec ecx - jnz nogetsoundflag - movzx eax,byte [sound_flag] ; get sound_flag - mov [esp+32],eax - ret - nogetsoundflag: -; cmp ecx,2 - dec ecx - jnz nosoundflag - xor byte [sound_flag], 1 - nosoundflag: - ret -;------------------------------------------------------------------------------ -sysfn_minimize: ; 18.10 = minimize window - mov [window_minimize],1 - ret -;------------------------------------------------------------------------------ -align 4 -sysfn_getdiskinfo: ; 18.11 = get disk info table -; cmp ecx,1 - dec ecx - jnz full_table - small_table: - call for_all_tables - mov ecx,10 - cld - rep movsb - ret - for_all_tables: - mov edi,edx - mov esi,DRIVE_DATA - ret - full_table: -; cmp ecx,2 - dec ecx - jnz exit_for_anyone - call for_all_tables - mov ecx,16384 - cld - rep movsd - ret -;------------------------------------------------------------------------------ -sysfn_lastkey: ; 18.12 = return 0 (backward compatibility) - and dword [esp+32], 0 - ret -;------------------------------------------------------------------------------ -sysfn_getversion: ; 18.13 = get kernel ID and version - mov edi,ecx - mov esi,version_inf - mov ecx,version_end-version_inf - rep movsb - ret -;------------------------------------------------------------------------------ -sysfn_waitretrace: ; 18.14 = sys wait retrace - ;wait retrace functions - sys_wait_retrace: - mov edx,0x3da - WaitRetrace_loop: - in al,dx - test al,1000b - jz WaitRetrace_loop - and [esp+32],dword 0 - ret -;------------------------------------------------------------------------------ -align 4 -sysfn_centermouse: ; 18.15 = mouse centered -; removed here by -; call mouse_centered -;* mouse centered - start code- Mario79 -;mouse_centered: -; push eax - mov eax,[Screen_Max_X] - shr eax,1 - mov [MOUSE_X],ax - mov eax,[Screen_Max_Y] - shr eax,1 - mov [MOUSE_Y],ax -; ret -;* mouse centered - end code- Mario79 - xor eax,eax - and [esp+32],eax -; pop eax - ret -;------------------------------------------------------------------------------ -align 4 -sysfn_mouse_acceleration: ; 18.19 = set/get mouse features - test ecx,ecx ; get mouse speed factor - jnz .set_mouse_acceleration - xor eax,eax - mov ax,[mouse_speed_factor] - mov [esp+32],eax - ret - .set_mouse_acceleration: -; cmp ecx,1 ; set mouse speed factor - dec ecx - jnz .get_mouse_delay - mov [mouse_speed_factor],dx - ret - .get_mouse_delay: -; cmp ecx,2 ; get mouse delay - dec ecx - jnz .set_mouse_delay - mov eax,[mouse_delay] - mov [esp+32],eax - ret - .set_mouse_delay: -; cmp ecx,3 ; set mouse delay - dec ecx - jnz .set_pointer_position - mov [mouse_delay],edx - ret - .set_pointer_position: -; cmp ecx,4 ; set mouse pointer position - dec ecx - jnz .set_mouse_button - cmp dx, word[Screen_Max_Y] - ja .end - rol edx,16 - cmp dx, word[Screen_Max_X] - ja .end - mov [MOUSE_X], edx - ret - .set_mouse_button: -; cmp ecx,5 ; set mouse button features - dec ecx - jnz .end - mov [BTN_DOWN],dl - mov [mouse_active],1 - .end: - ret -;------------------------------------------------------------------------------ -sysfn_getfreemem: - mov eax, [pg_data.pages_free] - shl eax, 2 - mov [esp+32],eax - ret - -sysfn_getallmem: - mov eax,[MEM_AMOUNT] - shr eax, 10 - mov [esp+32],eax - ret - -; // Alver, 2007-22-08 // { -sysfn_pid_to_slot: - mov eax, ecx - call pid_to_slot - mov [esp+32], eax - ret - -sysfn_min_rest_window: - pushad - mov eax, edx ; ebx - operating - shr ecx, 1 - jnc @f - call pid_to_slot -@@: - or eax, eax ; eax - number of slot - jz .error - cmp eax, 255 ; varify maximal slot number - ja .error - movzx eax, word [WIN_STACK + eax*2] - shr ecx, 1 - jc .restore - ; .minimize: - call minimize_window - jmp .exit -.restore: - call restore_minimized_window -.exit: - popad - xor eax, eax - mov [esp+32], eax - ret -.error: - popad - xor eax, eax - dec eax - mov [esp+32], eax - ret -; } \\ Alver, 2007-22-08 \\ - -uglobal -;// mike.dld, 2006-29-01 [ -screen_workarea RECT -;// mike.dld, 2006-29-01 ] -window_minimize db 0 -sound_flag db 0 -endg - -UID_NONE=0 -UID_MENUETOS=1 ;official -UID_KOLIBRI=2 ;russian - -iglobal -version_inf: - db 0,7,7,0 ; version 0.7.7.0 - db 0 - dd __REV__ -version_end: -endg - -sys_cachetodiskette: - cmp ebx, 1 - jne .no_floppy_a_save - mov [flp_number], 1 - jmp .save_image_on_floppy -.no_floppy_a_save: - cmp ebx, 2 - jne .no_floppy_b_save - mov [flp_number], 2 -.save_image_on_floppy: - call save_image - mov [esp + 32], dword 0 - cmp [FDC_Status], 0 - je .yes_floppy_save -.no_floppy_b_save: - mov [esp + 32], dword 1 -.yes_floppy_save: - ret - -uglobal -; bgrchanged dd 0x0 -align 4 -bgrlockpid dd 0 -bgrlock db 0 -endg - -sys_background: - - cmp ebx,1 ; BACKGROUND SIZE - jnz nosb1 - test ecx,ecx -; cmp ecx,0 - jz sbgrr - test edx,edx -; cmp edx,0 - jz sbgrr -@@: -;;Maxis use atomic bts for mutexes 4.4.2009 - bts dword [bgrlock], 0 - jnc @f - call change_task - jmp @b -@@: - mov [BgrDataWidth],ecx - mov [BgrDataHeight],edx -; mov [bgrchanged],1 - - pushad -; return memory for old background - mov eax, [img_background] - cmp eax, static_background_data - jz @f - stdcall kernel_free, eax -@@: -; calculate RAW size - xor eax,eax - inc eax - cmp [BgrDataWidth],eax - jae @f - mov [BgrDataWidth],eax -@@: - cmp [BgrDataHeight],eax - jae @f - mov [BgrDataHeight],eax -@@: - mov eax,[BgrDataWidth] - imul eax,[BgrDataHeight] - lea eax,[eax*3] - mov [mem_BACKGROUND],eax -; get memory for new background - stdcall kernel_alloc, eax - test eax, eax - jz .memfailed - mov [img_background], eax - jmp .exit -.memfailed: -; revert to static monotone data - mov [img_background], static_background_data - xor eax, eax - inc eax - mov [BgrDataWidth], eax - mov [BgrDataHeight], eax - mov [mem_BACKGROUND], 4 -.exit: - popad - mov [bgrlock], 0 - - sbgrr: - ret - -nosb1: - - cmp ebx,2 ; SET PIXEL - jnz nosb2 - - mov eax, [img_background] - test ecx, ecx - jz @f - cmp eax, static_background_data - jz .ret -@@: - mov ebx, [mem_BACKGROUND] - add ebx, 4095 - and ebx, -4096 - sub ebx, 4 - cmp ecx, ebx - ja .ret - - mov ebx,[eax+ecx] - and ebx,0xFF000000 ;255*256*256*256 - and edx,0x00FFFFFF ;255*256*256+255*256+255 - add edx,ebx - mov [eax+ecx],edx -.ret: - ret -nosb2: - - cmp ebx,3 ; DRAW BACKGROUND - jnz nosb3 -draw_background_temp: -; cmp [bgrchanged],1 ;0 -; je nosb31 -;draw_background_temp: -; mov [bgrchanged],1 ;0 - mov [background_defined], 1 - mov byte[BACKGROUND_CHANGED], 1 - call force_redraw_background - nosb31: - ret - nosb3: - - cmp ebx,4 ; TILED / STRETCHED - jnz nosb4 - cmp ecx,[BgrDrawMode] - je nosb41 - mov [BgrDrawMode],ecx -; mov [bgrchanged],1 - nosb41: - ret - nosb4: - - cmp ebx,5 ; BLOCK MOVE TO BGR - jnz nosb5 - cmp [img_background], static_background_data - jnz @f - test edx, edx - jnz .fin - cmp esi, 4 - ja .fin - @@: - ; bughere - mov eax, ecx - mov ebx, edx - add ebx, [img_background] ;IMG_BACKGROUND - mov ecx, esi - call memmove - .fin: - ret - nosb5: - - cmp ebx, 6 - jnz nosb6 -;;Maxis use atomic bts for mutex 4.4.2009 -@@: - bts dword [bgrlock], 0 - jnc @f - call change_task - jmp @b -@@: - mov eax, [CURRENT_TASK] - mov [bgrlockpid], eax - cmp [img_background], static_background_data - jz .nomem - stdcall user_alloc, [mem_BACKGROUND] - mov [esp+32], eax - test eax, eax - jz .nomem - mov ebx, eax - shr ebx, 12 - or dword [page_tabs+(ebx-1)*4], DONT_FREE_BLOCK - mov esi, [img_background] - shr esi, 12 - mov ecx, [mem_BACKGROUND] - add ecx, 0xFFF - shr ecx, 12 -.z: - mov eax, [page_tabs+ebx*4] - test al, 1 - jz @f - call free_page -@@: - mov eax, [page_tabs+esi*4] - or al, PG_UW - mov [page_tabs+ebx*4], eax - mov eax, ebx - shl eax, 12 - invlpg [eax] - inc ebx - inc esi - loop .z - ret -.nomem: - and [bgrlockpid], 0 - mov [bgrlock], 0 -nosb6: - cmp ebx, 7 - jnz nosb7 - cmp [bgrlock], 0 - jz .err - mov eax, [CURRENT_TASK] - cmp [bgrlockpid], eax - jnz .err - mov eax, ecx - mov ebx, ecx - shr eax, 12 - mov ecx, [page_tabs+(eax-1)*4] - test cl, USED_BLOCK+DONT_FREE_BLOCK - jz .err - jnp .err - push eax - shr ecx, 12 - dec ecx -@@: - and dword [page_tabs+eax*4], 0 - mov edx, eax - shl edx, 12 - push eax - invlpg [edx] - pop eax - inc eax - loop @b - pop eax - and dword [page_tabs+(eax-1)*4], not DONT_FREE_BLOCK - stdcall user_free, ebx - mov [esp+32], eax - and [bgrlockpid], 0 - mov [bgrlock], 0 - ret -.err: - and dword [esp+32], 0 - ret - -nosb7: - ret - -force_redraw_background: - and [draw_data+32 + RECT.left], 0 - and [draw_data+32 + RECT.top], 0 - push eax ebx - mov eax,[Screen_Max_X] - mov ebx,[Screen_Max_Y] - mov [draw_data+32 + RECT.right],eax - mov [draw_data+32 + RECT.bottom],ebx - pop ebx eax - inc byte[REDRAW_BACKGROUND] - ret - -align 4 - -sys_getbackground: -; cmp eax,1 ; SIZE - dec ebx - jnz nogb1 - mov eax,[BgrDataWidth] - shl eax,16 - mov ax,[BgrDataHeight] - mov [esp+32],eax - ret - -nogb1: -; cmp eax,2 ; PIXEL - dec ebx - jnz nogb2 - - mov eax, [img_background] - test ecx, ecx - jz @f - cmp eax, static_background_data - jz .ret -@@: - mov ebx, [mem_BACKGROUND] - add ebx, 4095 - and ebx, -4096 - sub ebx, 4 - cmp ecx, ebx - ja .ret - - mov eax,[ecx+eax] - - and eax, 0xFFFFFF - mov [esp+32],eax -.ret: - ret - nogb2: - -; cmp eax,4 ; TILED / STRETCHED - dec ebx - dec ebx - jnz nogb4 - mov eax,[BgrDrawMode] - nogb4: - mov [esp+32],eax - ret - -align 4 - -sys_getkey: - mov [esp + 32],dword 1 - ; test main buffer - mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK - movzx ecx, word [WIN_STACK + ebx * 2] - mov edx, [TASK_COUNT] - cmp ecx, edx - jne .finish - cmp [KEY_COUNT], byte 0 - je .finish - movzx eax, byte [KEY_BUFF] - shl eax, 8 - push eax - dec byte [KEY_COUNT] - and byte [KEY_COUNT], 127 - movzx ecx, byte [KEY_COUNT] - add ecx, 2 - mov eax, KEY_BUFF + 1 - mov ebx, KEY_BUFF - call memmove - pop eax -.ret_eax: - mov [esp + 32], eax - ret -.finish: -; test hotkeys buffer - mov ecx, hotkey_buffer -@@: - cmp [ecx], ebx - jz .found - add ecx, 8 - cmp ecx, hotkey_buffer + 120 * 8 - jb @b - ret -.found: - mov ax, [ecx + 6] - shl eax, 16 - mov ah, [ecx + 4] - mov al, 2 - and dword [ecx + 4], 0 - and dword [ecx], 0 - jmp .ret_eax - -align 4 - -sys_getbutton: - - mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK - mov [esp + 32], dword 1 - movzx ecx, word [WIN_STACK + ebx * 2] - mov edx, [TASK_COUNT] ; less than 256 processes - cmp ecx, edx - jne .exit - movzx eax, byte [BTN_COUNT] - test eax, eax - jz .exit - mov eax, [BTN_BUFF] - and al, 0xFE ; delete left button bit - mov [BTN_COUNT], byte 0 - mov [esp + 32], eax -.exit: - ret - - -align 4 - -sys_cpuusage: - -; RETURN: -; -; +00 dword process cpu usage -; +04 word position in windowing stack -; +06 word windowing stack value at current position (cpu nro) -; +10 12 bytes name -; +22 dword start in mem -; +26 dword used mem -; +30 dword PID , process idenfification number -; - - cmp ecx,-1 ; who am I ? - jne .no_who_am_i - mov ecx,[CURRENT_TASK] - .no_who_am_i: - cmp ecx, max_processes - ja .nofillbuf - -; +4: word: position of the window of thread in the window stack - mov ax, [WIN_STACK + ecx * 2] - mov [ebx+4], ax -; +6: word: number of the thread slot, which window has in the window stack -; position ecx (has no relation to the specific thread) - mov ax, [WIN_POS + ecx * 2] - mov [ebx+6], ax - - shl ecx, 5 - -; +0: dword: memory usage - mov eax, [ecx+CURRENT_TASK+TASKDATA.cpu_usage] - mov [ebx], eax -; +10: 11 bytes: name of the process - push ecx - lea eax, [ecx*8+SLOT_BASE+APPDATA.app_name] - add ebx, 10 - mov ecx, 11 - call memmove - pop ecx - -; +22: address of the process in memory -; +26: size of used memory - 1 - push edi - lea edi, [ebx+12] - xor eax, eax - mov edx, 0x100000*16 - cmp ecx, 1 shl 5 - je .os_mem - mov edx, [SLOT_BASE+ecx*8+APPDATA.mem_size] - mov eax, std_application_base_address -.os_mem: - stosd - lea eax, [edx-1] - stosd - -; +30: PID/TID - mov eax, [ecx+CURRENT_TASK+TASKDATA.pid] - stosd - - ; window position and size - push esi - lea esi, [ecx + window_data + WDATA.box] - movsd - movsd - movsd - movsd - - ; Process state (+50) - mov eax, dword [ecx+CURRENT_TASK+TASKDATA.state] - stosd - - ; Window client area box - lea esi, [ecx*8 + SLOT_BASE + APPDATA.wnd_clientbox] - movsd - movsd - movsd - movsd - - ; Window state - mov al, [ecx+window_data+WDATA.fl_wstate] - stosb - - ; Event mask (+71) - mov EAX, dword [ECX+CURRENT_TASK+TASKDATA.event_mask] - stosd - - pop esi - pop edi - -.nofillbuf: - ; return number of processes - - mov eax,[TASK_COUNT] - mov [esp+32],eax - ret - -align 4 -sys_clock: - cli - ; Mikhail Lisovin xx Jan 2005 - @@: mov al, 10 - out 0x70, al - in al, 0x71 - test al, al - jns @f - mov esi, 1 - call delay_ms - jmp @b - @@: - ; end Lisovin's fix - - xor al,al ; seconds - out 0x70,al - in al,0x71 - movzx ecx,al - mov al,02 ; minutes - shl ecx,16 - out 0x70,al - in al,0x71 - movzx edx,al - mov al,04 ; hours - shl edx,8 - out 0x70,al - in al,0x71 - add ecx,edx - movzx edx,al - add ecx,edx - sti - mov [esp + 32], ecx - ret - - -align 4 - -sys_date: - - cli - @@: mov al, 10 - out 0x70, al - in al, 0x71 - test al, al - jns @f - mov esi, 1 - call delay_ms - jmp @b - @@: - - mov ch,0 - mov al,7 ; date - out 0x70,al - in al,0x71 - mov cl,al - mov al,8 ; month - shl ecx,16 - out 0x70,al - in al,0x71 - mov ch,al - mov al,9 ; year - out 0x70,al - in al,0x71 - mov cl,al - sti - mov [esp+32], ecx - ret - - -; redraw status - -sys_redrawstat: - cmp ebx, 1 - jne no_widgets_away - ; buttons away - mov ecx,[CURRENT_TASK] - sys_newba2: - mov edi,[BTN_ADDR] - cmp [edi], dword 0 ; empty button list ? - je end_of_buttons_away - movzx ebx, word [edi] - inc ebx - mov eax,edi - sys_newba: - dec ebx - jz end_of_buttons_away - - add eax, 0x10 - cmp cx, [eax] - jnz sys_newba - - push eax ebx ecx - mov ecx,ebx - inc ecx - shl ecx, 4 - mov ebx, eax - add eax, 0x10 - call memmove - dec dword [edi] - pop ecx ebx eax - - jmp sys_newba2 - - end_of_buttons_away: - - ret - - no_widgets_away: - - cmp ebx, 2 - jnz srl1 - - mov edx, [TASK_BASE] ; return whole screen draw area for this app - add edx, draw_data - CURRENT_TASK - mov [edx + RECT.left], 0 - mov [edx + RECT.top], 0 - mov eax, [Screen_Max_X] - mov [edx + RECT.right], eax - mov eax, [Screen_Max_Y] - mov [edx + RECT.bottom], eax - - srl1: - ret - -;ok - 100% work -;nt - not tested -;--------------------------------------------------------------------------------------------- -;eax -;0 - task switch counter. Ret switch counter in eax. Block. ok. -;1 - change task. Ret nothing. Block. ok. -;2 - performance control -; ebx -; 0 - enable or disable (inversion) PCE flag on CR4 for rdmpc in user mode. -; returned new cr4 in eax. Ret cr4 in eax. Block. ok. -; 1 - is cache enabled. Ret cr0 in eax if enabled else zero in eax. Block. ok. -; 2 - enable cache. Ret 1 in eax. Ret nothing. Block. ok. -; 3 - disable cache. Ret 0 in eax. Ret nothing. Block. ok. -;eax -;3 - rdmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. -;4 - wrmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. -;--------------------------------------------------------------------------------------------- -iglobal -align 4 -sheduler: - dd sys_sheduler.00 - dd change_task - dd sys_sheduler.02 - dd sys_sheduler.03 - dd sys_sheduler.04 -endg -sys_sheduler: -;rewritten by 29.12.2009 - jmp dword [sheduler+ebx*4] -;.shed_counter: -.00: - mov eax,[context_counter] - mov [esp+32],eax - ret - -.02: -;.perf_control: - inc ebx ;before ebx=2, ebx=3 - cmp ebx,ecx ;if ecx=3, ebx=3 - jz cache_disable - - dec ebx ;ebx=2 - cmp ebx,ecx ; - jz cache_enable ;if ecx=2 and ebx=2 - - dec ebx ;ebx=1 - cmp ebx,ecx - jz is_cache_enabled ;if ecx=1 and ebx=1 - - dec ebx - test ebx,ecx ;ebx=0 and ecx=0 - jz modify_pce ;if ecx=0 - - ret - -.03: -;.rdmsr_instr: -;now counter in ecx -;(edx:eax) esi:edi => edx:esi - mov eax,esi - mov ecx,edx - rdmsr - mov [esp+32],eax - mov [esp+20],edx ;ret in ebx? - ret - -.04: -;.wrmsr_instr: -;now counter in ecx -;(edx:eax) esi:edi => edx:esi - ; Fast Call MSR can't be destroy - ; Ќ® MSR_AMD_EFER ¬®¦­® Ё§¬Ґ­пвм, в.Є. ў н⮬ ॣЁбвॠ«Ёи - ; ўЄ«оз овбп/ўлЄ«оз овбп а биЁаҐ­­лҐ ў®§¬®¦­®бвЁ - cmp edx,MSR_SYSENTER_CS - je @f - cmp edx,MSR_SYSENTER_ESP - je @f - cmp edx,MSR_SYSENTER_EIP - je @f - cmp edx,MSR_AMD_STAR - je @f - - mov eax,esi - mov ecx,edx - wrmsr - ; mov [esp + 32], eax - ; mov [esp + 20], edx ;ret in ebx? -@@: - ret - -cache_disable: - mov eax,cr0 - or eax,01100000000000000000000000000000b - mov cr0,eax - wbinvd ;set MESI -ret - -cache_enable: - mov eax,cr0 - and eax,10011111111111111111111111111111b - mov cr0,eax -ret - -is_cache_enabled: - mov eax,cr0 - mov ebx,eax - and eax,01100000000000000000000000000000b - jz cache_disabled - mov [esp+32],ebx -cache_disabled: - mov dword [esp+32],eax ;0 -ret - -modify_pce: - mov eax,cr4 -; mov ebx,0 -; or bx,100000000b ;pce -; xor eax,ebx ;invert pce - bts eax,8 ;pce=cr4[8] - mov cr4,eax - mov [esp+32],eax -ret -;--------------------------------------------------------------------------------------------- - - -; check if pixel is allowed to be drawn - -checkpixel: - push eax edx - - mov edx,[Screen_Max_X] ; screen x size - inc edx - imul edx, ebx - add eax, [_WinMapAddress] - mov dl, [eax+edx] ; lea eax, [...] - - xor ecx, ecx - mov eax, [CURRENT_TASK] - cmp al, dl - setne cl - - pop edx eax - ret - -iglobal - cpustring db 'CPU',0 -endg - -uglobal -background_defined db 0 ; diamond, 11.04.2006 -endg - -align 4 -; check misc - -checkmisc: - - cmp [ctrl_alt_del], 1 - jne nocpustart - - mov ebp, cpustring - call fs_execute_from_sysdir - - mov [ctrl_alt_del], 0 - -nocpustart: - cmp [mouse_active], 1 - jne mouse_not_active - mov [mouse_active], 0 - xor edi, edi - mov ecx, [TASK_COUNT] -set_mouse_event: - add edi, 256 - or [edi+SLOT_BASE+APPDATA.event_mask], dword 100000b - loop set_mouse_event - -mouse_not_active: - cmp byte[BACKGROUND_CHANGED], 0 - jz no_set_bgr_event - xor edi, edi - mov ecx, [TASK_COUNT] -set_bgr_event: - add edi, 256 - or [edi+SLOT_BASE+APPDATA.event_mask], 16 - loop set_bgr_event - mov byte[BACKGROUND_CHANGED], 0 -no_set_bgr_event: - cmp byte[REDRAW_BACKGROUND], 0 ; background update ? - jz nobackgr - cmp [background_defined], 0 - jz nobackgr -; mov [draw_data+32 + RECT.left],dword 0 -; mov [draw_data+32 + RECT.top],dword 0 -; mov eax,[Screen_Max_X] -; mov ebx,[Screen_Max_Y] -; mov [draw_data+32 + RECT.right],eax -; mov [draw_data+32 + RECT.bottom],ebx -@@: - call drawbackground - xor eax, eax - xchg al, [REDRAW_BACKGROUND] - test al, al ; got new update request? - jnz @b - mov [draw_data+32 + RECT.left], eax - mov [draw_data+32 + RECT.top], eax - mov [draw_data+32 + RECT.right], eax - mov [draw_data+32 + RECT.bottom], eax - mov [MOUSE_BACKGROUND],byte 0 - -nobackgr: - - ; system shutdown request - - cmp [SYS_SHUTDOWN],byte 0 - je noshutdown - - mov edx,[shutdown_processes] - - cmp [SYS_SHUTDOWN],dl - jne no_mark_system_shutdown - - lea ecx,[edx-1] - mov edx,OS_BASE+0x3040 - jecxz @f -markz: - mov [edx+TASKDATA.state],byte 3 - add edx,0x20 - loop markz -@@: - - no_mark_system_shutdown: - - call [_display.disable_mouse] - - dec byte [SYS_SHUTDOWN] - je system_shutdown - -noshutdown: - - - mov eax,[TASK_COUNT] ; termination - mov ebx,TASK_DATA+TASKDATA.state - mov esi,1 - -newct: - mov cl,[ebx] - cmp cl,byte 3 - jz terminate - cmp cl,byte 4 - jz terminate - - add ebx,0x20 - inc esi - dec eax - jnz newct - ret - -; redraw screen - -redrawscreen: - -; eax , if process window_data base is eax, do not set flag/limits - - pushad - push eax - -;;; mov ebx,2 -;;; call delay_hs - - ;mov ecx,0 ; redraw flags for apps - xor ecx,ecx - newdw2: - - inc ecx - push ecx - - mov eax,ecx - shl eax,5 - add eax,window_data - - cmp eax,[esp+4] - je not_this_task - ; check if window in redraw area - mov edi,eax - - cmp ecx,1 ; limit for background - jz bgli - - mov eax, [edi + WDATA.box.left] - mov ebx, [edi + WDATA.box.top] - mov ecx, [edi + WDATA.box.width] - mov edx, [edi + WDATA.box.height] - add ecx,eax - add edx,ebx - - mov ecx,[draw_limits.bottom] ; ecx = area y end ebx = window y start - cmp ecx,ebx - jb ricino - - mov ecx,[draw_limits.right] ; ecx = area x end eax = window x start - cmp ecx,eax - jb ricino - - mov eax, [edi + WDATA.box.left] - mov ebx, [edi + WDATA.box.top] - mov ecx, [edi + WDATA.box.width] - mov edx, [edi + WDATA.box.height] - add ecx, eax - add edx, ebx - - mov eax,[draw_limits.top] ; eax = area y start edx = window y end - cmp edx,eax - jb ricino - - mov eax,[draw_limits.left] ; eax = area x start ecx = window x end - cmp ecx,eax - jb ricino - - bgli: - - cmp dword[esp], 1 - jnz .az -; cmp byte[BACKGROUND_CHANGED], 0 -; jnz newdw8 - cmp byte[REDRAW_BACKGROUND], 0 - jz .az - mov dl, 0 - lea eax,[edi+draw_data-window_data] - mov ebx,[draw_limits.left] - cmp ebx,[eax+RECT.left] - jae @f - mov [eax+RECT.left],ebx - mov dl, 1 - @@: - mov ebx,[draw_limits.top] - cmp ebx,[eax+RECT.top] - jae @f - mov [eax+RECT.top],ebx - mov dl, 1 - @@: - mov ebx,[draw_limits.right] - cmp ebx,[eax+RECT.right] - jbe @f - mov [eax+RECT.right],ebx - mov dl, 1 - @@: - mov ebx,[draw_limits.bottom] - cmp ebx,[eax+RECT.bottom] - jbe @f - mov [eax+RECT.bottom],ebx - mov dl, 1 - @@: - add byte[REDRAW_BACKGROUND], dl - jmp newdw8 - .az: - - mov eax,edi - add eax,draw_data-window_data - - mov ebx,[draw_limits.left] ; set limits - mov [eax + RECT.left], ebx - mov ebx,[draw_limits.top] - mov [eax + RECT.top], ebx - mov ebx,[draw_limits.right] - mov [eax + RECT.right], ebx - mov ebx,[draw_limits.bottom] - mov [eax + RECT.bottom], ebx - - sub eax,draw_data-window_data - - cmp dword [esp],1 - jne nobgrd - inc byte[REDRAW_BACKGROUND] - - newdw8: - nobgrd: - - mov [eax + WDATA.fl_redraw],byte 1 ; mark as redraw - - ricino: - - not_this_task: - - pop ecx - - cmp ecx,[TASK_COUNT] - jle newdw2 - - pop eax - popad - - ret - -calculatebackground: ; background - - mov edi, [_WinMapAddress] ; set os to use all pixels - mov eax,0x01010101 - mov ecx, [_WinMapSize] - shr ecx, 2 - rep stosd - - mov byte[REDRAW_BACKGROUND], 0 ; do not draw background! - mov byte[BACKGROUND_CHANGED], 0 - - ret - -uglobal - imax dd 0x0 -endg - - - -delay_ms: ; delay in 1/1000 sec - - - push eax - push ecx - - mov ecx,esi - ; - imul ecx, 33941 - shr ecx, 9 - ; - - in al,0x61 - and al,0x10 - mov ah,al - cld - - cnt1: in al,0x61 - and al,0x10 - cmp al,ah - jz cnt1 - - mov ah,al - loop cnt1 - - pop ecx - pop eax - - ret - - -set_app_param: - mov edi, [TASK_BASE] - mov eax, [edi + TASKDATA.event_mask] - mov [edi + TASKDATA.event_mask], ebx - mov [esp+32], eax - ret - - - -delay_hs: ; delay in 1/100 secs -; ebx = delay time - push ecx - push edx - - mov edx,[timer_ticks] - - newtic: - mov ecx,[timer_ticks] - sub ecx,edx - cmp ecx,ebx - jae zerodelay - - call change_task - - jmp newtic - - zerodelay: - pop edx - pop ecx - - ret - -align 16 ;very often call this subrutine -memmove: ; memory move in bytes - -; eax = from -; ebx = to -; ecx = no of bytes - test ecx, ecx - jle .ret - - push esi edi ecx - - mov edi, ebx - mov esi, eax - - test ecx, not 11b - jz @f - - push ecx - shr ecx, 2 - rep movsd - pop ecx - and ecx, 11b - jz .finish - @@: - rep movsb - - .finish: - pop ecx edi esi - .ret: - ret - - -; Sysfunction 34, read_floppy_file, is obsolete. Use 58 or 70 function instead. -;align 4 -; -;read_floppy_file: -; -;; as input -;; -;; eax pointer to file -;; ebx file lenght -;; ecx start 512 byte block number -;; edx number of blocks to read -;; esi pointer to return/work area (atleast 20 000 bytes) -;; -;; -;; on return -;; -;; eax = 0 command succesful -;; 1 no fd base and/or partition defined -;; 2 yet unsupported FS -;; 3 unknown FS -;; 4 partition not defined at hd -;; 5 file not found -;; ebx = size of file -; -; mov edi,[TASK_BASE] -; add edi,0x10 -; add esi,[edi] -; add eax,[edi] -; -; pushad -; mov edi,esi -; add edi,1024 -; mov esi,0x100000+19*512 -; sub ecx,1 -; shl ecx,9 -; add esi,ecx -; shl edx,9 -; mov ecx,edx -; cld -; rep movsb -; popad -; -; mov [esp+36],eax -; mov [esp+24],ebx -; ret - - - -align 4 -set_io_access_rights: - push edi eax - mov edi, tss._io_map_0 -; mov ecx,eax -; and ecx,7 ; offset in byte -; shr eax,3 ; number of byte -; add edi,eax -; mov ebx,1 -; shl ebx,cl - test ebp,ebp -; cmp ebp,0 ; enable access - ebp = 0 - jnz .siar1 -; not ebx -; and [edi],byte bl - btr [edi], eax - pop eax edi - ret -.siar1: - bts [edi], eax - ; or [edi],byte bl ; disable access - ebp = 1 - pop eax edi - ret -;reserve/free group of ports -; * eax = 46 - number function -; * ebx = 0 - reserve, 1 - free -; * ecx = number start arrea of ports -; * edx = number end arrea of ports (include last number of port) -;Return value: -; * eax = 0 - succesful -; * eax = 1 - error -; * The system has reserve this ports: -; 0..0x2d, 0x30..0x4d, 0x50..0xdf, 0xe5..0xff (include last number of port). -;destroys eax,ebx, ebp -r_f_port_area: - - test ebx, ebx - jnz free_port_area -; je r_port_area -; jmp free_port_area - -; r_port_area: - -; pushad - - cmp ecx,edx ; beginning > end ? - ja rpal1 - cmp edx,65536 - jae rpal1 - mov eax,[RESERVED_PORTS] - test eax,eax ; no reserved areas ? - je rpal2 - cmp eax,255 ; max reserved - jae rpal1 - rpal3: - mov ebx,eax - shl ebx,4 - add ebx,RESERVED_PORTS - cmp ecx,[ebx+8] - ja rpal4 - cmp edx,[ebx+4] - jae rpal1 -; jb rpal4 -; jmp rpal1 - rpal4: - dec eax - jnz rpal3 - jmp rpal2 - rpal1: -; popad -; mov eax,1 - xor eax,eax - inc eax - ret - rpal2: -; popad - ; enable port access at port IO map - cli - pushad ; start enable io map - - cmp edx,65536 ;16384 - jae no_unmask_io ; jge - mov eax,ecx -; push ebp - xor ebp,ebp ; enable - eax = port -new_port_access: -; pushad - call set_io_access_rights -; popad - inc eax - cmp eax,edx - jbe new_port_access -; pop ebp -no_unmask_io: - popad ; end enable io map - sti - - mov eax,[RESERVED_PORTS] - add eax,1 - mov [RESERVED_PORTS],eax - shl eax,4 - add eax,RESERVED_PORTS - mov ebx,[TASK_BASE] - mov ebx,[ebx+TASKDATA.pid] - mov [eax],ebx - mov [eax+4],ecx - mov [eax+8],edx - - xor eax, eax - ret - -free_port_area: - -; pushad - mov eax,[RESERVED_PORTS] ; no reserved areas ? - test eax,eax - jz frpal2 - mov ebx,[TASK_BASE] - mov ebx,[ebx+TASKDATA.pid] - frpal3: - mov edi,eax - shl edi,4 - add edi,RESERVED_PORTS - cmp ebx,[edi] - jne frpal4 - cmp ecx,[edi+4] - jne frpal4 - cmp edx,[edi+8] - jne frpal4 - jmp frpal1 - frpal4: - dec eax - jnz frpal3 - frpal2: -; popad - inc eax - ret - frpal1: - push ecx - mov ecx,256 - sub ecx,eax - shl ecx,4 - mov esi,edi - add esi,16 - cld - rep movsb - - dec dword [RESERVED_PORTS] -;popad -;disable port access at port IO map - -; pushad ; start disable io map - pop eax ;start port - cmp edx,65536 ;16384 - jge no_mask_io - -; mov eax,ecx - xor ebp,ebp - inc ebp -new_port_access_disable: -; pushad -; mov ebp,1 ; disable - eax = port - call set_io_access_rights -; popad - inc eax - cmp eax,edx - jbe new_port_access_disable -no_mask_io: -; popad ; end disable io map - xor eax, eax - ret - - -align 4 -drawbackground: - inc [mouse_pause] - cmp [SCR_MODE],word 0x12 - je dbrv20 - dbrv12: - cmp [SCR_MODE],word 0100000000000000b - jge dbrv20 - cmp [SCR_MODE],word 0x13 - je dbrv20 - call vesa12_drawbackground - dec [mouse_pause] - call [draw_pointer] - ret - dbrv20: - cmp [BgrDrawMode],dword 1 - jne bgrstr - call vesa20_drawbackground_tiled - dec [mouse_pause] - call [draw_pointer] - ret - bgrstr: - call vesa20_drawbackground_stretch - dec [mouse_pause] - call [draw_pointer] - ret - -align 4 - -syscall_putimage: ; PutImage -sys_putimage: - test ecx,0x80008000 - jnz .exit - test ecx,0x0000FFFF - jz .exit - test ecx,0xFFFF0000 - jnz @f - .exit: - ret - @@: - mov edi,[current_slot] - add dx,word[edi+APPDATA.wnd_clientbox.top] - rol edx,16 - add dx,word[edi+APPDATA.wnd_clientbox.left] - rol edx,16 - .forced: - push ebp esi 0 - mov ebp, putimage_get24bpp - mov esi, putimage_init24bpp -sys_putimage_bpp: -; call [disable_mouse] ; this will be done in xxx_putimage -; mov eax, vga_putimage - cmp [SCR_MODE], word 0x12 - jz @f ;.doit - mov eax, vesa12_putimage - cmp [SCR_MODE], word 0100000000000000b - jae @f - cmp [SCR_MODE], word 0x13 - jnz .doit -@@: - mov eax, vesa20_putimage -.doit: - inc [mouse_pause] - call eax - dec [mouse_pause] - pop ebp esi ebp - jmp [draw_pointer] -align 4 -sys_putimage_palette: -; ebx = pointer to image -; ecx = [xsize]*65536 + [ysize] -; edx = [xstart]*65536 + [ystart] -; esi = number of bits per pixel, must be 8, 24 or 32 -; edi = pointer to palette -; ebp = row delta - mov eax, [CURRENT_TASK] - shl eax, 8 - add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.top] - rol edx, 16 - add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.left] - rol edx, 16 -.forced: - cmp esi, 1 - jnz @f - push edi - mov eax, [edi+4] - sub eax, [edi] - push eax - push dword [edi] - push 0ffffff80h - mov edi, esp - call put_mono_image - add esp, 12 - pop edi - ret -@@: - cmp esi, 2 - jnz @f - push edi - push 0ffffff80h - mov edi, esp - call put_2bit_image - pop eax - pop edi - ret -@@: - cmp esi, 4 - jnz @f - push edi - push 0ffffff80h - mov edi, esp - call put_4bit_image - pop eax - pop edi - ret -@@: - push ebp esi ebp - cmp esi, 8 - jnz @f - mov ebp, putimage_get8bpp - mov esi, putimage_init8bpp - jmp sys_putimage_bpp -@@: - cmp esi, 15 - jnz @f - mov ebp, putimage_get15bpp - mov esi, putimage_init15bpp - jmp sys_putimage_bpp -@@: - cmp esi, 16 - jnz @f - mov ebp, putimage_get16bpp - mov esi, putimage_init16bpp - jmp sys_putimage_bpp -@@: - cmp esi, 24 - jnz @f - mov ebp, putimage_get24bpp - mov esi, putimage_init24bpp - jmp sys_putimage_bpp -@@: - cmp esi, 32 - jnz @f - mov ebp, putimage_get32bpp - mov esi, putimage_init32bpp - jmp sys_putimage_bpp -@@: - pop ebp esi ebp - ret - -put_mono_image: - push ebp esi ebp - mov ebp, putimage_get1bpp - mov esi, putimage_init1bpp - jmp sys_putimage_bpp -put_2bit_image: - push ebp esi ebp - mov ebp, putimage_get2bpp - mov esi, putimage_init2bpp - jmp sys_putimage_bpp -put_4bit_image: - push ebp esi ebp - mov ebp, putimage_get4bpp - mov esi, putimage_init4bpp - jmp sys_putimage_bpp - -putimage_init24bpp: - lea eax, [eax*3] -putimage_init8bpp: - ret - -align 16 -putimage_get24bpp: - movzx eax, byte [esi+2] - shl eax, 16 - mov ax, [esi] - add esi, 3 - ret 4 -align 16 -putimage_get8bpp: - movzx eax, byte [esi] - push edx - mov edx, [esp+8] - mov eax, [edx+eax*4] - pop edx - inc esi - ret 4 - -putimage_init1bpp: - add eax, ecx - push ecx - add eax, 7 - add ecx, 7 - shr eax, 3 - shr ecx, 3 - sub eax, ecx - pop ecx - ret -align 16 -putimage_get1bpp: - push edx - mov edx, [esp+8] - mov al, [edx] - add al, al - jnz @f - lodsb - adc al, al -@@: - mov [edx], al - sbb eax, eax - and eax, [edx+8] - add eax, [edx+4] - pop edx - ret 4 - -putimage_init2bpp: - add eax, ecx - push ecx - add ecx, 3 - add eax, 3 - shr ecx, 2 - shr eax, 2 - sub eax, ecx - pop ecx - ret -align 16 -putimage_get2bpp: - push edx - mov edx, [esp+8] - mov al, [edx] - mov ah, al - shr al, 6 - shl ah, 2 - jnz .nonewbyte - lodsb - mov ah, al - shr al, 6 - shl ah, 2 - add ah, 1 -.nonewbyte: - mov [edx], ah - mov edx, [edx+4] - movzx eax, al - mov eax, [edx+eax*4] - pop edx - ret 4 - -putimage_init4bpp: - add eax, ecx - push ecx - add ecx, 1 - add eax, 1 - shr ecx, 1 - shr eax, 1 - sub eax, ecx - pop ecx - ret -align 16 -putimage_get4bpp: - push edx - mov edx, [esp+8] - add byte [edx], 80h - jc @f - movzx eax, byte [edx+1] - mov edx, [edx+4] - and eax, 0x0F - mov eax, [edx+eax*4] - pop edx - ret 4 -@@: - movzx eax, byte [esi] - add esi, 1 - mov [edx+1], al - shr eax, 4 - mov edx, [edx+4] - mov eax, [edx+eax*4] - pop edx - ret 4 - -putimage_init32bpp: - shl eax, 2 - ret -align 16 -putimage_get32bpp: - lodsd - ret 4 - -putimage_init15bpp: -putimage_init16bpp: - add eax, eax - ret -align 16 -putimage_get15bpp: -; 0RRRRRGGGGGBBBBB -> 00000000RRRRR000GGGGG000BBBBB000 - push ecx edx - movzx eax, word [esi] - add esi, 2 - mov ecx, eax - mov edx, eax - and eax, 0x1F - and ecx, 0x1F shl 5 - and edx, 0x1F shl 10 - shl eax, 3 - shl ecx, 6 - shl edx, 9 - or eax, ecx - or eax, edx - pop edx ecx - ret 4 - -align 16 -putimage_get16bpp: -; RRRRRGGGGGGBBBBB -> 00000000RRRRR000GGGGGG00BBBBB000 - push ecx edx - movzx eax, word [esi] - add esi, 2 - mov ecx, eax - mov edx, eax - and eax, 0x1F - and ecx, 0x3F shl 5 - and edx, 0x1F shl 11 - shl eax, 3 - shl ecx, 5 - shl edx, 8 - or eax, ecx - or eax, edx - pop edx ecx - ret 4 - -; eax x beginning -; ebx y beginning -; ecx x end - ; edx y end -; edi color - -__sys_drawbar: - mov esi,[current_slot] - add eax,[esi+APPDATA.wnd_clientbox.left] - add ecx,[esi+APPDATA.wnd_clientbox.left] - add ebx,[esi+APPDATA.wnd_clientbox.top] - add edx,[esi+APPDATA.wnd_clientbox.top] - .forced: - inc [mouse_pause] -; call [disable_mouse] - cmp [SCR_MODE],word 0x12 - je dbv20 - sdbv20: - cmp [SCR_MODE],word 0100000000000000b - jge dbv20 - cmp [SCR_MODE],word 0x13 - je dbv20 - call vesa12_drawbar - dec [mouse_pause] - call [draw_pointer] - ret - dbv20: - call vesa20_drawbar - dec [mouse_pause] - call [draw_pointer] - ret - - - -kb_read: - - push ecx edx - - mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's - kr_loop: - in al,0x64 - test al,1 - jnz kr_ready - loop kr_loop - mov ah,1 - jmp kr_exit - kr_ready: - push ecx - mov ecx,32 - kr_delay: - loop kr_delay - pop ecx - in al,0x60 - xor ah,ah - kr_exit: - - pop edx ecx - - ret - - -kb_write: - - push ecx edx - - mov dl,al -; mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's -; kw_loop1: -; in al,0x64 -; test al,0x20 -; jz kw_ok1 -; loop kw_loop1 -; mov ah,1 -; jmp kw_exit -; kw_ok1: - in al,0x60 - mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's - kw_loop: - in al,0x64 - test al,2 - jz kw_ok - loop kw_loop - mov ah,1 - jmp kw_exit - kw_ok: - mov al,dl - out 0x60,al - mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's - kw_loop3: - in al,0x64 - test al,2 - jz kw_ok3 - loop kw_loop3 - mov ah,1 - jmp kw_exit - kw_ok3: - mov ah,8 - kw_loop4: - mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's - kw_loop5: - in al,0x64 - test al,1 - jnz kw_ok4 - loop kw_loop5 - dec ah - jnz kw_loop4 - kw_ok4: - xor ah,ah - kw_exit: - - pop edx ecx - - ret - - -kb_cmd: - - mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's - c_wait: - in al,0x64 - test al,2 - jz c_send - loop c_wait - jmp c_error - c_send: - mov al,bl - out 0x64,al - mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's - c_accept: - in al,0x64 - test al,2 - jz c_ok - loop c_accept - c_error: - mov ah,1 - jmp c_exit - c_ok: - xor ah,ah - c_exit: - ret - - -setmouse: ; set mousepicture -pointer - ; ps2 mouse enable - - mov [MOUSE_PICTURE],dword mousepointer - - cli - - ret - -if used _rdtsc -_rdtsc: - bt [cpu_caps], CAPS_TSC - jnc ret_rdtsc - rdtsc - ret - ret_rdtsc: - mov edx,0xffffffff - mov eax,0xffffffff - ret -end if - -sys_msg_board_str: - - pushad - @@: - cmp [esi],byte 0 - je @f - mov eax,1 - movzx ebx,byte [esi] - call sys_msg_board - inc esi - jmp @b - @@: - popad - ret - -sys_msg_board_byte: -; in: al = byte to display -; out: nothing -; destroys: nothing - pushad - mov ecx, 2 - shl eax, 24 - jmp @f - -sys_msg_board_word: -; in: ax = word to display -; out: nothing -; destroys: nothing - pushad - mov ecx, 4 - shl eax, 16 - jmp @f - -sys_msg_board_dword: -; in: eax = dword to display -; out: nothing -; destroys: nothing - pushad - mov ecx, 8 -@@: - push ecx - rol eax, 4 - push eax - and al, 0xF - cmp al, 10 - sbb al, 69h - das - mov bl, al - xor eax, eax - inc eax - call sys_msg_board - pop eax - pop ecx - loop @b - popad - ret - -uglobal - msg_board_data: times 4096 db 0 - msg_board_count dd 0x0 -endg - -sys_msg_board: - -; eax=1 : write : bl byte to write -; eax=2 : read : ebx=0 -> no data, ebx=1 -> data in al - - mov ecx, [msg_board_count] - cmp eax, 1 - jne .smbl1 - -if defined debug_com_base - - push dx ax - - @@: ; Wait for empty transmit register (yes, this slows down system..) - mov dx, debug_com_base+5 - in al, dx - test al, 1 shl 5 - jz @r - - mov dx, debug_com_base ; Output the byte - mov al, bl - out dx, al - - pop ax dx - -end if - - mov [msg_board_data+ecx],bl - inc ecx - and ecx, 4095 - mov [msg_board_count], ecx - mov [check_idle_semaphore], 5 - ret -.smbl1: - cmp eax, 2 - jne .smbl2 - test ecx, ecx - jz .smbl21 - mov eax, msg_board_data+1 - mov ebx, msg_board_data - movzx edx, byte [ebx] - call memmove - dec [msg_board_count] - mov [esp + 36], edx ;eax - mov [esp + 24], dword 1 - ret -.smbl21: - mov [esp+36], ecx - mov [esp+24], ecx -.smbl2: - ret - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 66 sys function. ;; -;; in eax=66,ebx in [0..5],ecx,edx ;; -;; out eax ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -iglobal -align 4 -f66call: - dd sys_process_def.1 ; 1 = set keyboard mode - dd sys_process_def.2 ; 2 = get keyboard mode - dd sys_process_def.3 ; 3 = get keyboard ctrl, alt, shift - dd sys_process_def.4 - dd sys_process_def.5 -endg - - - - -sys_process_def: - dec ebx - cmp ebx,5 - jae .not_support ;if >=6 then or eax,-1 - - mov edi, [CURRENT_TASK] - jmp dword [f66call+ebx*4] - -.not_support: - or eax,-1 - ret - -.1: - shl edi,8 - mov [edi+SLOT_BASE + APPDATA.keyboard_mode],cl - - ret - -.2: ; 2 = get keyboard mode - shl edi,8 - movzx eax, byte [SLOT_BASE+edi + APPDATA.keyboard_mode] - mov [esp+32],eax - ret -; xor eax,eax -; movzx eax,byte [shift] -; movzx ebx,byte [ctrl] -; shl ebx,2 -; add eax,ebx -; movzx ebx,byte [alt] -; shl ebx,3 -; add eax,ebx -.3: ;3 = get keyboard ctrl, alt, shift - ;// mike.dld [ - mov eax, [kb_state] - ;// mike.dld ] - mov [esp+32],eax - ret - -.4: - mov eax, hotkey_list -@@: - cmp dword [eax+8], 0 - jz .found_free - add eax, 16 - cmp eax, hotkey_list+16*256 - jb @b - mov dword [esp+32], 1 - ret -.found_free: - mov [eax+8], edi - mov [eax+4], edx - movzx ecx, cl - lea ecx, [hotkey_scancodes+ecx*4] - mov edx, [ecx] - mov [eax], edx - mov [ecx], eax - mov [eax+12], ecx - jecxz @f - mov [edx+12], eax -@@: - and dword [esp+32], 0 - ret - -.5: - movzx ebx, cl - lea ebx, [hotkey_scancodes+ebx*4] - mov eax, [ebx] -.scan: - test eax, eax - jz .notfound - cmp [eax+8], edi - jnz .next - cmp [eax+4], edx - jz .found -.next: - mov eax, [eax] - jmp .scan -.notfound: - mov dword [esp+32], 1 - ret -.found: - mov ecx, [eax] - jecxz @f - mov edx, [eax+12] - mov [ecx+12], edx -@@: - mov ecx, [eax+12] - mov edx, [eax] - mov [ecx], edx - xor edx, edx - mov [eax+4], edx - mov [eax+8], edx - mov [eax+12], edx - mov [eax], edx - mov [esp+32], edx - ret - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; 61 sys function. ;; -;; in eax=61,ebx in [1..3] ;; -;; out eax ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -iglobal -align 4 -f61call: - dd sys_gs.1 ; resolution - dd sys_gs.2 ; bits per pixel - dd sys_gs.3 ; bytes per scanline -endg - - -align 4 - -sys_gs: ; direct screen access - dec ebx - cmp ebx,2 - ja .not_support - jmp dword [f61call+ebx*4] -.not_support: - or [esp+32],dword -1 - ret - - -.1: ; resolution - mov eax,[Screen_Max_X] - shl eax,16 - mov ax,[Screen_Max_Y] - add eax,0x00010001 - mov [esp+32],eax - ret -.2: ; bits per pixel - movzx eax,byte [ScreenBPP] - mov [esp+32],eax - ret -.3: ; bytes per scanline - mov eax,[BytesPerScanLine] - mov [esp+32],eax - ret - -align 4 ; system functions - -syscall_setpixel: ; SetPixel - - mov eax, ebx - mov ebx, ecx - mov ecx, edx - mov edx, [TASK_BASE] - add eax, [edx-twdw+WDATA.box.left] - add ebx, [edx-twdw+WDATA.box.top] - mov edi, [current_slot] - add eax, [edi+APPDATA.wnd_clientbox.left] - add ebx, [edi+APPDATA.wnd_clientbox.top] - xor edi, edi ; no force -; mov edi, 1 - call [_display.disable_mouse] - jmp [putpixel] - -align 4 - -syscall_writetext: ; WriteText - - mov eax,[TASK_BASE] - mov ebp,[eax-twdw+WDATA.box.left] - push esi - mov esi,[current_slot] - add ebp,[esi+APPDATA.wnd_clientbox.left] - shl ebp,16 - add ebp,[eax-twdw+WDATA.box.top] - add bp,word[esi+APPDATA.wnd_clientbox.top] - pop esi - add ebx,ebp - mov eax,edi - xor edi,edi - jmp dtext - -align 4 - -syscall_openramdiskfile: ; OpenRamdiskFile - - mov eax, ebx - mov ebx, ecx - mov ecx, edx - mov edx, esi - mov esi, 12 - call fileread - mov [esp+32], eax - ret - -align 4 - -syscall_drawrect: ; DrawRect - - mov edi, edx ; color + gradient - and edi, 0x80FFFFFF - test bx, bx ; x.size - je .drectr - test cx, cx ; y.size - je .drectr - - mov eax, ebx ; bad idea - mov ebx, ecx - - movzx ecx, ax ; ecx - x.size - shr eax, 16 ; eax - x.coord - movzx edx, bx ; edx - y.size - shr ebx, 16 ; ebx - y.coord - mov esi, [current_slot] - - add eax, [esi + APPDATA.wnd_clientbox.left] - add ebx, [esi + APPDATA.wnd_clientbox.top] - add ecx, eax - add edx, ebx - jmp [drawbar] -.drectr: - ret - -align 4 -syscall_getscreensize: ; GetScreenSize - mov ax, [Screen_Max_X] - shl eax, 16 - mov ax, [Screen_Max_Y] - mov [esp + 32], eax - ret - -align 4 - -syscall_cdaudio: ; CD - - cmp ebx, 4 - jb .audio - jz .eject - cmp ebx, 5 - jnz .ret -.load: - call .reserve - call LoadMedium - ;call .free - jmp .free -; ret -.eject: - call .reserve - call clear_CD_cache - call allow_medium_removal - call EjectMedium -; call .free - jmp .free -; ret -.audio: - call sys_cd_audio - mov [esp+36-4],eax -.ret: - ret - -.reserve: - call reserve_cd - mov eax, ecx - shr eax, 1 - and eax, 1 - inc eax - mov [ChannelNumber], ax - mov eax, ecx - and eax, 1 - mov [DiskNumber], al - call reserve_cd_channel - and ebx, 3 - inc ebx - mov [cdpos], ebx - add ebx, ebx - mov cl, 8 - sub cl, bl - mov al, [DRIVE_DATA+1] - shr al, cl - test al, 2 - jz .free;.err - ret -.free: - call free_cd_channel - and [cd_status], 0 - ret -.err: - call .free -; pop eax - ret - -align 4 - -syscall_getpixel: ; GetPixel - mov ecx, [Screen_Max_X] - inc ecx - xor edx, edx - mov eax, ebx - div ecx - mov ebx, edx - xchg eax, ebx - call dword [GETPIXEL] ; eax - x, ebx - y - mov [esp + 32], ecx - ret - -align 4 - -syscall_getarea: -;eax = 36 -;ebx = pointer to bufer for img BBGGRRBBGGRR... -;ecx = [size x]*65536 + [size y] -;edx = [start x]*65536 + [start y] - pushad - inc [mouse_pause] -; Check of use of the hardware cursor. - cmp [_display.disable_mouse],__sys_disable_mouse - jne @f -; Since the test for the coordinates of the mouse should not be used, -; then use the call [disable_mouse] is not possible! - cmp dword [MOUSE_VISIBLE],dword 0 - jne @f - pushf - cli - call draw_mouse_under - popf - mov [MOUSE_VISIBLE],dword 1 -@@: - mov edi,ebx - mov eax,edx - shr eax,16 - mov ebx,edx - and ebx,0xffff - dec eax - dec ebx - ; eax - x, ebx - y - mov edx,ecx - - shr ecx,16 - and edx,0xffff - mov esi,ecx - ; ecx - size x, edx - size y - - mov ebp,edx - dec ebp - lea ebp,[ebp*3] - - imul ebp,esi - - mov esi,ecx - dec esi - lea esi,[esi*3] - - add ebp,esi - add ebp,edi - - add ebx,edx - -.start_y: - push ecx edx -.start_x: - push eax ebx ecx - add eax,ecx - - call dword [GETPIXEL] ; eax - x, ebx - y - - mov [ebp],cx - shr ecx,16 - mov [ebp+2],cl - - pop ecx ebx eax - sub ebp,3 - dec ecx - jnz .start_x - pop edx ecx - dec ebx - dec edx - jnz .start_y - dec [mouse_pause] -; Check of use of the hardware cursor. - cmp [_display.disable_mouse],__sys_disable_mouse - jne @f - call [draw_pointer] -@@: - popad - ret - -align 4 - -syscall_drawline: ; DrawLine - - mov edi, [TASK_BASE] - movzx eax, word[edi-twdw+WDATA.box.left] - mov ebp, eax - mov esi, [current_slot] - add ebp, [esi+APPDATA.wnd_clientbox.left] - add ax, word[esi+APPDATA.wnd_clientbox.left] - add ebp,ebx - shl eax, 16 - movzx ebx, word[edi-twdw+WDATA.box.top] - add eax, ebp - mov ebp, ebx - add ebp, [esi+APPDATA.wnd_clientbox.top] - add bx, word[esi+APPDATA.wnd_clientbox.top] - add ebp, ecx - shl ebx, 16 - xor edi, edi - add ebx, ebp - mov ecx, edx - jmp [draw_line] - - - -align 4 -syscall_reserveportarea: ; ReservePortArea and FreePortArea - - call r_f_port_area - mov [esp+32],eax - ret - -align 4 -syscall_threads: ; CreateThreads -; eax=1 create thread -; -; ebx=thread start -; ecx=thread stack value -; -; on return : eax = pid - - call new_sys_threads - - mov [esp+32],eax - ret - -align 4 - -stack_driver_stat: - - call app_stack_handler ; Stack status - -; mov [check_idle_semaphore],5 ; enable these for zero delay -; call change_task ; between sent packet - - mov [esp+32],eax - ret - -align 4 - -socket: ; Socket interface - call app_socket_handler - -; mov [check_idle_semaphore],5 ; enable these for zero delay -; call change_task ; between sent packet - - mov [esp+36],eax - mov [esp+24],ebx - ret - -align 4 - -read_from_hd: ; Read from hd - fn not in use - - mov edi,[TASK_BASE] - add edi,TASKDATA.mem_start - add eax,[edi] - add ecx,[edi] - add edx,[edi] - call file_read - - mov [esp+36],eax - mov [esp+24],ebx - - ret - -paleholder: - ret - -align 4 -set_screen: - cmp eax, [Screen_Max_X] - jne .set - - cmp edx, [Screen_Max_Y] - jne .set - ret -.set: - pushfd - cli - - mov [Screen_Max_X], eax - mov [Screen_Max_Y], edx - mov [BytesPerScanLine], ecx - - mov [screen_workarea.right],eax - mov [screen_workarea.bottom], edx - - push ebx - push esi - push edi - - pushad - - stdcall kernel_free, [_WinMapAddress] - - mov eax, [_display.width] - mul [_display.height] - mov [_WinMapSize], eax - - stdcall kernel_alloc, eax - mov [_WinMapAddress], eax - test eax, eax - jz .epic_fail - - popad - - call repos_windows - xor eax, eax - xor ebx, ebx - mov ecx, [Screen_Max_X] - mov edx, [Screen_Max_Y] - call calculatescreen - pop edi - pop esi - pop ebx - - popfd - ret - -.epic_fail: - hlt ; Houston, we've had a problem - -; --------------- APM --------------------- -uglobal -apm_entry dp 0 -apm_vf dd 0 -endg - -align 4 -sys_apm: - xor eax,eax - cmp word [apm_vf], ax ; Check APM BIOS enable - jne @f - inc eax - or dword [esp + 44], eax ; error - add eax,7 - mov dword [esp + 32], eax ; 32-bit protected-mode interface not supported - ret - -@@: -; xchg eax, ecx -; xchg ebx, ecx - - cmp dx, 3 - ja @f - and [esp + 44], byte 0xfe ; emulate func 0..3 as func 0 - mov eax,[apm_vf] - mov [esp + 32], eax - shr eax, 16 - mov [esp + 28], eax - ret - -@@: - - mov esi,[master_tab+(OS_BASE shr 20)] - xchg [master_tab], esi - push esi - mov edi, cr3 - mov cr3, edi ;flush TLB - - call pword [apm_entry] ;call APM BIOS - - xchg eax, [esp] - mov [master_tab], eax - mov eax, cr3 - mov cr3, eax - pop eax - - mov [esp + 4 ], edi - mov [esp + 8], esi - mov [esp + 20], ebx - mov [esp + 24], edx - mov [esp + 28], ecx - mov [esp + 32], eax - setc al - and [esp + 44], byte 0xfe - or [esp + 44], al - ret -; ----------------------------------------- - -align 4 - -undefined_syscall: ; Undefined system call - mov [esp + 32], dword -1 - ret - -align 4 -system_shutdown: ; shut down the system - - cmp byte [BOOT_VAR+0x9030], 1 - jne @F - ret -@@: - call stop_all_services - push 3 ; stop playing cd - pop eax - call sys_cd_audio - -yes_shutdown_param: - cli - -if ~ defined extended_primary_loader - mov eax, kernel_file ; load kernel.mnt to 0x7000:0 - push 12 - pop esi - xor ebx,ebx - or ecx,-1 - mov edx, OS_BASE+0x70000 - call fileread - - mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0 - mov edi,OS_BASE+0x40000 - mov ecx,1000 - rep movsb -end if - - mov esi, BOOT_VAR ; restore 0x0 - 0xffff - mov edi, OS_BASE - mov ecx,0x10000/4 - cld - rep movsd - - call restorefatchain - - call IRQ_mask_all - -if 0 - mov word [OS_BASE+0x467+0],pr_mode_exit - mov word [OS_BASE+0x467+2],0x1000 - - mov al,0x0F - out 0x70,al - mov al,0x05 - out 0x71,al - - mov al,0xFE - out 0x64,al - - hlt - jmp $-1 - -else - cmp byte [OS_BASE + 0x9030], 2 - jnz no_acpi_power_off - -; scan for RSDP -; 1) The first 1 Kb of the Extended BIOS Data Area (EBDA). - movzx eax, word [OS_BASE + 0x40E] - shl eax, 4 - jz @f - mov ecx, 1024/16 - call scan_rsdp - jnc .rsdp_found -@@: -; 2) The BIOS read-only memory space between 0E0000h and 0FFFFFh. - mov eax, 0xE0000 - mov ecx, 0x2000 - call scan_rsdp - jc no_acpi_power_off -.rsdp_found: - mov esi, [eax+16] ; esi contains physical address of the RSDT - mov ebp, [ipc_tmp] - stdcall map_page, ebp, esi, PG_MAP - lea eax, [esi+1000h] - lea edx, [ebp+1000h] - stdcall map_page, edx, eax, PG_MAP - and esi, 0xFFF - add esi, ebp - cmp dword [esi], 'RSDT' - jnz no_acpi_power_off - mov ecx, [esi+4] - sub ecx, 24h - jbe no_acpi_power_off - shr ecx, 2 - add esi, 24h -.scan_fadt: - lodsd - mov ebx, eax - lea eax, [ebp+2000h] - stdcall map_page, eax, ebx, PG_MAP - lea eax, [ebp+3000h] - add ebx, 0x1000 - stdcall map_page, eax, ebx, PG_MAP - and ebx, 0xFFF - lea ebx, [ebx+ebp+2000h] - cmp dword [ebx], 'FACP' - jz .fadt_found - loop .scan_fadt - jmp no_acpi_power_off -.fadt_found: -; ebx is linear address of FADT - mov edi, [ebx+40] ; physical address of the DSDT - lea eax, [ebp+4000h] - stdcall map_page, eax, edi, PG_MAP - lea eax, [ebp+5000h] - lea esi, [edi+0x1000] - stdcall map_page, eax, esi, PG_MAP - and esi, 0xFFF - sub edi, esi - cmp dword [esi+ebp+4000h], 'DSDT' - jnz no_acpi_power_off - mov eax, [esi+ebp+4004h] ; DSDT length - sub eax, 36+4 - jbe no_acpi_power_off - add esi, 36 -.scan_dsdt: - cmp dword [esi+ebp+4000h], '_S5_' - jnz .scan_dsdt_cont - cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode - jnz .scan_dsdt_cont - mov dl, [esi+ebp+4000h+6] - cmp dl, 4 ; _S5_ package must contain 4 bytes - ; ...in theory; in practice, VirtualBox has 2 bytes - ja .scan_dsdt_cont - cmp dl, 1 - jb .scan_dsdt_cont - lea esi, [esi+ebp+4000h+7] - xor ecx, ecx - cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx - jz @f - cmp byte [esi], 0xA - jnz no_acpi_power_off - inc esi - mov cl, [esi] -@@: - inc esi - cmp dl, 2 - jb @f - cmp byte [esi], 0 - jz @f - cmp byte [esi], 0xA - jnz no_acpi_power_off - inc esi - mov ch, [esi] -@@: - jmp do_acpi_power_off -.scan_dsdt_cont: - inc esi - cmp esi, 0x1000 - jb @f - sub esi, 0x1000 - add edi, 0x1000 - push eax - lea eax, [ebp+4000h] - stdcall map_page, eax, edi, PG_MAP - push PG_MAP - lea eax, [edi+1000h] - push eax - lea eax, [ebp+5000h] - push eax - stdcall map_page - pop eax -@@: - dec eax - jnz .scan_dsdt - jmp no_acpi_power_off -do_acpi_power_off: - mov edx, [ebx+48] - test edx, edx - jz .nosmi - mov al, [ebx+52] - out dx, al - mov edx, [ebx+64] -@@: - in ax, dx - test al, 1 - jz @b -.nosmi: - and cx, 0x0707 - shl cx, 2 - or cx, 0x2020 - mov edx, [ebx+64] - in ax, dx - and ax, 203h - or ah, cl - out dx, ax - mov edx, [ebx+68] - test edx, edx - jz @f - in ax, dx - and ax, 203h - or ah, ch - out dx, ax -@@: - jmp $ - - -no_acpi_power_off: - mov word [OS_BASE+0x467+0],pr_mode_exit - mov word [OS_BASE+0x467+2],0x1000 - - mov al,0x0F - out 0x70,al - mov al,0x05 - out 0x71,al - - mov al,0xFE - out 0x64,al - - hlt - jmp $-1 - -scan_rsdp: - add eax, OS_BASE -.s: - cmp dword [eax], 'RSD ' - jnz .n - cmp dword [eax+4], 'PTR ' - jnz .n - xor edx, edx - xor esi, esi -@@: - add dl, [eax+esi] - inc esi - cmp esi, 20 - jnz @b - test dl, dl - jz .ok -.n: - add eax, 10h - loop .s - stc -.ok: - ret -end if - -include "data32.inc" - -__REV__ = __REV - -uglobals_size = $ - endofcode -diff16 "end of kernel code",0,$ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. +;; PROGRAMMING: +;; Ivan Poddubny +;; Marat Zakiyanov (Mario79) +;; VaStaNi +;; Trans +;; Mihail Semenyako (mike.dld) +;; Sergey Kuzmin (Wildwest) +;; Andrey Halyavin (halyavin) +;; Mihail Lisovin (Mihasik) +;; Andrey Ignatiev (andrew_programmer) +;; NoName +;; Evgeny Grechnikov (Diamond) +;; Iliya Mihailov (Ghost) +;; Sergey Semyonov (Serge) +;; Johnny_B +;; SPraid (simba) +;; Hidnplayr +;; Alexey Teplov () +;; Rus +;; Nable +;; shurf +;; Alver +;; Maxis +;; Galkov +;; CleverMouse +;; tsdima +;; turbanoff +;; Asper +;; art_zh +;; +;; Data in this file was originally part of MenuetOS project which is +;; distributed under the terms of GNU GPL. It is modified and redistributed as +;; part of KolibriOS project under the terms of GNU GPL. +;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa +;; PROGRAMMING: +;; +;; Ville Mikael Turjanmaa, villemt@itu.jyu.fi +;; - main os coding/design +;; Jan-Michael Brummer, BUZZ2@gmx.de +;; Felix Kaiser, info@felix-kaiser.de +;; Paolo Minazzi, paolo.minazzi@inwind.it +;; quickcode@mail.ru +;; Alexey, kgaz@crosswinds.net +;; Juan M. Caravaca, bitrider@wanadoo.es +;; kristol@nic.fi +;; Mike Hibbett, mikeh@oceanfree.net +;; Lasse Kuusijarvi, kuusijar@lut.fi +;; Jarek Pelczar, jarekp3@wp.pl +;; +;; KolibriOS is distributed in the hope that it will be useful, but WITHOUT ANY +;; WARRANTY. No author or distributor accepts responsibility to anyone for the +;; consequences of using it or for whether it serves any particular purpose or +;; works at all, unless he says so in writing. Refer to the GNU General Public +;; License (the "GPL") for full details. +; +;; Everyone is granted permission to copy, modify and redistribute KolibriOS, +;; but only under the conditions described in the GPL. A copy of this license +;; is supposed to have been given to you along with KolibriOS so you can know +;; your rights and responsibilities. It should be in a file named COPYING. +;; Among other things, the copyright notice and this notice must be preserved +;; on all copies. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +include 'macros.inc' + +$Revision$ + + +USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices + +; Enabling the next line will enable serial output console +;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used + +include "proc32.inc" +include "kglobals.inc" +include "lang.inc" + +include "const.inc" +max_processes equ 255 +tss_step equ (128+8192) ; tss & i/o - 65535 ports, * 256=557056*4 + + +os_stack equ (os_data_l-gdts) ; GDTs +os_code equ (os_code_l-gdts) +graph_data equ (3+graph_data_l-gdts) +tss0 equ (tss0_l-gdts) +app_code equ (3+app_code_l-gdts) +app_data equ (3+app_data_l-gdts) +app_tls equ (3+tls_data_l-gdts) +pci_code_sel equ (pci_code_32-gdts) +pci_data_sel equ (pci_data_32-gdts) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; Included files: +;; +;; Kernel16.inc +;; - Booteng.inc English text for bootup +;; - Bootcode.inc Hardware setup +;; - Pci16.inc PCI functions +;; +;; Kernel32.inc +;; - Sys32.inc Process management +;; - Shutdown.inc Shutdown and restart +;; - Fat32.inc Read / write hd +;; - Vesa12.inc Vesa 1.2 driver +;; - Vesa20.inc Vesa 2.0 driver +;; - Vga.inc VGA driver +;; - Stack.inc Network interface +;; - Mouse.inc Mouse pointer +;; - Scincode.inc Window skinning +;; - Pci32.inc PCI functions +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; 16 BIT ENTRY FROM BOOTSECTOR ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +use16 + org 0x0 + jmp start_of_code + +version db 'Kolibri OS version 0.7.7.0+ ',13,10,13,10,0 + +include "boot/bootstr.inc" ; language-independent boot messages +include "boot/preboot.inc" + +if lang eq en +include "boot/booteng.inc" ; english system boot messages +else if lang eq ru +include "boot/bootru.inc" ; russian system boot messages +include "boot/ru.inc" ; Russian font +else if lang eq et +include "boot/bootet.inc" ; estonian system boot messages +include "boot/et.inc" ; Estonian font +else +include "boot/bootge.inc" ; german system boot messages +end if + +include "boot/bootcode.inc" ; 16 bit system boot code +include "bus/pci/pci16.inc" +include "detect/biosdisk.inc" + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; SWITCH TO 32 BIT PROTECTED MODE ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; CR0 Flags - Protected mode and Paging + + mov ecx, CR0_PE + +; Enabling 32 bit protected mode + + sidt [cs:old_ints_h] + + cli ; disable all irqs + cld + mov al, 255 ; mask all irqs + out 0xa1, al + out 0x21, al + l.5: + in al, 0x64 ; Enable A20 + test al, 2 + jnz l.5 + mov al, 0xD1 + out 0x64, al + l.6: + in al, 0x64 + test al, 2 + jnz l.6 + mov al, 0xDF + out 0x60, al + l.7: + in al, 0x64 + test al, 2 + jnz l.7 + mov al, 0xFF + out 0x64, al + + lgdt [cs:tmp_gdt] ; Load GDT + mov eax, cr0 ; protected mode + or eax, ecx + and eax, 10011111b *65536*256 + 0xffffff ; caching enabled + mov cr0, eax + jmp pword os_code:B32 ; jmp to enable 32 bit mode + +align 8 +tmp_gdt: + + dw 23 + dd tmp_gdt+0x10000 + dw 0 + + dw 0xffff + dw 0x0000 + db 0x00 + dw 11011111b *256 +10011010b + db 0x00 + + dw 0xffff + dw 0x0000 + db 0x00 + dw 11011111b *256 +10010010b + db 0x00 + +include "data16.inc" + +use32 +org $+0x10000 + +align 4 +B32: + mov ax, os_stack ; Selector for os + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov esp, 0x006CC00 ; Set stack + +; CLEAR 0x280000 - HEAP_BASE + + xor eax, eax + mov edi, CLEAN_ZONE + mov ecx, (HEAP_BASE-OS_BASE-CLEAN_ZONE) / 4 + cld + rep stosd + +; CLEAR KERNEL UNDEFINED GLOBALS + mov edi, endofcode-OS_BASE + mov ecx, 0x90000 + sub ecx, edi + shr ecx, 2 + rep stosd + +; SAVE & CLEAR 0-0xffff + + xor esi, esi + mov edi, (BOOT_VAR-OS_BASE) + mov ecx, 0x10000 / 4 + rep movsd + mov edi, 0x1000 + mov ecx, 0xf000 / 4 + rep stosd + + call test_cpu + bts [cpu_caps-OS_BASE], CAPS_TSC ;force use rdtsc + + call check_acpi + call init_BIOS32 +; MEMORY MODEL + call mem_test + call init_mem + call init_page_map + +; ENABLE PAGING + + mov eax, sys_pgdir-OS_BASE + mov cr3, eax + + mov eax, cr0 + or eax, CR0_PG+CR0_WP + mov cr0, eax + + lgdt [gdts] + jmp pword os_code:high_code + +align 4 +bios32_entry dd ? +tmp_page_tabs dd ? + +use16 +org $-0x10000 +include "boot/shutdown.inc" ; shutdown or restart +org $+0x10000 +use32 + +__DEBUG__ fix 1 +__DEBUG_LEVEL__ fix 1 +include 'init.inc' + +org OS_BASE+$ + +align 4 +high_code: + mov ax, os_stack + mov bx, app_data + mov cx, app_tls + mov ss, ax + add esp, OS_BASE + + mov ds, bx + mov es, bx + mov fs, cx + mov gs, bx + + bt [cpu_caps], CAPS_PGE + jnc @F + + or dword [sys_pgdir+(OS_BASE shr 20)], PG_GLOBAL + + mov ebx, cr4 + or ebx, CR4_PGE + mov cr4, ebx +@@: + xor eax, eax + mov dword [sys_pgdir], eax + mov dword [sys_pgdir+4], eax + + mov eax, cr3 + mov cr3, eax ; flush TLB + + mov ecx, pg_data.mutex + call mutex_init + + mov ecx, disk_list_mutex + call mutex_init + +; SAVE REAL MODE VARIABLES + mov ax, [BOOT_VAR + 0x9031] + mov [IDEContrRegsBaseAddr], ax +; --------------- APM --------------------- + +; init selectors + mov ebx, [BOOT_VAR+0x9040] ; offset of APM entry point + movzx eax, word [BOOT_VAR+0x9050]; real-mode segment base address of + ; protected-mode 32-bit code segment + movzx ecx, word [BOOT_VAR+0x9052]; real-mode segment base address of + ; protected-mode 16-bit code segment + movzx edx, word [BOOT_VAR+0x9054]; real-mode segment base address of + ; protected-mode 16-bit data segment + + shl eax, 4 + mov [dword apm_code_32 + 2], ax + shr eax, 16 + mov [dword apm_code_32 + 4], al + + shl ecx, 4 + mov [dword apm_code_16 + 2], cx + shr ecx, 16 + mov [dword apm_code_16 + 4], cl + + shl edx, 4 + mov [dword apm_data_16 + 2], dx + shr edx, 16 + mov [dword apm_data_16 + 4], dl + + mov dword[apm_entry], ebx + mov word [apm_entry + 4], apm_code_32 - gdts + + mov eax, [BOOT_VAR + 0x9044]; version & flags + mov [apm_vf], eax +; ----------------------------------------- +; movzx eax,byte [BOOT_VAR+0x9010] ; mouse port +; mov [0xF604],byte 1 ;al + mov al, [BOOT_VAR+0x901F] ; DMA access + mov [allow_dma_access], al + movzx eax, byte [BOOT_VAR+0x9000] ; bpp + mov [ScreenBPP], al + + mov [_display.bpp], eax + mov [_display.vrefresh], 60 + mov [_display.disable_mouse], __sys_disable_mouse + + movzx eax, word [BOOT_VAR+0x900A]; X max + mov [_display.width], eax + dec eax + mov [Screen_Max_X], eax + mov [screen_workarea.right], eax + movzx eax, word [BOOT_VAR+0x900C]; Y max + mov [_display.height], eax + dec eax + mov [Screen_Max_Y], eax + mov [screen_workarea.bottom], eax + movzx eax, word [BOOT_VAR+0x9008]; screen mode + mov [SCR_MODE], eax + mov eax, [BOOT_VAR+0x9014] ; Vesa 1.2 bnk sw add + mov [BANK_SWITCH], eax + mov [BytesPerScanLine], word 640*4 ; Bytes PerScanLine + cmp [SCR_MODE], word 0x13 ; 320x200 + je @f + cmp [SCR_MODE], word 0x12 ; VGA 640x480 + je @f + movzx eax, word[BOOT_VAR+0x9001] ; for other modes + mov [BytesPerScanLine], ax + mov [_display.pitch], eax +@@: + mov eax, [_display.width] + mul [_display.height] + mov [_WinMapSize], eax + + mov esi, BOOT_VAR+0x9080 + movzx ecx, byte [esi-1] + mov [NumBiosDisks], ecx + mov edi, BiosDisksData + rep movsd + +; GRAPHICS ADDRESSES + + and byte [BOOT_VAR+0x901e], 0x0 + mov eax, [BOOT_VAR+0x9018] + mov [LFBAddress], eax + + cmp [SCR_MODE], word 0100000000000000b + jge setvesa20 + cmp [SCR_MODE], word 0x13 + je v20ga32 + mov [PUTPIXEL], dword Vesa12_putpixel24 ; Vesa 1.2 + mov [GETPIXEL], dword Vesa12_getpixel24 + cmp [ScreenBPP], byte 24 + jz ga24 + mov [PUTPIXEL], dword Vesa12_putpixel32 + mov [GETPIXEL], dword Vesa12_getpixel32 + ga24: + jmp v20ga24 + setvesa20: + mov [PUTPIXEL], dword Vesa20_putpixel24 ; Vesa 2.0 + mov [GETPIXEL], dword Vesa20_getpixel24 + cmp [ScreenBPP], byte 24 + jz v20ga24 + v20ga32: + mov [PUTPIXEL], dword Vesa20_putpixel32 + mov [GETPIXEL], dword Vesa20_getpixel32 + v20ga24: + cmp [SCR_MODE], word 0x12 ; 16 C VGA 640x480 + jne no_mode_0x12 + mov [PUTPIXEL], dword VGA_putpixel + mov [GETPIXEL], dword Vesa20_getpixel32 + no_mode_0x12: + +; -------- Fast System Call init ---------- +; Intel SYSENTER/SYSEXIT (AMD CPU support it too) + bt [cpu_caps], CAPS_SEP + jnc .SEnP ; SysEnter not Present + xor edx, edx + mov ecx, MSR_SYSENTER_CS + mov eax, os_code + wrmsr + mov ecx, MSR_SYSENTER_ESP +; mov eax, sysenter_stack ; Check it + xor eax, eax + wrmsr + mov ecx, MSR_SYSENTER_EIP + mov eax, sysenter_entry + wrmsr +.SEnP: +; AMD SYSCALL/SYSRET + cmp byte[cpu_vendor], 'A' + jne .noSYSCALL + mov eax, 0x80000001 + cpuid + test edx, 0x800 ; bit_11 - SYSCALL/SYSRET support + jz .noSYSCALL + mov ecx, MSR_AMD_EFER + rdmsr + or eax, 1 ; bit_0 - System Call Extension (SCE) + wrmsr + + ; !!!! It`s dirty hack, fix it !!! + ; Bits of EDX : + ; Bit 31–16 During the SYSRET instruction, this field is copied into the CS register + ; and the contents of this field, plus 8, are copied into the SS register. + ; Bit 15–0 During the SYSCALL instruction, this field is copied into the CS register + ; and the contents of this field, plus 8, are copied into the SS register. + + ; mov edx, (os_code + 16) * 65536 + os_code + mov edx, 0x1B0008 + + mov eax, syscall_entry + mov ecx, MSR_AMD_STAR + wrmsr +.noSYSCALL: +; ----------------------------------------- + stdcall alloc_page + stdcall map_page, tss-0xF80, eax, PG_SW + stdcall alloc_page + inc eax + mov [SLOT_BASE+256+APPDATA.io_map], eax + stdcall map_page, tss+0x80, eax, PG_SW + stdcall alloc_page + inc eax + mov dword [SLOT_BASE+256+APPDATA.io_map+4], eax + stdcall map_page, tss+0x1080, eax, PG_SW + +; LOAD IDT + + call build_interrupt_table ;lidt is executed + ;lidt [idtreg] + + call init_kernel_heap + stdcall kernel_alloc, RING0_STACK_SIZE+512 + mov [os_stack_seg], eax + + lea esp, [eax+RING0_STACK_SIZE] + + mov [tss._ss0], os_stack + mov [tss._esp0], esp + mov [tss._esp], esp + mov [tss._cs], os_code + mov [tss._ss], os_stack + mov [tss._ds], app_data + mov [tss._es], app_data + mov [tss._fs], app_data + mov [tss._gs], app_data + mov [tss._io], 128 +;Add IO access table - bit array of permitted ports + mov edi, tss._io_map_0 + xor eax, eax + not eax + mov ecx, 8192/4 + rep stosd ; access to 4096*8=65536 ports + + mov ax, tss0 + ltr ax + + mov [LFBSize], 0x800000 + call init_LFB + call init_fpu + call init_malloc + + stdcall alloc_kernel_space, 0x51000 + mov [default_io_map], eax + + add eax, 0x2000 + mov [ipc_tmp], eax + mov ebx, 0x1000 + + add eax, 0x40000 + mov [proc_mem_map], eax + + add eax, 0x8000 + mov [proc_mem_pdir], eax + + add eax, ebx + mov [proc_mem_tab], eax + + add eax, ebx + mov [tmp_task_pdir], eax + + add eax, ebx + mov [tmp_task_ptab], eax + + add eax, ebx + mov [ipc_pdir], eax + + add eax, ebx + mov [ipc_ptab], eax + + stdcall kernel_alloc, (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl \ + (unpack.lc+unpack.lp)))*4 + + mov [unpack.p], eax + + call init_events + mov eax, srv.fd-SRV_FD_OFFSET + mov [srv.fd], eax + mov [srv.bk], eax + +;Set base of graphic segment to linear address of LFB + mov eax, [LFBAddress] ; set for gs + mov [graph_data_l+2], ax + shr eax, 16 + mov [graph_data_l+4], al + mov [graph_data_l+7], ah + + stdcall kernel_alloc, [_WinMapSize] + mov [_WinMapAddress], eax + + xor eax, eax + inc eax + mov [CURRENT_TASK], eax ;dword 1 + mov [TASK_COUNT], eax ;dword 1 + mov [TASK_BASE], dword TASK_DATA + mov [current_slot], SLOT_BASE+256 + +; set background + + mov [BgrDrawMode], eax + mov [BgrDataWidth], eax + mov [BgrDataHeight], eax + mov [mem_BACKGROUND], 4 + mov [img_background], static_background_data + + mov [SLOT_BASE + 256 + APPDATA.dir_table], sys_pgdir - OS_BASE + + stdcall kernel_alloc, 0x10000/8 + mov edi, eax + mov [network_free_ports], eax + or eax, -1 + mov ecx, 0x10000/32 + rep stosd + +; REDIRECT ALL IRQ'S TO INT'S 0x20-0x2f + + call init_irqs + call PIC_init + +; Initialize system V86 machine + call init_sys_v86 + +; Initialize system timer (IRQ0) + call PIT_init + +; Try to Initialize APIC + call APIC_init + +; Enable timer IRQ (IRQ0) and hard drives IRQs (IRQ14, IRQ15) +; they are used: when partitions are scanned, hd_read relies on timer + call unmask_timer + stdcall enable_irq, 2 ; @#$%! PIC + stdcall enable_irq, 6 ; FDD + stdcall enable_irq, 13 ; co-processor + stdcall enable_irq, 14 + stdcall enable_irq, 15 + +; Enable interrupts in IDE controller + mov al, 0 + mov dx, 0x3F6 + out dx, al + mov dl, 0x76 + out dx, al + +;!!!!!!!!!!!!!!!!!!!!!!!!!! +include 'detect/disks.inc' +;!!!!!!!!!!!!!!!!!!!!!!!!!! + + call Parser_params + +if ~ defined extended_primary_loader +; ramdisk image should be loaded by extended primary loader if it exists +; READ RAMDISK IMAGE FROM HD + +;!!!!!!!!!!!!!!!!!!!!!!! +include 'boot/rdload.inc' +;!!!!!!!!!!!!!!!!!!!!!!! +end if +; mov [dma_hdd],1 +; CALCULATE FAT CHAIN FOR RAMDISK + + call calculatefatchain + +if 0 + mov ax, [OS_BASE+0x10000+bx_from_load] + cmp ax, 'r1'; if using not ram disk, then load librares and parameters {SPraid.simba} + je no_lib_load +; LOADING LIBRARES + stdcall dll.Load, @IMPORT ; loading librares for kernel (.obj files) + call load_file_parse_table ; prepare file parse table + call set_kernel_conf ; configure devices and gui +no_lib_load: +end if + +; LOAD FONTS I and II + + stdcall read_file, char, FONT_I, 0, 2304 + stdcall read_file, char2, FONT_II, 0, 2560 + + mov esi, boot_fonts + call boot_log + +; Display APIC status + mov esi, boot_APIC_found + cmp [irq_mode], IRQ_APIC + je @f + mov esi, boot_APIC_nfound +@@: + +; PRINT AMOUNT OF MEMORY + mov esi, boot_memdetect + call boot_log + + movzx ecx, word [boot_y] + if lang eq ru + or ecx, (10+30*6) shl 16 + else + or ecx, (10+29*6) shl 16 + end if + sub ecx, 10 + mov edx, 0xFFFFFF + mov ebx, [MEM_AMOUNT] + shr ebx, 20 + xor edi, edi + mov eax, 0x00040000 + inc edi + call display_number_force + +; BUILD SCHEDULER + + call build_scheduler; sys32.inc + + mov esi, boot_devices + call boot_log + + mov [pci_access_enabled], 1 + + +; SET PRELIMINARY WINDOW STACK AND POSITIONS + + mov esi, boot_windefs + call boot_log + call set_window_defaults + +; SET BACKGROUND DEFAULTS + + mov esi, boot_bgr + call boot_log + call init_background + call calculatebackground + +; RESERVE SYSTEM IRQ'S JA PORT'S + + mov esi, boot_resirqports + call boot_log + call reserve_irqs_ports + +; SET UP OS TASK + + mov esi, boot_setostask + call boot_log + + xor eax, eax + mov dword [SLOT_BASE+APPDATA.fpu_state], fpu_data + mov dword [SLOT_BASE+APPDATA.exc_handler], eax + mov dword [SLOT_BASE+APPDATA.except_mask], eax + + ; name for OS/IDLE process + + mov dword [SLOT_BASE+256+APPDATA.app_name], dword 'OS/I' + mov dword [SLOT_BASE+256+APPDATA.app_name+4], dword 'DLE ' + mov edi, [os_stack_seg] + mov dword [SLOT_BASE+256+APPDATA.pl0_stack], edi + add edi, 0x2000-512 + mov dword [SLOT_BASE+256+APPDATA.fpu_state], edi + mov dword [SLOT_BASE+256+APPDATA.saved_esp0], edi; just for case + ; [SLOT_BASE+256+APPDATA.io_map] was set earlier + + mov esi, fpu_data + mov ecx, 512/4 + cld + rep movsd + + mov dword [SLOT_BASE+256+APPDATA.exc_handler], eax + mov dword [SLOT_BASE+256+APPDATA.except_mask], eax + + mov ebx, SLOT_BASE+256+APP_OBJ_OFFSET + mov dword [SLOT_BASE+256+APPDATA.fd_obj], ebx + mov dword [SLOT_BASE+256+APPDATA.bk_obj], ebx + + mov dword [SLOT_BASE+256+APPDATA.cur_dir], sysdir_path + mov dword [SLOT_BASE+256+APPDATA.tls_base], eax + + ; task list + mov dword [TASK_DATA+TASKDATA.mem_start], eax; process base address + inc eax + mov dword [CURRENT_TASK], eax + mov dword [TASK_COUNT], eax + mov [current_slot], SLOT_BASE+256 + mov [TASK_BASE], dword TASK_DATA + mov byte[TASK_DATA+TASKDATA.wnd_number], al ; on screen number + mov dword [TASK_DATA+TASKDATA.pid], eax ; process id number + + call init_display + mov eax, [def_cursor] + mov [SLOT_BASE+APPDATA.cursor], eax + mov [SLOT_BASE+APPDATA.cursor+256], eax + + ; READ TSC / SECOND + + mov esi, boot_tsc + call boot_log + cli + rdtsc ;call _rdtsc + mov ecx, eax + mov esi, 250 ; wait 1/4 a second + call delay_ms + rdtsc ;call _rdtsc + sti + sub eax, ecx + shl eax, 2 + mov [CPU_FREQ], eax ; save tsc / sec +; mov ebx, 1000000 +; div ebx +; ў®®ЎйҐ-в® Їа®Ё§ў®¤ЁвҐ«м­®бвм ў ¤ ­­®¬ Є®­ЄаҐв­®¬ ¬Ґб⥠+; б®ўҐа襭­® ­ҐЄаЁвЁз­ , ­® зв®Ўл § вЄ­гвм «оЎЁвҐ«Ґ© +; ®ЇвЁ¬Ё§ЁагойЁе Є®¬ЇЁ«пв®а®ў џ‚“... + mov edx, 2251799814 + mul edx + shr edx, 19 + mov [stall_mcs], edx +; PRINT CPU FREQUENCY + mov esi, boot_cpufreq + call boot_log + + mov ebx, edx + movzx ecx, word [boot_y] + if lang eq ru + add ecx, (10+19*6) shl 16 - 10 ; 'Determining amount of memory' + else + add ecx, (10+17*6) shl 16 - 10 ; 'Determining amount of memory' + end if + mov edx, 0xFFFFFF + xor edi, edi + mov eax, 0x00040000 + inc edi + call display_number_force + +; SET VARIABLES + + call set_variables + +; STACK AND FDC + + call stack_init + call fdc_init + +; PALETTE FOR 320x200 and 640x480 16 col + + cmp [SCR_MODE], word 0x12 + jne no_pal_vga + mov esi, boot_pal_vga + call boot_log + call paletteVGA + no_pal_vga: + + cmp [SCR_MODE], word 0x13 + jne no_pal_ega + mov esi, boot_pal_ega + call boot_log + call palette320x200 + no_pal_ega: + +; LOAD DEFAULT SKIN + + call load_default_skin + +;protect io permission map + + mov esi, [default_io_map] + stdcall map_page, esi, [SLOT_BASE+256+APPDATA.io_map], PG_MAP + add esi, 0x1000 + stdcall map_page, esi, [SLOT_BASE+256+APPDATA.io_map+4], PG_MAP + + stdcall map_page, tss._io_map_0, \ + [SLOT_BASE+256+APPDATA.io_map], PG_MAP + stdcall map_page, tss._io_map_1, \ + [SLOT_BASE+256+APPDATA.io_map+4], PG_MAP + + mov ax, [OS_BASE+0x10000+bx_from_load] + cmp ax, 'r1'; if not rused ram disk - load network configuration from files {SPraid.simba} + je no_st_network + call set_network_conf + no_st_network: + +; LOAD FIRST APPLICATION + cli + +; cmp byte [BOOT_VAR+0x9030],1 +; jne no_load_vrr_m + +; mov ebp, vrr_m +; call fs_execute_from_sysdir +; +;; cmp eax,2 ; if vrr_m app found (PID=2) +; sub eax,2 +; jz first_app_found +; +;no_load_vrr_m: + + mov ebp, firstapp + call fs_execute_from_sysdir + +; cmp eax,2 ; continue if a process has been loaded + sub eax, 2 + jz first_app_found + + mov esi, boot_failed + call boot_log + + mov eax, 0xDEADBEEF ; otherwise halt + hlt + +first_app_found: + + cli + + ;mov [TASK_COUNT],dword 2 + push 1 + pop dword [CURRENT_TASK] ; set OS task fisrt + +; SET KEYBOARD PARAMETERS + mov al, 0xf6 ; reset keyboard, scan enabled + call kb_write + + ; wait until 8042 is ready + xor ecx, ecx + @@: + in al, 64h + and al, 00000010b + loopnz @b + + ; mov al, 0xED ; Keyboard LEDs - only for testing! + ; call kb_write + ; call kb_read + ; mov al, 111b + ; call kb_write + ; call kb_read + + mov al, 0xF3 ; set repeat rate & delay + call kb_write +; call kb_read + mov al, 0; 30 250 ;00100010b ; 24 500 ;00100100b ; 20 500 + call kb_write +; call kb_read + ;// mike.dld [ + call set_lights + ;// mike.dld ] + stdcall attach_int_handler, 1, irq1, 0 + +; SET MOUSE + + stdcall load_driver, szPS2MDriver +; stdcall load_driver, szCOM_MDriver + + mov esi, boot_setmouse + call boot_log + call setmouse + +; Setup serial output console (if enabled) + +if defined debug_com_base + + ; enable Divisor latch + + mov dx, debug_com_base+3 + mov al, 1 shl 7 + out dx, al + + ; Set speed to 115200 baud (max speed) + + mov dx, debug_com_base + mov al, 0x01 + out dx, al + + mov dx, debug_com_base+1 + mov al, 0x00 + out dx, al + + ; No parity, 8bits words, one stop bit, dlab bit back to 0 + + mov dx, debug_com_base+3 + mov al, 3 + out dx, al + + ; disable interrupts + + mov dx, debug_com_base+1 + mov al, 0 + out dx, al + + ; clear + enable fifo (64 bits) + + mov dx, debug_com_base+2 + mov al, 0x7 + 1 shl 5 + out dx, al + + +end if + +; START MULTITASKING + +; A 'All set - press ESC to start' messages if need +if preboot_blogesc + mov esi, boot_tasking + call boot_log +.bll1: + in al, 0x60 ; wait for ESC key press + cmp al, 129 + jne .bll1 +end if + + cmp [IDEContrRegsBaseAddr], 0 + setnz [dma_hdd] + mov [timer_ticks_enable], 1 ; for cd driver + + sti + call change_task + + jmp osloop + + + ; Fly :) + +include 'unpacker.inc' +include 'fdo.inc' + +align 4 +boot_log: + pushad + + mov ebx, 10*65536 + mov bx, word [boot_y] + add [boot_y], dword 10 + mov ecx, 0x80ffffff; ASCIIZ string with white color + xor edi, edi + mov edx, esi + inc edi + call dtext + + mov [novesachecksum], 1000 + call checkVga_N13 + + popad + + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; MAIN OS LOOP START ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +align 32 +osloop: + call [draw_pointer] + call window_check_events + call mouse_check_events + call checkmisc + call checkVga_N13 + call stack_handler + call checkidle + call check_fdd_motor_status + call check_ATAPI_device_event + call check_timers + jmp osloop +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; MAIN OS LOOP END ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +align 4 +checkidle: + pushad + call change_task + jmp idle_loop_entry + idle_loop: + cmp eax, [idlemem] ; eax == [timer_ticks] + jne idle_exit + rdtsc ;call _rdtsc + mov ecx, eax + hlt + rdtsc ;call _rdtsc + sub eax, ecx + add [idleuse], eax + idle_loop_entry: + mov eax, [timer_ticks]; eax = [timer_ticks] + cmp [check_idle_semaphore], 0 + je idle_loop + dec [check_idle_semaphore] + idle_exit: + mov [idlemem], eax ; eax == [timer_ticks] + popad + ret + +uglobal + idlemem dd 0x0 + idleuse dd 0x0 + idleusesec dd 0x0 + check_idle_semaphore dd 0x0 +endg + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; INCLUDED SYSTEM FILES ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +include "kernel32.inc" + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; KERNEL FUNCTIONS ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +reserve_irqs_ports: + + +; RESERVE PORTS + mov eax, RESERVED_PORTS + mov ecx, 1 + + mov [eax], dword 4 + + mov [eax+16], ecx + mov [eax+16+4], dword 0 + mov [eax+16+4], dword 0x2D + + mov [eax+32], ecx + mov [eax+32+4], dword 0x30 + mov [eax+32+8], dword 0x4D + + mov [eax+48], ecx + mov [eax+48+4], dword 0x50 + mov [eax+28+8], dword 0xDF + + mov [eax+64], ecx + mov [eax+64+4], dword 0xE5 + mov [eax+64+8], dword 0xFF + + ret + + +iglobal + process_number dd 0x1 +endg + +set_variables: + + mov ecx, 0x16 ; flush port 0x60 +.fl60: + in al, 0x60 + loop .fl60 + push eax + + mov ax, [BOOT_VAR+0x900c] + shr ax, 1 + shl eax, 16 + mov ax, [BOOT_VAR+0x900A] + shr ax, 1 + mov [MOUSE_X], eax + + xor eax, eax + mov [BTN_ADDR], dword BUTTON_INFO ; address of button list + + mov byte [MOUSE_BUFF_COUNT], al ; mouse buffer + mov byte [KEY_COUNT], al ; keyboard buffer + mov byte [BTN_COUNT], al ; button buffer +; mov [MOUSE_X],dword 100*65536+100 ; mouse x/y + + ;!! IP 04.02.2005: + mov byte [DONT_SWITCH], al; change task if possible + pop eax + ret + +align 4 +;input eax=43,bl-byte of output, ecx - number of port +sys_outport: + + mov edi, ecx ; separate flag for read / write + and ecx, 65535 + + mov eax, [RESERVED_PORTS] + test eax, eax + jnz .sopl8 + inc eax + mov [esp+32], eax + ret + + .sopl8: + mov edx, [TASK_BASE] + mov edx, [edx+0x4] + ;and ecx,65535 + ;cld - set on interrupt 0x40 + .sopl1: + + mov esi, eax + shl esi, 4 + add esi, RESERVED_PORTS + cmp edx, [esi+0] + jne .sopl2 + cmp ecx, [esi+4] + jb .sopl2 + cmp ecx, [esi+8] + jg .sopl2 +.sopl3: + + test edi, 0x80000000; read ? + jnz .sopl4 + + mov eax, ebx + mov dx, cx ; write + out dx, al + and [esp+32], dword 0 + ret + + .sopl2: + + dec eax + jnz .sopl1 + inc eax + mov [esp+32], eax + ret + + + .sopl4: + + mov dx, cx ; read + in al, dx + and eax, 0xff + and [esp+32], dword 0 + mov [esp+20], eax + ret + +display_number: +;It is not optimization + mov eax, ebx + mov ebx, ecx + mov ecx, edx + mov edx, esi + mov esi, edi +; eax = print type, al=0 -> ebx is number +; al=1 -> ebx is pointer +; ah=0 -> display decimal +; ah=1 -> display hexadecimal +; ah=2 -> display binary +; eax bits 16-21 = number of digits to display (0-32) +; eax bits 22-31 = reserved +; +; ebx = number or pointer +; ecx = x shl 16 + y +; edx = color + xor edi, edi +display_number_force: + push eax + and eax, 0x3fffffff + cmp eax, 0xffff ; length > 0 ? + pop eax + jge cont_displ + ret + cont_displ: + push eax + and eax, 0x3fffffff + cmp eax, 61*0x10000 ; length <= 60 ? + pop eax + jb cont_displ2 + ret + cont_displ2: + + pushad + + cmp al, 1 ; ecx is a pointer ? + jne displnl1 + mov ebp, ebx + add ebp, 4 + mov ebp, [ebp+std_application_base_address] + mov ebx, [ebx+std_application_base_address] + displnl1: + sub esp, 64 + + test ah, ah ; DECIMAL + jnz no_display_desnum + shr eax, 16 + and eax, 0xC03f +; and eax,0x3f + push eax + and eax, 0x3f + mov edi, esp + add edi, 4+64-1 + mov ecx, eax + mov eax, ebx + mov ebx, 10 + d_desnum: + xor edx, edx + call division_64_bits + div ebx + add dl, 48 + mov [edi], dl + dec edi + loop d_desnum + pop eax + call normalize_number + call draw_num_text + add esp, 64 + popad + ret + no_display_desnum: + + cmp ah, 0x01 ; HEXADECIMAL + jne no_display_hexnum + shr eax, 16 + and eax, 0xC03f +; and eax,0x3f + push eax + and eax, 0x3f + mov edi, esp + add edi, 4+64-1 + mov ecx, eax + mov eax, ebx + mov ebx, 16 + d_hexnum: + xor edx, edx + call division_64_bits + div ebx + hexletters = __fdo_hexdigits + add edx, hexletters + mov dl, [edx] + mov [edi], dl + dec edi + loop d_hexnum + pop eax + call normalize_number + call draw_num_text + add esp, 64 + popad + ret + no_display_hexnum: + + cmp ah, 0x02 ; BINARY + jne no_display_binnum + shr eax, 16 + and eax, 0xC03f +; and eax,0x3f + push eax + and eax, 0x3f + mov edi, esp + add edi, 4+64-1 + mov ecx, eax + mov eax, ebx + mov ebx, 2 + d_binnum: + xor edx, edx + call division_64_bits + div ebx + add dl, 48 + mov [edi], dl + dec edi + loop d_binnum + pop eax + call normalize_number + call draw_num_text + add esp, 64 + popad + ret + no_display_binnum: + + add esp, 64 + popad + ret + +normalize_number: + test ah, 0x80 + jz .continue + mov ecx, 48 + and eax, 0x3f +@@: + inc edi + cmp [edi], cl + jne .continue + dec eax + cmp eax, 1 + ja @r + mov al, 1 +.continue: + and eax, 0x3f + ret + +division_64_bits: + test [esp+1+4], byte 0x40 + jz .continue + push eax + mov eax, ebp + div ebx + mov ebp, eax + pop eax +.continue: + ret + +draw_num_text: + mov esi, eax + mov edx, 64+4 + sub edx, eax + add edx, esp + mov ebx, [esp+64+32-8+4] +; add window start x & y + mov ecx, [TASK_BASE] + + mov edi, [CURRENT_TASK] + shl edi, 8 + + mov eax, [ecx-twdw+WDATA.box.left] + add eax, [edi+SLOT_BASE+APPDATA.wnd_clientbox.left] + shl eax, 16 + add eax, [ecx-twdw+WDATA.box.top] + add eax, [edi+SLOT_BASE+APPDATA.wnd_clientbox.top] + add ebx, eax + mov ecx, [esp+64+32-12+4] + and ecx, not 0x80000000 ; force counted string + mov eax, [esp+64+8] ; background color (if given) + mov edi, [esp+64+4] + jmp dtext + +align 4 + +sys_setup: + +; 1=roland mpu midi base , base io address +; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus +; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 5=system language, 1eng 2fi 3ger 4rus +; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 8=fat32 partition in hd +; 9 +; 10 = sound dma channel +; 11 = enable lba read +; 12 = enable pci access + + + and [esp+32], dword 0 + dec ebx ; MIDI + jnz nsyse1 + cmp ecx, 0x100 + + jb nsyse1 + mov esi, 65535 + cmp esi, ecx + + jb nsyse1 + mov [midi_base], cx ;bx + mov word [mididp], cx;bx + inc cx ;bx + mov word [midisp], cx;bx + ret + +iglobal +midi_base dw 0 +endg + + nsyse1: + dec ebx ; KEYBOARD + jnz nsyse2 + mov edi, [TASK_BASE] + mov eax, [edi+TASKDATA.mem_start] + add eax, edx + + dec ecx + jnz kbnobase + mov ebx, keymap + mov ecx, 128 + call memmove + ret + kbnobase: + dec ecx + jnz kbnoshift + + mov ebx, keymap_shift + mov ecx, 128 + call memmove + ret + kbnoshift: + dec ecx + jnz kbnoalt + mov ebx, keymap_alt + mov ecx, 128 + call memmove + ret + kbnoalt: + sub ecx, 6 + jnz kbnocountry + mov word [keyboard], dx + ret + kbnocountry: + mov [esp+32], dword 1 + ret + nsyse2: + dec ebx ; CD + jnz nsyse4 + + test ecx, ecx + jz nosesl + + cmp ecx, 4 + ja nosesl + mov [cd_base], cl + + dec ecx + jnz noprma + mov [cdbase], 0x1f0 + mov [cdid], 0xa0 + noprma: + + dec ecx + jnz noprsl + mov [cdbase], 0x1f0 + mov [cdid], 0xb0 + noprsl: + dec ecx + jnz nosema + mov [cdbase], 0x170 + mov [cdid], 0xa0 + nosema: + dec ecx + jnz nosesl + mov [cdbase], 0x170 + mov [cdid], 0xb0 + nosesl: + ret + +iglobal +cd_base db 0 + +endg + nsyse4: + + sub ebx, 2 ; SYSTEM LANGUAGE + jnz nsyse5 + mov [syslang], ecx + ret + nsyse5: + + sub ebx, 2 ; HD BASE + jnz nsyse7 + + test ecx, ecx + jz nosethd + + cmp ecx, 4 + ja nosethd + mov [hd_base], cl + + cmp ecx, 1 + jnz noprmahd + mov [hdbase], 0x1f0 + and dword [hdid], 0x0 + mov dword [hdpos], ecx +; call set_FAT32_variables + noprmahd: + + cmp ecx, 2 + jnz noprslhd + mov [hdbase], 0x1f0 + mov [hdid], 0x10 + mov dword [hdpos], ecx +; call set_FAT32_variables + noprslhd: + + cmp ecx, 3 + jnz nosemahd + mov [hdbase], 0x170 + and dword [hdid], 0x0 + mov dword [hdpos], ecx +; call set_FAT32_variables + nosemahd: + + cmp ecx, 4 + jnz noseslhd + mov [hdbase], 0x170 + mov [hdid], 0x10 + mov dword [hdpos], ecx +; call set_FAT32_variables + noseslhd: + call reserve_hd1 + call reserve_hd_channel + call free_hd_channel + and dword [hd1_status], 0 ; free + nosethd: + ret + +iglobal +hd_base db 0 +endg + +nsyse7: + +; cmp eax,8 ; HD PARTITION + dec ebx + jnz nsyse8 + mov [fat32part], ecx +; call set_FAT32_variables + call reserve_hd1 + call reserve_hd_channel + call free_hd_channel +; pusha + call choice_necessity_partition_1 +; popa + and dword [hd1_status], 0 ; free + ret + +nsyse8: +; cmp eax,11 ; ENABLE LBA READ + and ecx, 1 + sub ebx, 3 + jnz no_set_lba_read + mov [lba_read_enabled], ecx + ret + +no_set_lba_read: +; cmp eax,12 ; ENABLE PCI ACCESS + dec ebx + jnz sys_setup_err + mov [pci_access_enabled], ecx + ret + +sys_setup_err: + or [esp+32], dword -1 + ret + +align 4 + +sys_getsetup: + +; 1=roland mpu midi base , base io address +; 2=keyboard 1, base kaybap 2, shift keymap, 9 country 1eng 2fi 3ger 4rus +; 3=cd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 5=system language, 1eng 2fi 3ger 4rus +; 7=hd base 1, pri.master 2, pri slave 3 sec master, 4 sec slave +; 8=fat32 partition in hd +; 9=get hs timer tic + +; cmp eax,1 + dec ebx + jnz ngsyse1 + movzx eax, [midi_base] + mov [esp+32], eax + ret +ngsyse1: +; cmp eax,2 + dec ebx + jnz ngsyse2 + + mov edi, [TASK_BASE] + mov ebx, [edi+TASKDATA.mem_start] + add ebx, edx + +; cmp ebx,1 + dec ecx + jnz kbnobaseret + mov eax, keymap + mov ecx, 128 + call memmove + ret +kbnobaseret: +; cmp ebx,2 + dec ecx + jnz kbnoshiftret + + mov eax, keymap_shift + mov ecx, 128 + call memmove + ret +kbnoshiftret: +; cmp ebx,3 + dec ecx + jne kbnoaltret + + mov eax, keymap_alt + mov ecx, 128 + call memmove + ret +kbnoaltret: +; cmp ebx,9 + sub ecx, 6 + jnz ngsyse2 + movzx eax, word [keyboard] + mov [esp+32], eax + ret + + +ngsyse2: +; cmp eax,3 + dec ebx + jnz ngsyse3 + movzx eax, [cd_base] + mov [esp+32], eax + ret +ngsyse3: +; cmp eax,5 + sub ebx, 2 + jnz ngsyse5 + mov eax, [syslang] + mov [esp+32], eax + ret +ngsyse5: +; cmp eax,7 + sub ebx, 2 + jnz ngsyse7 + movzx eax, [hd_base] + mov [esp+32], eax + ret +ngsyse7: +; cmp eax,8 + dec ebx + jnz ngsyse8 + mov eax, [fat32part] + mov [esp+32], eax + ret +ngsyse8: +; cmp eax,9 + dec ebx + jnz ngsyse9 + mov eax, [timer_ticks];[0xfdf0] + mov [esp+32], eax + ret +ngsyse9: +; cmp eax,11 + sub ebx, 2 + jnz ngsyse11 + mov eax, [lba_read_enabled] + mov [esp+32], eax + ret +ngsyse11: +; cmp eax,12 + dec ebx + jnz ngsyse12 + mov eax, [pci_access_enabled] + mov [esp+32], eax + ret +ngsyse12: + mov [esp+32], dword 1 + ret + + +get_timer_ticks: + mov eax, [timer_ticks] + ret + +iglobal +align 4 +mousefn dd msscreen, mswin, msbutton, msset + dd app_load_cursor + dd app_set_cursor + dd app_delete_cursor + dd msz +endg + +readmousepos: + +; eax=0 screen relative +; eax=1 window relative +; eax=2 buttons pressed +; eax=3 set mouse pos ; reserved +; eax=4 load cursor +; eax=5 set cursor +; eax=6 delete cursor ; reserved +; eax=7 get mouse_z + + cmp ebx, 7 + ja msset + jmp [mousefn+ebx*4] +msscreen: + mov eax, [MOUSE_X] + shl eax, 16 + mov ax, [MOUSE_Y] + mov [esp+36-4], eax + ret +mswin: + mov eax, [MOUSE_X] + shl eax, 16 + mov ax, [MOUSE_Y] + mov esi, [TASK_BASE] + mov bx, word [esi-twdw+WDATA.box.left] + shl ebx, 16 + mov bx, word [esi-twdw+WDATA.box.top] + sub eax, ebx + + mov edi, [CURRENT_TASK] + shl edi, 8 + sub ax, word[edi+SLOT_BASE+APPDATA.wnd_clientbox.top] + rol eax, 16 + sub ax, word[edi+SLOT_BASE+APPDATA.wnd_clientbox.left] + rol eax, 16 + mov [esp+36-4], eax + ret +msbutton: + movzx eax, byte [BTN_DOWN] + mov [esp+36-4], eax + ret +msz: + mov edi, [TASK_COUNT] + movzx edi, word [WIN_POS + edi*2] + cmp edi, [CURRENT_TASK] + jne @f + mov ax, [MOUSE_SCROLL_H] + shl eax, 16 + mov ax, [MOUSE_SCROLL_V] + mov [esp+36-4], eax + and [MOUSE_SCROLL_H], word 0 + and [MOUSE_SCROLL_V], word 0 + ret + @@: + and [esp+36-4], dword 0 +; ret +msset: + ret + +app_load_cursor: + cmp ecx, OS_BASE + jae msset + stdcall load_cursor, ecx, edx + mov [esp+36-4], eax + ret + +app_set_cursor: + stdcall set_cursor, ecx + mov [esp+36-4], eax + ret + +app_delete_cursor: + stdcall delete_cursor, ecx + mov [esp+36-4], eax + ret + +is_input: + + push edx + mov dx, word [midisp] + in al, dx + and al, 0x80 + pop edx + ret + +is_output: + + push edx + mov dx, word [midisp] + in al, dx + and al, 0x40 + pop edx + ret + + +get_mpu_in: + + push edx + mov dx, word [mididp] + in al, dx + pop edx + ret + + +put_mpu_out: + + push edx + mov dx, word [mididp] + out dx, al + pop edx + ret + + + +align 4 + +sys_midi: + cmp [mididp], 0 + jnz sm0 + mov [esp+36], dword 1 + ret +sm0: + and [esp+36], dword 0 + dec ebx + jnz smn1 + ; call setuart +su1: + call is_output + test al, al + jnz su1 + mov dx, word [midisp] + mov al, 0xff + out dx, al +su2: + mov dx, word [midisp] + mov al, 0xff + out dx, al + call is_input + test al, al + jnz su2 + call get_mpu_in + cmp al, 0xfe + jnz su2 +su3: + call is_output + test al, al + jnz su3 + mov dx, word [midisp] + mov al, 0x3f + out dx, al + ret +smn1: + dec ebx + jnz smn2 +sm10: + call get_mpu_in + call is_output + test al, al + jnz sm10 + mov al, bl + call put_mpu_out + smn2: + ret + +detect_devices: +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +;include 'detect/commouse.inc' +;include 'detect/ps2mouse.inc' +;include 'detect/dev_fd.inc' +;include 'detect/dev_hdcd.inc' +;include 'detect/sear_par.inc' +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ret + +sys_end: + + mov ecx, [current_slot] + mov eax, [ecx+APPDATA.tls_base] + test eax, eax + jz @F + + stdcall user_free, eax +@@: + + mov eax, [TASK_BASE] + mov [eax+TASKDATA.state], 3; terminate this program + + waitterm: ; wait here for termination + mov ebx, 100 + call delay_hs + jmp waitterm + +iglobal +align 4 +sys_system_table: + dd sysfn_deactivate ; 1 = deactivate window + dd sysfn_terminate ; 2 = terminate thread + dd sysfn_activate ; 3 = activate window + dd sysfn_getidletime ; 4 = get idle time + dd sysfn_getcpuclock ; 5 = get cpu clock + dd sysfn_saveramdisk ; 6 = save ramdisk + dd sysfn_getactive ; 7 = get active window + dd sysfn_sound_flag ; 8 = get/set sound_flag + dd sysfn_shutdown ; 9 = shutdown with parameter + dd sysfn_minimize ; 10 = minimize window + dd sysfn_getdiskinfo ; 11 = get disk subsystem info + dd sysfn_lastkey ; 12 = get last pressed key + dd sysfn_getversion ; 13 = get kernel version + dd sysfn_waitretrace ; 14 = wait retrace + dd sysfn_centermouse ; 15 = center mouse cursor + dd sysfn_getfreemem ; 16 = get free memory size + dd sysfn_getallmem ; 17 = get total memory size + dd sysfn_terminate2 ; 18 = terminate thread using PID + ; instead of slot + dd sysfn_mouse_acceleration; 19 = set/get mouse acceleration + dd sysfn_meminfo ; 20 = get extended memory info + dd sysfn_pid_to_slot ; 21 = get slot number for pid + dd sysfn_min_rest_window ; 22 = minimize and restore any window +sysfn_num = ($ - sys_system_table)/4 +endg +;------------------------------------------------------------------------------ +sys_system: + dec ebx + cmp ebx, sysfn_num + jae @f + jmp dword [sys_system_table + ebx*4] +@@: + ret +;------------------------------------------------------------------------------ +sysfn_shutdown: ; 18.9 = system shutdown + cmp ecx, 1 + jl exit_for_anyone + cmp ecx, 4 + jg exit_for_anyone + mov [BOOT_VAR+0x9030], cl + + mov eax, [TASK_COUNT] + mov [SYS_SHUTDOWN], al + mov [shutdown_processes], eax + and dword [esp+32], 0 + exit_for_anyone: + ret + uglobal + shutdown_processes: + dd 0x0 + endg +;------------------------------------------------------------------------------ +sysfn_terminate: ; 18.2 = TERMINATE + cmp ecx, 2 + jb noprocessterminate + mov edx, [TASK_COUNT] + cmp ecx, edx + ja noprocessterminate + mov eax, [TASK_COUNT] + shl ecx, 5 + mov edx, [ecx+CURRENT_TASK+TASKDATA.pid] + add ecx, CURRENT_TASK+TASKDATA.state + cmp byte [ecx], 9 + jz noprocessterminate + + ;call MEM_Heap_Lock ;guarantee that process isn't working with heap + mov [ecx], byte 3; clear possible i40's + ;call MEM_Heap_UnLock + + cmp edx, [application_table_status]; clear app table stat + jne noatsc + and [application_table_status], 0 + noatsc: + noprocessterminate: + ret +;------------------------------------------------------------------------------ +sysfn_terminate2: +;lock application_table_status mutex +.table_status: + cli + cmp [application_table_status], 0 + je .stf + sti + call change_task + jmp .table_status +.stf: + call set_application_table_status + mov eax, ecx + call pid_to_slot + test eax, eax + jz .not_found + mov ecx, eax + cli + call sysfn_terminate + and [application_table_status], 0 + sti + and dword [esp+32], 0 + ret +.not_found: + mov [application_table_status], 0 + or dword [esp+32], -1 + ret +;------------------------------------------------------------------------------ +sysfn_deactivate: ; 18.1 = DEACTIVATE WINDOW + cmp ecx, 2 + jb .nowindowdeactivate + cmp ecx, [TASK_COUNT] + ja .nowindowdeactivate + + movzx esi, word [WIN_STACK + ecx*2] + cmp esi, 1 + je .nowindowdeactivate ; already deactive + + mov edi, ecx + shl edi, 5 + add edi, window_data + movzx esi, word [WIN_STACK + ecx * 2] + lea esi, [WIN_POS + esi * 2] + call window._.window_deactivate + + xor eax, eax + mov byte[MOUSE_BACKGROUND], al + mov byte[DONT_DRAW_MOUSE], al + mov byte[MOUSE_DOWN], 0 + + call syscall_display_settings._.calculate_whole_screen + call syscall_display_settings._.redraw_whole_screen +.nowindowdeactivate: + ret + ;------------------------------------------------------------------------------ +sysfn_activate: ; 18.3 = ACTIVATE WINDOW + cmp ecx, 2 + jb .nowindowactivate + cmp ecx, [TASK_COUNT] + ja .nowindowactivate + + mov [window_minimize], 2; restore window if minimized + + movzx esi, word [WIN_STACK + ecx*2] + cmp esi, [TASK_COUNT] + je .nowindowactivate; already active + + mov edi, ecx + shl edi, 5 + add edi, window_data + movzx esi, word [WIN_STACK + ecx * 2] + lea esi, [WIN_POS + esi * 2] + call waredraw +.nowindowactivate: + ret +;------------------------------------------------------------------------------ +sysfn_getidletime: ; 18.4 = GET IDLETIME + mov eax, [idleusesec] + mov [esp+32], eax + ret +;------------------------------------------------------------------------------ +sysfn_getcpuclock: ; 18.5 = GET TSC/SEC + mov eax, [CPU_FREQ] + mov [esp+32], eax + ret +;------------------------------------------------------------------------------ +; SAVE ramdisk to /hd/1/menuet.img +;!!!!!!!!!!!!!!!!!!!!!!!! + include 'blkdev/rdsave.inc' +;!!!!!!!!!!!!!!!!!!!!!!!! +;------------------------------------------------------------------------------ +align 4 +sysfn_getactive: ; 18.7 = get active window + mov eax, [TASK_COUNT] + movzx eax, word [WIN_POS + eax*2] + mov [esp+32], eax + ret +;------------------------------------------------------------------------------ +sysfn_sound_flag: ; 18.8 = get/set sound_flag +; cmp ecx,1 + dec ecx + jnz nogetsoundflag + movzx eax, byte [sound_flag]; get sound_flag + mov [esp+32], eax + ret + nogetsoundflag: +; cmp ecx,2 + dec ecx + jnz nosoundflag + xor byte [sound_flag], 1 + nosoundflag: + ret +;------------------------------------------------------------------------------ +sysfn_minimize: ; 18.10 = minimize window + mov [window_minimize], 1 + ret +;------------------------------------------------------------------------------ +align 4 +sysfn_getdiskinfo: ; 18.11 = get disk info table +; cmp ecx,1 + dec ecx + jnz full_table + small_table: + call for_all_tables + mov ecx, 10 + cld + rep movsb + ret + for_all_tables: + mov edi, edx + mov esi, DRIVE_DATA + ret + full_table: +; cmp ecx,2 + dec ecx + jnz exit_for_anyone + call for_all_tables + mov ecx, 16384 + cld + rep movsd + ret +;------------------------------------------------------------------------------ +sysfn_lastkey: ; 18.12 = return 0 (backward compatibility) + and dword [esp+32], 0 + ret +;------------------------------------------------------------------------------ +sysfn_getversion: ; 18.13 = get kernel ID and version + mov edi, ecx + mov esi, version_inf + mov ecx, version_end-version_inf + rep movsb + ret +;------------------------------------------------------------------------------ +sysfn_waitretrace: ; 18.14 = sys wait retrace + ;wait retrace functions + sys_wait_retrace: + mov edx, 0x3da + WaitRetrace_loop: + in al, dx + test al, 1000b + jz WaitRetrace_loop + and [esp+32], dword 0 + ret +;------------------------------------------------------------------------------ +align 4 +sysfn_centermouse: ; 18.15 = mouse centered +; removed here by +; call mouse_centered +;* mouse centered - start code- Mario79 +;mouse_centered: +; push eax + mov eax, [Screen_Max_X] + shr eax, 1 + mov [MOUSE_X], ax + mov eax, [Screen_Max_Y] + shr eax, 1 + mov [MOUSE_Y], ax +; ret +;* mouse centered - end code- Mario79 + xor eax, eax + and [esp+32], eax +; pop eax + ret +;------------------------------------------------------------------------------ +align 4 +sysfn_mouse_acceleration: ; 18.19 = set/get mouse features + test ecx, ecx; get mouse speed factor + jnz .set_mouse_acceleration + xor eax, eax + mov ax, [mouse_speed_factor] + mov [esp+32], eax + ret + .set_mouse_acceleration: +; cmp ecx,1 ; set mouse speed factor + dec ecx + jnz .get_mouse_delay + mov [mouse_speed_factor], dx + ret + .get_mouse_delay: +; cmp ecx,2 ; get mouse delay + dec ecx + jnz .set_mouse_delay + mov eax, [mouse_delay] + mov [esp+32], eax + ret + .set_mouse_delay: +; cmp ecx,3 ; set mouse delay + dec ecx + jnz .set_pointer_position + mov [mouse_delay], edx + ret + .set_pointer_position: +; cmp ecx,4 ; set mouse pointer position + dec ecx + jnz .set_mouse_button + cmp dx, word[Screen_Max_Y] + ja .end + rol edx, 16 + cmp dx, word[Screen_Max_X] + ja .end + mov [MOUSE_X], edx + ret + .set_mouse_button: +; cmp ecx,5 ; set mouse button features + dec ecx + jnz .end + mov [BTN_DOWN], dl + mov [mouse_active], 1 + .end: + ret +;------------------------------------------------------------------------------ +sysfn_getfreemem: + mov eax, [pg_data.pages_free] + shl eax, 2 + mov [esp+32], eax + ret + +sysfn_getallmem: + mov eax, [MEM_AMOUNT] + shr eax, 10 + mov [esp+32], eax + ret + +; // Alver, 2007-22-08 // { +sysfn_pid_to_slot: + mov eax, ecx + call pid_to_slot + mov [esp+32], eax + ret + +sysfn_min_rest_window: + pushad + mov eax, edx ; ebx - operating + shr ecx, 1 + jnc @f + call pid_to_slot +@@: + or eax, eax ; eax - number of slot + jz .error + cmp eax, 255 ; varify maximal slot number + ja .error + movzx eax, word [WIN_STACK + eax*2] + shr ecx, 1 + jc .restore + ; .minimize: + call minimize_window + jmp .exit +.restore: + call restore_minimized_window +.exit: + popad + xor eax, eax + mov [esp+32], eax + ret +.error: + popad + xor eax, eax + dec eax + mov [esp+32], eax + ret +; } \\ Alver, 2007-22-08 \\ + +uglobal +;// mike.dld, 2006-29-01 [ +screen_workarea RECT +;// mike.dld, 2006-29-01 ] +window_minimize db 0 +sound_flag db 0 +endg + +UID_NONE=0 +UID_MENUETOS=1 ;official +UID_KOLIBRI=2 ;russian + +iglobal +version_inf: + db 0,7,7,0 ; version 0.7.7.0 + db 0 + dd __REV__ +version_end: +endg + +sys_cachetodiskette: + cmp ebx, 1 + jne .no_floppy_a_save + mov [flp_number], 1 + jmp .save_image_on_floppy +.no_floppy_a_save: + cmp ebx, 2 + jne .no_floppy_b_save + mov [flp_number], 2 +.save_image_on_floppy: + call save_image + mov [esp + 32], dword 0 + cmp [FDC_Status], 0 + je .yes_floppy_save +.no_floppy_b_save: + mov [esp + 32], dword 1 +.yes_floppy_save: + ret + +uglobal +; bgrchanged dd 0x0 +align 4 +bgrlockpid dd 0 +bgrlock db 0 +endg + +sys_background: + + cmp ebx, 1 ; BACKGROUND SIZE + jnz nosb1 + test ecx, ecx +; cmp ecx,0 + jz sbgrr + test edx, edx +; cmp edx,0 + jz sbgrr +@@: +;;Maxis use atomic bts for mutexes 4.4.2009 + bts dword [bgrlock], 0 + jnc @f + call change_task + jmp @b +@@: + mov [BgrDataWidth], ecx + mov [BgrDataHeight], edx +; mov [bgrchanged],1 + + pushad +; return memory for old background + mov eax, [img_background] + cmp eax, static_background_data + jz @f + stdcall kernel_free, eax +@@: +; calculate RAW size + xor eax, eax + inc eax + cmp [BgrDataWidth], eax + jae @f + mov [BgrDataWidth], eax +@@: + cmp [BgrDataHeight], eax + jae @f + mov [BgrDataHeight], eax +@@: + mov eax, [BgrDataWidth] + imul eax, [BgrDataHeight] + lea eax, [eax*3] + mov [mem_BACKGROUND], eax +; get memory for new background + stdcall kernel_alloc, eax + test eax, eax + jz .memfailed + mov [img_background], eax + jmp .exit +.memfailed: +; revert to static monotone data + mov [img_background], static_background_data + xor eax, eax + inc eax + mov [BgrDataWidth], eax + mov [BgrDataHeight], eax + mov [mem_BACKGROUND], 4 +.exit: + popad + mov [bgrlock], 0 + + sbgrr: + ret + +nosb1: + + cmp ebx, 2 ; SET PIXEL + jnz nosb2 + + mov eax, [img_background] + test ecx, ecx + jz @f + cmp eax, static_background_data + jz .ret +@@: + mov ebx, [mem_BACKGROUND] + add ebx, 4095 + and ebx, -4096 + sub ebx, 4 + cmp ecx, ebx + ja .ret + + mov ebx, [eax+ecx] + and ebx, 0xFF000000;255*256*256*256 + and edx, 0x00FFFFFF;255*256*256+255*256+255 + add edx, ebx + mov [eax+ecx], edx +.ret: + ret +nosb2: + + cmp ebx, 3 ; DRAW BACKGROUND + jnz nosb3 +draw_background_temp: +; cmp [bgrchanged],1 ;0 +; je nosb31 +;draw_background_temp: +; mov [bgrchanged],1 ;0 + mov [background_defined], 1 + mov byte[BACKGROUND_CHANGED], 1 + call force_redraw_background + nosb31: + ret + nosb3: + + cmp ebx, 4 ; TILED / STRETCHED + jnz nosb4 + cmp ecx, [BgrDrawMode] + je nosb41 + mov [BgrDrawMode], ecx +; mov [bgrchanged],1 + nosb41: + ret + nosb4: + + cmp ebx, 5 ; BLOCK MOVE TO BGR + jnz nosb5 + cmp [img_background], static_background_data + jnz @f + test edx, edx + jnz .fin + cmp esi, 4 + ja .fin + @@: + ; bughere + mov eax, ecx + mov ebx, edx + add ebx, [img_background];IMG_BACKGROUND + mov ecx, esi + call memmove + .fin: + ret + nosb5: + + cmp ebx, 6 + jnz nosb6 +;;Maxis use atomic bts for mutex 4.4.2009 +@@: + bts dword [bgrlock], 0 + jnc @f + call change_task + jmp @b +@@: + mov eax, [CURRENT_TASK] + mov [bgrlockpid], eax + cmp [img_background], static_background_data + jz .nomem + stdcall user_alloc, [mem_BACKGROUND] + mov [esp+32], eax + test eax, eax + jz .nomem + mov ebx, eax + shr ebx, 12 + or dword [page_tabs+(ebx-1)*4], DONT_FREE_BLOCK + mov esi, [img_background] + shr esi, 12 + mov ecx, [mem_BACKGROUND] + add ecx, 0xFFF + shr ecx, 12 +.z: + mov eax, [page_tabs+ebx*4] + test al, 1 + jz @f + call free_page +@@: + mov eax, [page_tabs+esi*4] + or al, PG_UW + mov [page_tabs+ebx*4], eax + mov eax, ebx + shl eax, 12 + invlpg [eax] + inc ebx + inc esi + loop .z + ret +.nomem: + and [bgrlockpid], 0 + mov [bgrlock], 0 +nosb6: + cmp ebx, 7 + jnz nosb7 + cmp [bgrlock], 0 + jz .err + mov eax, [CURRENT_TASK] + cmp [bgrlockpid], eax + jnz .err + mov eax, ecx + mov ebx, ecx + shr eax, 12 + mov ecx, [page_tabs+(eax-1)*4] + test cl, USED_BLOCK+DONT_FREE_BLOCK + jz .err + jnp .err + push eax + shr ecx, 12 + dec ecx +@@: + and dword [page_tabs+eax*4], 0 + mov edx, eax + shl edx, 12 + push eax + invlpg [edx] + pop eax + inc eax + loop @b + pop eax + and dword [page_tabs+(eax-1)*4], not DONT_FREE_BLOCK + stdcall user_free, ebx + mov [esp+32], eax + and [bgrlockpid], 0 + mov [bgrlock], 0 + ret +.err: + and dword [esp+32], 0 + ret + +nosb7: + ret + +force_redraw_background: + and [draw_data+32 + RECT.left], 0 + and [draw_data+32 + RECT.top], 0 + push eax ebx + mov eax, [Screen_Max_X] + mov ebx, [Screen_Max_Y] + mov [draw_data+32 + RECT.right], eax + mov [draw_data+32 + RECT.bottom], ebx + pop ebx eax + inc byte[REDRAW_BACKGROUND] + ret + +align 4 + +sys_getbackground: +; cmp eax,1 ; SIZE + dec ebx + jnz nogb1 + mov eax, [BgrDataWidth] + shl eax, 16 + mov ax, [BgrDataHeight] + mov [esp+32], eax + ret + +nogb1: +; cmp eax,2 ; PIXEL + dec ebx + jnz nogb2 + + mov eax, [img_background] + test ecx, ecx + jz @f + cmp eax, static_background_data + jz .ret +@@: + mov ebx, [mem_BACKGROUND] + add ebx, 4095 + and ebx, -4096 + sub ebx, 4 + cmp ecx, ebx + ja .ret + + mov eax, [ecx+eax] + + and eax, 0xFFFFFF + mov [esp+32], eax +.ret: + ret + nogb2: + +; cmp eax,4 ; TILED / STRETCHED + dec ebx + dec ebx + jnz nogb4 + mov eax, [BgrDrawMode] + nogb4: + mov [esp+32], eax + ret + +align 4 + +sys_getkey: + mov [esp + 32], dword 1 + ; test main buffer + mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK + movzx ecx, word [WIN_STACK + ebx * 2] + mov edx, [TASK_COUNT] + cmp ecx, edx + jne .finish + cmp [KEY_COUNT], byte 0 + je .finish + movzx eax, byte [KEY_BUFF] + shl eax, 8 + push eax + dec byte [KEY_COUNT] + and byte [KEY_COUNT], 127 + movzx ecx, byte [KEY_COUNT] + add ecx, 2 + mov eax, KEY_BUFF + 1 + mov ebx, KEY_BUFF + call memmove + pop eax +.ret_eax: + mov [esp + 32], eax + ret +.finish: +; test hotkeys buffer + mov ecx, hotkey_buffer +@@: + cmp [ecx], ebx + jz .found + add ecx, 8 + cmp ecx, hotkey_buffer + 120 * 8 + jb @b + ret +.found: + mov ax, [ecx + 6] + shl eax, 16 + mov ah, [ecx + 4] + mov al, 2 + and dword [ecx + 4], 0 + and dword [ecx], 0 + jmp .ret_eax + +align 4 + +sys_getbutton: + + mov ebx, [CURRENT_TASK] ; TOP OF WINDOW STACK + mov [esp + 32], dword 1 + movzx ecx, word [WIN_STACK + ebx * 2] + mov edx, [TASK_COUNT] ; less than 256 processes + cmp ecx, edx + jne .exit + movzx eax, byte [BTN_COUNT] + test eax, eax + jz .exit + mov eax, [BTN_BUFF] + and al, 0xFE ; delete left button bit + mov [BTN_COUNT], byte 0 + mov [esp + 32], eax +.exit: + ret + + +align 4 + +sys_cpuusage: + +; RETURN: +; +; +00 dword process cpu usage +; +04 word position in windowing stack +; +06 word windowing stack value at current position (cpu nro) +; +10 12 bytes name +; +22 dword start in mem +; +26 dword used mem +; +30 dword PID , process idenfification number +; + + cmp ecx, -1 ; who am I ? + jne .no_who_am_i + mov ecx, [CURRENT_TASK] + .no_who_am_i: + cmp ecx, max_processes + ja .nofillbuf + +; +4: word: position of the window of thread in the window stack + mov ax, [WIN_STACK + ecx * 2] + mov [ebx+4], ax +; +6: word: number of the thread slot, which window has in the window stack +; position ecx (has no relation to the specific thread) + mov ax, [WIN_POS + ecx * 2] + mov [ebx+6], ax + + shl ecx, 5 + +; +0: dword: memory usage + mov eax, [ecx+CURRENT_TASK+TASKDATA.cpu_usage] + mov [ebx], eax +; +10: 11 bytes: name of the process + push ecx + lea eax, [ecx*8+SLOT_BASE+APPDATA.app_name] + add ebx, 10 + mov ecx, 11 + call memmove + pop ecx + +; +22: address of the process in memory +; +26: size of used memory - 1 + push edi + lea edi, [ebx+12] + xor eax, eax + mov edx, 0x100000*16 + cmp ecx, 1 shl 5 + je .os_mem + mov edx, [SLOT_BASE+ecx*8+APPDATA.mem_size] + mov eax, std_application_base_address +.os_mem: + stosd + lea eax, [edx-1] + stosd + +; +30: PID/TID + mov eax, [ecx+CURRENT_TASK+TASKDATA.pid] + stosd + + ; window position and size + push esi + lea esi, [ecx + window_data + WDATA.box] + movsd + movsd + movsd + movsd + + ; Process state (+50) + mov eax, dword [ecx+CURRENT_TASK+TASKDATA.state] + stosd + + ; Window client area box + lea esi, [ecx*8 + SLOT_BASE + APPDATA.wnd_clientbox] + movsd + movsd + movsd + movsd + + ; Window state + mov al, [ecx+window_data+WDATA.fl_wstate] + stosb + + ; Event mask (+71) + mov EAX, dword [ECX+CURRENT_TASK+TASKDATA.event_mask] + stosd + + pop esi + pop edi + +.nofillbuf: + ; return number of processes + + mov eax, [TASK_COUNT] + mov [esp+32], eax + ret + +align 4 +sys_clock: + cli + ; Mikhail Lisovin xx Jan 2005 + @@: + mov al, 10 + out 0x70, al + in al, 0x71 + test al, al + jns @f + mov esi, 1 + call delay_ms + jmp @b + @@: + ; end Lisovin's fix + + xor al, al ; seconds + out 0x70, al + in al, 0x71 + movzx ecx, al + mov al, 02 ; minutes + shl ecx, 16 + out 0x70, al + in al, 0x71 + movzx edx, al + mov al, 04 ; hours + shl edx, 8 + out 0x70, al + in al, 0x71 + add ecx, edx + movzx edx, al + add ecx, edx + sti + mov [esp + 32], ecx + ret + + +align 4 + +sys_date: + + cli + @@: + mov al, 10 + out 0x70, al + in al, 0x71 + test al, al + jns @f + mov esi, 1 + call delay_ms + jmp @b + @@: + + mov ch, 0 + mov al, 7 ; date + out 0x70, al + in al, 0x71 + mov cl, al + mov al, 8 ; month + shl ecx, 16 + out 0x70, al + in al, 0x71 + mov ch, al + mov al, 9 ; year + out 0x70, al + in al, 0x71 + mov cl, al + sti + mov [esp+32], ecx + ret + + +; redraw status + +sys_redrawstat: + cmp ebx, 1 + jne no_widgets_away + ; buttons away + mov ecx, [CURRENT_TASK] + sys_newba2: + mov edi, [BTN_ADDR] + cmp [edi], dword 0 ; empty button list ? + je end_of_buttons_away + movzx ebx, word [edi] + inc ebx + mov eax, edi + sys_newba: + dec ebx + jz end_of_buttons_away + + add eax, 0x10 + cmp cx, [eax] + jnz sys_newba + + push eax ebx ecx + mov ecx, ebx + inc ecx + shl ecx, 4 + mov ebx, eax + add eax, 0x10 + call memmove + dec dword [edi] + pop ecx ebx eax + + jmp sys_newba2 + + end_of_buttons_away: + + ret + + no_widgets_away: + + cmp ebx, 2 + jnz srl1 + + mov edx, [TASK_BASE] ; return whole screen draw area for this app + add edx, draw_data - CURRENT_TASK + mov [edx + RECT.left], 0 + mov [edx + RECT.top], 0 + mov eax, [Screen_Max_X] + mov [edx + RECT.right], eax + mov eax, [Screen_Max_Y] + mov [edx + RECT.bottom], eax + + srl1: + ret + +;ok - 100% work +;nt - not tested +;--------------------------------------------------------------------------------------------- +;eax +;0 - task switch counter. Ret switch counter in eax. Block. ok. +;1 - change task. Ret nothing. Block. ok. +;2 - performance control +; ebx +; 0 - enable or disable (inversion) PCE flag on CR4 for rdmpc in user mode. +; returned new cr4 in eax. Ret cr4 in eax. Block. ok. +; 1 - is cache enabled. Ret cr0 in eax if enabled else zero in eax. Block. ok. +; 2 - enable cache. Ret 1 in eax. Ret nothing. Block. ok. +; 3 - disable cache. Ret 0 in eax. Ret nothing. Block. ok. +;eax +;3 - rdmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. +;4 - wrmsr. Counter in edx. (edx:eax) [esi:edi, edx] => [edx:esi, ecx]. Ret in ebx:eax. Block. ok. +;--------------------------------------------------------------------------------------------- +iglobal +align 4 +sheduler: + dd sys_sheduler.00 + dd change_task + dd sys_sheduler.02 + dd sys_sheduler.03 + dd sys_sheduler.04 +endg +sys_sheduler: +;rewritten by 29.12.2009 + jmp dword [sheduler+ebx*4] +;.shed_counter: +.00: + mov eax, [context_counter] + mov [esp+32], eax + ret + +.02: +;.perf_control: + inc ebx ;before ebx=2, ebx=3 + cmp ebx, ecx ;if ecx=3, ebx=3 + jz cache_disable + + dec ebx ;ebx=2 + cmp ebx, ecx ; + jz cache_enable ;if ecx=2 and ebx=2 + + dec ebx ;ebx=1 + cmp ebx, ecx + jz is_cache_enabled ;if ecx=1 and ebx=1 + + dec ebx + test ebx, ecx ;ebx=0 and ecx=0 + jz modify_pce ;if ecx=0 + + ret + +.03: +;.rdmsr_instr: +;now counter in ecx +;(edx:eax) esi:edi => edx:esi + mov eax, esi + mov ecx, edx + rdmsr + mov [esp+32], eax + mov [esp+20], edx ;ret in ebx? + ret + +.04: +;.wrmsr_instr: +;now counter in ecx +;(edx:eax) esi:edi => edx:esi + ; Fast Call MSR can't be destroy + ; Ќ® MSR_AMD_EFER ¬®¦­® Ё§¬Ґ­пвм, в.Є. ў н⮬ ॣЁбвॠ«Ёи + ; ўЄ«оз овбп/ўлЄ«оз овбп а биЁаҐ­­лҐ ў®§¬®¦­®бвЁ + cmp edx, MSR_SYSENTER_CS + je @f + cmp edx, MSR_SYSENTER_ESP + je @f + cmp edx, MSR_SYSENTER_EIP + je @f + cmp edx, MSR_AMD_STAR + je @f + + mov eax, esi + mov ecx, edx + wrmsr + ; mov [esp + 32], eax + ; mov [esp + 20], edx ;ret in ebx? +@@: + ret + +cache_disable: + mov eax, cr0 + or eax, 01100000000000000000000000000000b + mov cr0, eax + wbinvd ;set MESI + ret + +cache_enable: + mov eax, cr0 + and eax, 10011111111111111111111111111111b + mov cr0, eax + ret + +is_cache_enabled: + mov eax, cr0 + mov ebx, eax + and eax, 01100000000000000000000000000000b + jz cache_disabled + mov [esp+32], ebx +cache_disabled: + mov dword [esp+32], eax;0 + ret + +modify_pce: + mov eax, cr4 +; mov ebx,0 +; or bx,100000000b ;pce +; xor eax,ebx ;invert pce + bts eax, 8;pce=cr4[8] + mov cr4, eax + mov [esp+32], eax + ret +;--------------------------------------------------------------------------------------------- + + +; check if pixel is allowed to be drawn + +checkpixel: + push eax edx + + mov edx, [Screen_Max_X] ; screen x size + inc edx + imul edx, ebx + add eax, [_WinMapAddress] + mov dl, [eax+edx]; lea eax, [...] + + xor ecx, ecx + mov eax, [CURRENT_TASK] + cmp al, dl + setne cl + + pop edx eax + ret + +iglobal + cpustring db 'CPU',0 +endg + +uglobal +background_defined db 0 ; diamond, 11.04.2006 +endg + +align 4 +; check misc + +checkmisc: + + cmp [ctrl_alt_del], 1 + jne nocpustart + + mov ebp, cpustring + call fs_execute_from_sysdir + + mov [ctrl_alt_del], 0 + +nocpustart: + cmp [mouse_active], 1 + jne mouse_not_active + mov [mouse_active], 0 + xor edi, edi + mov ecx, [TASK_COUNT] +set_mouse_event: + add edi, 256 + or [edi+SLOT_BASE+APPDATA.event_mask], dword 100000b + loop set_mouse_event + +mouse_not_active: + cmp byte[BACKGROUND_CHANGED], 0 + jz no_set_bgr_event + xor edi, edi + mov ecx, [TASK_COUNT] +set_bgr_event: + add edi, 256 + or [edi+SLOT_BASE+APPDATA.event_mask], 16 + loop set_bgr_event + mov byte[BACKGROUND_CHANGED], 0 +no_set_bgr_event: + cmp byte[REDRAW_BACKGROUND], 0 ; background update ? + jz nobackgr + cmp [background_defined], 0 + jz nobackgr +; mov [draw_data+32 + RECT.left],dword 0 +; mov [draw_data+32 + RECT.top],dword 0 +; mov eax,[Screen_Max_X] +; mov ebx,[Screen_Max_Y] +; mov [draw_data+32 + RECT.right],eax +; mov [draw_data+32 + RECT.bottom],ebx +@@: + call drawbackground + xor eax, eax + xchg al, [REDRAW_BACKGROUND] + test al, al ; got new update request? + jnz @b + mov [draw_data+32 + RECT.left], eax + mov [draw_data+32 + RECT.top], eax + mov [draw_data+32 + RECT.right], eax + mov [draw_data+32 + RECT.bottom], eax + mov [MOUSE_BACKGROUND], byte 0 + +nobackgr: + + ; system shutdown request + + cmp [SYS_SHUTDOWN], byte 0 + je noshutdown + + mov edx, [shutdown_processes] + + cmp [SYS_SHUTDOWN], dl + jne no_mark_system_shutdown + + lea ecx, [edx-1] + mov edx, OS_BASE+0x3040 + jecxz @f +markz: + mov [edx+TASKDATA.state], byte 3 + add edx, 0x20 + loop markz +@@: + + no_mark_system_shutdown: + + call [_display.disable_mouse] + + dec byte [SYS_SHUTDOWN] + je system_shutdown + +noshutdown: + + + mov eax, [TASK_COUNT] ; termination + mov ebx, TASK_DATA+TASKDATA.state + mov esi, 1 + +newct: + mov cl, [ebx] + cmp cl, byte 3 + jz terminate + cmp cl, byte 4 + jz terminate + + add ebx, 0x20 + inc esi + dec eax + jnz newct + ret + +; redraw screen + +redrawscreen: + +; eax , if process window_data base is eax, do not set flag/limits + + pushad + push eax + +;;; mov ebx,2 +;;; call delay_hs + + ;mov ecx,0 ; redraw flags for apps + xor ecx, ecx + newdw2: + + inc ecx + push ecx + + mov eax, ecx + shl eax, 5 + add eax, window_data + + cmp eax, [esp+4] + je not_this_task + ; check if window in redraw area + mov edi, eax + + cmp ecx, 1 ; limit for background + jz bgli + + mov eax, [edi + WDATA.box.left] + mov ebx, [edi + WDATA.box.top] + mov ecx, [edi + WDATA.box.width] + mov edx, [edi + WDATA.box.height] + add ecx, eax + add edx, ebx + + mov ecx, [draw_limits.bottom] ; ecx = area y end ebx = window y start + cmp ecx, ebx + jb ricino + + mov ecx, [draw_limits.right] ; ecx = area x end eax = window x start + cmp ecx, eax + jb ricino + + mov eax, [edi + WDATA.box.left] + mov ebx, [edi + WDATA.box.top] + mov ecx, [edi + WDATA.box.width] + mov edx, [edi + WDATA.box.height] + add ecx, eax + add edx, ebx + + mov eax, [draw_limits.top] ; eax = area y start edx = window y end + cmp edx, eax + jb ricino + + mov eax, [draw_limits.left] ; eax = area x start ecx = window x end + cmp ecx, eax + jb ricino + + bgli: + + cmp dword[esp], 1 + jnz .az +; cmp byte[BACKGROUND_CHANGED], 0 +; jnz newdw8 + cmp byte[REDRAW_BACKGROUND], 0 + jz .az + mov dl, 0 + lea eax, [edi+draw_data-window_data] + mov ebx, [draw_limits.left] + cmp ebx, [eax+RECT.left] + jae @f + mov [eax+RECT.left], ebx + mov dl, 1 + @@: + mov ebx, [draw_limits.top] + cmp ebx, [eax+RECT.top] + jae @f + mov [eax+RECT.top], ebx + mov dl, 1 + @@: + mov ebx, [draw_limits.right] + cmp ebx, [eax+RECT.right] + jbe @f + mov [eax+RECT.right], ebx + mov dl, 1 + @@: + mov ebx, [draw_limits.bottom] + cmp ebx, [eax+RECT.bottom] + jbe @f + mov [eax+RECT.bottom], ebx + mov dl, 1 + @@: + add byte[REDRAW_BACKGROUND], dl + jmp newdw8 + .az: + + mov eax, edi + add eax, draw_data-window_data + + mov ebx, [draw_limits.left] ; set limits + mov [eax + RECT.left], ebx + mov ebx, [draw_limits.top] + mov [eax + RECT.top], ebx + mov ebx, [draw_limits.right] + mov [eax + RECT.right], ebx + mov ebx, [draw_limits.bottom] + mov [eax + RECT.bottom], ebx + + sub eax, draw_data-window_data + + cmp dword [esp], 1 + jne nobgrd + inc byte[REDRAW_BACKGROUND] + + newdw8: + nobgrd: + + mov [eax + WDATA.fl_redraw], byte 1 ; mark as redraw + + ricino: + + not_this_task: + + pop ecx + + cmp ecx, [TASK_COUNT] + jle newdw2 + + pop eax + popad + + ret + +calculatebackground: ; background + + mov edi, [_WinMapAddress] ; set os to use all pixels + mov eax, 0x01010101 + mov ecx, [_WinMapSize] + shr ecx, 2 + rep stosd + + mov byte[REDRAW_BACKGROUND], 0 ; do not draw background! + mov byte[BACKGROUND_CHANGED], 0 + + ret + +uglobal + imax dd 0x0 +endg + + + +delay_ms: ; delay in 1/1000 sec + + + push eax + push ecx + + mov ecx, esi + ; + imul ecx, 33941 + shr ecx, 9 + ; + + in al, 0x61 + and al, 0x10 + mov ah, al + cld + + cnt1: + in al, 0x61 + and al, 0x10 + cmp al, ah + jz cnt1 + + mov ah, al + loop cnt1 + + pop ecx + pop eax + + ret + + +set_app_param: + mov edi, [TASK_BASE] + mov eax, [edi + TASKDATA.event_mask] + mov [edi + TASKDATA.event_mask], ebx + mov [esp+32], eax + ret + + + +delay_hs: ; delay in 1/100 secs +; ebx = delay time + push ecx + push edx + + mov edx, [timer_ticks] + + newtic: + mov ecx, [timer_ticks] + sub ecx, edx + cmp ecx, ebx + jae zerodelay + + call change_task + + jmp newtic + + zerodelay: + pop edx + pop ecx + + ret + +align 16 ;very often call this subrutine +memmove: ; memory move in bytes + +; eax = from +; ebx = to +; ecx = no of bytes + test ecx, ecx + jle .ret + + push esi edi ecx + + mov edi, ebx + mov esi, eax + + test ecx, not 11b + jz @f + + push ecx + shr ecx, 2 + rep movsd + pop ecx + and ecx, 11b + jz .finish + @@: + rep movsb + + .finish: + pop ecx edi esi + .ret: + ret + + +; Sysfunction 34, read_floppy_file, is obsolete. Use 58 or 70 function instead. +;align 4 +; +;read_floppy_file: +; +;; as input +;; +;; eax pointer to file +;; ebx file lenght +;; ecx start 512 byte block number +;; edx number of blocks to read +;; esi pointer to return/work area (atleast 20 000 bytes) +;; +;; +;; on return +;; +;; eax = 0 command succesful +;; 1 no fd base and/or partition defined +;; 2 yet unsupported FS +;; 3 unknown FS +;; 4 partition not defined at hd +;; 5 file not found +;; ebx = size of file +; +; mov edi,[TASK_BASE] +; add edi,0x10 +; add esi,[edi] +; add eax,[edi] +; +; pushad +; mov edi,esi +; add edi,1024 +; mov esi,0x100000+19*512 +; sub ecx,1 +; shl ecx,9 +; add esi,ecx +; shl edx,9 +; mov ecx,edx +; cld +; rep movsb +; popad +; +; mov [esp+36],eax +; mov [esp+24],ebx +; ret + + + +align 4 +set_io_access_rights: + push edi eax + mov edi, tss._io_map_0 +; mov ecx,eax +; and ecx,7 ; offset in byte +; shr eax,3 ; number of byte +; add edi,eax +; mov ebx,1 +; shl ebx,cl + test ebp, ebp +; cmp ebp,0 ; enable access - ebp = 0 + jnz .siar1 +; not ebx +; and [edi],byte bl + btr [edi], eax + pop eax edi + ret +.siar1: + bts [edi], eax + ; or [edi],byte bl ; disable access - ebp = 1 + pop eax edi + ret +;reserve/free group of ports +; * eax = 46 - number function +; * ebx = 0 - reserve, 1 - free +; * ecx = number start arrea of ports +; * edx = number end arrea of ports (include last number of port) +;Return value: +; * eax = 0 - succesful +; * eax = 1 - error +; * The system has reserve this ports: +; 0..0x2d, 0x30..0x4d, 0x50..0xdf, 0xe5..0xff (include last number of port). +;destroys eax,ebx, ebp +r_f_port_area: + + test ebx, ebx + jnz free_port_area +; je r_port_area +; jmp free_port_area + +; r_port_area: + +; pushad + + cmp ecx, edx ; beginning > end ? + ja rpal1 + cmp edx, 65536 + jae rpal1 + mov eax, [RESERVED_PORTS] + test eax, eax ; no reserved areas ? + je rpal2 + cmp eax, 255 ; max reserved + jae rpal1 + rpal3: + mov ebx, eax + shl ebx, 4 + add ebx, RESERVED_PORTS + cmp ecx, [ebx+8] + ja rpal4 + cmp edx, [ebx+4] + jae rpal1 +; jb rpal4 +; jmp rpal1 + rpal4: + dec eax + jnz rpal3 + jmp rpal2 + rpal1: +; popad +; mov eax,1 + xor eax, eax + inc eax + ret + rpal2: +; popad + ; enable port access at port IO map + cli + pushad ; start enable io map + + cmp edx, 65536;16384 + jae no_unmask_io; jge + mov eax, ecx +; push ebp + xor ebp, ebp ; enable - eax = port +new_port_access: +; pushad + call set_io_access_rights +; popad + inc eax + cmp eax, edx + jbe new_port_access +; pop ebp +no_unmask_io: + popad ; end enable io map + sti + + mov eax, [RESERVED_PORTS] + add eax, 1 + mov [RESERVED_PORTS], eax + shl eax, 4 + add eax, RESERVED_PORTS + mov ebx, [TASK_BASE] + mov ebx, [ebx+TASKDATA.pid] + mov [eax], ebx + mov [eax+4], ecx + mov [eax+8], edx + + xor eax, eax + ret + +free_port_area: + +; pushad + mov eax, [RESERVED_PORTS]; no reserved areas ? + test eax, eax + jz frpal2 + mov ebx, [TASK_BASE] + mov ebx, [ebx+TASKDATA.pid] + frpal3: + mov edi, eax + shl edi, 4 + add edi, RESERVED_PORTS + cmp ebx, [edi] + jne frpal4 + cmp ecx, [edi+4] + jne frpal4 + cmp edx, [edi+8] + jne frpal4 + jmp frpal1 + frpal4: + dec eax + jnz frpal3 + frpal2: +; popad + inc eax + ret + frpal1: + push ecx + mov ecx, 256 + sub ecx, eax + shl ecx, 4 + mov esi, edi + add esi, 16 + cld + rep movsb + + dec dword [RESERVED_PORTS] +;popad +;disable port access at port IO map + +; pushad ; start disable io map + pop eax ;start port + cmp edx, 65536;16384 + jge no_mask_io + +; mov eax,ecx + xor ebp, ebp + inc ebp +new_port_access_disable: +; pushad +; mov ebp,1 ; disable - eax = port + call set_io_access_rights +; popad + inc eax + cmp eax, edx + jbe new_port_access_disable +no_mask_io: +; popad ; end disable io map + xor eax, eax + ret + + +align 4 +drawbackground: + inc [mouse_pause] + cmp [SCR_MODE], word 0x12 + je dbrv20 + dbrv12: + cmp [SCR_MODE], word 0100000000000000b + jge dbrv20 + cmp [SCR_MODE], word 0x13 + je dbrv20 + call vesa12_drawbackground + dec [mouse_pause] + call [draw_pointer] + ret + dbrv20: + cmp [BgrDrawMode], dword 1 + jne bgrstr + call vesa20_drawbackground_tiled + dec [mouse_pause] + call [draw_pointer] + ret + bgrstr: + call vesa20_drawbackground_stretch + dec [mouse_pause] + call [draw_pointer] + ret + +align 4 + +syscall_putimage: ; PutImage +sys_putimage: + test ecx, 0x80008000 + jnz .exit + test ecx, 0x0000FFFF + jz .exit + test ecx, 0xFFFF0000 + jnz @f + .exit: + ret + @@: + mov edi, [current_slot] + add dx, word[edi+APPDATA.wnd_clientbox.top] + rol edx, 16 + add dx, word[edi+APPDATA.wnd_clientbox.left] + rol edx, 16 + .forced: + push ebp esi 0 + mov ebp, putimage_get24bpp + mov esi, putimage_init24bpp +sys_putimage_bpp: +; call [disable_mouse] ; this will be done in xxx_putimage +; mov eax, vga_putimage + cmp [SCR_MODE], word 0x12 + jz @f ;.doit + mov eax, vesa12_putimage + cmp [SCR_MODE], word 0100000000000000b + jae @f + cmp [SCR_MODE], word 0x13 + jnz .doit +@@: + mov eax, vesa20_putimage +.doit: + inc [mouse_pause] + call eax + dec [mouse_pause] + pop ebp esi ebp + jmp [draw_pointer] +align 4 +sys_putimage_palette: +; ebx = pointer to image +; ecx = [xsize]*65536 + [ysize] +; edx = [xstart]*65536 + [ystart] +; esi = number of bits per pixel, must be 8, 24 or 32 +; edi = pointer to palette +; ebp = row delta + mov eax, [CURRENT_TASK] + shl eax, 8 + add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.top] + rol edx, 16 + add dx, word [eax+SLOT_BASE+APPDATA.wnd_clientbox.left] + rol edx, 16 +.forced: + cmp esi, 1 + jnz @f + push edi + mov eax, [edi+4] + sub eax, [edi] + push eax + push dword [edi] + push 0ffffff80h + mov edi, esp + call put_mono_image + add esp, 12 + pop edi + ret +@@: + cmp esi, 2 + jnz @f + push edi + push 0ffffff80h + mov edi, esp + call put_2bit_image + pop eax + pop edi + ret +@@: + cmp esi, 4 + jnz @f + push edi + push 0ffffff80h + mov edi, esp + call put_4bit_image + pop eax + pop edi + ret +@@: + push ebp esi ebp + cmp esi, 8 + jnz @f + mov ebp, putimage_get8bpp + mov esi, putimage_init8bpp + jmp sys_putimage_bpp +@@: + cmp esi, 15 + jnz @f + mov ebp, putimage_get15bpp + mov esi, putimage_init15bpp + jmp sys_putimage_bpp +@@: + cmp esi, 16 + jnz @f + mov ebp, putimage_get16bpp + mov esi, putimage_init16bpp + jmp sys_putimage_bpp +@@: + cmp esi, 24 + jnz @f + mov ebp, putimage_get24bpp + mov esi, putimage_init24bpp + jmp sys_putimage_bpp +@@: + cmp esi, 32 + jnz @f + mov ebp, putimage_get32bpp + mov esi, putimage_init32bpp + jmp sys_putimage_bpp +@@: + pop ebp esi ebp + ret + +put_mono_image: + push ebp esi ebp + mov ebp, putimage_get1bpp + mov esi, putimage_init1bpp + jmp sys_putimage_bpp +put_2bit_image: + push ebp esi ebp + mov ebp, putimage_get2bpp + mov esi, putimage_init2bpp + jmp sys_putimage_bpp +put_4bit_image: + push ebp esi ebp + mov ebp, putimage_get4bpp + mov esi, putimage_init4bpp + jmp sys_putimage_bpp + +putimage_init24bpp: + lea eax, [eax*3] +putimage_init8bpp: + ret + +align 16 +putimage_get24bpp: + movzx eax, byte [esi+2] + shl eax, 16 + mov ax, [esi] + add esi, 3 + ret 4 +align 16 +putimage_get8bpp: + movzx eax, byte [esi] + push edx + mov edx, [esp+8] + mov eax, [edx+eax*4] + pop edx + inc esi + ret 4 + +putimage_init1bpp: + add eax, ecx + push ecx + add eax, 7 + add ecx, 7 + shr eax, 3 + shr ecx, 3 + sub eax, ecx + pop ecx + ret +align 16 +putimage_get1bpp: + push edx + mov edx, [esp+8] + mov al, [edx] + add al, al + jnz @f + lodsb + adc al, al +@@: + mov [edx], al + sbb eax, eax + and eax, [edx+8] + add eax, [edx+4] + pop edx + ret 4 + +putimage_init2bpp: + add eax, ecx + push ecx + add ecx, 3 + add eax, 3 + shr ecx, 2 + shr eax, 2 + sub eax, ecx + pop ecx + ret +align 16 +putimage_get2bpp: + push edx + mov edx, [esp+8] + mov al, [edx] + mov ah, al + shr al, 6 + shl ah, 2 + jnz .nonewbyte + lodsb + mov ah, al + shr al, 6 + shl ah, 2 + add ah, 1 +.nonewbyte: + mov [edx], ah + mov edx, [edx+4] + movzx eax, al + mov eax, [edx+eax*4] + pop edx + ret 4 + +putimage_init4bpp: + add eax, ecx + push ecx + add ecx, 1 + add eax, 1 + shr ecx, 1 + shr eax, 1 + sub eax, ecx + pop ecx + ret +align 16 +putimage_get4bpp: + push edx + mov edx, [esp+8] + add byte [edx], 80h + jc @f + movzx eax, byte [edx+1] + mov edx, [edx+4] + and eax, 0x0F + mov eax, [edx+eax*4] + pop edx + ret 4 +@@: + movzx eax, byte [esi] + add esi, 1 + mov [edx+1], al + shr eax, 4 + mov edx, [edx+4] + mov eax, [edx+eax*4] + pop edx + ret 4 + +putimage_init32bpp: + shl eax, 2 + ret +align 16 +putimage_get32bpp: + lodsd + ret 4 + +putimage_init15bpp: +putimage_init16bpp: + add eax, eax + ret +align 16 +putimage_get15bpp: +; 0RRRRRGGGGGBBBBB -> 00000000RRRRR000GGGGG000BBBBB000 + push ecx edx + movzx eax, word [esi] + add esi, 2 + mov ecx, eax + mov edx, eax + and eax, 0x1F + and ecx, 0x1F shl 5 + and edx, 0x1F shl 10 + shl eax, 3 + shl ecx, 6 + shl edx, 9 + or eax, ecx + or eax, edx + pop edx ecx + ret 4 + +align 16 +putimage_get16bpp: +; RRRRRGGGGGGBBBBB -> 00000000RRRRR000GGGGGG00BBBBB000 + push ecx edx + movzx eax, word [esi] + add esi, 2 + mov ecx, eax + mov edx, eax + and eax, 0x1F + and ecx, 0x3F shl 5 + and edx, 0x1F shl 11 + shl eax, 3 + shl ecx, 5 + shl edx, 8 + or eax, ecx + or eax, edx + pop edx ecx + ret 4 + +; eax x beginning +; ebx y beginning +; ecx x end + ; edx y end +; edi color + +__sys_drawbar: + mov esi, [current_slot] + add eax, [esi+APPDATA.wnd_clientbox.left] + add ecx, [esi+APPDATA.wnd_clientbox.left] + add ebx, [esi+APPDATA.wnd_clientbox.top] + add edx, [esi+APPDATA.wnd_clientbox.top] + .forced: + inc [mouse_pause] +; call [disable_mouse] + cmp [SCR_MODE], word 0x12 + je dbv20 + sdbv20: + cmp [SCR_MODE], word 0100000000000000b + jge dbv20 + cmp [SCR_MODE], word 0x13 + je dbv20 + call vesa12_drawbar + dec [mouse_pause] + call [draw_pointer] + ret + dbv20: + call vesa20_drawbar + dec [mouse_pause] + call [draw_pointer] + ret + + + +kb_read: + + push ecx edx + + mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's + kr_loop: + in al, 0x64 + test al, 1 + jnz kr_ready + loop kr_loop + mov ah, 1 + jmp kr_exit + kr_ready: + push ecx + mov ecx, 32 + kr_delay: + loop kr_delay + pop ecx + in al, 0x60 + xor ah, ah + kr_exit: + + pop edx ecx + + ret + + +kb_write: + + push ecx edx + + mov dl, al +; mov ecx,0x1ffff ; last 0xffff, new value in view of fast CPU's +; kw_loop1: +; in al,0x64 +; test al,0x20 +; jz kw_ok1 +; loop kw_loop1 +; mov ah,1 +; jmp kw_exit +; kw_ok1: + in al, 0x60 + mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's + kw_loop: + in al, 0x64 + test al, 2 + jz kw_ok + loop kw_loop + mov ah, 1 + jmp kw_exit + kw_ok: + mov al, dl + out 0x60, al + mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's + kw_loop3: + in al, 0x64 + test al, 2 + jz kw_ok3 + loop kw_loop3 + mov ah, 1 + jmp kw_exit + kw_ok3: + mov ah, 8 + kw_loop4: + mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's + kw_loop5: + in al, 0x64 + test al, 1 + jnz kw_ok4 + loop kw_loop5 + dec ah + jnz kw_loop4 + kw_ok4: + xor ah, ah + kw_exit: + + pop edx ecx + + ret + + +kb_cmd: + + mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's + c_wait: + in al, 0x64 + test al, 2 + jz c_send + loop c_wait + jmp c_error + c_send: + mov al, bl + out 0x64, al + mov ecx, 0x1ffff; last 0xffff, new value in view of fast CPU's + c_accept: + in al, 0x64 + test al, 2 + jz c_ok + loop c_accept + c_error: + mov ah, 1 + jmp c_exit + c_ok: + xor ah, ah + c_exit: + ret + + +setmouse: ; set mousepicture -pointer + ; ps2 mouse enable + + mov [MOUSE_PICTURE], dword mousepointer + + cli + + ret + +if used _rdtsc +_rdtsc: + bt [cpu_caps], CAPS_TSC + jnc ret_rdtsc + rdtsc + ret + ret_rdtsc: + mov edx, 0xffffffff + mov eax, 0xffffffff + ret +end if + +sys_msg_board_str: + + pushad + @@: + cmp [esi], byte 0 + je @f + mov eax, 1 + movzx ebx, byte [esi] + call sys_msg_board + inc esi + jmp @b + @@: + popad + ret + +sys_msg_board_byte: +; in: al = byte to display +; out: nothing +; destroys: nothing + pushad + mov ecx, 2 + shl eax, 24 + jmp @f + +sys_msg_board_word: +; in: ax = word to display +; out: nothing +; destroys: nothing + pushad + mov ecx, 4 + shl eax, 16 + jmp @f + +sys_msg_board_dword: +; in: eax = dword to display +; out: nothing +; destroys: nothing + pushad + mov ecx, 8 +@@: + push ecx + rol eax, 4 + push eax + and al, 0xF + cmp al, 10 + sbb al, 69h + das + mov bl, al + xor eax, eax + inc eax + call sys_msg_board + pop eax + pop ecx + loop @b + popad + ret + +uglobal + msg_board_data: + times 4096 db 0 + msg_board_count dd 0x0 +endg + +sys_msg_board: + +; eax=1 : write : bl byte to write +; eax=2 : read : ebx=0 -> no data, ebx=1 -> data in al + + mov ecx, [msg_board_count] + cmp eax, 1 + jne .smbl1 + +if defined debug_com_base + + push dx ax + + @@: ; Wait for empty transmit register (yes, this slows down system..) + mov dx, debug_com_base+5 + in al, dx + test al, 1 shl 5 + jz @r + + mov dx, debug_com_base ; Output the byte + mov al, bl + out dx, al + + pop ax dx + +end if + + mov [msg_board_data+ecx], bl + inc ecx + and ecx, 4095 + mov [msg_board_count], ecx + mov [check_idle_semaphore], 5 + ret +.smbl1: + cmp eax, 2 + jne .smbl2 + test ecx, ecx + jz .smbl21 + mov eax, msg_board_data+1 + mov ebx, msg_board_data + movzx edx, byte [ebx] + call memmove + dec [msg_board_count] + mov [esp + 36], edx ;eax + mov [esp + 24], dword 1 + ret +.smbl21: + mov [esp+36], ecx + mov [esp+24], ecx +.smbl2: + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 66 sys function. ;; +;; in eax=66,ebx in [0..5],ecx,edx ;; +;; out eax ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +iglobal +align 4 +f66call: + dd sys_process_def.1 ; 1 = set keyboard mode + dd sys_process_def.2 ; 2 = get keyboard mode + dd sys_process_def.3 ; 3 = get keyboard ctrl, alt, shift + dd sys_process_def.4 + dd sys_process_def.5 +endg + + + + +sys_process_def: + dec ebx + cmp ebx, 5 + jae .not_support ;if >=6 then or eax,-1 + + mov edi, [CURRENT_TASK] + jmp dword [f66call+ebx*4] + +.not_support: + or eax, -1 + ret + +.1: + shl edi, 8 + mov [edi+SLOT_BASE + APPDATA.keyboard_mode], cl + + ret + +.2: ; 2 = get keyboard mode + shl edi, 8 + movzx eax, byte [SLOT_BASE+edi + APPDATA.keyboard_mode] + mov [esp+32], eax + ret +; xor eax,eax +; movzx eax,byte [shift] +; movzx ebx,byte [ctrl] +; shl ebx,2 +; add eax,ebx +; movzx ebx,byte [alt] +; shl ebx,3 +; add eax,ebx +.3: ;3 = get keyboard ctrl, alt, shift + ;// mike.dld [ + mov eax, [kb_state] + ;// mike.dld ] + mov [esp+32], eax + ret + +.4: + mov eax, hotkey_list +@@: + cmp dword [eax+8], 0 + jz .found_free + add eax, 16 + cmp eax, hotkey_list+16*256 + jb @b + mov dword [esp+32], 1 + ret +.found_free: + mov [eax+8], edi + mov [eax+4], edx + movzx ecx, cl + lea ecx, [hotkey_scancodes+ecx*4] + mov edx, [ecx] + mov [eax], edx + mov [ecx], eax + mov [eax+12], ecx + jecxz @f + mov [edx+12], eax +@@: + and dword [esp+32], 0 + ret + +.5: + movzx ebx, cl + lea ebx, [hotkey_scancodes+ebx*4] + mov eax, [ebx] +.scan: + test eax, eax + jz .notfound + cmp [eax+8], edi + jnz .next + cmp [eax+4], edx + jz .found +.next: + mov eax, [eax] + jmp .scan +.notfound: + mov dword [esp+32], 1 + ret +.found: + mov ecx, [eax] + jecxz @f + mov edx, [eax+12] + mov [ecx+12], edx +@@: + mov ecx, [eax+12] + mov edx, [eax] + mov [ecx], edx + xor edx, edx + mov [eax+4], edx + mov [eax+8], edx + mov [eax+12], edx + mov [eax], edx + mov [esp+32], edx + ret + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 61 sys function. ;; +;; in eax=61,ebx in [1..3] ;; +;; out eax ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +iglobal +align 4 +f61call: + dd sys_gs.1 ; resolution + dd sys_gs.2 ; bits per pixel + dd sys_gs.3 ; bytes per scanline +endg + + +align 4 + +sys_gs: ; direct screen access + dec ebx + cmp ebx, 2 + ja .not_support + jmp dword [f61call+ebx*4] +.not_support: + or [esp+32], dword -1 + ret + + +.1: ; resolution + mov eax, [Screen_Max_X] + shl eax, 16 + mov ax, [Screen_Max_Y] + add eax, 0x00010001 + mov [esp+32], eax + ret +.2: ; bits per pixel + movzx eax, byte [ScreenBPP] + mov [esp+32], eax + ret +.3: ; bytes per scanline + mov eax, [BytesPerScanLine] + mov [esp+32], eax + ret + +align 4 ; system functions + +syscall_setpixel: ; SetPixel + + mov eax, ebx + mov ebx, ecx + mov ecx, edx + mov edx, [TASK_BASE] + add eax, [edx-twdw+WDATA.box.left] + add ebx, [edx-twdw+WDATA.box.top] + mov edi, [current_slot] + add eax, [edi+APPDATA.wnd_clientbox.left] + add ebx, [edi+APPDATA.wnd_clientbox.top] + xor edi, edi ; no force +; mov edi, 1 + call [_display.disable_mouse] + jmp [putpixel] + +align 4 + +syscall_writetext: ; WriteText + + mov eax, [TASK_BASE] + mov ebp, [eax-twdw+WDATA.box.left] + push esi + mov esi, [current_slot] + add ebp, [esi+APPDATA.wnd_clientbox.left] + shl ebp, 16 + add ebp, [eax-twdw+WDATA.box.top] + add bp, word[esi+APPDATA.wnd_clientbox.top] + pop esi + add ebx, ebp + mov eax, edi + xor edi, edi + jmp dtext + +align 4 + +syscall_openramdiskfile: ; OpenRamdiskFile + + mov eax, ebx + mov ebx, ecx + mov ecx, edx + mov edx, esi + mov esi, 12 + call fileread + mov [esp+32], eax + ret + +align 4 + +syscall_drawrect: ; DrawRect + + mov edi, edx ; color + gradient + and edi, 0x80FFFFFF + test bx, bx ; x.size + je .drectr + test cx, cx ; y.size + je .drectr + + mov eax, ebx ; bad idea + mov ebx, ecx + + movzx ecx, ax ; ecx - x.size + shr eax, 16 ; eax - x.coord + movzx edx, bx ; edx - y.size + shr ebx, 16 ; ebx - y.coord + mov esi, [current_slot] + + add eax, [esi + APPDATA.wnd_clientbox.left] + add ebx, [esi + APPDATA.wnd_clientbox.top] + add ecx, eax + add edx, ebx + jmp [drawbar] +.drectr: + ret + +align 4 +syscall_getscreensize: ; GetScreenSize + mov ax, [Screen_Max_X] + shl eax, 16 + mov ax, [Screen_Max_Y] + mov [esp + 32], eax + ret + +align 4 + +syscall_cdaudio: ; CD + + cmp ebx, 4 + jb .audio + jz .eject + cmp ebx, 5 + jnz .ret +.load: + call .reserve + call LoadMedium + ;call .free + jmp .free +; ret +.eject: + call .reserve + call clear_CD_cache + call allow_medium_removal + call EjectMedium +; call .free + jmp .free +; ret +.audio: + call sys_cd_audio + mov [esp+36-4], eax +.ret: + ret + +.reserve: + call reserve_cd + mov eax, ecx + shr eax, 1 + and eax, 1 + inc eax + mov [ChannelNumber], ax + mov eax, ecx + and eax, 1 + mov [DiskNumber], al + call reserve_cd_channel + and ebx, 3 + inc ebx + mov [cdpos], ebx + add ebx, ebx + mov cl, 8 + sub cl, bl + mov al, [DRIVE_DATA+1] + shr al, cl + test al, 2 + jz .free;.err + ret +.free: + call free_cd_channel + and [cd_status], 0 + ret +.err: + call .free +; pop eax + ret + +align 4 + +syscall_getpixel: ; GetPixel + mov ecx, [Screen_Max_X] + inc ecx + xor edx, edx + mov eax, ebx + div ecx + mov ebx, edx + xchg eax, ebx + call dword [GETPIXEL]; eax - x, ebx - y + mov [esp + 32], ecx + ret + +align 4 + +syscall_getarea: +;eax = 36 +;ebx = pointer to bufer for img BBGGRRBBGGRR... +;ecx = [size x]*65536 + [size y] +;edx = [start x]*65536 + [start y] + pushad + inc [mouse_pause] +; Check of use of the hardware cursor. + cmp [_display.disable_mouse], __sys_disable_mouse + jne @f +; Since the test for the coordinates of the mouse should not be used, +; then use the call [disable_mouse] is not possible! + cmp dword [MOUSE_VISIBLE], dword 0 + jne @f + pushf + cli + call draw_mouse_under + popf + mov [MOUSE_VISIBLE], dword 1 +@@: + mov edi, ebx + mov eax, edx + shr eax, 16 + mov ebx, edx + and ebx, 0xffff + dec eax + dec ebx + ; eax - x, ebx - y + mov edx, ecx + + shr ecx, 16 + and edx, 0xffff + mov esi, ecx + ; ecx - size x, edx - size y + + mov ebp, edx + dec ebp + lea ebp, [ebp*3] + + imul ebp, esi + + mov esi, ecx + dec esi + lea esi, [esi*3] + + add ebp, esi + add ebp, edi + + add ebx, edx + +.start_y: + push ecx edx +.start_x: + push eax ebx ecx + add eax, ecx + + call dword [GETPIXEL]; eax - x, ebx - y + + mov [ebp], cx + shr ecx, 16 + mov [ebp+2], cl + + pop ecx ebx eax + sub ebp, 3 + dec ecx + jnz .start_x + pop edx ecx + dec ebx + dec edx + jnz .start_y + dec [mouse_pause] +; Check of use of the hardware cursor. + cmp [_display.disable_mouse], __sys_disable_mouse + jne @f + call [draw_pointer] +@@: + popad + ret + +align 4 + +syscall_drawline: ; DrawLine + + mov edi, [TASK_BASE] + movzx eax, word[edi-twdw+WDATA.box.left] + mov ebp, eax + mov esi, [current_slot] + add ebp, [esi+APPDATA.wnd_clientbox.left] + add ax, word[esi+APPDATA.wnd_clientbox.left] + add ebp, ebx + shl eax, 16 + movzx ebx, word[edi-twdw+WDATA.box.top] + add eax, ebp + mov ebp, ebx + add ebp, [esi+APPDATA.wnd_clientbox.top] + add bx, word[esi+APPDATA.wnd_clientbox.top] + add ebp, ecx + shl ebx, 16 + xor edi, edi + add ebx, ebp + mov ecx, edx + jmp [draw_line] + + + +align 4 +syscall_reserveportarea: ; ReservePortArea and FreePortArea + + call r_f_port_area + mov [esp+32], eax + ret + +align 4 +syscall_threads: ; CreateThreads +; eax=1 create thread +; +; ebx=thread start +; ecx=thread stack value +; +; on return : eax = pid + + call new_sys_threads + + mov [esp+32], eax + ret + +align 4 + +stack_driver_stat: + + call app_stack_handler ; Stack status + +; mov [check_idle_semaphore],5 ; enable these for zero delay +; call change_task ; between sent packet + + mov [esp+32], eax + ret + +align 4 + +socket: ; Socket interface + call app_socket_handler + +; mov [check_idle_semaphore],5 ; enable these for zero delay +; call change_task ; between sent packet + + mov [esp+36], eax + mov [esp+24], ebx + ret + +align 4 + +read_from_hd: ; Read from hd - fn not in use + + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add eax, [edi] + add ecx, [edi] + add edx, [edi] + call file_read + + mov [esp+36], eax + mov [esp+24], ebx + + ret + +paleholder: + ret + +align 4 +set_screen: + cmp eax, [Screen_Max_X] + jne .set + + cmp edx, [Screen_Max_Y] + jne .set + ret +.set: + pushfd + cli + + mov [Screen_Max_X], eax + mov [Screen_Max_Y], edx + mov [BytesPerScanLine], ecx + + mov [screen_workarea.right], eax + mov [screen_workarea.bottom], edx + + push ebx + push esi + push edi + + pushad + + stdcall kernel_free, [_WinMapAddress] + + mov eax, [_display.width] + mul [_display.height] + mov [_WinMapSize], eax + + stdcall kernel_alloc, eax + mov [_WinMapAddress], eax + test eax, eax + jz .epic_fail + + popad + + call repos_windows + xor eax, eax + xor ebx, ebx + mov ecx, [Screen_Max_X] + mov edx, [Screen_Max_Y] + call calculatescreen + pop edi + pop esi + pop ebx + + popfd + ret + +.epic_fail: + hlt ; Houston, we've had a problem + +; --------------- APM --------------------- +uglobal +apm_entry dp 0 +apm_vf dd 0 +endg + +align 4 +sys_apm: + xor eax, eax + cmp word [apm_vf], ax ; Check APM BIOS enable + jne @f + inc eax + or dword [esp + 44], eax ; error + add eax, 7 + mov dword [esp + 32], eax ; 32-bit protected-mode interface not supported + ret + +@@: +; xchg eax, ecx +; xchg ebx, ecx + + cmp dx, 3 + ja @f + and [esp + 44], byte 0xfe ; emulate func 0..3 as func 0 + mov eax, [apm_vf] + mov [esp + 32], eax + shr eax, 16 + mov [esp + 28], eax + ret + +@@: + + mov esi, [master_tab+(OS_BASE shr 20)] + xchg [master_tab], esi + push esi + mov edi, cr3 + mov cr3, edi ;flush TLB + + call pword [apm_entry] ;call APM BIOS + + xchg eax, [esp] + mov [master_tab], eax + mov eax, cr3 + mov cr3, eax + pop eax + + mov [esp + 4 ], edi + mov [esp + 8], esi + mov [esp + 20], ebx + mov [esp + 24], edx + mov [esp + 28], ecx + mov [esp + 32], eax + setc al + and [esp + 44], byte 0xfe + or [esp + 44], al + ret +; ----------------------------------------- + +align 4 + +undefined_syscall: ; Undefined system call + mov [esp + 32], dword -1 + ret + +align 4 +system_shutdown: ; shut down the system + + cmp byte [BOOT_VAR+0x9030], 1 + jne @F + ret +@@: + call stop_all_services + push 3 ; stop playing cd + pop eax + call sys_cd_audio + +yes_shutdown_param: + cli + +if ~ defined extended_primary_loader + mov eax, kernel_file ; load kernel.mnt to 0x7000:0 + push 12 + pop esi + xor ebx, ebx + or ecx, -1 + mov edx, OS_BASE+0x70000 + call fileread + + mov esi, restart_kernel_4000+OS_BASE+0x10000 ; move kernel re-starter to 0x4000:0 + mov edi, OS_BASE+0x40000 + mov ecx, 1000 + rep movsb +end if + + mov esi, BOOT_VAR ; restore 0x0 - 0xffff + mov edi, OS_BASE + mov ecx, 0x10000/4 + cld + rep movsd + + call restorefatchain + + call IRQ_mask_all + +if 0 + mov word [OS_BASE+0x467+0], pr_mode_exit + mov word [OS_BASE+0x467+2], 0x1000 + + mov al, 0x0F + out 0x70, al + mov al, 0x05 + out 0x71, al + + mov al, 0xFE + out 0x64, al + + hlt + jmp $-1 + +else + cmp byte [OS_BASE + 0x9030], 2 + jnz no_acpi_power_off + +; scan for RSDP +; 1) The first 1 Kb of the Extended BIOS Data Area (EBDA). + movzx eax, word [OS_BASE + 0x40E] + shl eax, 4 + jz @f + mov ecx, 1024/16 + call scan_rsdp + jnc .rsdp_found +@@: +; 2) The BIOS read-only memory space between 0E0000h and 0FFFFFh. + mov eax, 0xE0000 + mov ecx, 0x2000 + call scan_rsdp + jc no_acpi_power_off +.rsdp_found: + mov esi, [eax+16] ; esi contains physical address of the RSDT + mov ebp, [ipc_tmp] + stdcall map_page, ebp, esi, PG_MAP + lea eax, [esi+1000h] + lea edx, [ebp+1000h] + stdcall map_page, edx, eax, PG_MAP + and esi, 0xFFF + add esi, ebp + cmp dword [esi], 'RSDT' + jnz no_acpi_power_off + mov ecx, [esi+4] + sub ecx, 24h + jbe no_acpi_power_off + shr ecx, 2 + add esi, 24h +.scan_fadt: + lodsd + mov ebx, eax + lea eax, [ebp+2000h] + stdcall map_page, eax, ebx, PG_MAP + lea eax, [ebp+3000h] + add ebx, 0x1000 + stdcall map_page, eax, ebx, PG_MAP + and ebx, 0xFFF + lea ebx, [ebx+ebp+2000h] + cmp dword [ebx], 'FACP' + jz .fadt_found + loop .scan_fadt + jmp no_acpi_power_off +.fadt_found: +; ebx is linear address of FADT + mov edi, [ebx+40] ; physical address of the DSDT + lea eax, [ebp+4000h] + stdcall map_page, eax, edi, PG_MAP + lea eax, [ebp+5000h] + lea esi, [edi+0x1000] + stdcall map_page, eax, esi, PG_MAP + and esi, 0xFFF + sub edi, esi + cmp dword [esi+ebp+4000h], 'DSDT' + jnz no_acpi_power_off + mov eax, [esi+ebp+4004h] ; DSDT length + sub eax, 36+4 + jbe no_acpi_power_off + add esi, 36 +.scan_dsdt: + cmp dword [esi+ebp+4000h], '_S5_' + jnz .scan_dsdt_cont + cmp byte [esi+ebp+4000h+4], 12h ; DefPackage opcode + jnz .scan_dsdt_cont + mov dl, [esi+ebp+4000h+6] + cmp dl, 4 ; _S5_ package must contain 4 bytes + ; ...in theory; in practice, VirtualBox has 2 bytes + ja .scan_dsdt_cont + cmp dl, 1 + jb .scan_dsdt_cont + lea esi, [esi+ebp+4000h+7] + xor ecx, ecx + cmp byte [esi], 0 ; 0 means zero byte, 0Ah xx means byte xx + jz @f + cmp byte [esi], 0xA + jnz no_acpi_power_off + inc esi + mov cl, [esi] +@@: + inc esi + cmp dl, 2 + jb @f + cmp byte [esi], 0 + jz @f + cmp byte [esi], 0xA + jnz no_acpi_power_off + inc esi + mov ch, [esi] +@@: + jmp do_acpi_power_off +.scan_dsdt_cont: + inc esi + cmp esi, 0x1000 + jb @f + sub esi, 0x1000 + add edi, 0x1000 + push eax + lea eax, [ebp+4000h] + stdcall map_page, eax, edi, PG_MAP + push PG_MAP + lea eax, [edi+1000h] + push eax + lea eax, [ebp+5000h] + push eax + stdcall map_page + pop eax +@@: + dec eax + jnz .scan_dsdt + jmp no_acpi_power_off +do_acpi_power_off: + mov edx, [ebx+48] + test edx, edx + jz .nosmi + mov al, [ebx+52] + out dx, al + mov edx, [ebx+64] +@@: + in ax, dx + test al, 1 + jz @b +.nosmi: + and cx, 0x0707 + shl cx, 2 + or cx, 0x2020 + mov edx, [ebx+64] + in ax, dx + and ax, 203h + or ah, cl + out dx, ax + mov edx, [ebx+68] + test edx, edx + jz @f + in ax, dx + and ax, 203h + or ah, ch + out dx, ax +@@: + jmp $ + + +no_acpi_power_off: + mov word [OS_BASE+0x467+0], pr_mode_exit + mov word [OS_BASE+0x467+2], 0x1000 + + mov al, 0x0F + out 0x70, al + mov al, 0x05 + out 0x71, al + + mov al, 0xFE + out 0x64, al + + hlt + jmp $-1 + +scan_rsdp: + add eax, OS_BASE +.s: + cmp dword [eax], 'RSD ' + jnz .n + cmp dword [eax+4], 'PTR ' + jnz .n + xor edx, edx + xor esi, esi +@@: + add dl, [eax+esi] + inc esi + cmp esi, 20 + jnz @b + test dl, dl + jz .ok +.n: + add eax, 10h + loop .s + stc +.ok: + ret +end if + +include "data32.inc" + +__REV__ = __REV + +uglobals_size = $ - endofcode +diff16 "end of kernel code",0,$ diff --git a/kernel/trunk/kglobals.inc b/kernel/trunk/kglobals.inc index 3299a5ebe..25caea62f 100644 --- a/kernel/trunk/kglobals.inc +++ b/kernel/trunk/kglobals.inc @@ -1,69 +1,69 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;------------------------------------------------------------------ -; use "iglobal" for inserting initialized global data definitions. -;------------------------------------------------------------------ -macro iglobal { - IGlobals equ IGlobals, - macro __IGlobalBlock { } - -macro iglobal_nested { - IGlobals equ IGlobals, - macro __IGlobalBlock \{ } - -;------------------------------------------------------------- -; use 'uglobal' for inserting uninitialized global definitions. -; even when you define some data values, these variables -; will be stored as uninitialized data. -;------------------------------------------------------------- -macro uglobal { - UGlobals equ UGlobals, - macro __UGlobalBlock { } - -macro uglobal_nested { - UGlobals equ UGlobals, - macro __UGlobalBlock \{ } - -endg fix } ; Use endg for ending iglobal and uglobal blocks. -endg_nested fix \} - -macro IncludeIGlobals{ - macro IGlobals dummy,[n] \{ __IGlobalBlock - purge __IGlobalBlock \} - match I, IGlobals \{ I \} } - - -macro IncludeUGlobals{ - macro UGlobals dummy,[n] \{ - \common - \local begin, size - begin = $ - virtual at $ - \forward - __UGlobalBlock - purge __UGlobalBlock - \common - size = $ - begin - end virtual - rb size - \} - match U, UGlobals \{ U \} } - -macro IncludeAllGlobals { - IncludeIGlobals - IncludeUGlobals -} - -iglobal -endg - -uglobal -endg +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;------------------------------------------------------------------ +; use "iglobal" for inserting initialized global data definitions. +;------------------------------------------------------------------ +macro iglobal { + IGlobals equ IGlobals, + macro __IGlobalBlock { } + +macro iglobal_nested { + IGlobals equ IGlobals, + macro __IGlobalBlock \{ } + +;------------------------------------------------------------- +; use 'uglobal' for inserting uninitialized global definitions. +; even when you define some data values, these variables +; will be stored as uninitialized data. +;------------------------------------------------------------- +macro uglobal { + UGlobals equ UGlobals, + macro __UGlobalBlock { } + +macro uglobal_nested { + UGlobals equ UGlobals, + macro __UGlobalBlock \{ } + +endg fix } ; Use endg for ending iglobal and uglobal blocks. +endg_nested fix \} + +macro IncludeIGlobals{ + macro IGlobals dummy,[n] \{ __IGlobalBlock + purge __IGlobalBlock \} + match I, IGlobals \{ I \} } + + +macro IncludeUGlobals{ + macro UGlobals dummy,[n] \{ + \common + \local begin, size + begin = $ + virtual at $ + \forward + __UGlobalBlock + purge __UGlobalBlock + \common + size = $ - begin + end virtual + rb size + \} + match U, UGlobals \{ U \} } + +macro IncludeAllGlobals { + IncludeIGlobals + IncludeUGlobals +} + +iglobal +endg + +uglobal +endg diff --git a/kernel/trunk/macros.inc b/kernel/trunk/macros.inc index 30bbf66cf..a7906bc5b 100644 --- a/kernel/trunk/macros.inc +++ b/kernel/trunk/macros.inc @@ -1,138 +1,138 @@ - -__REV = 0 - -macro $Revision a { - match =: Num =$,a \{ - if __REV < Num - __REV = Num - end if - \} -} - -$Revision$ - - -; structure definition helper -macro struct name, [arg] - { - common - name@struct equ name - struc name arg { - } - -macro declare_sizeof xname,value -{ sizeof.#xname = value } - -macro struct_helper name - { - match xname,name - \{ - virtual at 0 - xname xname - declare_sizeof xname, $ - xname - name equ sizeof.#xname - end virtual - \} - } - -ends fix } struct_helper name@struct - -;// mike.dld, 2006-29-01 [ - -; macros definition -macro diff16 title,l1,l2 -{ - local s,d - s = l2-l1 - display title,': 0x' - repeat 16 - d = 48 + s shr ((16-%) shl 2) and $0F - if d > 57 - d = d + 65-57-1 - end if - display d - end repeat - display 13,10 -} -macro diff10 title,l1,l2 - { - local s,d,z,m - s = l2-l1 - z = 0 - m = 1000000000 - display title,': ' - repeat 10 - d = '0' + s / m - s = s - (s/m)*m - m = m / 10 - if d <> '0' - z = 1 - end if - if z <> 0 - display d - end if - end repeat - display 13,10 - } - -include 'kglobals.inc' - -; \begin{diamond}[29.09.2006] -; may be useful for kernel debugging -; example 1: -; dbgstr 'Hello, World!' -; example 2: -; dbgstr 'Hello, World!', save_flags -macro dbgstr string*, f -{ -local a -iglobal_nested -a db 'K : ',string,13,10,0 -endg_nested -if ~ f eq - pushfd -end if - push esi - mov esi, a - call sys_msg_board_str - pop esi -if ~ f eq - popfd -end if -} -; \end{diamond}[29.09.2006] - -macro Mov op1,op2,op3 ; op1 = op2 = op3 - { - mov op2,op3 - mov op1,op2 - } - -macro __list_add new, prev, next -{ - mov [next+LHEAD.prev], new - mov [new+LHEAD.next], next - mov [new+LHEAD.prev], prev - mov [prev+LHEAD.next], new -} - -macro list_add new, head -{ - mov eax, [head+LHEAD.next] - __list_add new, head, eax -} - -macro list_add_tail new, head -{ - mov eax, [head+LHEAD.prev] - __list_add new, eax, head -} - -macro list_del entry -{ - mov edx, [entry+list_fd] - mov ecx, [entry+list_bk] - mov [edx+list_bk], ecx - mov [ecx+list_fd], edx -} - + +__REV = 0 + +macro $Revision a { + match =: Num =$,a \{ + if __REV < Num + __REV = Num + end if + \} +} + +$Revision$ + + +; structure definition helper +macro struct name, [arg] + { + common + name@struct equ name + struc name arg { + } + +macro declare_sizeof xname,value +{ sizeof.#xname = value } + +macro struct_helper name + { + match xname,name + \{ + virtual at 0 + xname xname + declare_sizeof xname, $ - xname + name equ sizeof.#xname + end virtual + \} + } + +ends fix } struct_helper name@struct + +;// mike.dld, 2006-29-01 [ + +; macros definition +macro diff16 title,l1,l2 +{ + local s,d + s = l2-l1 + display title,': 0x' + repeat 16 + d = 48 + s shr ((16-%) shl 2) and $0F + if d > 57 + d = d + 65-57-1 + end if + display d + end repeat + display 13,10 +} +macro diff10 title,l1,l2 + { + local s,d,z,m + s = l2-l1 + z = 0 + m = 1000000000 + display title,': ' + repeat 10 + d = '0' + s / m + s = s - (s/m)*m + m = m / 10 + if d <> '0' + z = 1 + end if + if z <> 0 + display d + end if + end repeat + display 13,10 + } + +include 'kglobals.inc' + +; \begin{diamond}[29.09.2006] +; may be useful for kernel debugging +; example 1: +; dbgstr 'Hello, World!' +; example 2: +; dbgstr 'Hello, World!', save_flags +macro dbgstr string*, f +{ +local a +iglobal_nested +a db 'K : ',string,13,10,0 +endg_nested +if ~ f eq + pushfd +end if + push esi + mov esi, a + call sys_msg_board_str + pop esi +if ~ f eq + popfd +end if +} +; \end{diamond}[29.09.2006] + +macro Mov op1,op2,op3 ; op1 = op2 = op3 + { + mov op2, op3 + mov op1, op2 + } + +macro __list_add new, prev, next +{ + mov [next+LHEAD.prev], new + mov [new+LHEAD.next], next + mov [new+LHEAD.prev], prev + mov [prev+LHEAD.next], new +} + +macro list_add new, head +{ + mov eax, [head+LHEAD.next] + __list_add new, head, eax +} + +macro list_add_tail new, head +{ + mov eax, [head+LHEAD.prev] + __list_add new, eax, head +} + +macro list_del entry +{ + mov edx, [entry+list_fd] + mov ecx, [entry+list_bk] + mov [edx+list_bk], ecx + mov [ecx+list_fd], edx +} + diff --git a/kernel/trunk/memmap.inc b/kernel/trunk/memmap.inc index 78656f479..84fd8b1d6 100644 --- a/kernel/trunk/memmap.inc +++ b/kernel/trunk/memmap.inc @@ -1,264 +1,264 @@ -; -; MEMORY MAP -; -; Boot: -; -; 0:9000 byte bits per pixel -; 0:9001 word scanline length -; 0:9008 word vesa video mode -; 0:900A word X res -; 0:900C word Y res -; 0:9010 byte mouse port - not used -; 0:9014 dword Vesa 1.2 pm bank switch -; 0:9018 dword Vesa 2.0 LFB address -; 0:901C byte 0 or 1 : enable MTRR graphics acceleration -; 0:901D byte not used anymore (0 or 1 : enable system log display) -; 0:901E byte 0 or 1 : enable direct lfb write, paging disabled -; 0:901F byte DMA write : 1=yes, 2=no -; 0:9020 8bytes pci data -; 0:9030 byte VRR start enabled 1, 2-no -; 0:9031 word IDEContrRegsBaseAddr -; 0x9040 - dword - entry point of APM BIOS -; 0x9044 - word - version (BCD) -; 0x9046 - word - flags -; 0:907F byte number of BIOS hard disks -; 0:9080 Nbytes BIOS hard disks -; 0:9100 word available physical memory map: number of blocks -; 0:9104 available physical memory map: blocks -; -; Runtime: -; -; 0x00000000 -> 0x7FFFFFFF application 2Gb - -; 0x80000000 -> 0FFF physical page zero - do not write -; (used by int 13h in some configurations) -; -; 0x80001000 -> 2FFF window_data - 256 entries -; -; 0000 dword x start -; 0004 dword y start -; 0008 dword x size -; 000C dword y size -; 0010 dword color of work area -; 0014 dword color of grab bar -; 0018 dword color of frames -; 001C dword window flags, +30 = window drawn, +31 redraw flag -; -; 3000 -> 4FFF task list - 256 entries -; -; 00 dword process count -; 04 dword no of processes -; 10 dword base of running process at 0x3000+ -; -; 20 dword application event mask -; 24 dword PID - process identification number -; 2a byte slot state: 0=running, 1,2=suspended -; 3=zombie, 4=terminate, -; 5=waiting for event, 9 = not used -; 2e byte window number on screen -; 30 dword exact position in memory -; 34 dword counter sum -; 38 dword time stamp counter add -; 3c dword cpu usage in cpu timer tics -; -; -; 5000 -> 68FF free (6k6) -; 6900 -> 6EFF saved picture under mouse pointer (1k5) -; -; 6F00 -> 6FFF free (256) -; -; 7000 -> 7FFF used CD driver -; -; 8000 -> A3FF used FLOPPY driver -; -; A400 -> B0FF free (3k3), unused ACTIVE_PROC_STACK - -; B100 -> B307 IDT for int_0x00..int_0x40 - -; B308 -> BFFF free (3k3) - -; C000 -> C3FF window stack C000 no of windows - all in words -; C402 -> C7FF window position in stack -; D000 -> D1FF FDC controller -; D200 -> D3FF FDC controller for Fat12 -; D400 -> DFFF free (3k) -; E000 byte multitasking started -; E020 dword putpixel address -; E024 dword getpixel address -; E030 dword Vesa 1.2 pm bank switch address -; E034 -> F1FF free (4k5) -; F200 dword mousepicture -pointer -; F204 dword mouse appearance counter -; F208 -> F2FF free (248) -; F300 dword x & y temp for windowmove -; F304 -> F3FF free (252) -; F400 byte no of keys in buffer -; F401 byte 'buffer' -; F402 -> F4FF reserved for keys -; F500 byte no of buttons in buffer -; F501 dword 'buffer' -; F502 -> F5FF reserved for buttons -; F600 dword tsc / second -; F604 byte (unused?) mouse port: 1 ps2, 2 com1, 3 com2 -; F605 -> FAFF free (1k2) -; FB00 -> FB0F mouse memory 00 chunk count, that includes: -; FB08 word -- mouse H-scroll -; FB0A word -- mouse x -; FB0C word -- mouse y -; FB0E word -- mouse V-scroll -; FB10 -> FB17 mouse color mem -; FB21 x move -; FB22 y move -; FB28 high bits temp -; FB30 color temp -; FB40 byte buttons down -; FB44 byte 0 mouse down -> do not draw -; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under -; FBF1 byte bits per pixel -; FC00 -> FCFE com1/ps2 buffer -; FCFF com1/ps2 buffer count starting from FC00 -; FD00 -> FDFF free (256) -; FE00 dword screen x size -; FE04 dword screen y size -; FE08 dword screen y multiplier -; FE0C dword screen mode -; FE10 -> FE7F free (112) -; FE80 dword address of LFB in physical -; FE84 dword address of applications memory start in physical ? -; FE88 dword address of button list -; FE8C dword memory to use -; FE90 -> FEFF free (112) -; FF00 byte 1 = system shutdown request -; FF01 byte task activation request? -; FFF0 byte >0 if redraw background request from app -; FFF1 byte >0 if background changed -; FFF2 write and read bank in screen -; FFF4 byte 0 if first mouse draw & do not return picture under -; FFF5 byte 1 do not draw pointer -; FFFF byte do not change task for 1/100 sec. -; -; 0x80010000 -> 6CBFF kernel, 32-bit run-time code (up to 371 Kb) - -; 0x8006CC00 -> 6DBFF stack at boot time (4Kb) -; -; 0x8006DC00 -> 6E5FF basic text font II -; 0x8006E600 -> 6Efff basic text font I -; 0x8006F000 -> 6FFFF main page directory - -; 0x80070000 -> 7FFFF data of retrieved disks and partitions (Mario79) -; 0x80080000 -> 8FFFF additional app info, in 256 byte steps - 256 entries -; -; 00 11db name of app running -; 0x10 dword pointer to fpu save area -; 0x14 dword event count -; 0x18 dword user fpu exceptoins handler -; 0x1c dword user sse exceptions handler -; 20 dword PL0 stack base -; 24 dword user heap base -; 28 dword user heap top -; 2c dword window cursor handle -; 30 dword first event in list -; 34 dword last event in list -; 38 dword first kernel object in list -; 3c dword last kernel object in list -; 40 dword thread esp -; 44 dword io permission map page 0 -; 48 dword io permission map page 1 -; 4c dword debug state: 1= load debug registers -; 50 dword current directory ptr -; 54 dword wait timeout -; 58 dword thread TSS._esp0 (= pl0 stack base + size except for V86) -; 5C-7F unused -; -; 80 dword address of random shaped window area -; 84 byte shape area scale -; 88 dword free -; 8C dword application memory size -; 90 dword window X position save -; 94 dword window Y position save -; 98 dword window X size save -; 9C dword window Y size save -; A0 dword IPC memory start -; A4 dword IPC memory size -; A8 dword event bits: mouse, stack,.. -; AC dword 0 or debugger slot -; B0 dword free -; B4 byte keyboard mode: 0 = keymap, 1 = scancodes -; B8 dword physical address of directory table -; BC dword address of debug event memory -; C0 5 dd thread debug registers: DR0,DR1,DR2,DR3,DR7 -; -; 0x80090000 -> 9FFFF tmp (64k) - unused? -; 0x800A0000 -> AFFFF screen access area -; 0x800B0000 -> FFFFF bios rest in peace -area (320k) ? -; 0x80100000 -> 27FFFF diskette image (1m5) -; 0x80280000 -> 281FFF ramdisk fat (8k) -; 0x80282000 -> 283FFF floppy fat (8k) -; -; 0x80284000 -> 28BFFF HDD DMA AREA (32k) -; 0x8028C000 -> 297FFF free (48k) -; -; 0x80298000 -> 29ffff auxiliary table for background smoothing code (32k) -; -; 0x802A0000 -> 2B00ff wav device buffer (64k) -; 0x802A0000 -> 2B00ff wav device status (256) -; 0x802B0100 -> 2Bffff free (63k8) -; 0x802C0000 -> 2C3fff button info (8k) -; -; 0000 word number of buttons -; first button entry at 0x10 -; +0000 word process number -; +0002 word button id number : bits 00-15 -; +0004 word x start -; +0006 word x size -; +0008 word y start -; +000A word y size -; +000C word button id number : bits 16-31 -; -; 0x802C4000 -> 2CFFFF free (48k) -; -; 0x802D0000 -> 2DFFFF reserved port area (64k) -; -; 0000 dword no of port areas reserved -; 0010 dword process id -; dword start port -; dword end port -; dword 0 -; -; 0x802E0000 -> 2EFFFF irq data area (64k) -; 0x802F0000 -> 2FFFFF low memory save (64k) -; -; 0x80300000 -> 31FFFF tcp memory (128k) -; 0x80320000 -> 327FFF tcp memory (32k) -; -; 0x80328000 -> 32FFFF !vrr driver (32k) - -; 0x80330000 -> 377FFF skin data (32k) - -; 0x80338000 -> 338FFF draw data - 256 entries (4k) -; 00 dword draw limit - x start -; 04 dword draw limit - y start -; 08 dword draw limit - x end -; 0C dword draw limit - y end -; 0x80339000 -> 3BFFF3 free (12k) -; 0x8033BFF4 -> 33BFFF background info -; 0x8033C000 page map (length b = memsize shr 15) -; 0x8033C000 + b start of static pagetables - -; 0x803FFFFF <- no direct address translation beyond this point -; ============================================================= - -; 0x805FF000 -> 5FFF80 TSS -; 0x80600000 -> 601FFF i/o maps - -; 0x80800000 -> kernel heap -; 0x80FFFFFF heap min limit -; 0xFDBFFFFF heap max limit - -; 0xF0000000 -> 0xF1FFFFFF PCI-express extended config space -; 0xFDC00000 -> 0xFDFFFFFF page tables 4Mb -; 0xFE000000 -> 0xFFFFFFFF LFB 32Mb -; 0xFE000000 -> 0xFE7FFFFF application available LFB 8Mb -; 0xFE800000 -> 0xFFFFFFFF kernel LFB part 24 Mb - - +; +; MEMORY MAP +; +; Boot: +; +; 0:9000 byte bits per pixel +; 0:9001 word scanline length +; 0:9008 word vesa video mode +; 0:900A word X res +; 0:900C word Y res +; 0:9010 byte mouse port - not used +; 0:9014 dword Vesa 1.2 pm bank switch +; 0:9018 dword Vesa 2.0 LFB address +; 0:901C byte 0 or 1 : enable MTRR graphics acceleration +; 0:901D byte not used anymore (0 or 1 : enable system log display) +; 0:901E byte 0 or 1 : enable direct lfb write, paging disabled +; 0:901F byte DMA write : 1=yes, 2=no +; 0:9020 8bytes pci data +; 0:9030 byte VRR start enabled 1, 2-no +; 0:9031 word IDEContrRegsBaseAddr +; 0x9040 - dword - entry point of APM BIOS +; 0x9044 - word - version (BCD) +; 0x9046 - word - flags +; 0:907F byte number of BIOS hard disks +; 0:9080 Nbytes BIOS hard disks +; 0:9100 word available physical memory map: number of blocks +; 0:9104 available physical memory map: blocks +; +; Runtime: +; +; 0x00000000 -> 0x7FFFFFFF application 2Gb + +; 0x80000000 -> 0FFF physical page zero - do not write +; (used by int 13h in some configurations) +; +; 0x80001000 -> 2FFF window_data - 256 entries +; +; 0000 dword x start +; 0004 dword y start +; 0008 dword x size +; 000C dword y size +; 0010 dword color of work area +; 0014 dword color of grab bar +; 0018 dword color of frames +; 001C dword window flags, +30 = window drawn, +31 redraw flag +; +; 3000 -> 4FFF task list - 256 entries +; +; 00 dword process count +; 04 dword no of processes +; 10 dword base of running process at 0x3000+ +; +; 20 dword application event mask +; 24 dword PID - process identification number +; 2a byte slot state: 0=running, 1,2=suspended +; 3=zombie, 4=terminate, +; 5=waiting for event, 9 = not used +; 2e byte window number on screen +; 30 dword exact position in memory +; 34 dword counter sum +; 38 dword time stamp counter add +; 3c dword cpu usage in cpu timer tics +; +; +; 5000 -> 68FF free (6k6) +; 6900 -> 6EFF saved picture under mouse pointer (1k5) +; +; 6F00 -> 6FFF free (256) +; +; 7000 -> 7FFF used CD driver +; +; 8000 -> A3FF used FLOPPY driver +; +; A400 -> B0FF free (3k3), unused ACTIVE_PROC_STACK + +; B100 -> B307 IDT for int_0x00..int_0x40 + +; B308 -> BFFF free (3k3) + +; C000 -> C3FF window stack C000 no of windows - all in words +; C402 -> C7FF window position in stack +; D000 -> D1FF FDC controller +; D200 -> D3FF FDC controller for Fat12 +; D400 -> DFFF free (3k) +; E000 byte multitasking started +; E020 dword putpixel address +; E024 dword getpixel address +; E030 dword Vesa 1.2 pm bank switch address +; E034 -> F1FF free (4k5) +; F200 dword mousepicture -pointer +; F204 dword mouse appearance counter +; F208 -> F2FF free (248) +; F300 dword x & y temp for windowmove +; F304 -> F3FF free (252) +; F400 byte no of keys in buffer +; F401 byte 'buffer' +; F402 -> F4FF reserved for keys +; F500 byte no of buttons in buffer +; F501 dword 'buffer' +; F502 -> F5FF reserved for buttons +; F600 dword tsc / second +; F604 byte (unused?) mouse port: 1 ps2, 2 com1, 3 com2 +; F605 -> FAFF free (1k2) +; FB00 -> FB0F mouse memory 00 chunk count, that includes: +; FB08 word -- mouse H-scroll +; FB0A word -- mouse x +; FB0C word -- mouse y +; FB0E word -- mouse V-scroll +; FB10 -> FB17 mouse color mem +; FB21 x move +; FB22 y move +; FB28 high bits temp +; FB30 color temp +; FB40 byte buttons down +; FB44 byte 0 mouse down -> do not draw +; FB4A -> FB4D FB4A-B x-under - FB4C-D y-under +; FBF1 byte bits per pixel +; FC00 -> FCFE com1/ps2 buffer +; FCFF com1/ps2 buffer count starting from FC00 +; FD00 -> FDFF free (256) +; FE00 dword screen x size +; FE04 dword screen y size +; FE08 dword screen y multiplier +; FE0C dword screen mode +; FE10 -> FE7F free (112) +; FE80 dword address of LFB in physical +; FE84 dword address of applications memory start in physical ? +; FE88 dword address of button list +; FE8C dword memory to use +; FE90 -> FEFF free (112) +; FF00 byte 1 = system shutdown request +; FF01 byte task activation request? +; FFF0 byte >0 if redraw background request from app +; FFF1 byte >0 if background changed +; FFF2 write and read bank in screen +; FFF4 byte 0 if first mouse draw & do not return picture under +; FFF5 byte 1 do not draw pointer +; FFFF byte do not change task for 1/100 sec. +; +; 0x80010000 -> 6CBFF kernel, 32-bit run-time code (up to 371 Kb) + +; 0x8006CC00 -> 6DBFF stack at boot time (4Kb) +; +; 0x8006DC00 -> 6E5FF basic text font II +; 0x8006E600 -> 6Efff basic text font I +; 0x8006F000 -> 6FFFF main page directory + +; 0x80070000 -> 7FFFF data of retrieved disks and partitions (Mario79) +; 0x80080000 -> 8FFFF additional app info, in 256 byte steps - 256 entries +; +; 00 11db name of app running +; 0x10 dword pointer to fpu save area +; 0x14 dword event count +; 0x18 dword user fpu exceptoins handler +; 0x1c dword user sse exceptions handler +; 20 dword PL0 stack base +; 24 dword user heap base +; 28 dword user heap top +; 2c dword window cursor handle +; 30 dword first event in list +; 34 dword last event in list +; 38 dword first kernel object in list +; 3c dword last kernel object in list +; 40 dword thread esp +; 44 dword io permission map page 0 +; 48 dword io permission map page 1 +; 4c dword debug state: 1= load debug registers +; 50 dword current directory ptr +; 54 dword wait timeout +; 58 dword thread TSS._esp0 (= pl0 stack base + size except for V86) +; 5C-7F unused +; +; 80 dword address of random shaped window area +; 84 byte shape area scale +; 88 dword free +; 8C dword application memory size +; 90 dword window X position save +; 94 dword window Y position save +; 98 dword window X size save +; 9C dword window Y size save +; A0 dword IPC memory start +; A4 dword IPC memory size +; A8 dword event bits: mouse, stack,.. +; AC dword 0 or debugger slot +; B0 dword free +; B4 byte keyboard mode: 0 = keymap, 1 = scancodes +; B8 dword physical address of directory table +; BC dword address of debug event memory +; C0 5 dd thread debug registers: DR0,DR1,DR2,DR3,DR7 +; +; 0x80090000 -> 9FFFF tmp (64k) - unused? +; 0x800A0000 -> AFFFF screen access area +; 0x800B0000 -> FFFFF bios rest in peace -area (320k) ? +; 0x80100000 -> 27FFFF diskette image (1m5) +; 0x80280000 -> 281FFF ramdisk fat (8k) +; 0x80282000 -> 283FFF floppy fat (8k) +; +; 0x80284000 -> 28BFFF HDD DMA AREA (32k) +; 0x8028C000 -> 297FFF free (48k) +; +; 0x80298000 -> 29ffff auxiliary table for background smoothing code (32k) +; +; 0x802A0000 -> 2B00ff wav device buffer (64k) +; 0x802A0000 -> 2B00ff wav device status (256) +; 0x802B0100 -> 2Bffff free (63k8) +; 0x802C0000 -> 2C3fff button info (8k) +; +; 0000 word number of buttons +; first button entry at 0x10 +; +0000 word process number +; +0002 word button id number : bits 00-15 +; +0004 word x start +; +0006 word x size +; +0008 word y start +; +000A word y size +; +000C word button id number : bits 16-31 +; +; 0x802C4000 -> 2CFFFF free (48k) +; +; 0x802D0000 -> 2DFFFF reserved port area (64k) +; +; 0000 dword no of port areas reserved +; 0010 dword process id +; dword start port +; dword end port +; dword 0 +; +; 0x802E0000 -> 2EFFFF irq data area (64k) +; 0x802F0000 -> 2FFFFF low memory save (64k) +; +; 0x80300000 -> 31FFFF tcp memory (128k) +; 0x80320000 -> 327FFF tcp memory (32k) +; +; 0x80328000 -> 32FFFF !vrr driver (32k) + +; 0x80330000 -> 377FFF skin data (32k) + +; 0x80338000 -> 338FFF draw data - 256 entries (4k) +; 00 dword draw limit - x start +; 04 dword draw limit - y start +; 08 dword draw limit - x end +; 0C dword draw limit - y end +; 0x80339000 -> 3BFFF3 free (12k) +; 0x8033BFF4 -> 33BFFF background info +; 0x8033C000 page map (length b = memsize shr 15) +; 0x8033C000 + b start of static pagetables + +; 0x803FFFFF <- no direct address translation beyond this point +; ============================================================= + +; 0x805FF000 -> 5FFF80 TSS +; 0x80600000 -> 601FFF i/o maps + +; 0x80800000 -> kernel heap +; 0x80FFFFFF heap min limit +; 0xFDBFFFFF heap max limit + +; 0xF0000000 -> 0xF1FFFFFF PCI-express extended config space +; 0xFDC00000 -> 0xFDFFFFFF page tables 4Mb +; 0xFE000000 -> 0xFFFFFFFF LFB 32Mb +; 0xFE000000 -> 0xFE7FFFFF application available LFB 8Mb +; 0xFE800000 -> 0xFFFFFFFF kernel LFB part 24 Mb + + diff --git a/kernel/trunk/network/eth_drv/arp.inc b/kernel/trunk/network/eth_drv/arp.inc index e98734d96..39fe3216a 100644 --- a/kernel/trunk/network/eth_drv/arp.inc +++ b/kernel/trunk/network/eth_drv/arp.inc @@ -1,556 +1,557 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ARP.INC ;; -;; ;; -;; Address Resolution Protocol ;; -;; ;; -;; This file contains the following: ;; -;; arp_table_manager - Manages an ARPTable ;; -;; arp_request - Sends an ARP request on the ethernet ;; -;; arp_handler - Called when an ARP packet is received ;; -;; ;; -;; Changes history: ;; -;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; -;; 11.11.2006 - [Johnny_B] and [smb] ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -ARP_NO_ENTRY equ 0 -ARP_VALID_MAPPING equ 1 -ARP_AWAITING_RESPONSE equ 2 -ARP_RESPONSE_TIMEOUT equ 3 - -struc ARP_ENTRY ;=14 bytes -{ .IP dd ? ;+00 - .MAC dp ? ;+04 - .Status dw ? ;+10 - .TTL dw ? ;+12 : ( in seconds ) -} - -virtual at 0 - ARP_ENTRY ARP_ENTRY -end virtual - -; The TTL field is decremented every second, and is deleted when it -; reaches 0. It is refreshed every time a packet is received -; If the TTL field is 0xFFFF it is a static entry and is never deleted -; The status field can be the following values: -; 0x0000 entry not used -; 0x0001 entry holds a valid mapping -; 0x0002 entry contains an IP address, awaiting ARP response -; 0x0003 No response received to ARP request. -; The last status value is provided to allow the network layer to delete -; a packet that is queued awaiting an ARP response - - -; The follow is the ARP Table. -; This table must be manually updated and the kernel recompilied if -; changes are made to it. -; Empty entries are filled with zeros - -ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry -ARP_TABLE_SIZE equ 20 ; Size of table -ARP_TABLE_ENTRIES equ 0 ; Number of static entries in the table - -;TO ADD A STATIC ENTRY, DONT FORGET, PUT "ARPTable" from "uglobal" to "iglobal"!!! -;AND ALSO - IP and MAC have net byte-order, BUT STATUS AND TTL HAVE A MIRROR BYTE-ORDER!!! -uglobal - ARPTable: -;example, static entry -> db 11,22,33,44, 0x11,0x22,0x33,0x44,0x55,0x66, 0x01,0x00, 0xFF,0xFF - times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0 -endg - -iglobal - NumARP: dd ARP_TABLE_ENTRIES - ARPTable_ptr dd ARPTable ;pointer to ARPTable -endg - -ARP_REQ_OPCODE equ 0x0100 ;request -ARP_REP_OPCODE equ 0x0200 ;reply - -struc ARP_PACKET -{ .HardwareType dw ? ;+00 - .ProtocolType dw ? ;+02 - .HardwareSize db ? ;+04 - .ProtocolSize db ? ;+05 - .Opcode dw ? ;+06 - .SenderMAC dp ? ;+08 - .SenderIP dd ? ;+14 - .TargetMAC dp ? ;+18 - .TargetIP dd ? ;+24 -} - -virtual at 0 - ARP_PACKET ARP_PACKET -end virtual - - - -;*************************************************************************** -; Function -; arp_table_manager [by Johnny_B] -; -; Description -; Does a most required operations with ARP-table -; IN: -; Operation: see Opcode's constants below -; Index: Index of entry in the ARP-table -; Extra: Extra parameter for some Opcodes -; OUT: -; EAX = Returned value depends on opcodes, more detailed see below -; -;*************************************************************************** -;Opcode's constants -ARP_TABLE_ADD equ 1 -ARP_TABLE_DEL equ 2 -ARP_TABLE_GET equ 3 -ARP_TABLE_GET_ENTRIES_NUMBER equ 4 -ARP_TABLE_IP_TO_MAC equ 5 -ARP_TABLE_TIMER equ 6 - -;Index's constants -EXTRA_IS_ARP_PACKET_PTR equ 0 ;if Extra contain pointer to ARP_PACKET -EXTRA_IS_ARP_ENTRY_PTR equ -1 ;if Extra contain pointer to ARP_ENTRY - -align 4 -proc arp_table_manager stdcall uses ebx esi edi ecx edx,\ - Opcode:DWORD,Index:DWORD,Extra:DWORD - - mov ebx, dword[ARPTable_ptr] ;ARPTable base - mov ecx, dword[NumARP] ;ARP-entries counter - - mov eax, dword[Opcode] - cmp eax, ARP_TABLE_TIMER - je .timer - cmp eax, ARP_TABLE_ADD - je .add - cmp eax, ARP_TABLE_DEL - je .del - cmp eax, ARP_TABLE_GET - je .get - cmp eax, ARP_TABLE_IP_TO_MAC - je .ip_to_mac - cmp eax, ARP_TABLE_GET_ENTRIES_NUMBER - je .get_entries_number - jmp .exit ;if unknown opcode - - -;;BEGIN TIMER -;;Description: it must be callback every second. It is responsible for removing expired routes. -;;IN: Operation: ARP_TABLE_TIMER -;; Index: must be zero -;; Extra: must be zero -;;OUT: -;; EAX=not defined -;; -.timer: - test ecx, ecx - jz .exit ;if NumARP=0 nothing to do - sub ecx, ARP_TABLE_ENTRIES ;ecx=dynamic entries number - jz .exit ;if NumARP=number of static entries then exit - - add ebx, ARP_TABLE_ENTRIES*ARP_ENTRY_SIZE ;ebx=dynamic entries base - - .timer_loop: - movsx esi, word [ebx + ARP_ENTRY.TTL] - cmp esi, 0xFFFFFFFF - je .timer_loop_end ;if TTL==0xFFFF then it's static entry - - test esi, esi - jnz .timer_loop_end_with_dec ;if TTL!=0 - - ; Ok, TTL is 0 - ;if Status==AWAITING_RESPONSE and TTL==0 - ;then we have to change it to ARP_RESPONSE_TIMEOUT - cmp word [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE - jne @f - - mov word [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT - mov word [ebx + ARP_ENTRY.TTL], word 0x000A ;10 sec - jmp .timer_loop_end - - @@: - ;if TTL==0 and Status==VALID_MAPPING, we have to delete it - ;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too - mov esi, dword[NumARP] - sub esi, ecx ;esi=index of entry, will be deleted - stdcall arp_table_manager,ARP_TABLE_DEL,esi,0 ;opcode,index,extra - jmp .timer_loop_end - - - .timer_loop_end_with_dec: - dec word [ebx + ARP_ENTRY.TTL] ;decrease TTL - .timer_loop_end: - add ebx, ARP_ENTRY_SIZE - loop .timer_loop - - jmp .exit -;;END TIMER - -;;BEGIN ADD -;;Description: it adds an entry in the table. If ARP-table already -;; contains same IP, it will be updated. -;;IN: Operation: ARP_TABLE_ADD -;; Index: specifies what contains Extra-parameter -;; Extra: if Index==EXTRA_IS_ARP_PACKET_PTR, -;; then Extra contains pointer to ARP_PACKET, -;; otherwise Extra contains pointer to ARP_ENTRY -;;OUT: -;; EAX=index of entry, that has been added -;; -.add: - - sub esp, ARP_ENTRY_SIZE ;Allocate ARP_ENTRY_SIZE byte in stack - - mov esi, [Extra] ;pointer - mov edi, [Index] ;opcode - - cmp edi, EXTRA_IS_ARP_PACKET_PTR - je .arp_packet_to_entry ;if Extra contain ptr to ARP_PACKET and we have to form arp-entry - ;else it contain ptr to arp-entry - - cld - ; esi already has been loaded - mov edi, esp ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) - mov ecx,ARP_ENTRY_SIZE/2 ;ARP_ENTRY_SIZE must be even number!!! - rep movsw ;copy - jmp .search - - .arp_packet_to_entry: - mov edx, dword[esi + ARP_PACKET.SenderIP] ;esi=base of ARP_PACKET - mov [esp + ARP_ENTRY.IP], edx - - cld - lea esi, [esi + ARP_PACKET.SenderMAC] - lea edi, [esp + ARP_ENTRY.MAC] - movsd - movsw - mov word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING ; specify the type - a valid entry - mov word[esp + ARP_ENTRY.TTL], 0x0E10 ; = 1 hour - - .search: - mov edx, dword[esp + ARP_ENTRY.IP] ;edx=IP-address, which we'll search - mov ecx, dword[NumARP] ;ecx=ARP-entries counter - jecxz .add_to_end ;if ARP-entries number == 0 - imul eax, ecx, ARP_ENTRY_SIZE ;eax=current table size(in bytes) - @@: - sub eax, ARP_ENTRY_SIZE - cmp dword[ebx + eax + ARP_ENTRY.IP], edx - loopnz @b - jz .replace ; found, replace existing entry, ptr to it is in eax - - .add_to_end: - ;else add to end - or eax,-1 ;set eax=0xFFFFFFFF if adding is impossible - mov ecx, dword[NumARP] - cmp ecx, ARP_TABLE_SIZE - je .add_exit ;if arp-entries number is equal to arp-table maxsize - - imul eax, dword[NumARP], ARP_ENTRY_SIZE ;eax=ptr to end of ARPTable - inc dword [NumARP] ;increase ARP-entries counter - - .replace: - cld - mov esi, esp ;esp=base of ARP-entry, that will be added - lea edi, [ebx + eax] ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) - mov ecx,ARP_ENTRY_SIZE/2 ;ARP_ENTRY_SIZE must be even number!!! - rep movsw - - mov ecx, ARP_ENTRY_SIZE - xor edx, edx ;"div" takes operand from EDX:EAX - div ecx ;eax=index of entry, which has been added - -.add_exit: - add esp, ARP_ENTRY_SIZE ;free stack - jmp .exit -;;END ADD - -;;BEGIN DEL -;;Description: it deletes an entry in the table. -;;IN: Operation: ARP_TABLE_DEL -;; Index: index of entry, that should be deleted -;; Extra: must be zero -;;OUT: -;; EAX=not defined -;; -.del: - mov esi, [Index] - imul esi, ARP_ENTRY_SIZE - - mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE - sub ecx, esi - - lea edi, [ebx + esi] ;edi=ptr to entry that should be deleted - lea esi, [edi + ARP_ENTRY_SIZE] ;esi=ptr to next entry - - shr ecx,1 ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER! - cld - rep movsw - - dec dword[NumARP] ;decrease arp-entries counter - jmp .exit -;;END DEL - -;;BEGIN GET -;;Description: it reads an entry of table into buffer. -;;IN: Operation: ARP_TABLE_GET -;; Index: index of entry, that should be read -;; Extra: pointer to buffer for reading(size must be equal to ARP_ENTRY_SIZE) -;;OUT: -;; EAX=not defined -;; -.get: - mov esi, [Index] - imul esi, ARP_ENTRY_SIZE ;esi=ptr to required ARP_ENTRY - mov edi, [Extra] ;edi=buffer for reading - mov ecx, ARP_ENTRY_SIZE/2 ; must be even number!!! - cld - rep movsw - jmp .exit -;;END GET - -;;BEGIN IP_TO_MAC -;;Description: it gets an IP from Index, scans each entry in the table and writes -;; MAC, that relates to specified IP, into buffer specified in Extra. -;; And if it cannot find an IP-address in the table, it does an ARP-request of that. -;;IN: Operation: ARP_TABLE_IP_TO_MAC -;; Index: IP that should be transformed into MAC -;; Extra: pointer to buffer where will be written the MAC-address. -;;OUT: -;; EAX=ARP table entry status code. -;; If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request. -;; If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system. -;; If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long. -;; If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC. -;; -;; If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet -;; resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this -;; function with 1sec delay. sure, only if it not return a valid MAC after a first call. -;; -.ip_to_mac: - - xor eax, eax - mov edi, dword[Extra] - cld - stosd - stosw - - - ; first, check destination IP to see if it is on 'this' network. - ; The test is: - ; if ( destIP & subnet_mask == stack_ip & subnet_mask ) - ; destination is local - ; else - ; destination is remote, so pass to gateway - - mov eax, [Index] ;eax=required IP - mov esi, eax - and esi, [subnet_mask] - mov ecx, [stack_ip] - and ecx, [subnet_mask] - cmp esi, ecx - je @f ;if we and target IP are located in the same network - mov eax, [gateway_ip] - mov [Index], eax - @@: - - cmp dword[NumARP], 0 - je .ip_to_mac_send_request ;if ARP-table not contain an entries, we have to request IP. - ;EAX will be containing a zero, it's equal to ARP_NO_ENTRY - - mov ecx, dword[NumARP] - imul esi, ecx, ARP_ENTRY_SIZE ;esi=current ARP-table size - - @@: - sub esi, ARP_ENTRY_SIZE - cmp [ebx + esi], eax ; ebx=ARPTable base - loopnz @b ; Return back if non match - jnz .ip_to_mac_send_request ; and request IP->MAC if none found in the table - - ; Return the entry status in eax - movzx eax, word[ebx + esi + ARP_ENTRY.Status] - - ; esi holds index - cld - lea esi, [ebx + esi + ARP_ENTRY.MAC] - mov edi, [Extra] ;edi=ptr to buffer for write MAC - movsd - movsw - jmp .exit - - .ip_to_mac_send_request: - stdcall arp_request,[Index],stack_ip,node_addr ;TargetIP,SenderIP_ptr,SenderMAC_ptr - mov eax, ARP_NO_ENTRY - jmp .exit - -;;END IP_TO_MAC - -;;BEGIN GET_ENTRIES_NUMBER -;;Description: returns an ARP-entries number in the ARPTable -;;IN: Operation: ARP_TABLE_GET_ENTRIES_NUMBER -;; Index: must be zero -;; Extra: must be zero -;;OUT: -;; EAX=ARP-entries number in the ARPTable - .get_entries_number: - mov eax, dword[NumARP] - jmp .exit -;;END GET_ENTRIES_NUMBER - -.exit: - ret -endp - - -;*************************************************************************** -; Function -; arp_handler -; -; Description -; Called when an ARP packet is received on the ethernet -; Header + Data is in Ether_buffer[] -; It looks to see if the packet is a request to resolve this Hosts -; IP address. If it is, send the ARP reply packet. -; This Hosts IP address is in dword [stack_ip] ( in network format ) -; This Hosts MAC address is in node_addr[6] -; All registers may be destroyed -; -;*************************************************************************** -arp_handler: - ; Is this a REQUEST? - ; Is this a request for My Host IP - ; Yes - So construct a response message. - ; Send this message to the ethernet card for transmission - - stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_PACKET_PTR,ETH_FRAME.Data + ARP_PACKET - - inc dword[arp_rx_count] ;increase ARP-packets counter - - cmp word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REQ_OPCODE ; Is this a request packet? - jne .exit ; No - so exit - - mov eax, [stack_ip] - cmp eax, dword[ETH_FRAME.Data + ARP_PACKET.TargetIP] ; Is it looking for my IP address? - jne .exit ; No - so quit now - - ; OK, it is a request for my MAC address. Build the frame and send it - ; We can reuse the packet. - - mov word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REP_OPCODE - - cld - mov esi, ETH_FRAME.Data + ARP_PACKET.SenderMAC - mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC - movsd - movsw - - mov esi, ETH_FRAME.Data + ARP_PACKET.SenderIP - mov edi, ETH_FRAME.Data + ARP_PACKET.TargetIP - movsd - - mov esi, node_addr - mov edi, ETH_FRAME.Data + ARP_PACKET.SenderMAC - movsd - movsw - - mov esi, stack_ip - mov edi, ETH_FRAME.Data + ARP_PACKET.SenderIP - movsd - - ; Now, send it! - mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC ;ptr to destination MAC address - mov bx, ETHER_ARP ;type of protocol - mov ecx, 28 ;data size - mov esi, ETH_FRAME.Data + ARP_PACKET ;ptr to data - push ebp - call dword [drvr_transmit] ;transmit packet - pop ebp - - .exit: - ret - - -;*************************************************************************** -; Function -; arp_request [by Johnny_B] -; -; Description -; Sends an ARP request on the ethernet -; IN: -; TargetIP : requested IP address -; SenderIP_ptr : POINTER to sender's IP address(our system's address) -; SenderMAC_ptr : POINTER to sender's MAC address(our system's address) -; OUT: -; EAX=0 (if all is ok), otherwise EAX is not defined -; -; EBX,ESI,EDI will be saved -; -;*************************************************************************** -proc arp_request stdcall uses ebx esi edi,\ - TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD - - inc dword[arp_tx_count] ; increase counter - - sub esp, 28 ; allocate memory for ARP_PACKET - - mov word[esp + ARP_PACKET.HardwareType],0x0100 ;Ethernet - mov word[esp + ARP_PACKET.ProtocolType],0x0008 ;IP - mov byte[esp + ARP_PACKET.HardwareSize],0x06 ;MAC-addr length - mov byte[esp + ARP_PACKET.ProtocolSize],0x04 ;IP-addr length - mov word[esp + ARP_PACKET.Opcode],0x0100 ;Request - - cld - mov esi,[SenderMAC_ptr] - lea edi,[esp + ARP_PACKET.SenderMAC] ;Our MAC-addr - movsd - movsw - - mov esi,[SenderIP_ptr] - lea edi,[esp + ARP_PACKET.SenderIP] ;Our IP-addr - movsd - - xor eax, eax - lea edi, [esp + ARP_PACKET.TargetMAC] ;Required MAC-addr(zeroed) - stosd - stosw - - mov esi, dword[TargetIP] - mov dword[esp + ARP_PACKET.TargetIP],esi ;Required IP-addr(we get it as function parameter) - - ; Now, send it! - mov edi, broadcast_add ; Pointer to 48 bit destination address - mov bx, ETHER_ARP ; Type of packet - mov ecx, 28 ; size of packet - lea esi, [esp + ARP_PACKET]; pointer to packet data - push ebp - call dword [drvr_transmit] ; Call the drivers transmit function - pop ebp - - add esp, 28 ; free memory, allocated before for ARP_PACKET - - ; Add an entry in the ARP table, awaiting response - sub esp, ARP_ENTRY_SIZE ;allocate memory for ARP-entry - - mov esi, dword[TargetIP] - mov dword[esp + ARP_ENTRY.IP],esi - - lea edi, [esp + ARP_ENTRY.MAC] - xor eax, eax - stosd - stosw - - mov word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE - mov word[esp + ARP_ENTRY.TTL], 0x000A ; 10 seconds - - stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_ENTRY_PTR,esp - add esp, ARP_ENTRY_SIZE ; free memory - -.exit: - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ARP.INC ;; +;; ;; +;; Address Resolution Protocol ;; +;; ;; +;; This file contains the following: ;; +;; arp_table_manager - Manages an ARPTable ;; +;; arp_request - Sends an ARP request on the ethernet ;; +;; arp_handler - Called when an ARP packet is received ;; +;; ;; +;; Changes history: ;; +;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; +;; 11.11.2006 - [Johnny_B] and [smb] ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +ARP_NO_ENTRY equ 0 +ARP_VALID_MAPPING equ 1 +ARP_AWAITING_RESPONSE equ 2 +ARP_RESPONSE_TIMEOUT equ 3 + +struc ARP_ENTRY ;=14 bytes +{ .IP dd ? ;+00 + .MAC dp ? ;+04 + .Status dw ? ;+10 + .TTL dw ? ;+12 : ( in seconds ) +} + +virtual at 0 + ARP_ENTRY ARP_ENTRY +end virtual + +; The TTL field is decremented every second, and is deleted when it +; reaches 0. It is refreshed every time a packet is received +; If the TTL field is 0xFFFF it is a static entry and is never deleted +; The status field can be the following values: +; 0x0000 entry not used +; 0x0001 entry holds a valid mapping +; 0x0002 entry contains an IP address, awaiting ARP response +; 0x0003 No response received to ARP request. +; The last status value is provided to allow the network layer to delete +; a packet that is queued awaiting an ARP response + + +; The follow is the ARP Table. +; This table must be manually updated and the kernel recompilied if +; changes are made to it. +; Empty entries are filled with zeros + +ARP_ENTRY_SIZE equ 14 ; Number of bytes per entry +ARP_TABLE_SIZE equ 20 ; Size of table +ARP_TABLE_ENTRIES equ 0 ; Number of static entries in the table + +;TO ADD A STATIC ENTRY, DONT FORGET, PUT "ARPTable" from "uglobal" to "iglobal"!!! +;AND ALSO - IP and MAC have net byte-order, BUT STATUS AND TTL HAVE A MIRROR BYTE-ORDER!!! +uglobal + ARPTable: +;example, static entry -> db 11,22,33,44, 0x11,0x22,0x33,0x44,0x55,0x66, 0x01,0x00, 0xFF,0xFF + times ( ARP_TABLE_SIZE - ARP_TABLE_ENTRIES ) * ARP_ENTRY_SIZE db 0 +endg + +iglobal + NumARP: + dd ARP_TABLE_ENTRIES + ARPTable_ptr dd ARPTable ;pointer to ARPTable +endg + +ARP_REQ_OPCODE equ 0x0100 ;request +ARP_REP_OPCODE equ 0x0200 ;reply + +struc ARP_PACKET +{ .HardwareType dw ? ;+00 + .ProtocolType dw ? ;+02 + .HardwareSize db ? ;+04 + .ProtocolSize db ? ;+05 + .Opcode dw ? ;+06 + .SenderMAC dp ? ;+08 + .SenderIP dd ? ;+14 + .TargetMAC dp ? ;+18 + .TargetIP dd ? ;+24 +} + +virtual at 0 + ARP_PACKET ARP_PACKET +end virtual + + + +;*************************************************************************** +; Function +; arp_table_manager [by Johnny_B] +; +; Description +; Does a most required operations with ARP-table +; IN: +; Operation: see Opcode's constants below +; Index: Index of entry in the ARP-table +; Extra: Extra parameter for some Opcodes +; OUT: +; EAX = Returned value depends on opcodes, more detailed see below +; +;*************************************************************************** +;Opcode's constants +ARP_TABLE_ADD equ 1 +ARP_TABLE_DEL equ 2 +ARP_TABLE_GET equ 3 +ARP_TABLE_GET_ENTRIES_NUMBER equ 4 +ARP_TABLE_IP_TO_MAC equ 5 +ARP_TABLE_TIMER equ 6 + +;Index's constants +EXTRA_IS_ARP_PACKET_PTR equ 0 ;if Extra contain pointer to ARP_PACKET +EXTRA_IS_ARP_ENTRY_PTR equ -1 ;if Extra contain pointer to ARP_ENTRY + +align 4 +proc arp_table_manager stdcall uses ebx esi edi ecx edx,\ + Opcode:DWORD,Index:DWORD,Extra:DWORD + + mov ebx, dword[ARPTable_ptr];ARPTable base + mov ecx, dword[NumARP] ;ARP-entries counter + + mov eax, dword[Opcode] + cmp eax, ARP_TABLE_TIMER + je .timer + cmp eax, ARP_TABLE_ADD + je .add + cmp eax, ARP_TABLE_DEL + je .del + cmp eax, ARP_TABLE_GET + je .get + cmp eax, ARP_TABLE_IP_TO_MAC + je .ip_to_mac + cmp eax, ARP_TABLE_GET_ENTRIES_NUMBER + je .get_entries_number + jmp .exit ;if unknown opcode + + +;;BEGIN TIMER +;;Description: it must be callback every second. It is responsible for removing expired routes. +;;IN: Operation: ARP_TABLE_TIMER +;; Index: must be zero +;; Extra: must be zero +;;OUT: +;; EAX=not defined +;; +.timer: + test ecx, ecx + jz .exit;if NumARP=0 nothing to do + sub ecx, ARP_TABLE_ENTRIES;ecx=dynamic entries number + jz .exit;if NumARP=number of static entries then exit + + add ebx, ARP_TABLE_ENTRIES*ARP_ENTRY_SIZE;ebx=dynamic entries base + + .timer_loop: + movsx esi, word [ebx + ARP_ENTRY.TTL] + cmp esi, 0xFFFFFFFF + je .timer_loop_end;if TTL==0xFFFF then it's static entry + + test esi, esi + jnz .timer_loop_end_with_dec;if TTL!=0 + + ; Ok, TTL is 0 + ;if Status==AWAITING_RESPONSE and TTL==0 + ;then we have to change it to ARP_RESPONSE_TIMEOUT + cmp word [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE + jne @f + + mov word [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT + mov word [ebx + ARP_ENTRY.TTL], word 0x000A;10 sec + jmp .timer_loop_end + + @@: + ;if TTL==0 and Status==VALID_MAPPING, we have to delete it + ;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too + mov esi, dword[NumARP] + sub esi, ecx ;esi=index of entry, will be deleted + stdcall arp_table_manager, ARP_TABLE_DEL, esi, 0;opcode,index,extra + jmp .timer_loop_end + + + .timer_loop_end_with_dec: + dec word [ebx + ARP_ENTRY.TTL];decrease TTL + .timer_loop_end: + add ebx, ARP_ENTRY_SIZE + loop .timer_loop + + jmp .exit +;;END TIMER + +;;BEGIN ADD +;;Description: it adds an entry in the table. If ARP-table already +;; contains same IP, it will be updated. +;;IN: Operation: ARP_TABLE_ADD +;; Index: specifies what contains Extra-parameter +;; Extra: if Index==EXTRA_IS_ARP_PACKET_PTR, +;; then Extra contains pointer to ARP_PACKET, +;; otherwise Extra contains pointer to ARP_ENTRY +;;OUT: +;; EAX=index of entry, that has been added +;; +.add: + + sub esp, ARP_ENTRY_SIZE;Allocate ARP_ENTRY_SIZE byte in stack + + mov esi, [Extra];pointer + mov edi, [Index];opcode + + cmp edi, EXTRA_IS_ARP_PACKET_PTR + je .arp_packet_to_entry;if Extra contain ptr to ARP_PACKET and we have to form arp-entry + ;else it contain ptr to arp-entry + + cld + ; esi already has been loaded + mov edi, esp ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) + mov ecx, ARP_ENTRY_SIZE/2;ARP_ENTRY_SIZE must be even number!!! + rep movsw ;copy + jmp .search + + .arp_packet_to_entry: + mov edx, dword[esi + ARP_PACKET.SenderIP];esi=base of ARP_PACKET + mov [esp + ARP_ENTRY.IP], edx + + cld + lea esi, [esi + ARP_PACKET.SenderMAC] + lea edi, [esp + ARP_ENTRY.MAC] + movsd + movsw + mov word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING; specify the type - a valid entry + mov word[esp + ARP_ENTRY.TTL], 0x0E10; = 1 hour + + .search: + mov edx, dword[esp + ARP_ENTRY.IP];edx=IP-address, which we'll search + mov ecx, dword[NumARP] ;ecx=ARP-entries counter + jecxz .add_to_end ;if ARP-entries number == 0 + imul eax, ecx, ARP_ENTRY_SIZE ;eax=current table size(in bytes) + @@: + sub eax, ARP_ENTRY_SIZE + cmp dword[ebx + eax + ARP_ENTRY.IP], edx + loopnz @b + jz .replace ; found, replace existing entry, ptr to it is in eax + + .add_to_end: + ;else add to end + or eax, -1;set eax=0xFFFFFFFF if adding is impossible + mov ecx, dword[NumARP] + cmp ecx, ARP_TABLE_SIZE + je .add_exit;if arp-entries number is equal to arp-table maxsize + + imul eax, dword[NumARP], ARP_ENTRY_SIZE;eax=ptr to end of ARPTable + inc dword [NumARP];increase ARP-entries counter + + .replace: + cld + mov esi, esp ;esp=base of ARP-entry, that will be added + lea edi, [ebx + eax] ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) + mov ecx, ARP_ENTRY_SIZE/2;ARP_ENTRY_SIZE must be even number!!! + rep movsw + + mov ecx, ARP_ENTRY_SIZE + xor edx, edx;"div" takes operand from EDX:EAX + div ecx ;eax=index of entry, which has been added + +.add_exit: + add esp, ARP_ENTRY_SIZE;free stack + jmp .exit +;;END ADD + +;;BEGIN DEL +;;Description: it deletes an entry in the table. +;;IN: Operation: ARP_TABLE_DEL +;; Index: index of entry, that should be deleted +;; Extra: must be zero +;;OUT: +;; EAX=not defined +;; +.del: + mov esi, [Index] + imul esi, ARP_ENTRY_SIZE + + mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY_SIZE + sub ecx, esi + + lea edi, [ebx + esi] ;edi=ptr to entry that should be deleted + lea esi, [edi + ARP_ENTRY_SIZE];esi=ptr to next entry + + shr ecx, 1 ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER! + cld + rep movsw + + dec dword[NumARP];decrease arp-entries counter + jmp .exit +;;END DEL + +;;BEGIN GET +;;Description: it reads an entry of table into buffer. +;;IN: Operation: ARP_TABLE_GET +;; Index: index of entry, that should be read +;; Extra: pointer to buffer for reading(size must be equal to ARP_ENTRY_SIZE) +;;OUT: +;; EAX=not defined +;; +.get: + mov esi, [Index] + imul esi, ARP_ENTRY_SIZE;esi=ptr to required ARP_ENTRY + mov edi, [Extra] ;edi=buffer for reading + mov ecx, ARP_ENTRY_SIZE/2; must be even number!!! + cld + rep movsw + jmp .exit +;;END GET + +;;BEGIN IP_TO_MAC +;;Description: it gets an IP from Index, scans each entry in the table and writes +;; MAC, that relates to specified IP, into buffer specified in Extra. +;; And if it cannot find an IP-address in the table, it does an ARP-request of that. +;;IN: Operation: ARP_TABLE_IP_TO_MAC +;; Index: IP that should be transformed into MAC +;; Extra: pointer to buffer where will be written the MAC-address. +;;OUT: +;; EAX=ARP table entry status code. +;; If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request. +;; If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system. +;; If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long. +;; If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC. +;; +;; If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet +;; resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this +;; function with 1sec delay. sure, only if it not return a valid MAC after a first call. +;; +.ip_to_mac: + + xor eax, eax + mov edi, dword[Extra] + cld + stosd + stosw + + + ; first, check destination IP to see if it is on 'this' network. + ; The test is: + ; if ( destIP & subnet_mask == stack_ip & subnet_mask ) + ; destination is local + ; else + ; destination is remote, so pass to gateway + + mov eax, [Index] ;eax=required IP + mov esi, eax + and esi, [subnet_mask] + mov ecx, [stack_ip] + and ecx, [subnet_mask] + cmp esi, ecx + je @f ;if we and target IP are located in the same network + mov eax, [gateway_ip] + mov [Index], eax + @@: + + cmp dword[NumARP], 0 + je .ip_to_mac_send_request;if ARP-table not contain an entries, we have to request IP. + ;EAX will be containing a zero, it's equal to ARP_NO_ENTRY + + mov ecx, dword[NumARP] + imul esi, ecx, ARP_ENTRY_SIZE;esi=current ARP-table size + + @@: + sub esi, ARP_ENTRY_SIZE + cmp [ebx + esi], eax ; ebx=ARPTable base + loopnz @b ; Return back if non match + jnz .ip_to_mac_send_request; and request IP->MAC if none found in the table + + ; Return the entry status in eax + movzx eax, word[ebx + esi + ARP_ENTRY.Status] + + ; esi holds index + cld + lea esi, [ebx + esi + ARP_ENTRY.MAC] + mov edi, [Extra];edi=ptr to buffer for write MAC + movsd + movsw + jmp .exit + + .ip_to_mac_send_request: + stdcall arp_request, [Index], stack_ip, node_addr;TargetIP,SenderIP_ptr,SenderMAC_ptr + mov eax, ARP_NO_ENTRY + jmp .exit + +;;END IP_TO_MAC + +;;BEGIN GET_ENTRIES_NUMBER +;;Description: returns an ARP-entries number in the ARPTable +;;IN: Operation: ARP_TABLE_GET_ENTRIES_NUMBER +;; Index: must be zero +;; Extra: must be zero +;;OUT: +;; EAX=ARP-entries number in the ARPTable + .get_entries_number: + mov eax, dword[NumARP] + jmp .exit +;;END GET_ENTRIES_NUMBER + +.exit: + ret +endp + + +;*************************************************************************** +; Function +; arp_handler +; +; Description +; Called when an ARP packet is received on the ethernet +; Header + Data is in Ether_buffer[] +; It looks to see if the packet is a request to resolve this Hosts +; IP address. If it is, send the ARP reply packet. +; This Hosts IP address is in dword [stack_ip] ( in network format ) +; This Hosts MAC address is in node_addr[6] +; All registers may be destroyed +; +;*************************************************************************** +arp_handler: + ; Is this a REQUEST? + ; Is this a request for My Host IP + ; Yes - So construct a response message. + ; Send this message to the ethernet card for transmission + + stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_PACKET_PTR, ETH_FRAME.Data + ARP_PACKET + + inc dword[arp_rx_count];increase ARP-packets counter + + cmp word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REQ_OPCODE; Is this a request packet? + jne .exit ; No - so exit + + mov eax, [stack_ip] + cmp eax, dword[ETH_FRAME.Data + ARP_PACKET.TargetIP] ; Is it looking for my IP address? + jne .exit ; No - so quit now + + ; OK, it is a request for my MAC address. Build the frame and send it + ; We can reuse the packet. + + mov word[ETH_FRAME.Data + ARP_PACKET.Opcode], ARP_REP_OPCODE + + cld + mov esi, ETH_FRAME.Data + ARP_PACKET.SenderMAC + mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC + movsd + movsw + + mov esi, ETH_FRAME.Data + ARP_PACKET.SenderIP + mov edi, ETH_FRAME.Data + ARP_PACKET.TargetIP + movsd + + mov esi, node_addr + mov edi, ETH_FRAME.Data + ARP_PACKET.SenderMAC + movsd + movsw + + mov esi, stack_ip + mov edi, ETH_FRAME.Data + ARP_PACKET.SenderIP + movsd + + ; Now, send it! + mov edi, ETH_FRAME.Data + ARP_PACKET.TargetMAC;ptr to destination MAC address + mov bx, ETHER_ARP ;type of protocol + mov ecx, 28 ;data size + mov esi, ETH_FRAME.Data + ARP_PACKET ;ptr to data + push ebp + call dword [drvr_transmit] ;transmit packet + pop ebp + + .exit: + ret + + +;*************************************************************************** +; Function +; arp_request [by Johnny_B] +; +; Description +; Sends an ARP request on the ethernet +; IN: +; TargetIP : requested IP address +; SenderIP_ptr : POINTER to sender's IP address(our system's address) +; SenderMAC_ptr : POINTER to sender's MAC address(our system's address) +; OUT: +; EAX=0 (if all is ok), otherwise EAX is not defined +; +; EBX,ESI,EDI will be saved +; +;*************************************************************************** +proc arp_request stdcall uses ebx esi edi,\ + TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD + + inc dword[arp_tx_count]; increase counter + + sub esp, 28; allocate memory for ARP_PACKET + + mov word[esp + ARP_PACKET.HardwareType], 0x0100;Ethernet + mov word[esp + ARP_PACKET.ProtocolType], 0x0008;IP + mov byte[esp + ARP_PACKET.HardwareSize], 0x06;MAC-addr length + mov byte[esp + ARP_PACKET.ProtocolSize], 0x04;IP-addr length + mov word[esp + ARP_PACKET.Opcode], 0x0100 ;Request + + cld + mov esi, [SenderMAC_ptr] + lea edi, [esp + ARP_PACKET.SenderMAC] ;Our MAC-addr + movsd + movsw + + mov esi, [SenderIP_ptr] + lea edi, [esp + ARP_PACKET.SenderIP] ;Our IP-addr + movsd + + xor eax, eax + lea edi, [esp + ARP_PACKET.TargetMAC] ;Required MAC-addr(zeroed) + stosd + stosw + + mov esi, dword[TargetIP] + mov dword[esp + ARP_PACKET.TargetIP], esi;Required IP-addr(we get it as function parameter) + + ; Now, send it! + mov edi, broadcast_add ; Pointer to 48 bit destination address + mov bx, ETHER_ARP ; Type of packet + mov ecx, 28 ; size of packet + lea esi, [esp + ARP_PACKET]; pointer to packet data + push ebp + call dword [drvr_transmit]; Call the drivers transmit function + pop ebp + + add esp, 28; free memory, allocated before for ARP_PACKET + + ; Add an entry in the ARP table, awaiting response + sub esp, ARP_ENTRY_SIZE;allocate memory for ARP-entry + + mov esi, dword[TargetIP] + mov dword[esp + ARP_ENTRY.IP], esi + + lea edi, [esp + ARP_ENTRY.MAC] + xor eax, eax + stosd + stosw + + mov word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE + mov word[esp + ARP_ENTRY.TTL], 0x000A; 10 seconds + + stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_ENTRY_PTR, esp + add esp, ARP_ENTRY_SIZE; free memory + +.exit: + ret +endp diff --git a/kernel/trunk/network/eth_drv/drivers/3c59x.inc b/kernel/trunk/network/eth_drv/drivers/3c59x.inc index a61d8297a..6a8776a78 100644 --- a/kernel/trunk/network/eth_drv/drivers/3c59x.inc +++ b/kernel/trunk/network/eth_drv/drivers/3c59x.inc @@ -1,2378 +1,2404 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;; Copyright (c) 2004, Endre Kozma -;; All rights reserved. -;; -;; Redistribution and use in source and binary forms, with or without -;; modification, are permitted provided that the following conditions are -;; met: -;; -;; 1. Redistributions of source code must retain the above copyright notice, -;; this list of conditions and the following disclaimer. -;; -;; 2. Redistributions in binary form must reproduce the above copyright -;; notice, this list of conditions and the following disclaimer in the -;; documentation and/or other materials provided with the distribution. -;; -;; 3. The name of the author may not be used to endorse or promote products -;; derived from this software without specific prior written permission. -;; -;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; 3C59X.INC ;; -;; ;; -;; Ethernet driver for Menuet OS ;; -;; ;; -;; Driver for 3Com fast etherlink 3c59x and ;; -;; etherlink XL 3c900 and 3c905 cards ;; -;; References: ;; -;; www.3Com.com - data sheets ;; -;; DP83840A.pdf - ethernet physical layer ;; -;; 3c59x.c - linux driver ;; -;; ethernet driver template by Mike Hibbett ;; -;; ;; -;; Credits ;; -;; Mike Hibbett, ;; -;; who kindly supplied me with a 3Com905C-TX-M card ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; History -;; ======= -;; $Log: 3C59X.INC,v $ -;; Revision 1.3 2004/07/11 12:21:12 kozma -;; Support of vortex chips (3c59x) added. -;; Support of 3c920 and 3c982 added. -;; Corrections. -;; -;; Revision 1.2 2004/06/12 19:40:20 kozma -;; Function e3c59x_set_available_media added in order to set -;; the default media in case auto detection finds no valid link. -;; Incorrect mii check removed (3c900 Cyclone works now). -;; Cleanups. -;; -;; Revision 1.1 2004/06/12 18:27:15 kozma -;; Initial revision -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; comment the next line out if you don't want debug info printed -; on the debug board. This option adds a lot of bytes to the driver -; so it's worth to comment it out. -; E3C59X_DEBUG equ 1 - -; forcing full duplex mode makes sense at some cards and link types - E3C59X_FORCE_FD equ 1 - -macro virt_to_dma reg -{ -sub reg, OS_BASE -} - -macro dma_to_virt reg -{ -add reg, OS_BASE -} - -macro zero_to_virt reg -{ - -} - -macro virt_to_zero reg -{ - -} - -macro zero_to_dma reg -{ -sub reg, OS_BASE -} - -macro dma_to_zero reg -{ -add reg, OS_BASE -} - -macro strtbl name, [string] -{ -common - label name dword -forward - local label - dd label -forward - label db string, 0 -} - -; Ethernet frame symbols - ETH_ALEN equ 6 - ETH_HLEN equ (2*ETH_ALEN+2) - ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for - ; mininmum 64bytes frame length -; PCI programming - PCI_REG_COMMAND equ 0x4 ; command register - PCI_REG_STATUS equ 0x6 ; status register - PCI_REG_LATENCY equ 0xd ; latency timer register - PCI_REG_CAP_PTR equ 0x34 ; capabilities pointer - PCI_REG_CAPABILITY_ID equ 0x0 ; capapility ID in pm register block - PCI_REG_PM_STATUS equ 0x4 ; power management status register - PCI_REG_PM_CTRL equ 0x4 ; power management control register - PCI_BIT_PIO equ 0 ; bit0: io space control - PCI_BIT_MMIO equ 1 ; bit1: memory space control - PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master -; Registers - E3C59X_REG_POWER_MGMT_CTRL equ 0x7c - E3C59X_REG_UP_LIST_PTR equ 0x38 - E3C59X_REG_UP_PKT_STATUS equ 0x30 - E3C59X_REG_TX_FREE_THRESH equ 0x2f - E3C59X_REG_DN_LIST_PTR equ 0x24 - E3C59X_REG_DMA_CTRL equ 0x20 - E3C59X_REG_TX_STATUS equ 0x1b - E3C59X_REG_RX_STATUS equ 0x18 - E3C59X_REG_TX_DATA equ 0x10 -; Common window registers - E3C59X_REG_INT_STATUS equ 0xe - E3C59X_REG_COMMAND equ 0xe -; Register window 7 - E3C59X_REG_MASTER_STATUS equ 0xc - E3C59X_REG_POWER_MGMT_EVENT equ 0xc - E3C59X_REG_MASTER_LEN equ 0x6 - E3C59X_REG_VLAN_ETHER_TYPE equ 0x4 - E3C59X_REG_VLAN_MASK equ 0x0 - E3C59X_REG_MASTER_ADDRESS equ 0x0 -; Register window 6 - E3C59X_REG_BYTES_XMITTED_OK equ 0xc - E3C59X_REG_BYTES_RCVD_OK equ 0xa - E3C59X_REG_UPPER_FRAMES_OK equ 0x9 - E3C59X_REG_FRAMES_DEFERRED equ 0x8 - E3C59X_REG_FRAMES_RCVD_OK equ 0x7 - E3C59X_REG_FRAMES_XMITTED_OK equ 0x6 - E3C59X_REG_RX_OVERRUNS equ 0x5 - E3C59X_REG_LATE_COLLISIONS equ 0x4 - E3C59X_REG_SINGLE_COLLISIONS equ 0x3 - E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2 - E3C59X_REG_SQE_ERRORS equ 0x1 - E3C59X_REG_CARRIER_LOST equ 0x0 -; Register window 5 - E3C59X_REG_INDICATION_ENABLE equ 0xc - E3C59X_REG_INTERRUPT_ENABLE equ 0xa - E3C59X_REG_TX_RECLAIM_THRESH equ 0x9 - E3C59X_REG_RX_FILTER equ 0x8 - E3C59X_REG_RX_EARLY_THRESH equ 0x6 - E3C59X_REG_TX_START_THRESH equ 0x0 -; Register window 4 - E3C59X_REG_UPPER_BYTES_OK equ 0xe - E3C59X_REG_BAD_SSD equ 0xc - E3C59X_REG_MEDIA_STATUS equ 0xa - E3C59X_REG_PHYSICAL_MGMT equ 0x8 - E3C59X_REG_NETWORK_DIAGNOSTIC equ 0x6 - E3C59X_REG_FIFO_DIAGNOSTIC equ 0x4 - E3C59X_REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported -; Bits in register window 4 - E3C59X_BIT_AUTOSELECT equ 24 -; Register window 3 - E3C59X_REG_TX_FREE equ 0xc - E3C59X_REG_RX_FREE equ 0xa - E3C59X_REG_MEDIA_OPTIONS equ 0x8 - E3C59X_REG_MAC_CONTROL equ 0x6 - E3C59X_REG_MAX_PKT_SIZE equ 0x4 - E3C59X_REG_INTERNAL_CONFIG equ 0x0 -; Register window 2 - E3C59X_REG_RESET_OPTIONS equ 0xc - E3C59X_REG_STATION_MASK_HI equ 0xa - E3C59X_REG_STATION_MASK_MID equ 0x8 - E3C59X_REG_STATION_MASK_LO equ 0x6 - E3C59X_REG_STATION_ADDRESS_HI equ 0x4 - E3C59X_REG_STATION_ADDRESS_MID equ 0x2 - E3C59X_REG_STATION_ADDRESS_LO equ 0x0 -; Register window 1 - E3C59X_REG_TRIGGER_BITS equ 0xc - E3C59X_REG_SOS_BITS equ 0xa - E3C59X_REG_WAKE_ON_TIMER equ 0x8 - E3C59X_REG_SMB_RXBYTES equ 0x7 - E3C59X_REG_SMB_DIAG equ 0x5 - E3C59X_REG_SMB_ARB equ 0x4 - E3C59X_REG_SMB_STATUS equ 0x2 - E3C59X_REG_SMB_ADDRESS equ 0x1 - E3C59X_REG_SMB_FIFO_DATA equ 0x0 -; Register window 0 - E3C59X_REG_EEPROM_DATA equ 0xc - E3C59X_REG_EEPROM_COMMAND equ 0xa - E3C59X_REG_BIOS_ROM_DATA equ 0x8 - E3C59X_REG_BIOS_ROM_ADDR equ 0x4 -; Physical management bits - E3C59X_BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData - E3C59X_BIT_MGMT_DATA equ 1 ; MII management data bit - E3C59X_BIT_MGMT_CLK equ 0 ; MII management clock -; MII commands - E3C59X_MII_CMD_MASK equ (1111b shl 10) - E3C59X_MII_CMD_READ equ (0110b shl 10) - E3C59X_MII_CMD_WRITE equ (0101b shl 10) -; MII registers - E3C59X_REG_MII_BMCR equ 0 ; basic mode control register - E3C59X_REG_MII_BMSR equ 1 ; basic mode status register - E3C59X_REG_MII_ANAR equ 4 ; auto negotiation advertisement register - E3C59X_REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register - E3C59X_REG_MII_ANER equ 6 ; auto negotiation expansion register -; MII bits - E3C59X_BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete - E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6 -; eeprom bits and commands - E3C59X_EEPROM_CMD_READ equ 0x80 - E3C59X_EEPROM_BIT_BUSY equ 15 -; eeprom registers - E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa - E3C59X_EEPROM_REG_CAPABILITIES equ 0x10 -; Commands for command register - E3C59X_SELECT_REGISTER_WINDOW equ (1 shl 11) - - IS_VORTEX equ 0x1 - IS_BOOMERANG equ 0x2 - IS_CYCLONE equ 0x4 - IS_TORNADO equ 0x8 - EEPROM_8BIT equ 0x10 - HAS_PWR_CTRL equ 0x20 - HAS_MII equ 0x40 - HAS_NWAY equ 0x80 - HAS_CB_FNS equ 0x100 - INVERT_MII_PWR equ 0x200 - INVERT_LED_PWR equ 0x400 - MAX_COLLISION_RESET equ 0x800 - EEPROM_OFFSET equ 0x1000 - HAS_HWCKSM equ 0x2000 - EXTRA_PREAMBLE equ 0x4000 - -iglobal - align 4 -e3c59x_hw_versions: - dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps - dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex - dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex - dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx - dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4 - dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII - dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT - dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo - dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO - dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo - dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC - dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL - dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx - dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4 - dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx - dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC - dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx - dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado - dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone - dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone - dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane - dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane - dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \ - or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado - dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \ - or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane - dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus - dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus - dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \ - or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus - dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ - or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus - dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ - or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus - dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ - or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus - dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ - or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus - dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado - dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado - dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A - dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B - dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4 - dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado -E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions -endg - -; RX/TX buffers sizes - E3C59X_MAX_ETH_PKT_SIZE equ 1536 ; max packet size - E3C59X_NUM_RX_DESC equ 4 ; a power of 2 number - E3C59X_NUM_TX_DESC equ 4 ; a power of 2 number - E3C59X_RX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC) - E3C59X_TX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC) -; Download Packet Descriptor - E3C59X_DPD_DN_NEXT_PTR equ 0 - E3C59X_DPD_FRAME_START_HDR equ 4 - E3C59X_DPD_DN_FRAG_ADDR equ 8 ; for packet data - E3C59X_DPD_DN_FRAG_LEN equ 12 ; for packet data - E3C59X_DPD_SIZE equ 16 ; a power of 2 number -; Upload Packet Descriptor - E3C59X_UPD_UP_NEXT_PTR equ 0 - E3C59X_UPD_PKT_STATUS equ 4 - E3C59X_UPD_UP_FRAG_ADDR equ 8 ; for packet data - E3C59X_UPD_UP_FRAG_LEN equ 12 ; for packet data - E3C59X_UPD_SIZE equ 16 - -; RX/TX buffers -if defined E3C59X_LINUX - E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment - e3c59x_rx_buff = 0 -else - E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment - e3c59x_rx_buff = eth_data_start -end if - - e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE - e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE - e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC) - -uglobal -e3c59x_curr_upd: dd 0 -e3c59x_prev_dpd: dd 0 -e3c59x_prev_tx_frame: dd 0 -e3c59x_transmit_function: dd 0 -e3c59x_receive_function: dd 0 -endg - -iglobal -e3c59x_ver_id: db 17 -endg - -uglobal -e3c59x_full_bus_master: db 0 -e3c59x_has_hwcksm: db 0 -e3c59x_preamble: db 0 -e3c59x_dn_list_ptr_cleared: db 0 -e3c59x_self_directed_packet: rb 6 -endg - -if defined E3C59X_DEBUG -e3c59x_hw_type_str: db "Detected hardware type : ", 0 -e3c59x_device_str: db "Device ID : 0x" -e3c59x_device_id_str: db "ffff", 13, 10, 0 -e3c59x_vendor_str: db "Vendor ID : 0x" -e3c59x_vendor_id_str: db "ffff", 13, 10, 0 -e3c59x_io_info_str: db "IO address : 0x" -e3c59x_io_addr_str: db "ffff", 13, 10, 0 -e3c59x_mac_info_str: db "MAC address : " -e3c59x_mac_addr_str: db "ff:ff:ff:ff:ff:ff", 13, 10, 0 -e3c59x_boomerang_str: db " (boomerang)", 13, 10, 0 -e3c59x_vortex_str: db " (vortex)", 13, 10, 0 -e3c59x_link_type_str: db "Established link type : ", 0 -e3c59x_new_line_str: db 13, 10, 0 -e3c59x_link_type: dd 0 - -e3c59x_charset: db '0123456789abcdef' - -strtbl e3c59x_link_str, \ - "No valid link type detected", \ - "10BASE-T half duplex", \ - "10BASE-T full-duplex", \ - "100BASE-TX half duplex", \ - "100BASE-TX full duplex", \ - "100BASE-T4", \ - "100BASE-FX", \ - "10Mbps AUI", \ - "10Mbps COAX (BNC)", \ - "miiDevice - not supported" - -strtbl e3c59x_hw_str, \ - "3c590 Vortex 10Mbps", \ - "3c592 EISA 10Mbps Demon/Vortex", \ - "3c597 EISA Fast Demon/Vortex", \ - "3c595 Vortex 100baseTx", \ - "3c595 Vortex 100baseT4", \ - "3c595 Vortex 100base-MII", \ - "3c900 Boomerang 10baseT", \ - "3c900 Boomerang 10Mbps Combo", \ - "3c900 Cyclone 10Mbps TPO", \ - "3c900 Cyclone 10Mbps Combo", \ - "3c900 Cyclone 10Mbps TPC", \ - "3c900B-FL Cyclone 10base-FL", \ - "3c905 Boomerang 100baseTx", \ - "3c905 Boomerang 100baseT4", \ - "3c905B Cyclone 100baseTx", \ - "3c905B Cyclone 10/100/BNC", \ - "3c905B-FX Cyclone 100baseFx", \ - "3c905C Tornado", \ - "3c980 Cyclone", \ - "3c982 Dual Port Server Cyclone", \ - "3cSOHO100-TX Hurricane", \ - "3c555 Laptop Hurricane", \ - "3c556 Laptop Tornado", \ - "3c556B Laptop Hurricane", \ - "3c575 [Megahertz] 10/100 LAN CardBus", \ - "3c575 Boomerang CardBus", \ - "3CCFE575BT Cyclone CardBus", \ - "3CCFE575CT Tornado CardBus", \ - "3CCFE656 Cyclone CardBus", \ - "3CCFEM656B Cyclone+Winmodem CardBus", \ - "3CXFEM656C Tornado+Winmodem CardBus", \ - "3c450 HomePNA Tornado", \ - "3c920 Tornado", \ - "3c982 Hydra Dual Port A", \ - "3c982 Hydra Dual Port B", \ - "3c905B-T4", \ - "3c920B-EMB-WNM Tornado" - -end if ; defined E3C59X_DEBUG - -;*************************************************************************** -; Function -; e3c59x_debug -; Description -; prints debug info to the debug board -; Parameters -; ebp - io_addr -; Return value -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** -if defined E3C59X_DEBUG - align 4 -e3c59x_debug: - pushad -; print device type - mov esi, e3c59x_hw_type_str - call sys_msg_board_str - movzx ecx, byte [e3c59x_ver_id] - mov esi, [e3c59x_hw_str+ecx*4] - call sys_msg_board_str - mov esi, e3c59x_boomerang_str - cmp dword [e3c59x_transmit_function], e3c59x_boomerang_transmit - jz .boomerang - mov esi, e3c59x_vortex_str -.boomerang: - call sys_msg_board_str -; print device/vendor - mov ax, [pci_data+2] - mov cl, 2 - mov ebx, e3c59x_device_id_str - call e3c59x_print_hex - mov esi, e3c59x_device_str - call sys_msg_board_str - mov ax, [pci_data] - mov cl, 2 - mov ebx, e3c59x_vendor_id_str - call e3c59x_print_hex - mov esi, e3c59x_vendor_str - call sys_msg_board_str -; print io address - mov ax, [io_addr] - mov ebx, e3c59x_io_addr_str - mov cl, 2 - call e3c59x_print_hex - mov esi, e3c59x_io_info_str - call sys_msg_board_str -; print MAC address - mov ebx, e3c59x_mac_addr_str - xor ecx, ecx -.mac_loop: - push ecx - mov al, [node_addr+ecx] - mov cl, 1 - call e3c59x_print_hex - inc ebx - pop ecx - inc cl - cmp cl, 6 - jne .mac_loop - mov esi, e3c59x_mac_info_str - call sys_msg_board_str -; print link type - mov esi, e3c59x_link_type_str - call sys_msg_board_str - xor eax, eax - bsr ax, word [e3c59x_link_type] - jz @f - sub ax, 4 -@@: - mov esi, [e3c59x_link_str+eax*4] - call sys_msg_board_str - mov esi, e3c59x_new_line_str - call sys_msg_board_str - popad - ret - -;*************************************************************************** -; Function -; e3c59x_print_hex -; Description -; prints a hexadecimal value -; Parameters -; eax - value to be printed out -; ebx - where to print -; cl - value size (1, 2, 4) -; Return value -; ebx - end address after the print -; Destroyed registers -; eax, ebx -; -;*************************************************************************** - align 4 -e3c59x_print_hex: - cmp cl, 1 - je .print_byte - cmp cl, 2 - jz .print_word -.print_dword: - push eax - bswap eax - xchg ah, al - call .print_word - pop eax -.print_word: - push eax - xchg ah, al - call .print_byte - pop eax -.print_byte: - movzx eax, al - push eax - and al, 0xf0 - shr al, 4 - mov al, byte [eax+e3c59x_charset] - mov [ebx], al - inc ebx - pop eax - and al, 0x0f - mov al, byte [eax+e3c59x_charset] - mov [ebx], al - inc ebx - ret -end if ; defined E3C59X_DEBUG - -;*************************************************************************** -; Function -; e3c59x_try_link_detect -; Description -; e3c59x_try_link_detect checks if link exists -; Parameters -; ebp - io_addr -; Return value -; al - 0 ; no link detected -; al - 1 ; link detected -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** - align 4 -e3c59x_try_link_detect: -; download self-directed packet - mov edi, node_addr - mov bx, 0x0608 ; packet type - mov esi, e3c59x_self_directed_packet - mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes - call dword [e3c59x_transmit_function] -; switch to register window 5 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 - out dx, ax -; program RxFilter for promiscuous operation - mov ax, (10000b shl 11) - lea edx, [ebp+E3C59X_REG_RX_FILTER] - in al, dx - or al, 1111b - lea edx, [ebp+E3C59X_REG_COMMAND] - out dx, ax -; switch to register window 4 - mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 - out dx, ax -; check loop - xor ebx, ebx - mov ecx, 0xffff ; 65535 tries -.loop: - push ecx ebx - call dword [e3c59x_receive_function] - pop ebx ecx - test al, al - jnz .finish -.no_packet_received: -; switch to register window 4 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 - out dx, ax -; read linkbeatdetect - lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] - in ax, dx - test ah, 1000b ; test linkBeatDetect - jnz .link_detected - xor al, al - jmp .finish -.link_detected: -; test carrierSense - test al, 100000b - jz .no_carrier_sense - inc ebx -.no_carrier_sense: - dec ecx - jns .loop -; assume the link is good if 0 < ebx < 25 % - test ebx, ebx - setnz al - jz .finish - cmp ebx, 16384 ; 25% - setb al -.finish: -if defined E3C59X_DEBUG - test al, al - jz @f - or byte [e3c59x_link_type+1], 100b -@@: -end if ; defined E3C59X_DEBUG - ret - -;*************************************************************************** -; Function -; e3c59x_try_phy -; Description -; e3c59x_try_phy checks the auto-negotiation function -; in the PHY at PHY index. It can also be extended to -; include link detection for non-IEEE 802.3u -; auto-negotiation devices, for instance the BCM5000. -; Parameters -; ah - PHY index -; ebp - io_addr -; Return value -; al - 0 link is auto-negotiated -; al - 1 no link is auto-negotiated -; Destroyed registers -; eax, ebx, ecx, edx, esi -; -;*************************************************************************** - align 4 -e3c59x_try_phy: - mov al, E3C59X_REG_MII_BMCR - push eax - call e3c59x_mdio_read ; returns with window #4 - or ah, 0x80 ; software reset - mov ebx, eax - pop eax - push eax - call e3c59x_mdio_write ; returns with window #4 -; wait for reset to complete - mov esi, 2000 ; 2000ms = 2s - call delay_ms - pop eax - push eax - call e3c59x_mdio_read ; returns with window #4 - test ah, 0x80 - jnz .fail_finish - pop eax - push eax -; wait for a while after reset - mov esi, 20 ; 20ms - call delay_ms - pop eax - push eax - mov al, E3C59X_REG_MII_BMSR - call e3c59x_mdio_read ; returns with window #4 - test al, 1 ; extended capability supported? - jz .no_ext_cap -; auto-neg capable? - test al, 1000b - jz .fail_finish ; not auto-negotiation capable -; auto-neg complete? - test al, 100000b - jnz .auto_neg_ok -; restart auto-negotiation - pop eax - push eax - mov al, E3C59X_REG_MII_ANAR - push eax - call e3c59x_mdio_read ; returns with window #4 - or ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX - mov ebx, eax - pop eax - call e3c59x_mdio_write ; returns with window #4 - pop eax - push eax - call e3c59x_mdio_read ; returns with window #4 - mov ebx, eax - or bh, 10010b ; restart auto-negotiation - pop eax - push eax - call e3c59x_mdio_write ; returns with window #4 - mov esi, 4000 ; 4000ms = 4 seconds - call delay_ms - pop eax - push eax - mov al, E3C59X_REG_MII_BMSR - call e3c59x_mdio_read ; returns with window #4 - test al, 100000b ; auto-neg complete? - jnz .auto_neg_ok - jmp .fail_finish -.auto_neg_ok: -; compare advertisement and link partner ability registers - pop eax - push eax - mov al, E3C59X_REG_MII_ANAR - call e3c59x_mdio_read ; returns with window #4 - xchg eax, [esp] - mov al, E3C59X_REG_MII_ANLPAR - call e3c59x_mdio_read ; returns with window #4 - pop ebx - and eax, ebx - and eax, 1111100000b - push eax -if defined E3C59X_DEBUG - mov word [e3c59x_link_type], ax -end if ; defined E3C59X_DEBUG -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax -; set full-duplex mode - lea edx, [ebp+E3C59X_REG_MAC_CONTROL] - in ax, dx - and ax, not 0x120 ; clear full duplex and flow control - pop ebx - test ebx, (1010b shl 5) ; check for full-duplex - jz .half_duplex - or ax, 0x120 ; set full duplex and flow control -.half_duplex: - out dx, ax - mov al, 1 - ret -.no_ext_cap: -; not yet implemented BCM5000 -.fail_finish: - pop eax - xor al, al - ret - -;*************************************************************************** -; Function -; e3c59x_try_mii -; Description -; e3c59x_try_MII checks the on-chip auto-negotiation logic -; or an off-chip MII PHY, depending upon what is set in -; xcvrSelect by the caller. -; It exits when it finds the first device with a good link. -; Parameters -; ebp - io_addr -; Return value -; al - 0 -; al - 1 -; Destroyed registers -; eax, ebx, ecx, edx, esi -; -;*************************************************************************** - align 4 -e3c59x_try_mii: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - and eax, (1111b shl 20) - cmp eax, (1000b shl 20) ; is auto-negotiation set? - jne .mii_device -; auto-negotiation is set -; switch to register window 4 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 - out dx, ax -; PHY==24 is the on-chip auto-negotiation logic -; it supports only 10base-T and 100base-TX - mov ah, 24 - call e3c59x_try_phy - test al, al - jz .fail_finish - mov cl, 24 - jmp .check_preamble -.mii_device: - cmp eax, (0110b shl 20) - jne .fail_finish - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 - out dx, ax - lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] - in ax, dx - and al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA) - cmp al, (1 shl E3C59X_BIT_MGMT_DATA) - je .serch_for_phy - xor al, al - ret -.serch_for_phy: -; search for PHY - mov cl, 31 -.search_phy_loop: - cmp cl, 24 - je .next_phy - mov ah, cl ; ah = phy - mov al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register - push ecx - call e3c59x_mdio_read - pop ecx - test ax, ax - jz .next_phy - cmp ax, 0xffff - je .next_phy - mov ah, cl ; ah = phy - push ecx - call e3c59x_try_phy - pop ecx - test al, al - jnz .check_preamble -.next_phy: - dec cl - jns .search_phy_loop -.fail_finish: - xor al, al - ret -; epilog -.check_preamble: - push eax ; eax contains the return value of e3c59x_try_phy -; check hard coded preamble forcing - movzx eax, byte [e3c59x_ver_id] - test word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE - setnz [e3c59x_preamble] ; force preamble - jnz .finish -; check mii for preamble suppression - mov ah, cl - mov al, E3C59X_REG_MII_BMSR - call e3c59x_mdio_read - test al, 1000000b ; preamble suppression? - setz [e3c59x_preamble] ; no -.finish: - pop eax - ret - -;*************************************************************************** -; Function -; e3c59x_test_packet -; Description -; e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port -; Parameters -; ebp - io_addr -; Return value -; al - 0 -; al - 1 -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** - align 4 -e3c59x_test_packet: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax -; set fullDuplexEnable in MacControl register - lea edx, [ebp+E3C59X_REG_MAC_CONTROL] - in ax, dx - or ax, 0x120 - out dx, ax -; switch to register window 5 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 - out dx, ax -; set RxFilter to enable individual address matches - mov ax, (10000b shl 11) - lea edx, [ebp+E3C59X_REG_RX_FILTER] - in al, dx - or al, 1 - lea edx, [ebp+E3C59X_REG_COMMAND] - out dx, ax -; issue RxEnable and TxEnable - call e3c59x_rx_reset - call e3c59x_tx_reset -; download a self-directed test packet - mov edi, node_addr - mov bx, 0x0608 ; packet type - mov esi, e3c59x_self_directed_packet - mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes - call dword [e3c59x_transmit_function] -; wait for 2s - mov esi, 2000 ; 2000ms = 2s - call delay_ms -; check if self-directed packet is received - call dword [e3c59x_receive_function] - test al, al - jnz .finish -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax -; clear fullDuplexEnable in MacControl register - lea edx, [ebp+E3C59X_REG_MAC_CONTROL] - in ax, dx - and ax, not 0x120 - out dx, ax - xor al, al -.finish: - ret - -;*************************************************************************** -; Function -; e3c59x_try_loopback -; Description -; tries a loopback packet for 10BASE2 or AUI port -; Parameters -; al - 0: 10Mbps AUI connector -; 1: 10BASE-2 -; ebp - io_addr -; Return value -; al - 0 -; al - 1 -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** - align 4 -e3c59x_try_loopback: - push eax -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax - pop eax - push eax -if defined E3C59X_DEBUG - mov bl, al - inc bl - shl bl, 3 - or byte [e3c59x_link_type+1], bl -end if ; defined E3C59X_DEBUG - test al, al ; aui or coax? - jz .complete_loopback -; enable 100BASE-2 DC-DC converter - mov ax, (10b shl 11) ; EnableDcConverter - out dx, ax -.complete_loopback: - mov cl, 2 ; give a port 3 chances to complete a loopback -.next_try: - push ecx - call e3c59x_test_packet - pop ecx - test al, al - jnz .finish - dec cl - jns .next_try -.finish: - xchg eax, [esp] - test al, al - jz .aui_finish -; issue DisableDcConverter command - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (10111b shl 11) - out dx, ax -.aui_finish: - pop eax ; al contains the result of operation -if defined E3C59X_DEBUG - test al, al - jnz @f - and byte [e3c59x_link_type+1], not 11000b -@@: -end if ; defined E3C59X_DEBUG - ret - -;*************************************************************************** -; Function -; e3c59x_set_available_media -; Description -; sets the first available media -; Parameters -; ebp - io_addr -; Return value -; al - 0 -; al - 1 -; Destroyed registers -; eax, edx -; -;*************************************************************************** - align 4 -e3c59x_set_available_media: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - push eax - lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] - in ax, dx - test al, 10b - jz @f -; baseTXAvailable - pop eax - and eax, not (1111b shl 20) - or eax, (100b shl 20) -if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD - mov word [e3c59x_link_type], (1 shl 8) -else if defined E3C59X_DEBUG - mov word [e3c59x_link_type], (1 shl 7) -end if - jmp .set_media -@@: - test al, 100b - jz @f -; baseFXAvailable - pop eax - and eax, not (1111b shl 20) - or eax, (101b shl 20) -if defined E3C59X_DEBUG - mov word [e3c59x_link_type], (1 shl 10) -end if - jmp .set_media -@@: - test al, 1000000b - jz @f -; miiDevice - pop eax - and eax, not (1111b shl 20) - or eax, (0110b shl 20) -if defined E3C59X_DEBUG - mov word [e3c59x_link_type], (1 shl 13) -end if - jmp .set_media -@@: - test al, 1000b - jz @f -.set_default: -; 10bTAvailable - pop eax - and eax, not (1111b shl 20) -if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD - mov word [e3c59x_link_type], (1 shl 6) -else if defined E3C59X_DEBUG - mov word [e3c59x_link_type], (1 shl 5) -end if ; E3C59X_FORCE_FD - jmp .set_media -@@: - test al, 10000b - jz @f -; coaxAvailable - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (10b shl 11) ; EnableDcConverter - out dx, ax - pop eax - and eax, not (1111b shl 20) - or eax, (11b shl 20) -if defined E3C59X_DEBUG - mov word [e3c59x_link_type], (1 shl 12) -end if ; defined E3C59X_DEBUG - jmp .set_media -@@: - test al, 10000b - jz .set_default -; auiAvailable - pop eax - and eax, not (1111b shl 20) - or eax, (1 shl 20) -if defined E3C59X_DEBUG - mov word [e3c59x_link_type], (1 shl 11) -end if ; defined E3C59X_DEBUG -.set_media: - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - out dx, eax -if defined E3C59X_FORCE_FD -; set fullDuplexEnable in MacControl register - lea edx, [ebp+E3C59X_REG_MAC_CONTROL] - in ax, dx - or ax, 0x120 - out dx, ax -end if ; E3C59X_FORCE_FD - mov al, 1 - ret - -;*************************************************************************** -; Function -; e3c59x_set_active_port -; Description -; It selects the media port (transceiver) to be used -; Parameters: -; ebp - io_addr -; Return value: -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** - align 4 -e3c59x_set_active_port: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - test eax, (1 shl 24) ; check if autoselect enable - jz .set_first_available_media -; check 100BASE-TX and 10BASE-T - lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] - in ax, dx - test al, 1010b ; check whether 100BASE-TX or 10BASE-T available - jz .mii_device ; they are not available -; set auto-negotiation - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - and eax, not (1111b shl 20) - or eax, (1000b shl 20) - out dx, eax - call e3c59x_try_mii - test al, al - jz .mii_device - ret -.mii_device: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax -; check for off-chip mii device - lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] - in ax, dx - test al, 1000000b ; check miiDevice - jz .base_fx - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - and eax, not (1111b shl 20) - or eax, (0110b shl 20) ; set MIIDevice - out dx, eax - call e3c59x_try_mii - test al, al - jz .base_fx - ret -.base_fx: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax -; check for 100BASE-FX - lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] - in ax, dx ; read media option register - test al, 100b ; check 100BASE-FX - jz .aui_enable - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - and eax, not (1111b shl 20) - or eax, (0101b shl 20) ; set 100base-FX - out dx, eax - call e3c59x_try_link_detect - test al, al - jz .aui_enable - ret -.aui_enable: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax -; check for 10Mbps AUI connector - lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] - in ax, dx ; read media option register - test al, 100000b ; check 10Mbps AUI connector - jz .coax_available - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - and eax, not (1111b shl 20) - or eax, (0001b shl 20) ; set 10Mbps AUI connector - out dx, eax - xor al, al ; try 10Mbps AUI connector - call e3c59x_try_loopback - test al, al - jz .coax_available - ret -.coax_available: -; switch to register window 3 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 - out dx, ax -; check for coaxial 10BASE-2 port - lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] - in ax, dx ; read media option register - test al, 10000b ; check 10BASE-2 - jz .set_first_available_media - lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] - in eax, dx - and eax, not (1111b shl 20) - or eax, (0011b shl 20) ; set 10BASE-2 - out dx, eax - mov al, 1 - call e3c59x_try_loopback - test al, al - jz .set_first_available_media - ret -.set_first_available_media: - jmp e3c59x_set_available_media - -;*************************************************************************** -; Function -; e3c59x_wake_up -; Description -; set the power state to D0 -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** - align 4 -e3c59x_wake_up: -; wake up - we directly do it by programming PCI -; check if the device is power management capable - mov al, 2 - mov ah, [pci_bus] - mov bl, PCI_REG_STATUS - mov bh, [pci_dev] - push eax ebx - call pci_read_reg - test al, 10000b ; is there "new capabilities" linked list? - pop ebx eax - jz .device_awake -; search for power management register - mov al, 1 - mov bl, PCI_REG_CAP_PTR - push eax ebx - call pci_read_reg - mov cl, al - cmp cl, 0x3f - pop ebx eax - jbe .device_awake -; traverse the list - mov al, 2 -.pm_loop: - mov bl, cl - push eax ebx - call pci_read_reg - cmp al, 1 - je .set_pm_state - test ah, ah - mov cl, ah - pop ebx eax - jnz .pm_loop - jmp .device_awake -; waku up the device if necessary -.set_pm_state: - pop ebx eax - add bl, PCI_REG_PM_CTRL - push eax ebx - call pci_read_reg - mov cx, ax - test cl, 3 - pop ebx eax - jz .device_awake - and cl, not 11b ; set state to D0 - call pci_write_reg -.device_awake: - ret - -;*************************************************************************** -; Function -; e3c59x_probe -; Description -; Searches for an ethernet card, enables it and clears the rx buffer -; If a card was found, it enables the ethernet -> TCPIP link -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** - align 4 -e3c59x_probe: - movzx ebp, word [io_addr] - mov al, 2 - mov ah, [pci_bus] - mov bh, [pci_dev] - mov bl, PCI_REG_COMMAND - push ebp eax ebx - call pci_read_reg - mov cx, ax - or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) - and cl, not (1 shl PCI_BIT_MMIO) - pop ebx eax - call pci_write_reg -; wake up the card - call e3c59x_wake_up - pop ebp -; get chip version - mov ax, [pci_data+2] - mov ecx, E3C59X_HW_VERSIONS_SIZE/4-1 -.chip_ver_loop: - cmp ax, [e3c59x_hw_versions+ecx*4] - jz .chip_ver_found - dec ecx - jns .chip_ver_loop - xor ecx, ecx -.chip_ver_found: - mov [e3c59x_ver_id], cl - test word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM - setnz [e3c59x_has_hwcksm] -; set pci latency for vortex cards - test word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX - jz .not_vortex - mov cx, 11111000b ; 248 = max latency - mov al, 1 - mov ah, [pci_bus] - mov bl, PCI_REG_LATENCY - mov bh, [pci_dev] - call pci_write_reg -.not_vortex: -; set RX/TX functions - mov ax, E3C59X_EEPROM_REG_CAPABILITIES - call e3c59x_read_eeprom - test al, 100000b ; full bus master? - setnz [e3c59x_full_bus_master] - jnz .boomerang_func - mov dword [e3c59x_transmit_function], e3c59x_vortex_transmit - mov dword [e3c59x_receive_function], e3c59x_vortex_poll - jmp @f -.boomerang_func: ; full bus master, so use boomerang functions - mov dword [e3c59x_transmit_function], e3c59x_boomerang_transmit - mov dword [e3c59x_receive_function], e3c59x_boomerang_poll -@@: -; read MAC from eeprom - mov ecx, 2 -.mac_loop: - lea ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx] - call e3c59x_read_eeprom - xchg ah, al ; htons - mov [node_addr+ecx*2], ax - dec ecx - jns .mac_loop - test byte [e3c59x_full_bus_master], 0xff - jz .set_preamble -; switch to register window 2 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 - out dx, ax -; activate xcvr by setting some magic bits - lea edx, [ebp+E3C59X_REG_RESET_OPTIONS] - in ax, dx - and ax, not 0x4010 - movzx ebx, byte [e3c59x_ver_id] - test word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR - jz @f - or al, 0x10 -@@: - test word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR - jz @f - or ah, 0x40 -@@: - out dx, ax -.set_preamble: -; use preamble as default - mov byte [e3c59x_preamble], 1 ; enable preamble - -;*************************************************************************** -; Function -; e3c59x_reset -; Description -; Place the chip (ie, the ethernet card) into a virgin state -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** -e3c59x_reset: -; issue global reset - call e3c59x_global_reset -; disable interrupts - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (1110b shl 11) - out dx, ax -; enable Statistics - mov ax, (10101b shl 11) - out dx, ax -; set indication - mov ax, (1111b shl 11) or 0x6c6 - out dx, ax -; acknowledge (clear) every interrupt indicator - mov ax, (1101b shl 11) or 0x661 - out dx, ax -; switch to register window 2 - mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 - out dx, ax -; write MAC addres back into the station address registers - lea edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO] - mov esi, node_addr - cld - outsw - add edx, 2 - outsw - add edx, 2 - outsw - add edx, 2 -; clear station mask - xor eax, eax - out dx, ax - add edx, 2 - out dx, ax - add edx, 2 - out dx, ax -; switch to register window 6 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+6 - out dx, ax -; clear all statistics by reading - lea edx, [ebp+E3C59X_REG_CARRIER_LOST] - mov cl, 9 -.stat_clearing_loop: - in al, dx - inc edx - dec cl - jns .stat_clearing_loop - in ax, dx - add dx, 2 - in ax, dx -; switch to register window 4 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 - out dx, ax -; clear BadSSD - lea edx, [ebp+E3C59X_REG_BAD_SSD] - in al, dx -; clear extra statistics bit in NetworkDiagnostic - lea edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC] - in ax, dx - or ax, 0x0040 - out dx, ax -; SetRxEarlyThreshold - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2) - out dx, ax - test byte [e3c59x_full_bus_master], 0xff - jz .skip_boomerang_setting -; set upRxEarlyEnable - lea edx, [ebp+E3C59X_REG_DMA_CTRL] - in eax, dx - or eax, 0x20 - out dx, eax -; TxFreeThreshold - lea edx, [ebp+E3C59X_REG_TX_FREE_THRESH] - mov al, (E3C59X_MAX_ETH_PKT_SIZE / 256) - out dx, al -; program DnListPtr - lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] - xor eax, eax - out dx, eax -.skip_boomerang_setting: -; initialization - call e3c59x_rx_reset - call e3c59x_tx_reset - call e3c59x_set_active_port - call e3c59x_rx_reset - call e3c59x_tx_reset -; switch to register window 5 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 - out dx, ax -; program RxFilter for promiscuous operation - mov ax, (10000b shl 11) - lea edx, [ebp+E3C59X_REG_RX_FILTER] - in al, dx - or al, 1111b - lea edx, [ebp+E3C59X_REG_COMMAND] - out dx, ax -; switch to register window 4 - mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 - out dx, ax -; wait for linkDetect - lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] - mov cl, 20 ; wait for max 2s - mov esi, 100 ; 100ms -.link_detect_loop: - call delay_ms - in ax, dx - test ah, 1000b ; linkDetect - jnz @f - dec cl - jnz .link_detect_loop -@@: -; Indicate that we have successfully reset the card - mov eax, [pci_data] - mov [eth_status], eax -if defined E3C59X_DEBUG - call e3c59x_debug -end if ; defined E3C59X_DEBUG - ret - -;*************************************************************************** -; Function -; e3c59x_global_reset -; Description -; resets the device -; Parameters: -; ebp - io_addr -; Return value: -; Destroyed registers -; ax, ecx, edx, esi -; -;*************************************************************************** - align 4 -e3c59x_global_reset: -; GlobalReset - lea edx, [ebp+E3C59X_REG_COMMAND] - xor eax, eax -; or al, 0x14 - out dx, ax -; wait for GlobalReset to complete - mov ecx, 64000 -.global_reset_loop: - in ax, dx - test ah, 10000b ; check CmdInProgress - jz .finish - dec ecx - jnz .global_reset_loop -.finish: -; wait for 2 seconds for NIC to boot - mov esi, 2000 ; 2000ms = 2s - push ebp - call delay_ms - pop ebp - ret - -;*************************************************************************** -; Function -; e3c59x_tx_reset -; Description -; resets and enables transmitter engine -; Parameters: -; ebp - io_addr -; Return value: -; Destroyed registers -; ax, ecx, edx -; -;*************************************************************************** - align 4 -e3c59x_tx_reset: -; TxReset - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (01011b shl 11) - out dx, ax -; Wait for TxReset to complete - mov ecx, 200000 -.tx_reset_loop: - in ax, dx - test ah, 10000b ; check CmdInProgress - jz .tx_set_prev - dec ecx - jns .tx_reset_loop -.tx_set_prev: - test byte [e3c59x_full_bus_master], 0xff - jz .tx_enable -; init last_dpd - mov dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE - mov dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE -.tx_enable: - mov ax, (01001b shl 11) ; TxEnable - out dx, ax - ret - -;*************************************************************************** -; Function -; e3c59x_rx_reset -; Description -; resets and enables receiver engine -; Parameters: -; ebp - io_addr -; Return value: -; Destroyed registers -; eax, ebx, ecx, edx, edi, esi -; -;*************************************************************************** - align 4 -e3c59x_rx_reset: - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (0101b shl 11) or 0x4 ; RxReset - out dx, ax -; wait for RxReset to complete - mov ecx, 200000 -.rx_reset_loop: - in ax, dx - test ah, 10000b ; check CmdInProgress - jz .setup_upd - dec ecx - jns .rx_reset_loop -.setup_upd: -; check if full bus mastering - test byte [e3c59x_full_bus_master], 0xff - jz .rx_enable -; create upd ring - mov eax, e3c59x_upd_buff - zero_to_virt eax - mov [e3c59x_curr_upd], eax - mov esi, eax - virt_to_dma esi - mov edi, e3c59x_rx_buff - zero_to_dma edi - mov ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE - zero_to_virt ebx - mov cl, E3C59X_NUM_RX_DESC-1 -.upd_loop: - mov [ebx+E3C59X_UPD_UP_NEXT_PTR], esi - and dword [eax+E3C59X_UPD_PKT_STATUS], 0 - mov [eax+E3C59X_UPD_UP_FRAG_ADDR], edi - mov dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31) - add edi, E3C59X_MAX_ETH_FRAME_SIZE - add esi, E3C59X_UPD_SIZE - mov ebx, eax - add eax, E3C59X_UPD_SIZE - dec cl - jns .upd_loop - mov eax, e3c59x_upd_buff - zero_to_dma eax - lea edx, [ebp+E3C59X_REG_UP_LIST_PTR] - out dx, eax ; write E3C59X_REG_UP_LIST_PTR - lea edx, [ebp+E3C59X_REG_COMMAND] -.rx_enable: - mov ax, (00100b shl 11) ; RxEnable - out dx, ax - ret - -;*************************************************************************** -; Function -; e3c59x_write_eeprom -; Description -; reads eeprom -; Note : the caller must switch to the register window 0 -; before calling this function -; Parameters: -; ax - register to be read (only the first 63 words can be read) -; cx - value to be read into the register -; Return value: -; ax - word read -; Destroyed registers -; ax, ebx, edx -; -;*************************************************************************** -; align 4 -;e3c59x_write_eeprom: -; mov edx, [io_addr] -; add edx, E3C59X_REG_EEPROM_COMMAND -; cmp ah, 11b -; ja .finish ; address may have a value of maximal 1023 -; shl ax, 2 -; shr al, 2 -; push eax -;; wait for busy -; mov ebx, 0xffff -;@@: -; in ax, dx -; test ah, 0x80 -; jz .write_enable -; dec ebx -; jns @r -;; write enable -;.write_enable: -; xor eax, eax -; mov eax, (11b shl 4) -; out dx, ax -;; wait for busy -; mov ebx, 0xffff -;@@: -; in ax, dx -; test ah, 0x80 -; jz .erase_loop -; dec ebx -; jns @r -;.erase_loop: -; pop eax -; push eax -; or ax, (11b shl 6) ; erase register -; out dx, ax -; mov ebx, 0xffff -;@@: -; in ax, dx -; test ah, 0x80 -; jz .write_reg -; dec ebx -; jns @r -;.write_reg: -; add edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND -; mov eax, ecx -; out dx, ax -;; write enable -; add edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA -; xor eax, eax -; mov eax, (11b shl 4) -; out dx, ax -; wait for busy -; mov ebx, 0xffff -;@@: -; in ax, dx -; test ah, 0x80 -; jz .issue_write_reg -; dec ebx -; jns @r -;.issue_write_reg: -; pop eax -; or ax, 01b shl 6 -; out dx, ax -;.finish: -; ret -;*************************************************************************** -; Function -; e3c59x_read_eeprom -; Description -; reads eeprom -; Parameters: -; ax - register to be read (only the first 63 words can be read) -; ebp - io_addr -; Return value: -; ax - word read -; Destroyed registers -; ax, ebx, edx, ebp -; -;*************************************************************************** - align 4 -e3c59x_read_eeprom: - push eax -; switch to register window 0 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+0 - out dx, ax - pop eax - and ax, 111111b ; take only the first 6 bits into account - movzx ebx, byte [e3c59x_ver_id] - test word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT - jz @f - add ax, 0x230 ; hardware constant - jmp .read -@@: - add ax, E3C59X_EEPROM_CMD_READ - test word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET - jz .read - add ax, 0x30 -.read: - lea edx, [ebp+E3C59X_REG_EEPROM_COMMAND] - out dx, ax - mov ebx, 0xffff ; duration of about 162 us ;-) -.wait_for_reading: - in ax, dx - test ah, 0x80 ; check bit eepromBusy - jz .read_data - dec ebx - jns .wait_for_reading -.read_data: - lea edx, [ebp+E3C59X_REG_EEPROM_DATA] - in ax, dx - ret - -;*************************************************************************** -; Function -; e3c59x_mdio_sync -; Description -; initial synchronization -; Parameters -; ebp - io_addr -; Return value -; Destroyed registers -; ax, edx, cl -; -;*************************************************************************** - align 4 -e3c59x_mdio_sync: -; switch to register window 4 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 - out dx, ax - cmp byte [e3c59x_preamble], 0 - je .no_preamble -; send 32 logic ones - lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] - mov cl, 31 -.loop: - mov ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR) - out dx, ax - in ax, dx ; delay - mov ax, (1 shl E3C59X_BIT_MGMT_DATA) \ - or (1 shl E3C59X_BIT_MGMT_DIR) \ - or (1 shl E3C59X_BIT_MGMT_CLK) - out dx, ax - in ax, dx ; delay - dec cl - jns .loop -.no_preamble: - ret - -;*************************************************************************** -; Function -; e3c59x_mdio_read -; Description -; read MII register -; see page 16 in D83840A.pdf -; Parameters -; ah - PHY addr -; al - register addr -; ebp - io_addr -; Return value -; ax - register read -; Destroyed registers -; eax, ebx, cx, edx -; -;*************************************************************************** - align 4 -e3c59x_mdio_read: - push eax - call e3c59x_mdio_sync ; returns with window #4 - pop eax - lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] - shl al, 3 - shr ax, 3 - and ax, not E3C59X_MII_CMD_MASK - or ax, E3C59X_MII_CMD_READ - mov ebx, eax - xor ecx, ecx - mov cl, 13 -.cmd_loop: - mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii - bt ebx, ecx - jnc .zero_bit - or al, (1 shl E3C59X_BIT_MGMT_DATA) -.zero_bit: - out dx, ax - push eax - in ax, dx ; delay - pop eax - or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write - out dx, ax - in ax, dx ; delay - dec cl - jns .cmd_loop -; read data (18 bits with the two transition bits) - mov cl, 17 - xor ebx, ebx -.read_loop: - shl ebx, 1 - xor eax, eax ; read comand - out dx, ax - in ax, dx ; delay - in ax, dx - test al, (1 shl E3C59X_BIT_MGMT_DATA) - jz .dont_set - inc ebx -.dont_set: - mov ax, (1 shl E3C59X_BIT_MGMT_CLK) - out dx, ax - in ax, dx ; delay - dec cl - jns .read_loop - mov eax, ebx - ret - -;*************************************************************************** -; Function -; e3c59x_mdio_write -; Description -; write MII register -; see page 16 in D83840A.pdf -; Parameters -; ah - PHY addr -; al - register addr -; bx - word to be written -; ebp - io_addr -; Return value -; ax - register read -; Destroyed registers -; eax, ebx, cx, edx -; -;*************************************************************************** - align 4 -e3c59x_mdio_write: - push eax - call e3c59x_mdio_sync - pop eax - lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] - shl al, 3 - shr ax, 3 - and ax, not E3C59X_MII_CMD_MASK - or ax, E3C59X_MII_CMD_WRITE - shl eax, 2 - or eax, 10b ; transition bits - shl eax, 16 - mov ax, bx - mov ebx, eax - mov ecx, 31 -.cmd_loop: - mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii - bt ebx, ecx - jnc .zero_bit - or al, (1 shl E3C59X_BIT_MGMT_DATA) -.zero_bit: - out dx, ax - push eax - in ax, dx ; delay - pop eax - or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write - out dx, ax - in ax, dx ; delay - dec ecx - jns .cmd_loop - ret - -;*************************************************************************** -; Function -; e3c59x_transmit -; Description -; Transmits a packet of data via the ethernet card -; edi - Pointer to 48 bit destination address -; bx - Type of packet -; ecx - size of packet -; esi - pointer to packet data -; ebp - io_addr -; Destroyed registers -; eax, ecx, edx, ebp -; -;*************************************************************************** - align 4 -e3c59x_transmit: - jmp dword [e3c59x_transmit_function] - -;*************************************************************************** -; Function -; e3c59x_check_tx_status -; Description -; Checks TxStatus queue. -; Return value -; al - 0 no error was found -; al - 1 error was found TxReset is needed -; Destroyed registers -; eax, ecx, edx, ebp -; -;*************************************************************************** -e3c59x_check_tx_status: - movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC -; clear TxStatus queue - lea edx, [ebp+E3C59X_REG_TX_STATUS] - mov cl, 31 ; max number of queue entries -.tx_status_loop: - in al, dx - test al, al - jz .finish ; no error - test al, 0x3f - jnz .finish ; error -.no_error_found: -; clear current TxStatus entry which advances the next one - xor al, al - out dx, al - dec cl - jns .tx_status_loop -.finish: - ret - -;*************************************************************************** -; Function -; e3c59x_vortex_transmit -; Description -; Transmits a packet of data via the ethernet card -; edi - Pointer to 48 bit destination address -; bx - Type of packet -; ecx - size of packet -; esi - pointer to packet data -; ebp - io_addr -; Destroyed registers -; eax, edx, ecx, edi, esi, ebp -; -;*************************************************************************** - align 4 -e3c59x_vortex_transmit: - push ecx - call e3c59x_check_tx_status - pop ecx - test al, al - jz .no_error_found - jmp e3c59x_tx_reset -.no_error_found: -; switch to register window 7 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 - out dx, ax -; check for master operation in progress - lea edx, [ebp+E3C59X_REG_MASTER_STATUS] - in ax, dx - test ah, 0x80 - jnz .finish ; no DMA for sending -; dword boundary correction - cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE - ja .finish ; packet is too long -; write Frame Start Header - mov eax, ecx -; add header length and extend the complete length to dword boundary - add eax, ETH_HLEN+3 - and eax, not 3 - lea edx, [ebp+E3C59X_REG_TX_DATA] - out dx, eax -; prepare the complete frame - push esi - mov esi, edi - mov edi, e3c59x_tx_buff - zero_to_virt edi - cld -; copy destination address - movsd - movsw -; copy source address - mov esi, node_addr - movsd - movsw -; copy packet type - mov [edi], bx - add edi, 2 -; copy packet data - pop esi - push ecx - shr ecx, 2 - rep movsd - pop ecx - and ecx, 3 - rep movsb - mov ecx, eax -; program frame address to be sent - lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] - mov eax, e3c59x_tx_buff - zero_to_dma eax - out dx, eax -; program frame length - lea edx, [ebp+E3C59X_REG_MASTER_LEN] - mov eax, ecx - out dx, ax -; start DMA Down - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (10100b shl 11) + 1 ; StartDMADown - out dx, ax -.finish: - ret - -;*************************************************************************** -; Function -; e3c59x_boomerang_transmit -; Description -; Transmits a packet of data via the ethernet card -; edi - Pointer to 48 bit destination address -; bx - Type of packet -; ecx - size of packet -; esi - pointer to packet data -; ebp - io_addr -; Destroyed registers -; eax, ebx, ecx, edx, esi, edi, ebp -; -;*************************************************************************** - align 4 -e3c59x_boomerang_transmit: - push ecx - call e3c59x_check_tx_status - pop ecx - test al, al - jz .no_error_found - jmp e3c59x_tx_reset -.no_error_found: - cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE - ja .finish ; packet is too long -; calculate descriptor address - mov eax, [e3c59x_prev_dpd] - cmp eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE - jb @f -; wrap around - mov eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE -@@: - add eax, E3C59X_DPD_SIZE - zero_to_virt eax - push eax -; check DnListPtr - lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] - in eax, dx -; mark if Dn_List_Ptr is cleared - test eax, eax - setz [e3c59x_dn_list_ptr_cleared] -; finish if no more free descriptor is available - FIXME! - cmp eax, [esp] - pop eax - jz .finish - push eax esi - mov esi, edi -; calculate tx_buffer address - mov edi, [e3c59x_prev_tx_frame] - cmp edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE - jb @f -; wrap around - mov edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE -@@: - add edi, E3C59X_MAX_ETH_FRAME_SIZE - zero_to_virt edi - mov eax, edi - cld -; copy destination address - movsd - movsw -; copy source address - mov esi, node_addr - movsd - movsw -; copy packet type - mov [edi], bx - add edi, 2 -; copy packet data - pop esi - push ecx - shr ecx, 2 - rep movsd - pop ecx - push ecx - and ecx, 3 - rep movsb -; padding, do we really need it? - pop ecx - add ecx, ETH_HLEN - cmp ecx, ETH_ZLEN - jae @f - mov ecx, ETH_ZLEN -@@: -; calculate - mov ebx, ecx - ;test byte [e3c59x_has_hwcksm], 0xff - ;jz @f - ;or ebx, (1 shl 26) ; set AddTcpChecksum -;@@: - or ebx, 0x8000 ; transmission complete notification - or ecx, 0x80000000 ; last fragment -; program DPD - mov edi, eax - pop eax - and dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0 - mov dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx - virt_to_dma edi - mov dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi - mov [eax+E3C59X_DPD_DN_FRAG_LEN], ecx -; calculate physical address - virt_to_dma eax - push eax - cmp byte [e3c59x_dn_list_ptr_cleared], 0 - jz .add_to_list -; write Dn_List_Ptr - out dx, eax - jmp .finish -.add_to_list: -; DnStall - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, ((110b shl 11)+2) - out dx, ax -; wait for DnStall to complete - mov ecx, 6000 -.wait_for_stall: - in ax, dx ; read E3C59X_REG_INT_STATUS - test ah, 10000b - jz .dnstall_ok - dec ecx - jnz .wait_for_stall -.dnstall_ok: - pop eax - push eax - mov ebx, [e3c59x_prev_dpd] - zero_to_virt ebx - mov [ebx], eax - lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] - in eax, dx - test eax, eax - jnz .dnunstall -; if Dn_List_Ptr has been cleared fill it up - pop eax - push eax - out dx, eax -.dnunstall: -; DnUnStall - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, ((110b shl 11)+3) - out dx, ax -.finish: - pop eax - dma_to_zero eax - mov [e3c59x_prev_dpd], eax - dma_to_zero edi - mov [e3c59x_prev_tx_frame], edi - ret - -;*************************************************************************** -; Function -; e3c59x_poll -; Description -; Polls the ethernet card for a received packet -; Received data, if any, ends up in Ether_buffer -; Destroyed registers -; eax, ebx, edx, ecx, edi, esi, ebp -; -;*************************************************************************** - align 4 -e3c59x_poll: - jmp dword [e3c59x_receive_function] - -;*************************************************************************** -; Function -; e3c59x_vortex_poll -; Description -; Polls the ethernet card for a received packet -; Received data, if any, ends up in Ether_buffer -; Parameters -; ebp - io_addr -; Return value -; al - 0 ; no packet received -; al - 1 ; packet received -; Destroyed registers -; eax, ebx, edx, ecx, edi, esi, ebp -; -;*************************************************************************** - align 4 -e3c59x_vortex_poll: - and word [eth_rx_data_len], 0 ; assume no packet received - movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC -.rx_status_loop: -; examine RxStatus - lea edx, [ebp+E3C59X_REG_RX_STATUS] - in ax, dx - test ax, ax - jz .finish - test ah, 0x80 ; rxIncomplete - jz .check_error - jmp .finish -.check_error: - test ah, 0x40 - jz .check_length -; discard the top frame received advancing the next one - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (01000b shl 11) - out dx, ax - jmp .rx_status_loop -.check_length: - and eax, 0x1fff - cmp eax, E3C59X_MAX_ETH_PKT_SIZE - ja .discard_frame ; frame is too long discard it -.check_dma: - push eax -; switch to register window 7 - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 - out dx, ax -; check for master operation in progress - lea edx, [ebp+E3C59X_REG_MASTER_STATUS] - in ax, dx - test ah, 0x80 - jz .read_frame ; no DMA for receiving - pop eax - jmp .finish -.read_frame: -; program buffer address to read in - lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] -if defined E3C59X_LINUX - mov eax, e3c59x_rx_buff - zero_to_dma eax -else - mov eax, Ether_buffer -end if - out dx, eax -; program frame length - lea edx, [ebp+E3C59X_REG_MASTER_LEN] - mov ax, 1560 - out dx, ax -; start DMA Up - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (10100b shl 11) ; StartDMAUp - out dx, ax -; check for master operation in progress -.dma_loop: - lea edx, [ebp+E3C59X_REG_MASTER_STATUS] - in ax, dx - test ah, 0x80 - jnz .dma_loop -; registrate the received packet length - pop eax - mov word [eth_rx_data_len], ax -; discard the top frame received -.discard_frame: - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, (01000b shl 11) - out dx, ax -.finish: -; set return value - cmp word [eth_rx_data_len], 0 - setne al - ret - -;*************************************************************************** -; Function -; e3c59x_boomerang_poll -; Description -; Polls the ethernet card for a received packet -; Received data, if any, ends up in Ether_buffer -; Parameters -; ebp - io_addr -; Return value -; al - 0 ; no packet received -; al - 1 ; packet received -; Destroyed registers -; eax, edx, ecx, edi, esi, ebp -; -;*************************************************************************** - align 4 -e3c59x_boomerang_poll: - and word [eth_rx_data_len], 0 ; assume no packet received - movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC -; check if packet is uploaded - mov eax, [e3c59x_curr_upd] - test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete - jnz .check_error - jmp .finish -; packet is uploaded check for any error -.check_error: - test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError - jz .copy_packet_length - and dword [eax+E3C59X_UPD_PKT_STATUS], 0 - jmp .finish -.copy_packet_length: - mov ecx, [eax+E3C59X_UPD_PKT_STATUS] - and ecx, 0x1fff - cmp ecx, E3C59X_MAX_ETH_PKT_SIZE - jbe .copy_packet - and dword [eax+E3C59X_UPD_PKT_STATUS], 0 - jmp .finish -.copy_packet: - push ecx - mov word [eth_rx_data_len], cx - mov esi, [eax+E3C59X_UPD_UP_FRAG_ADDR] - dma_to_virt esi - mov edi, Ether_buffer - shr ecx, 2 ; first copy dword-wise - cld - rep movsd ; copy the dwords - pop ecx - and ecx, 3 - rep movsb ; copy the rest bytes - mov eax, [e3c59x_curr_upd] - and dword [eax+E3C59X_UPD_PKT_STATUS], 0 - virt_to_zero eax - cmp eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE - jb .no_wrap -; wrap around - mov eax, e3c59x_upd_buff-E3C59X_UPD_SIZE -.no_wrap: - add eax, E3C59X_UPD_SIZE - zero_to_virt eax - mov [e3c59x_curr_upd], eax -.finish: -; check if the NIC is in the upStall state - lea edx, [ebp+E3C59X_REG_UP_PKT_STATUS] - in eax, dx - test ah, 0x20 ; UpStalled - jz .noUpUnStall -; issue upUnStall command - lea edx, [ebp+E3C59X_REG_COMMAND] - mov ax, ((110b shl 11)+1) ; upUnStall - out dx, ax -.noUpUnStall: -; set return value - cmp word [eth_rx_data_len], 0 - setnz al - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;; Copyright (c) 2004, Endre Kozma +;; All rights reserved. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions are +;; met: +;; +;; 1. Redistributions of source code must retain the above copyright notice, +;; this list of conditions and the following disclaimer. +;; +;; 2. Redistributions in binary form must reproduce the above copyright +;; notice, this list of conditions and the following disclaimer in the +;; documentation and/or other materials provided with the distribution. +;; +;; 3. The name of the author may not be used to endorse or promote products +;; derived from this software without specific prior written permission. +;; +;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +;; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +;; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +;; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +;; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +;; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +;; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +;; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; 3C59X.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Driver for 3Com fast etherlink 3c59x and ;; +;; etherlink XL 3c900 and 3c905 cards ;; +;; References: ;; +;; www.3Com.com - data sheets ;; +;; DP83840A.pdf - ethernet physical layer ;; +;; 3c59x.c - linux driver ;; +;; ethernet driver template by Mike Hibbett ;; +;; ;; +;; Credits ;; +;; Mike Hibbett, ;; +;; who kindly supplied me with a 3Com905C-TX-M card ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; History +;; ======= +;; $Log: 3C59X.INC,v $ +;; Revision 1.3 2004/07/11 12:21:12 kozma +;; Support of vortex chips (3c59x) added. +;; Support of 3c920 and 3c982 added. +;; Corrections. +;; +;; Revision 1.2 2004/06/12 19:40:20 kozma +;; Function e3c59x_set_available_media added in order to set +;; the default media in case auto detection finds no valid link. +;; Incorrect mii check removed (3c900 Cyclone works now). +;; Cleanups. +;; +;; Revision 1.1 2004/06/12 18:27:15 kozma +;; Initial revision +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; comment the next line out if you don't want debug info printed +; on the debug board. This option adds a lot of bytes to the driver +; so it's worth to comment it out. +; E3C59X_DEBUG equ 1 + +; forcing full duplex mode makes sense at some cards and link types + E3C59X_FORCE_FD equ 1 + +macro virt_to_dma reg +{ + sub reg, OS_BASE +} + +macro dma_to_virt reg +{ + add reg, OS_BASE +} + +macro zero_to_virt reg +{ + +} + +macro virt_to_zero reg +{ + +} + +macro zero_to_dma reg +{ + sub reg, OS_BASE +} + +macro dma_to_zero reg +{ + add reg, OS_BASE +} + +macro strtbl name, [string] +{ +common + label name dword +forward + local label + dd label +forward + label db string, 0 +} + +; Ethernet frame symbols + ETH_ALEN equ 6 + ETH_HLEN equ (2*ETH_ALEN+2) + ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length +; PCI programming + PCI_REG_COMMAND equ 0x4 ; command register + PCI_REG_STATUS equ 0x6 ; status register + PCI_REG_LATENCY equ 0xd ; latency timer register + PCI_REG_CAP_PTR equ 0x34 ; capabilities pointer + PCI_REG_CAPABILITY_ID equ 0x0 ; capapility ID in pm register block + PCI_REG_PM_STATUS equ 0x4 ; power management status register + PCI_REG_PM_CTRL equ 0x4 ; power management control register + PCI_BIT_PIO equ 0 ; bit0: io space control + PCI_BIT_MMIO equ 1 ; bit1: memory space control + PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master +; Registers + E3C59X_REG_POWER_MGMT_CTRL equ 0x7c + E3C59X_REG_UP_LIST_PTR equ 0x38 + E3C59X_REG_UP_PKT_STATUS equ 0x30 + E3C59X_REG_TX_FREE_THRESH equ 0x2f + E3C59X_REG_DN_LIST_PTR equ 0x24 + E3C59X_REG_DMA_CTRL equ 0x20 + E3C59X_REG_TX_STATUS equ 0x1b + E3C59X_REG_RX_STATUS equ 0x18 + E3C59X_REG_TX_DATA equ 0x10 +; Common window registers + E3C59X_REG_INT_STATUS equ 0xe + E3C59X_REG_COMMAND equ 0xe +; Register window 7 + E3C59X_REG_MASTER_STATUS equ 0xc + E3C59X_REG_POWER_MGMT_EVENT equ 0xc + E3C59X_REG_MASTER_LEN equ 0x6 + E3C59X_REG_VLAN_ETHER_TYPE equ 0x4 + E3C59X_REG_VLAN_MASK equ 0x0 + E3C59X_REG_MASTER_ADDRESS equ 0x0 +; Register window 6 + E3C59X_REG_BYTES_XMITTED_OK equ 0xc + E3C59X_REG_BYTES_RCVD_OK equ 0xa + E3C59X_REG_UPPER_FRAMES_OK equ 0x9 + E3C59X_REG_FRAMES_DEFERRED equ 0x8 + E3C59X_REG_FRAMES_RCVD_OK equ 0x7 + E3C59X_REG_FRAMES_XMITTED_OK equ 0x6 + E3C59X_REG_RX_OVERRUNS equ 0x5 + E3C59X_REG_LATE_COLLISIONS equ 0x4 + E3C59X_REG_SINGLE_COLLISIONS equ 0x3 + E3C59X_REG_MULTIPLE_COLLISIONS equ 0x2 + E3C59X_REG_SQE_ERRORS equ 0x1 + E3C59X_REG_CARRIER_LOST equ 0x0 +; Register window 5 + E3C59X_REG_INDICATION_ENABLE equ 0xc + E3C59X_REG_INTERRUPT_ENABLE equ 0xa + E3C59X_REG_TX_RECLAIM_THRESH equ 0x9 + E3C59X_REG_RX_FILTER equ 0x8 + E3C59X_REG_RX_EARLY_THRESH equ 0x6 + E3C59X_REG_TX_START_THRESH equ 0x0 +; Register window 4 + E3C59X_REG_UPPER_BYTES_OK equ 0xe + E3C59X_REG_BAD_SSD equ 0xc + E3C59X_REG_MEDIA_STATUS equ 0xa + E3C59X_REG_PHYSICAL_MGMT equ 0x8 + E3C59X_REG_NETWORK_DIAGNOSTIC equ 0x6 + E3C59X_REG_FIFO_DIAGNOSTIC equ 0x4 + E3C59X_REG_VCO_DIAGNOSTIC equ 0x2 ; may not supported +; Bits in register window 4 + E3C59X_BIT_AUTOSELECT equ 24 +; Register window 3 + E3C59X_REG_TX_FREE equ 0xc + E3C59X_REG_RX_FREE equ 0xa + E3C59X_REG_MEDIA_OPTIONS equ 0x8 + E3C59X_REG_MAC_CONTROL equ 0x6 + E3C59X_REG_MAX_PKT_SIZE equ 0x4 + E3C59X_REG_INTERNAL_CONFIG equ 0x0 +; Register window 2 + E3C59X_REG_RESET_OPTIONS equ 0xc + E3C59X_REG_STATION_MASK_HI equ 0xa + E3C59X_REG_STATION_MASK_MID equ 0x8 + E3C59X_REG_STATION_MASK_LO equ 0x6 + E3C59X_REG_STATION_ADDRESS_HI equ 0x4 + E3C59X_REG_STATION_ADDRESS_MID equ 0x2 + E3C59X_REG_STATION_ADDRESS_LO equ 0x0 +; Register window 1 + E3C59X_REG_TRIGGER_BITS equ 0xc + E3C59X_REG_SOS_BITS equ 0xa + E3C59X_REG_WAKE_ON_TIMER equ 0x8 + E3C59X_REG_SMB_RXBYTES equ 0x7 + E3C59X_REG_SMB_DIAG equ 0x5 + E3C59X_REG_SMB_ARB equ 0x4 + E3C59X_REG_SMB_STATUS equ 0x2 + E3C59X_REG_SMB_ADDRESS equ 0x1 + E3C59X_REG_SMB_FIFO_DATA equ 0x0 +; Register window 0 + E3C59X_REG_EEPROM_DATA equ 0xc + E3C59X_REG_EEPROM_COMMAND equ 0xa + E3C59X_REG_BIOS_ROM_DATA equ 0x8 + E3C59X_REG_BIOS_ROM_ADDR equ 0x4 +; Physical management bits + E3C59X_BIT_MGMT_DIR equ 2 ; drive with the data written in mgmtData + E3C59X_BIT_MGMT_DATA equ 1 ; MII management data bit + E3C59X_BIT_MGMT_CLK equ 0 ; MII management clock +; MII commands + E3C59X_MII_CMD_MASK equ (1111b shl 10) + E3C59X_MII_CMD_READ equ (0110b shl 10) + E3C59X_MII_CMD_WRITE equ (0101b shl 10) +; MII registers + E3C59X_REG_MII_BMCR equ 0 ; basic mode control register + E3C59X_REG_MII_BMSR equ 1 ; basic mode status register + E3C59X_REG_MII_ANAR equ 4 ; auto negotiation advertisement register + E3C59X_REG_MII_ANLPAR equ 5 ; auto negotiation link partner ability register + E3C59X_REG_MII_ANER equ 6 ; auto negotiation expansion register +; MII bits + E3C59X_BIT_MII_AUTONEG_COMPLETE equ 5 ; auto-negotiation complete + E3C59X_BIT_MII_PREAMBLE_SUPPRESSION equ 6 +; eeprom bits and commands + E3C59X_EEPROM_CMD_READ equ 0x80 + E3C59X_EEPROM_BIT_BUSY equ 15 +; eeprom registers + E3C59X_EEPROM_REG_OEM_NODE_ADDR equ 0xa + E3C59X_EEPROM_REG_CAPABILITIES equ 0x10 +; Commands for command register + E3C59X_SELECT_REGISTER_WINDOW equ (1 shl 11) + + IS_VORTEX equ 0x1 + IS_BOOMERANG equ 0x2 + IS_CYCLONE equ 0x4 + IS_TORNADO equ 0x8 + EEPROM_8BIT equ 0x10 + HAS_PWR_CTRL equ 0x20 + HAS_MII equ 0x40 + HAS_NWAY equ 0x80 + HAS_CB_FNS equ 0x100 + INVERT_MII_PWR equ 0x200 + INVERT_LED_PWR equ 0x400 + MAX_COLLISION_RESET equ 0x800 + EEPROM_OFFSET equ 0x1000 + HAS_HWCKSM equ 0x2000 + EXTRA_PREAMBLE equ 0x4000 + +iglobal + align 4 +e3c59x_hw_versions: + dw 0x5900, IS_VORTEX ; 3c590 Vortex 10Mbps + dw 0x5920, IS_VORTEX ; 3c592 EISA 10Mbps Demon/Vortex + dw 0x5970, IS_VORTEX ; 3c597 EISA Fast Demon/Vortex + dw 0x5950, IS_VORTEX ; 3c595 Vortex 100baseTx + dw 0x5951, IS_VORTEX ; 3c595 Vortex 100baseT4 + dw 0x5952, IS_VORTEX ; 3c595 Vortex 100base-MII + dw 0x9000, IS_BOOMERANG ; 3c900 Boomerang 10baseT + dw 0x9001, IS_BOOMERANG ; 3c900 Boomerang 10Mbps Combo + dw 0x9004, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPO + dw 0x9005, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps Combo + dw 0x9006, IS_CYCLONE or HAS_HWCKSM ; 3c900 Cyclone 10Mbps TPC + dw 0x900A, IS_CYCLONE or HAS_HWCKSM ; 3c900B-FL Cyclone 10base-FL + dw 0x9050, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseTx + dw 0x9051, IS_BOOMERANG or HAS_MII ; 3c905 Boomerang 100baseT4 + dw 0x9055, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B Cyclone 100baseTx + dw 0x9058, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c905B Cyclone 10/100/BNC + dw 0x905A, IS_CYCLONE or HAS_HWCKSM ; 3c905B-FX Cyclone 100baseFx + dw 0x9200, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c905C Tornado + dw 0x9800, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3c980 Cyclone + dw 0x9805, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c982 Dual Port Server Cyclone + dw 0x7646, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM ; 3cSOHO100-TX Hurricane + dw 0x5055, IS_CYCLONE or EEPROM_8BIT or HAS_HWCKSM ; 3c555 Laptop Hurricane + dw 0x6055, IS_TORNADO or HAS_NWAY or EEPROM_8BIT or HAS_CB_FNS \ + or INVERT_MII_PWR or HAS_HWCKSM ; 3c556 Laptop Tornado + dw 0x6056, IS_TORNADO or HAS_NWAY or EEPROM_OFFSET or HAS_CB_FNS \ + or INVERT_MII_PWR or HAS_HWCKSM ; 3c556B Laptop Hurricane + dw 0x5b57, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 [Megahertz] 10/100 LAN CardBus + dw 0x5057, IS_BOOMERANG or HAS_MII or EEPROM_8BIT ; 3c575 Boomerang CardBus + dw 0x5157, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT \ + or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE575BT Cyclone CardBus + dw 0x5257, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CCFE575CT Tornado CardBus + dw 0x6560, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFE656 Cyclone CardBus + dw 0x6562, IS_CYCLONE or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or INVERT_LED_PWR or HAS_HWCKSM ; 3CCFEM656B Cyclone+Winmodem CardBus + dw 0x6564, IS_TORNADO or HAS_NWAY or HAS_CB_FNS or EEPROM_8BIT or INVERT_MII_PWR \ + or MAX_COLLISION_RESET or HAS_HWCKSM ; 3CXFEM656C Tornado+Winmodem CardBus + dw 0x4500, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c450 HomePNA Tornado + dw 0x9201, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920 Tornado + dw 0x1201, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port A + dw 0x1202, IS_TORNADO or HAS_HWCKSM or HAS_NWAY ; 3c982 Hydra Dual Port B + dw 0x9056, IS_CYCLONE or HAS_NWAY or HAS_HWCKSM or EXTRA_PREAMBLE ; 3c905B-T4 + dw 0x9210, IS_TORNADO or HAS_NWAY or HAS_HWCKSM ; 3c920B-EMB-WNM Tornado +E3C59X_HW_VERSIONS_SIZE= $-e3c59x_hw_versions +endg + +; RX/TX buffers sizes + E3C59X_MAX_ETH_PKT_SIZE equ 1536 ; max packet size + E3C59X_NUM_RX_DESC equ 4 ; a power of 2 number + E3C59X_NUM_TX_DESC equ 4 ; a power of 2 number + E3C59X_RX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_RX_DESC) + E3C59X_TX_BUFFER_SIZE equ (E3C59X_MAX_ETH_FRAME_SIZE*E3C59X_NUM_TX_DESC) +; Download Packet Descriptor + E3C59X_DPD_DN_NEXT_PTR equ 0 + E3C59X_DPD_FRAME_START_HDR equ 4 + E3C59X_DPD_DN_FRAG_ADDR equ 8 ; for packet data + E3C59X_DPD_DN_FRAG_LEN equ 12 ; for packet data + E3C59X_DPD_SIZE equ 16 ; a power of 2 number +; Upload Packet Descriptor + E3C59X_UPD_UP_NEXT_PTR equ 0 + E3C59X_UPD_PKT_STATUS equ 4 + E3C59X_UPD_UP_FRAG_ADDR equ 8 ; for packet data + E3C59X_UPD_UP_FRAG_LEN equ 12 ; for packet data + E3C59X_UPD_SIZE equ 16 + +; RX/TX buffers +if defined E3C59X_LINUX + E3C59X_MAX_ETH_FRAME_SIZE = 160 ; size of ethernet frame + bytes alignment + e3c59x_rx_buff = 0 +else + E3C59X_MAX_ETH_FRAME_SIZE = 1520 ; size of ethernet frame + bytes alignment + e3c59x_rx_buff = eth_data_start +end if + + e3c59x_tx_buff = e3c59x_rx_buff+E3C59X_RX_BUFFER_SIZE + e3c59x_dpd_buff = e3c59x_tx_buff+E3C59X_TX_BUFFER_SIZE + e3c59x_upd_buff = e3c59x_dpd_buff+(E3C59X_DPD_SIZE*E3C59X_NUM_TX_DESC) + +uglobal +e3c59x_curr_upd: + dd 0 +e3c59x_prev_dpd: + dd 0 +e3c59x_prev_tx_frame: + dd 0 +e3c59x_transmit_function: + dd 0 +e3c59x_receive_function: + dd 0 +endg + +iglobal +e3c59x_ver_id: + db 17 +endg + +uglobal +e3c59x_full_bus_master: + db 0 +e3c59x_has_hwcksm: + db 0 +e3c59x_preamble: + db 0 +e3c59x_dn_list_ptr_cleared: + db 0 +e3c59x_self_directed_packet: + rb 6 +endg + +if defined E3C59X_DEBUG +e3c59x_hw_type_str: + db "Detected hardware type : ", 0 +e3c59x_device_str: + db "Device ID : 0x" +e3c59x_device_id_str: + db "ffff", 13, 10, 0 +e3c59x_vendor_str: + db "Vendor ID : 0x" +e3c59x_vendor_id_str: + db "ffff", 13, 10, 0 +e3c59x_io_info_str: + db "IO address : 0x" +e3c59x_io_addr_str: + db "ffff", 13, 10, 0 +e3c59x_mac_info_str: + db "MAC address : " +e3c59x_mac_addr_str: + db "ff:ff:ff:ff:ff:ff", 13, 10, 0 +e3c59x_boomerang_str: + db " (boomerang)", 13, 10, 0 +e3c59x_vortex_str: + db " (vortex)", 13, 10, 0 +e3c59x_link_type_str: + db "Established link type : ", 0 +e3c59x_new_line_str: + db 13, 10, 0 +e3c59x_link_type: + dd 0 + +e3c59x_charset: + db '0123456789abcdef' + +strtbl e3c59x_link_str, \ + "No valid link type detected", \ + "10BASE-T half duplex", \ + "10BASE-T full-duplex", \ + "100BASE-TX half duplex", \ + "100BASE-TX full duplex", \ + "100BASE-T4", \ + "100BASE-FX", \ + "10Mbps AUI", \ + "10Mbps COAX (BNC)", \ + "miiDevice - not supported" + +strtbl e3c59x_hw_str, \ + "3c590 Vortex 10Mbps", \ + "3c592 EISA 10Mbps Demon/Vortex", \ + "3c597 EISA Fast Demon/Vortex", \ + "3c595 Vortex 100baseTx", \ + "3c595 Vortex 100baseT4", \ + "3c595 Vortex 100base-MII", \ + "3c900 Boomerang 10baseT", \ + "3c900 Boomerang 10Mbps Combo", \ + "3c900 Cyclone 10Mbps TPO", \ + "3c900 Cyclone 10Mbps Combo", \ + "3c900 Cyclone 10Mbps TPC", \ + "3c900B-FL Cyclone 10base-FL", \ + "3c905 Boomerang 100baseTx", \ + "3c905 Boomerang 100baseT4", \ + "3c905B Cyclone 100baseTx", \ + "3c905B Cyclone 10/100/BNC", \ + "3c905B-FX Cyclone 100baseFx", \ + "3c905C Tornado", \ + "3c980 Cyclone", \ + "3c982 Dual Port Server Cyclone", \ + "3cSOHO100-TX Hurricane", \ + "3c555 Laptop Hurricane", \ + "3c556 Laptop Tornado", \ + "3c556B Laptop Hurricane", \ + "3c575 [Megahertz] 10/100 LAN CardBus", \ + "3c575 Boomerang CardBus", \ + "3CCFE575BT Cyclone CardBus", \ + "3CCFE575CT Tornado CardBus", \ + "3CCFE656 Cyclone CardBus", \ + "3CCFEM656B Cyclone+Winmodem CardBus", \ + "3CXFEM656C Tornado+Winmodem CardBus", \ + "3c450 HomePNA Tornado", \ + "3c920 Tornado", \ + "3c982 Hydra Dual Port A", \ + "3c982 Hydra Dual Port B", \ + "3c905B-T4", \ + "3c920B-EMB-WNM Tornado" + +end if ; defined E3C59X_DEBUG + +;*************************************************************************** +; Function +; e3c59x_debug +; Description +; prints debug info to the debug board +; Parameters +; ebp - io_addr +; Return value +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** +if defined E3C59X_DEBUG + align 4 +e3c59x_debug: + pushad +; print device type + mov esi, e3c59x_hw_type_str + call sys_msg_board_str + movzx ecx, byte [e3c59x_ver_id] + mov esi, [e3c59x_hw_str+ecx*4] + call sys_msg_board_str + mov esi, e3c59x_boomerang_str + cmp dword [e3c59x_transmit_function], e3c59x_boomerang_transmit + jz .boomerang + mov esi, e3c59x_vortex_str +.boomerang: + call sys_msg_board_str +; print device/vendor + mov ax, [pci_data+2] + mov cl, 2 + mov ebx, e3c59x_device_id_str + call e3c59x_print_hex + mov esi, e3c59x_device_str + call sys_msg_board_str + mov ax, [pci_data] + mov cl, 2 + mov ebx, e3c59x_vendor_id_str + call e3c59x_print_hex + mov esi, e3c59x_vendor_str + call sys_msg_board_str +; print io address + mov ax, [io_addr] + mov ebx, e3c59x_io_addr_str + mov cl, 2 + call e3c59x_print_hex + mov esi, e3c59x_io_info_str + call sys_msg_board_str +; print MAC address + mov ebx, e3c59x_mac_addr_str + xor ecx, ecx +.mac_loop: + push ecx + mov al, [node_addr+ecx] + mov cl, 1 + call e3c59x_print_hex + inc ebx + pop ecx + inc cl + cmp cl, 6 + jne .mac_loop + mov esi, e3c59x_mac_info_str + call sys_msg_board_str +; print link type + mov esi, e3c59x_link_type_str + call sys_msg_board_str + xor eax, eax + bsr ax, word [e3c59x_link_type] + jz @f + sub ax, 4 +@@: + mov esi, [e3c59x_link_str+eax*4] + call sys_msg_board_str + mov esi, e3c59x_new_line_str + call sys_msg_board_str + popad + ret + +;*************************************************************************** +; Function +; e3c59x_print_hex +; Description +; prints a hexadecimal value +; Parameters +; eax - value to be printed out +; ebx - where to print +; cl - value size (1, 2, 4) +; Return value +; ebx - end address after the print +; Destroyed registers +; eax, ebx +; +;*************************************************************************** + align 4 +e3c59x_print_hex: + cmp cl, 1 + je .print_byte + cmp cl, 2 + jz .print_word +.print_dword: + push eax + bswap eax + xchg ah, al + call .print_word + pop eax +.print_word: + push eax + xchg ah, al + call .print_byte + pop eax +.print_byte: + movzx eax, al + push eax + and al, 0xf0 + shr al, 4 + mov al, byte [eax+e3c59x_charset] + mov [ebx], al + inc ebx + pop eax + and al, 0x0f + mov al, byte [eax+e3c59x_charset] + mov [ebx], al + inc ebx + ret +end if ; defined E3C59X_DEBUG + +;*************************************************************************** +; Function +; e3c59x_try_link_detect +; Description +; e3c59x_try_link_detect checks if link exists +; Parameters +; ebp - io_addr +; Return value +; al - 0 ; no link detected +; al - 1 ; link detected +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_try_link_detect: +; download self-directed packet + mov edi, node_addr + mov bx, 0x0608 ; packet type + mov esi, e3c59x_self_directed_packet + mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes + call dword [e3c59x_transmit_function] +; switch to register window 5 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 + out dx, ax +; program RxFilter for promiscuous operation + mov ax, (10000b shl 11) + lea edx, [ebp+E3C59X_REG_RX_FILTER] + in al, dx + or al, 1111b + lea edx, [ebp+E3C59X_REG_COMMAND] + out dx, ax +; switch to register window 4 + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; check loop + xor ebx, ebx + mov ecx, 0xffff ; 65535 tries +.loop: + push ecx ebx + call dword [e3c59x_receive_function] + pop ebx ecx + test al, al + jnz .finish +.no_packet_received: +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; read linkbeatdetect + lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] + in ax, dx + test ah, 1000b ; test linkBeatDetect + jnz .link_detected + xor al, al + jmp .finish +.link_detected: +; test carrierSense + test al, 100000b + jz .no_carrier_sense + inc ebx +.no_carrier_sense: + dec ecx + jns .loop +; assume the link is good if 0 < ebx < 25 % + test ebx, ebx + setnz al + jz .finish + cmp ebx, 16384 ; 25% + setb al +.finish: +if defined E3C59X_DEBUG + test al, al + jz @f + or byte [e3c59x_link_type+1], 100b +@@: +end if ; defined E3C59X_DEBUG + ret + +;*************************************************************************** +; Function +; e3c59x_try_phy +; Description +; e3c59x_try_phy checks the auto-negotiation function +; in the PHY at PHY index. It can also be extended to +; include link detection for non-IEEE 802.3u +; auto-negotiation devices, for instance the BCM5000. +; Parameters +; ah - PHY index +; ebp - io_addr +; Return value +; al - 0 link is auto-negotiated +; al - 1 no link is auto-negotiated +; Destroyed registers +; eax, ebx, ecx, edx, esi +; +;*************************************************************************** + align 4 +e3c59x_try_phy: + mov al, E3C59X_REG_MII_BMCR + push eax + call e3c59x_mdio_read ; returns with window #4 + or ah, 0x80 ; software reset + mov ebx, eax + pop eax + push eax + call e3c59x_mdio_write ; returns with window #4 +; wait for reset to complete + mov esi, 2000 ; 2000ms = 2s + call delay_ms + pop eax + push eax + call e3c59x_mdio_read ; returns with window #4 + test ah, 0x80 + jnz .fail_finish + pop eax + push eax +; wait for a while after reset + mov esi, 20 ; 20ms + call delay_ms + pop eax + push eax + mov al, E3C59X_REG_MII_BMSR + call e3c59x_mdio_read ; returns with window #4 + test al, 1 ; extended capability supported? + jz .no_ext_cap +; auto-neg capable? + test al, 1000b + jz .fail_finish ; not auto-negotiation capable +; auto-neg complete? + test al, 100000b + jnz .auto_neg_ok +; restart auto-negotiation + pop eax + push eax + mov al, E3C59X_REG_MII_ANAR + push eax + call e3c59x_mdio_read ; returns with window #4 + or ax, (1111b shl 5) ; advertise only 10base-T and 100base-TX + mov ebx, eax + pop eax + call e3c59x_mdio_write ; returns with window #4 + pop eax + push eax + call e3c59x_mdio_read ; returns with window #4 + mov ebx, eax + or bh, 10010b ; restart auto-negotiation + pop eax + push eax + call e3c59x_mdio_write ; returns with window #4 + mov esi, 4000 ; 4000ms = 4 seconds + call delay_ms + pop eax + push eax + mov al, E3C59X_REG_MII_BMSR + call e3c59x_mdio_read ; returns with window #4 + test al, 100000b ; auto-neg complete? + jnz .auto_neg_ok + jmp .fail_finish +.auto_neg_ok: +; compare advertisement and link partner ability registers + pop eax + push eax + mov al, E3C59X_REG_MII_ANAR + call e3c59x_mdio_read ; returns with window #4 + xchg eax, [esp] + mov al, E3C59X_REG_MII_ANLPAR + call e3c59x_mdio_read ; returns with window #4 + pop ebx + and eax, ebx + and eax, 1111100000b + push eax +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], ax +end if ; defined E3C59X_DEBUG +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; set full-duplex mode + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + and ax, not 0x120 ; clear full duplex and flow control + pop ebx + test ebx, (1010b shl 5) ; check for full-duplex + jz .half_duplex + or ax, 0x120 ; set full duplex and flow control +.half_duplex: + out dx, ax + mov al, 1 + ret +.no_ext_cap: +; not yet implemented BCM5000 +.fail_finish: + pop eax + xor al, al + ret + +;*************************************************************************** +; Function +; e3c59x_try_mii +; Description +; e3c59x_try_MII checks the on-chip auto-negotiation logic +; or an off-chip MII PHY, depending upon what is set in +; xcvrSelect by the caller. +; It exits when it finds the first device with a good link. +; Parameters +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, ebx, ecx, edx, esi +; +;*************************************************************************** + align 4 +e3c59x_try_mii: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, (1111b shl 20) + cmp eax, (1000b shl 20) ; is auto-negotiation set? + jne .mii_device +; auto-negotiation is set +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; PHY==24 is the on-chip auto-negotiation logic +; it supports only 10base-T and 100base-TX + mov ah, 24 + call e3c59x_try_phy + test al, al + jz .fail_finish + mov cl, 24 + jmp .check_preamble +.mii_device: + cmp eax, (0110b shl 20) + jne .fail_finish + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + in ax, dx + and al, (1 shl E3C59X_BIT_MGMT_DIR) or (1 shl E3C59X_BIT_MGMT_DATA) + cmp al, (1 shl E3C59X_BIT_MGMT_DATA) + je .serch_for_phy + xor al, al + ret +.serch_for_phy: +; search for PHY + mov cl, 31 +.search_phy_loop: + cmp cl, 24 + je .next_phy + mov ah, cl ; ah = phy + mov al, E3C59X_REG_MII_BMCR ; al = Basic Mode Status Register + push ecx + call e3c59x_mdio_read + pop ecx + test ax, ax + jz .next_phy + cmp ax, 0xffff + je .next_phy + mov ah, cl ; ah = phy + push ecx + call e3c59x_try_phy + pop ecx + test al, al + jnz .check_preamble +.next_phy: + dec cl + jns .search_phy_loop +.fail_finish: + xor al, al + ret +; epilog +.check_preamble: + push eax ; eax contains the return value of e3c59x_try_phy +; check hard coded preamble forcing + movzx eax, byte [e3c59x_ver_id] + test word [eax*4+e3c59x_hw_versions+2], EXTRA_PREAMBLE + setnz [e3c59x_preamble] ; force preamble + jnz .finish +; check mii for preamble suppression + mov ah, cl + mov al, E3C59X_REG_MII_BMSR + call e3c59x_mdio_read + test al, 1000000b ; preamble suppression? + setz [e3c59x_preamble] ; no +.finish: + pop eax + ret + +;*************************************************************************** +; Function +; e3c59x_test_packet +; Description +; e3c59x_try_loopback try a loopback packet for 10BASE2 or AUI port +; Parameters +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_test_packet: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; set fullDuplexEnable in MacControl register + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + or ax, 0x120 + out dx, ax +; switch to register window 5 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 + out dx, ax +; set RxFilter to enable individual address matches + mov ax, (10000b shl 11) + lea edx, [ebp+E3C59X_REG_RX_FILTER] + in al, dx + or al, 1 + lea edx, [ebp+E3C59X_REG_COMMAND] + out dx, ax +; issue RxEnable and TxEnable + call e3c59x_rx_reset + call e3c59x_tx_reset +; download a self-directed test packet + mov edi, node_addr + mov bx, 0x0608 ; packet type + mov esi, e3c59x_self_directed_packet + mov ecx, 6 ; 6 + 6 + 2 + 6 = 20 bytes + call dword [e3c59x_transmit_function] +; wait for 2s + mov esi, 2000 ; 2000ms = 2s + call delay_ms +; check if self-directed packet is received + call dword [e3c59x_receive_function] + test al, al + jnz .finish +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; clear fullDuplexEnable in MacControl register + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + and ax, not 0x120 + out dx, ax + xor al, al +.finish: + ret + +;*************************************************************************** +; Function +; e3c59x_try_loopback +; Description +; tries a loopback packet for 10BASE2 or AUI port +; Parameters +; al - 0: 10Mbps AUI connector +; 1: 10BASE-2 +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_try_loopback: + push eax +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + pop eax + push eax +if defined E3C59X_DEBUG + mov bl, al + inc bl + shl bl, 3 + or byte [e3c59x_link_type+1], bl +end if ; defined E3C59X_DEBUG + test al, al ; aui or coax? + jz .complete_loopback +; enable 100BASE-2 DC-DC converter + mov ax, (10b shl 11) ; EnableDcConverter + out dx, ax +.complete_loopback: + mov cl, 2 ; give a port 3 chances to complete a loopback +.next_try: + push ecx + call e3c59x_test_packet + pop ecx + test al, al + jnz .finish + dec cl + jns .next_try +.finish: + xchg eax, [esp] + test al, al + jz .aui_finish +; issue DisableDcConverter command + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10111b shl 11) + out dx, ax +.aui_finish: + pop eax ; al contains the result of operation +if defined E3C59X_DEBUG + test al, al + jnz @f + and byte [e3c59x_link_type+1], not 11000b +@@: +end if ; defined E3C59X_DEBUG + ret + +;*************************************************************************** +; Function +; e3c59x_set_available_media +; Description +; sets the first available media +; Parameters +; ebp - io_addr +; Return value +; al - 0 +; al - 1 +; Destroyed registers +; eax, edx +; +;*************************************************************************** + align 4 +e3c59x_set_available_media: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + push eax + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx + test al, 10b + jz @f +; baseTXAvailable + pop eax + and eax, not (1111b shl 20) + or eax, (100b shl 20) +if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD + mov word [e3c59x_link_type], (1 shl 8) +else if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 7) +end if + jmp .set_media +@@: + test al, 100b + jz @f +; baseFXAvailable + pop eax + and eax, not (1111b shl 20) + or eax, (101b shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 10) +end if + jmp .set_media +@@: + test al, 1000000b + jz @f +; miiDevice + pop eax + and eax, not (1111b shl 20) + or eax, (0110b shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 13) +end if + jmp .set_media +@@: + test al, 1000b + jz @f +.set_default: +; 10bTAvailable + pop eax + and eax, not (1111b shl 20) +if defined E3C59X_DEBUG & defined E3C59X_FORCE_FD + mov word [e3c59x_link_type], (1 shl 6) +else if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 5) +end if ; E3C59X_FORCE_FD + jmp .set_media +@@: + test al, 10000b + jz @f +; coaxAvailable + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10b shl 11) ; EnableDcConverter + out dx, ax + pop eax + and eax, not (1111b shl 20) + or eax, (11b shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 12) +end if ; defined E3C59X_DEBUG + jmp .set_media +@@: + test al, 10000b + jz .set_default +; auiAvailable + pop eax + and eax, not (1111b shl 20) + or eax, (1 shl 20) +if defined E3C59X_DEBUG + mov word [e3c59x_link_type], (1 shl 11) +end if ; defined E3C59X_DEBUG +.set_media: + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + out dx, eax +if defined E3C59X_FORCE_FD +; set fullDuplexEnable in MacControl register + lea edx, [ebp+E3C59X_REG_MAC_CONTROL] + in ax, dx + or ax, 0x120 + out dx, ax +end if ; E3C59X_FORCE_FD + mov al, 1 + ret + +;*************************************************************************** +; Function +; e3c59x_set_active_port +; Description +; It selects the media port (transceiver) to be used +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_set_active_port: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + test eax, (1 shl 24) ; check if autoselect enable + jz .set_first_available_media +; check 100BASE-TX and 10BASE-T + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx + test al, 1010b ; check whether 100BASE-TX or 10BASE-T available + jz .mii_device ; they are not available +; set auto-negotiation + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (1000b shl 20) + out dx, eax + call e3c59x_try_mii + test al, al + jz .mii_device + ret +.mii_device: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for off-chip mii device + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx + test al, 1000000b ; check miiDevice + jz .base_fx + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0110b shl 20) ; set MIIDevice + out dx, eax + call e3c59x_try_mii + test al, al + jz .base_fx + ret +.base_fx: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for 100BASE-FX + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx ; read media option register + test al, 100b ; check 100BASE-FX + jz .aui_enable + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0101b shl 20) ; set 100base-FX + out dx, eax + call e3c59x_try_link_detect + test al, al + jz .aui_enable + ret +.aui_enable: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for 10Mbps AUI connector + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx ; read media option register + test al, 100000b ; check 10Mbps AUI connector + jz .coax_available + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0001b shl 20) ; set 10Mbps AUI connector + out dx, eax + xor al, al ; try 10Mbps AUI connector + call e3c59x_try_loopback + test al, al + jz .coax_available + ret +.coax_available: +; switch to register window 3 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+3 + out dx, ax +; check for coaxial 10BASE-2 port + lea edx, [ebp+E3C59X_REG_MEDIA_OPTIONS] + in ax, dx ; read media option register + test al, 10000b ; check 10BASE-2 + jz .set_first_available_media + lea edx, [ebp+E3C59X_REG_INTERNAL_CONFIG] + in eax, dx + and eax, not (1111b shl 20) + or eax, (0011b shl 20) ; set 10BASE-2 + out dx, eax + mov al, 1 + call e3c59x_try_loopback + test al, al + jz .set_first_available_media + ret +.set_first_available_media: + jmp e3c59x_set_available_media + +;*************************************************************************** +; Function +; e3c59x_wake_up +; Description +; set the power state to D0 +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_wake_up: +; wake up - we directly do it by programming PCI +; check if the device is power management capable + mov al, 2 + mov ah, [pci_bus] + mov bl, PCI_REG_STATUS + mov bh, [pci_dev] + push eax ebx + call pci_read_reg + test al, 10000b ; is there "new capabilities" linked list? + pop ebx eax + jz .device_awake +; search for power management register + mov al, 1 + mov bl, PCI_REG_CAP_PTR + push eax ebx + call pci_read_reg + mov cl, al + cmp cl, 0x3f + pop ebx eax + jbe .device_awake +; traverse the list + mov al, 2 +.pm_loop: + mov bl, cl + push eax ebx + call pci_read_reg + cmp al, 1 + je .set_pm_state + test ah, ah + mov cl, ah + pop ebx eax + jnz .pm_loop + jmp .device_awake +; waku up the device if necessary +.set_pm_state: + pop ebx eax + add bl, PCI_REG_PM_CTRL + push eax ebx + call pci_read_reg + mov cx, ax + test cl, 3 + pop ebx eax + jz .device_awake + and cl, not 11b ; set state to D0 + call pci_write_reg +.device_awake: + ret + +;*************************************************************************** +; Function +; e3c59x_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_probe: + movzx ebp, word [io_addr] + mov al, 2 + mov ah, [pci_bus] + mov bh, [pci_dev] + mov bl, PCI_REG_COMMAND + push ebp eax ebx + call pci_read_reg + mov cx, ax + or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) + and cl, not (1 shl PCI_BIT_MMIO) + pop ebx eax + call pci_write_reg +; wake up the card + call e3c59x_wake_up + pop ebp +; get chip version + mov ax, [pci_data+2] + mov ecx, E3C59X_HW_VERSIONS_SIZE/4-1 +.chip_ver_loop: + cmp ax, [e3c59x_hw_versions+ecx*4] + jz .chip_ver_found + dec ecx + jns .chip_ver_loop + xor ecx, ecx +.chip_ver_found: + mov [e3c59x_ver_id], cl + test word [e3c59x_hw_versions+2+ecx*4], HAS_HWCKSM + setnz [e3c59x_has_hwcksm] +; set pci latency for vortex cards + test word [e3c59x_hw_versions+2+ecx*4], IS_VORTEX + jz .not_vortex + mov cx, 11111000b ; 248 = max latency + mov al, 1 + mov ah, [pci_bus] + mov bl, PCI_REG_LATENCY + mov bh, [pci_dev] + call pci_write_reg +.not_vortex: +; set RX/TX functions + mov ax, E3C59X_EEPROM_REG_CAPABILITIES + call e3c59x_read_eeprom + test al, 100000b ; full bus master? + setnz [e3c59x_full_bus_master] + jnz .boomerang_func + mov dword [e3c59x_transmit_function], e3c59x_vortex_transmit + mov dword [e3c59x_receive_function], e3c59x_vortex_poll + jmp @f +.boomerang_func: ; full bus master, so use boomerang functions + mov dword [e3c59x_transmit_function], e3c59x_boomerang_transmit + mov dword [e3c59x_receive_function], e3c59x_boomerang_poll +@@: +; read MAC from eeprom + mov ecx, 2 +.mac_loop: + lea ax, [E3C59X_EEPROM_REG_OEM_NODE_ADDR+ecx] + call e3c59x_read_eeprom + xchg ah, al ; htons + mov [node_addr+ecx*2], ax + dec ecx + jns .mac_loop + test byte [e3c59x_full_bus_master], 0xff + jz .set_preamble +; switch to register window 2 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 + out dx, ax +; activate xcvr by setting some magic bits + lea edx, [ebp+E3C59X_REG_RESET_OPTIONS] + in ax, dx + and ax, not 0x4010 + movzx ebx, byte [e3c59x_ver_id] + test word [ebx*4+e3c59x_hw_versions+2], INVERT_LED_PWR + jz @f + or al, 0x10 +@@: + test word [ebx*4+e3c59x_hw_versions+2], INVERT_MII_PWR + jz @f + or ah, 0x40 +@@: + out dx, ax +.set_preamble: +; use preamble as default + mov byte [e3c59x_preamble], 1 ; enable preamble + +;*************************************************************************** +; Function +; e3c59x_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** +e3c59x_reset: +; issue global reset + call e3c59x_global_reset +; disable interrupts + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (1110b shl 11) + out dx, ax +; enable Statistics + mov ax, (10101b shl 11) + out dx, ax +; set indication + mov ax, (1111b shl 11) or 0x6c6 + out dx, ax +; acknowledge (clear) every interrupt indicator + mov ax, (1101b shl 11) or 0x661 + out dx, ax +; switch to register window 2 + mov ax, E3C59X_SELECT_REGISTER_WINDOW+2 + out dx, ax +; write MAC addres back into the station address registers + lea edx, [ebp+E3C59X_REG_STATION_ADDRESS_LO] + mov esi, node_addr + cld + outsw + add edx, 2 + outsw + add edx, 2 + outsw + add edx, 2 +; clear station mask + xor eax, eax + out dx, ax + add edx, 2 + out dx, ax + add edx, 2 + out dx, ax +; switch to register window 6 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+6 + out dx, ax +; clear all statistics by reading + lea edx, [ebp+E3C59X_REG_CARRIER_LOST] + mov cl, 9 +.stat_clearing_loop: + in al, dx + inc edx + dec cl + jns .stat_clearing_loop + in ax, dx + add dx, 2 + in ax, dx +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; clear BadSSD + lea edx, [ebp+E3C59X_REG_BAD_SSD] + in al, dx +; clear extra statistics bit in NetworkDiagnostic + lea edx, [ebp+E3C59X_REG_NETWORK_DIAGNOSTIC] + in ax, dx + or ax, 0x0040 + out dx, ax +; SetRxEarlyThreshold + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10001b shl 11)+(E3C59X_MAX_ETH_PKT_SIZE shr 2) + out dx, ax + test byte [e3c59x_full_bus_master], 0xff + jz .skip_boomerang_setting +; set upRxEarlyEnable + lea edx, [ebp+E3C59X_REG_DMA_CTRL] + in eax, dx + or eax, 0x20 + out dx, eax +; TxFreeThreshold + lea edx, [ebp+E3C59X_REG_TX_FREE_THRESH] + mov al, (E3C59X_MAX_ETH_PKT_SIZE / 256) + out dx, al +; program DnListPtr + lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] + xor eax, eax + out dx, eax +.skip_boomerang_setting: +; initialization + call e3c59x_rx_reset + call e3c59x_tx_reset + call e3c59x_set_active_port + call e3c59x_rx_reset + call e3c59x_tx_reset +; switch to register window 5 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+5 + out dx, ax +; program RxFilter for promiscuous operation + mov ax, (10000b shl 11) + lea edx, [ebp+E3C59X_REG_RX_FILTER] + in al, dx + or al, 1111b + lea edx, [ebp+E3C59X_REG_COMMAND] + out dx, ax +; switch to register window 4 + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax +; wait for linkDetect + lea edx, [ebp+E3C59X_REG_MEDIA_STATUS] + mov cl, 20 ; wait for max 2s + mov esi, 100 ; 100ms +.link_detect_loop: + call delay_ms + in ax, dx + test ah, 1000b ; linkDetect + jnz @f + dec cl + jnz .link_detect_loop +@@: +; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax +if defined E3C59X_DEBUG + call e3c59x_debug +end if ; defined E3C59X_DEBUG + ret + +;*************************************************************************** +; Function +; e3c59x_global_reset +; Description +; resets the device +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; ax, ecx, edx, esi +; +;*************************************************************************** + align 4 +e3c59x_global_reset: +; GlobalReset + lea edx, [ebp+E3C59X_REG_COMMAND] + xor eax, eax +; or al, 0x14 + out dx, ax +; wait for GlobalReset to complete + mov ecx, 64000 +.global_reset_loop: + in ax, dx + test ah, 10000b ; check CmdInProgress + jz .finish + dec ecx + jnz .global_reset_loop +.finish: +; wait for 2 seconds for NIC to boot + mov esi, 2000 ; 2000ms = 2s + push ebp + call delay_ms + pop ebp + ret + +;*************************************************************************** +; Function +; e3c59x_tx_reset +; Description +; resets and enables transmitter engine +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; ax, ecx, edx +; +;*************************************************************************** + align 4 +e3c59x_tx_reset: +; TxReset + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (01011b shl 11) + out dx, ax +; Wait for TxReset to complete + mov ecx, 200000 +.tx_reset_loop: + in ax, dx + test ah, 10000b ; check CmdInProgress + jz .tx_set_prev + dec ecx + jns .tx_reset_loop +.tx_set_prev: + test byte [e3c59x_full_bus_master], 0xff + jz .tx_enable +; init last_dpd + mov dword [e3c59x_prev_dpd], e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE + mov dword [e3c59x_prev_tx_frame], e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE +.tx_enable: + mov ax, (01001b shl 11) ; TxEnable + out dx, ax + ret + +;*************************************************************************** +; Function +; e3c59x_rx_reset +; Description +; resets and enables receiver engine +; Parameters: +; ebp - io_addr +; Return value: +; Destroyed registers +; eax, ebx, ecx, edx, edi, esi +; +;*************************************************************************** + align 4 +e3c59x_rx_reset: + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (0101b shl 11) or 0x4 ; RxReset + out dx, ax +; wait for RxReset to complete + mov ecx, 200000 +.rx_reset_loop: + in ax, dx + test ah, 10000b ; check CmdInProgress + jz .setup_upd + dec ecx + jns .rx_reset_loop +.setup_upd: +; check if full bus mastering + test byte [e3c59x_full_bus_master], 0xff + jz .rx_enable +; create upd ring + mov eax, e3c59x_upd_buff + zero_to_virt eax + mov [e3c59x_curr_upd], eax + mov esi, eax + virt_to_dma esi + mov edi, e3c59x_rx_buff + zero_to_dma edi + mov ebx, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE + zero_to_virt ebx + mov cl, E3C59X_NUM_RX_DESC-1 +.upd_loop: + mov [ebx+E3C59X_UPD_UP_NEXT_PTR], esi + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + mov [eax+E3C59X_UPD_UP_FRAG_ADDR], edi + mov dword [eax+E3C59X_UPD_UP_FRAG_LEN], E3C59X_MAX_ETH_FRAME_SIZE or (1 shl 31) + add edi, E3C59X_MAX_ETH_FRAME_SIZE + add esi, E3C59X_UPD_SIZE + mov ebx, eax + add eax, E3C59X_UPD_SIZE + dec cl + jns .upd_loop + mov eax, e3c59x_upd_buff + zero_to_dma eax + lea edx, [ebp+E3C59X_REG_UP_LIST_PTR] + out dx, eax ; write E3C59X_REG_UP_LIST_PTR + lea edx, [ebp+E3C59X_REG_COMMAND] +.rx_enable: + mov ax, (00100b shl 11) ; RxEnable + out dx, ax + ret + +;*************************************************************************** +; Function +; e3c59x_write_eeprom +; Description +; reads eeprom +; Note : the caller must switch to the register window 0 +; before calling this function +; Parameters: +; ax - register to be read (only the first 63 words can be read) +; cx - value to be read into the register +; Return value: +; ax - word read +; Destroyed registers +; ax, ebx, edx +; +;*************************************************************************** +; align 4 +;e3c59x_write_eeprom: +; mov edx, [io_addr] +; add edx, E3C59X_REG_EEPROM_COMMAND +; cmp ah, 11b +; ja .finish ; address may have a value of maximal 1023 +; shl ax, 2 +; shr al, 2 +; push eax +;; wait for busy +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .write_enable +; dec ebx +; jns @r +;; write enable +;.write_enable: +; xor eax, eax +; mov eax, (11b shl 4) +; out dx, ax +;; wait for busy +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .erase_loop +; dec ebx +; jns @r +;.erase_loop: +; pop eax +; push eax +; or ax, (11b shl 6) ; erase register +; out dx, ax +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .write_reg +; dec ebx +; jns @r +;.write_reg: +; add edx, E3C59X_REG_EEPROM_DATA-E3C59X_REG_EEPROM_COMMAND +; mov eax, ecx +; out dx, ax +;; write enable +; add edx, E3C59X_REG_EEPROM_COMMAND-E3C59X_REG_EEPROM_DATA +; xor eax, eax +; mov eax, (11b shl 4) +; out dx, ax +; wait for busy +; mov ebx, 0xffff +;@@: +; in ax, dx +; test ah, 0x80 +; jz .issue_write_reg +; dec ebx +; jns @r +;.issue_write_reg: +; pop eax +; or ax, 01b shl 6 +; out dx, ax +;.finish: +; ret +;*************************************************************************** +; Function +; e3c59x_read_eeprom +; Description +; reads eeprom +; Parameters: +; ax - register to be read (only the first 63 words can be read) +; ebp - io_addr +; Return value: +; ax - word read +; Destroyed registers +; ax, ebx, edx, ebp +; +;*************************************************************************** + align 4 +e3c59x_read_eeprom: + push eax +; switch to register window 0 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+0 + out dx, ax + pop eax + and ax, 111111b ; take only the first 6 bits into account + movzx ebx, byte [e3c59x_ver_id] + test word [ebx*4+e3c59x_hw_versions+2], EEPROM_8BIT + jz @f + add ax, 0x230 ; hardware constant + jmp .read +@@: + add ax, E3C59X_EEPROM_CMD_READ + test word [ebx*4+e3c59x_hw_versions+2], EEPROM_OFFSET + jz .read + add ax, 0x30 +.read: + lea edx, [ebp+E3C59X_REG_EEPROM_COMMAND] + out dx, ax + mov ebx, 0xffff ; duration of about 162 us ;-) +.wait_for_reading: + in ax, dx + test ah, 0x80 ; check bit eepromBusy + jz .read_data + dec ebx + jns .wait_for_reading +.read_data: + lea edx, [ebp+E3C59X_REG_EEPROM_DATA] + in ax, dx + ret + +;*************************************************************************** +; Function +; e3c59x_mdio_sync +; Description +; initial synchronization +; Parameters +; ebp - io_addr +; Return value +; Destroyed registers +; ax, edx, cl +; +;*************************************************************************** + align 4 +e3c59x_mdio_sync: +; switch to register window 4 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+4 + out dx, ax + cmp byte [e3c59x_preamble], 0 + je .no_preamble +; send 32 logic ones + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + mov cl, 31 +.loop: + mov ax, (1 shl E3C59X_BIT_MGMT_DATA) or (1 shl E3C59X_BIT_MGMT_DIR) + out dx, ax + in ax, dx ; delay + mov ax, (1 shl E3C59X_BIT_MGMT_DATA) \ + or (1 shl E3C59X_BIT_MGMT_DIR) \ + or (1 shl E3C59X_BIT_MGMT_CLK) + out dx, ax + in ax, dx ; delay + dec cl + jns .loop +.no_preamble: + ret + +;*************************************************************************** +; Function +; e3c59x_mdio_read +; Description +; read MII register +; see page 16 in D83840A.pdf +; Parameters +; ah - PHY addr +; al - register addr +; ebp - io_addr +; Return value +; ax - register read +; Destroyed registers +; eax, ebx, cx, edx +; +;*************************************************************************** + align 4 +e3c59x_mdio_read: + push eax + call e3c59x_mdio_sync ; returns with window #4 + pop eax + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + shl al, 3 + shr ax, 3 + and ax, not E3C59X_MII_CMD_MASK + or ax, E3C59X_MII_CMD_READ + mov ebx, eax + xor ecx, ecx + mov cl, 13 +.cmd_loop: + mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii + bt ebx, ecx + jnc .zero_bit + or al, (1 shl E3C59X_BIT_MGMT_DATA) +.zero_bit: + out dx, ax + push eax + in ax, dx ; delay + pop eax + or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write + out dx, ax + in ax, dx ; delay + dec cl + jns .cmd_loop +; read data (18 bits with the two transition bits) + mov cl, 17 + xor ebx, ebx +.read_loop: + shl ebx, 1 + xor eax, eax ; read comand + out dx, ax + in ax, dx ; delay + in ax, dx + test al, (1 shl E3C59X_BIT_MGMT_DATA) + jz .dont_set + inc ebx +.dont_set: + mov ax, (1 shl E3C59X_BIT_MGMT_CLK) + out dx, ax + in ax, dx ; delay + dec cl + jns .read_loop + mov eax, ebx + ret + +;*************************************************************************** +; Function +; e3c59x_mdio_write +; Description +; write MII register +; see page 16 in D83840A.pdf +; Parameters +; ah - PHY addr +; al - register addr +; bx - word to be written +; ebp - io_addr +; Return value +; ax - register read +; Destroyed registers +; eax, ebx, cx, edx +; +;*************************************************************************** + align 4 +e3c59x_mdio_write: + push eax + call e3c59x_mdio_sync + pop eax + lea edx, [ebp+E3C59X_REG_PHYSICAL_MGMT] + shl al, 3 + shr ax, 3 + and ax, not E3C59X_MII_CMD_MASK + or ax, E3C59X_MII_CMD_WRITE + shl eax, 2 + or eax, 10b ; transition bits + shl eax, 16 + mov ax, bx + mov ebx, eax + mov ecx, 31 +.cmd_loop: + mov ax, (1 shl E3C59X_BIT_MGMT_DIR) ; write mii + bt ebx, ecx + jnc .zero_bit + or al, (1 shl E3C59X_BIT_MGMT_DATA) +.zero_bit: + out dx, ax + push eax + in ax, dx ; delay + pop eax + or al, (1 shl E3C59X_BIT_MGMT_CLK) ; write + out dx, ax + in ax, dx ; delay + dec ecx + jns .cmd_loop + ret + +;*************************************************************************** +; Function +; e3c59x_transmit +; Description +; Transmits a packet of data via the ethernet card +; edi - Pointer to 48 bit destination address +; bx - Type of packet +; ecx - size of packet +; esi - pointer to packet data +; ebp - io_addr +; Destroyed registers +; eax, ecx, edx, ebp +; +;*************************************************************************** + align 4 +e3c59x_transmit: + jmp dword [e3c59x_transmit_function] + +;*************************************************************************** +; Function +; e3c59x_check_tx_status +; Description +; Checks TxStatus queue. +; Return value +; al - 0 no error was found +; al - 1 error was found TxReset is needed +; Destroyed registers +; eax, ecx, edx, ebp +; +;*************************************************************************** +e3c59x_check_tx_status: + movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC +; clear TxStatus queue + lea edx, [ebp+E3C59X_REG_TX_STATUS] + mov cl, 31 ; max number of queue entries +.tx_status_loop: + in al, dx + test al, al + jz .finish ; no error + test al, 0x3f + jnz .finish ; error +.no_error_found: +; clear current TxStatus entry which advances the next one + xor al, al + out dx, al + dec cl + jns .tx_status_loop +.finish: + ret + +;*************************************************************************** +; Function +; e3c59x_vortex_transmit +; Description +; Transmits a packet of data via the ethernet card +; edi - Pointer to 48 bit destination address +; bx - Type of packet +; ecx - size of packet +; esi - pointer to packet data +; ebp - io_addr +; Destroyed registers +; eax, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_vortex_transmit: + push ecx + call e3c59x_check_tx_status + pop ecx + test al, al + jz .no_error_found + jmp e3c59x_tx_reset +.no_error_found: +; switch to register window 7 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 + out dx, ax +; check for master operation in progress + lea edx, [ebp+E3C59X_REG_MASTER_STATUS] + in ax, dx + test ah, 0x80 + jnz .finish ; no DMA for sending +; dword boundary correction + cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE + ja .finish ; packet is too long +; write Frame Start Header + mov eax, ecx +; add header length and extend the complete length to dword boundary + add eax, ETH_HLEN+3 + and eax, not 3 + lea edx, [ebp+E3C59X_REG_TX_DATA] + out dx, eax +; prepare the complete frame + push esi + mov esi, edi + mov edi, e3c59x_tx_buff + zero_to_virt edi + cld +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 +; copy packet data + pop esi + push ecx + shr ecx, 2 + rep movsd + pop ecx + and ecx, 3 + rep movsb + mov ecx, eax +; program frame address to be sent + lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] + mov eax, e3c59x_tx_buff + zero_to_dma eax + out dx, eax +; program frame length + lea edx, [ebp+E3C59X_REG_MASTER_LEN] + mov eax, ecx + out dx, ax +; start DMA Down + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10100b shl 11) + 1 ; StartDMADown + out dx, ax +.finish: + ret + +;*************************************************************************** +; Function +; e3c59x_boomerang_transmit +; Description +; Transmits a packet of data via the ethernet card +; edi - Pointer to 48 bit destination address +; bx - Type of packet +; ecx - size of packet +; esi - pointer to packet data +; ebp - io_addr +; Destroyed registers +; eax, ebx, ecx, edx, esi, edi, ebp +; +;*************************************************************************** + align 4 +e3c59x_boomerang_transmit: + push ecx + call e3c59x_check_tx_status + pop ecx + test al, al + jz .no_error_found + jmp e3c59x_tx_reset +.no_error_found: + cmp ecx, E3C59X_MAX_ETH_FRAME_SIZE + ja .finish ; packet is too long +; calculate descriptor address + mov eax, [e3c59x_prev_dpd] + cmp eax, e3c59x_dpd_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_DPD_SIZE + jb @f +; wrap around + mov eax, e3c59x_dpd_buff-E3C59X_DPD_SIZE +@@: + add eax, E3C59X_DPD_SIZE + zero_to_virt eax + push eax +; check DnListPtr + lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] + in eax, dx +; mark if Dn_List_Ptr is cleared + test eax, eax + setz [e3c59x_dn_list_ptr_cleared] +; finish if no more free descriptor is available - FIXME! + cmp eax, [esp] + pop eax + jz .finish + push eax esi + mov esi, edi +; calculate tx_buffer address + mov edi, [e3c59x_prev_tx_frame] + cmp edi, e3c59x_tx_buff+(E3C59X_NUM_TX_DESC-1)*E3C59X_MAX_ETH_FRAME_SIZE + jb @f +; wrap around + mov edi, e3c59x_tx_buff-E3C59X_MAX_ETH_FRAME_SIZE +@@: + add edi, E3C59X_MAX_ETH_FRAME_SIZE + zero_to_virt edi + mov eax, edi + cld +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 +; copy packet data + pop esi + push ecx + shr ecx, 2 + rep movsd + pop ecx + push ecx + and ecx, 3 + rep movsb +; padding, do we really need it? + pop ecx + add ecx, ETH_HLEN + cmp ecx, ETH_ZLEN + jae @f + mov ecx, ETH_ZLEN +@@: +; calculate + mov ebx, ecx + ;test byte [e3c59x_has_hwcksm], 0xff + ;jz @f + ;or ebx, (1 shl 26) ; set AddTcpChecksum +;@@: + or ebx, 0x8000 ; transmission complete notification + or ecx, 0x80000000 ; last fragment +; program DPD + mov edi, eax + pop eax + and dword [eax+E3C59X_DPD_DN_NEXT_PTR], 0 + mov dword [eax+E3C59X_DPD_FRAME_START_HDR], ebx + virt_to_dma edi + mov dword [eax+E3C59X_DPD_DN_FRAG_ADDR], edi + mov [eax+E3C59X_DPD_DN_FRAG_LEN], ecx +; calculate physical address + virt_to_dma eax + push eax + cmp byte [e3c59x_dn_list_ptr_cleared], 0 + jz .add_to_list +; write Dn_List_Ptr + out dx, eax + jmp .finish +.add_to_list: +; DnStall + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, ((110b shl 11)+2) + out dx, ax +; wait for DnStall to complete + mov ecx, 6000 +.wait_for_stall: + in ax, dx ; read E3C59X_REG_INT_STATUS + test ah, 10000b + jz .dnstall_ok + dec ecx + jnz .wait_for_stall +.dnstall_ok: + pop eax + push eax + mov ebx, [e3c59x_prev_dpd] + zero_to_virt ebx + mov [ebx], eax + lea edx, [ebp+E3C59X_REG_DN_LIST_PTR] + in eax, dx + test eax, eax + jnz .dnunstall +; if Dn_List_Ptr has been cleared fill it up + pop eax + push eax + out dx, eax +.dnunstall: +; DnUnStall + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, ((110b shl 11)+3) + out dx, ax +.finish: + pop eax + dma_to_zero eax + mov [e3c59x_prev_dpd], eax + dma_to_zero edi + mov [e3c59x_prev_tx_frame], edi + ret + +;*************************************************************************** +; Function +; e3c59x_poll +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Destroyed registers +; eax, ebx, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_poll: + jmp dword [e3c59x_receive_function] + +;*************************************************************************** +; Function +; e3c59x_vortex_poll +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Parameters +; ebp - io_addr +; Return value +; al - 0 ; no packet received +; al - 1 ; packet received +; Destroyed registers +; eax, ebx, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_vortex_poll: + and word [eth_rx_data_len], 0 ; assume no packet received + movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC +.rx_status_loop: +; examine RxStatus + lea edx, [ebp+E3C59X_REG_RX_STATUS] + in ax, dx + test ax, ax + jz .finish + test ah, 0x80 ; rxIncomplete + jz .check_error + jmp .finish +.check_error: + test ah, 0x40 + jz .check_length +; discard the top frame received advancing the next one + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (01000b shl 11) + out dx, ax + jmp .rx_status_loop +.check_length: + and eax, 0x1fff + cmp eax, E3C59X_MAX_ETH_PKT_SIZE + ja .discard_frame ; frame is too long discard it +.check_dma: + push eax +; switch to register window 7 + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, E3C59X_SELECT_REGISTER_WINDOW+7 + out dx, ax +; check for master operation in progress + lea edx, [ebp+E3C59X_REG_MASTER_STATUS] + in ax, dx + test ah, 0x80 + jz .read_frame ; no DMA for receiving + pop eax + jmp .finish +.read_frame: +; program buffer address to read in + lea edx, [ebp+E3C59X_REG_MASTER_ADDRESS] +if defined E3C59X_LINUX + mov eax, e3c59x_rx_buff + zero_to_dma eax +else + mov eax, Ether_buffer +end if + out dx, eax +; program frame length + lea edx, [ebp+E3C59X_REG_MASTER_LEN] + mov ax, 1560 + out dx, ax +; start DMA Up + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (10100b shl 11) ; StartDMAUp + out dx, ax +; check for master operation in progress +.dma_loop: + lea edx, [ebp+E3C59X_REG_MASTER_STATUS] + in ax, dx + test ah, 0x80 + jnz .dma_loop +; registrate the received packet length + pop eax + mov word [eth_rx_data_len], ax +; discard the top frame received +.discard_frame: + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, (01000b shl 11) + out dx, ax +.finish: +; set return value + cmp word [eth_rx_data_len], 0 + setne al + ret + +;*************************************************************************** +; Function +; e3c59x_boomerang_poll +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Parameters +; ebp - io_addr +; Return value +; al - 0 ; no packet received +; al - 1 ; packet received +; Destroyed registers +; eax, edx, ecx, edi, esi, ebp +; +;*************************************************************************** + align 4 +e3c59x_boomerang_poll: + and word [eth_rx_data_len], 0 ; assume no packet received + movzx ebp, word [io_addr] ; to be implemented in ETHERNET.INC +; check if packet is uploaded + mov eax, [e3c59x_curr_upd] + test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x80 ; upPktComplete + jnz .check_error + jmp .finish +; packet is uploaded check for any error +.check_error: + test byte [eax+E3C59X_UPD_PKT_STATUS+1], 0x40 ; upError + jz .copy_packet_length + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + jmp .finish +.copy_packet_length: + mov ecx, [eax+E3C59X_UPD_PKT_STATUS] + and ecx, 0x1fff + cmp ecx, E3C59X_MAX_ETH_PKT_SIZE + jbe .copy_packet + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + jmp .finish +.copy_packet: + push ecx + mov word [eth_rx_data_len], cx + mov esi, [eax+E3C59X_UPD_UP_FRAG_ADDR] + dma_to_virt esi + mov edi, Ether_buffer + shr ecx, 2 ; first copy dword-wise + cld + rep movsd ; copy the dwords + pop ecx + and ecx, 3 + rep movsb ; copy the rest bytes + mov eax, [e3c59x_curr_upd] + and dword [eax+E3C59X_UPD_PKT_STATUS], 0 + virt_to_zero eax + cmp eax, e3c59x_upd_buff+(E3C59X_NUM_RX_DESC-1)*E3C59X_UPD_SIZE + jb .no_wrap +; wrap around + mov eax, e3c59x_upd_buff-E3C59X_UPD_SIZE +.no_wrap: + add eax, E3C59X_UPD_SIZE + zero_to_virt eax + mov [e3c59x_curr_upd], eax +.finish: +; check if the NIC is in the upStall state + lea edx, [ebp+E3C59X_REG_UP_PKT_STATUS] + in eax, dx + test ah, 0x20 ; UpStalled + jz .noUpUnStall +; issue upUnStall command + lea edx, [ebp+E3C59X_REG_COMMAND] + mov ax, ((110b shl 11)+1) ; upUnStall + out dx, ax +.noUpUnStall: +; set return value + cmp word [eth_rx_data_len], 0 + setnz al + ret diff --git a/kernel/trunk/network/eth_drv/drivers/forcedeth.inc b/kernel/trunk/network/eth_drv/drivers/forcedeth.inc index a520b9b0d..74caa5097 100644 --- a/kernel/trunk/network/eth_drv/drivers/forcedeth.inc +++ b/kernel/trunk/network/eth_drv/drivers/forcedeth.inc @@ -42,412 +42,412 @@ $Revision$ ; forcedeth Register Definitions ;************************************************************************** -PCI_REG_COMMAND equ 0x04 ; command register +PCI_REG_COMMAND equ 0x04 ; command register -PCI_COMMAND_IO equ 0x01 ; Enable response in I/O space -PCI_COMMAND_MASTER equ 0x04 ; Enable bus mastering -PCI_LATENCY_TIMER equ 0x0d ; 8 bits +PCI_COMMAND_IO equ 0x01 ; Enable response in I/O space +PCI_COMMAND_MASTER equ 0x04 ; Enable bus mastering +PCI_LATENCY_TIMER equ 0x0d ; 8 bits -PCI_VENDOR_ID equ 0x00 ; 16 bit -PCI_REVISION_ID equ 0x08 ; 8 bits +PCI_VENDOR_ID equ 0x00 ; 16 bit +PCI_REVISION_ID equ 0x08 ; 8 bits -PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits -PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits -PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits -PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits -PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits -PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits +PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits +PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits +PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits +PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits +PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits +PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits -PCI_BASE_ADDRESS_SPACE_IO equ 0x01 -PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) -PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) +PCI_BASE_ADDRESS_SPACE_IO equ 0x01 +PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) +PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) -PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 -PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address -PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] -PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address +PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 +PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address +PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] +PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address ; NIC specific static variables go here -PCI_DEVICE_ID_NVIDIA_NVENET_1 equ 0x01c3 -PCI_DEVICE_ID_NVIDIA_NVENET_2 equ 0x0066 -PCI_DEVICE_ID_NVIDIA_NVENET_4 equ 0x0086 -PCI_DEVICE_ID_NVIDIA_NVENET_5 equ 0x008c -PCI_DEVICE_ID_NVIDIA_NVENET_3 equ 0x00d6 -PCI_DEVICE_ID_NVIDIA_NVENET_7 equ 0x00df -PCI_DEVICE_ID_NVIDIA_NVENET_6 equ 0x00e6 -PCI_DEVICE_ID_NVIDIA_NVENET_8 equ 0x0056 -PCI_DEVICE_ID_NVIDIA_NVENET_9 equ 0x0057 -PCI_DEVICE_ID_NVIDIA_NVENET_10 equ 0x0037 -PCI_DEVICE_ID_NVIDIA_NVENET_11 equ 0x0038 -PCI_DEVICE_ID_NVIDIA_NVENET_12 equ 0x0268 -PCI_DEVICE_ID_NVIDIA_NVENET_13 equ 0x0269 -PCI_DEVICE_ID_NVIDIA_NVENET_14 equ 0x0372 -PCI_DEVICE_ID_NVIDIA_NVENET_15 equ 0x0373 +PCI_DEVICE_ID_NVIDIA_NVENET_1 equ 0x01c3 +PCI_DEVICE_ID_NVIDIA_NVENET_2 equ 0x0066 +PCI_DEVICE_ID_NVIDIA_NVENET_4 equ 0x0086 +PCI_DEVICE_ID_NVIDIA_NVENET_5 equ 0x008c +PCI_DEVICE_ID_NVIDIA_NVENET_3 equ 0x00d6 +PCI_DEVICE_ID_NVIDIA_NVENET_7 equ 0x00df +PCI_DEVICE_ID_NVIDIA_NVENET_6 equ 0x00e6 +PCI_DEVICE_ID_NVIDIA_NVENET_8 equ 0x0056 +PCI_DEVICE_ID_NVIDIA_NVENET_9 equ 0x0057 +PCI_DEVICE_ID_NVIDIA_NVENET_10 equ 0x0037 +PCI_DEVICE_ID_NVIDIA_NVENET_11 equ 0x0038 +PCI_DEVICE_ID_NVIDIA_NVENET_12 equ 0x0268 +PCI_DEVICE_ID_NVIDIA_NVENET_13 equ 0x0269 +PCI_DEVICE_ID_NVIDIA_NVENET_14 equ 0x0372 +PCI_DEVICE_ID_NVIDIA_NVENET_15 equ 0x0373 -ETH_DATA_LEN equ 1500 +ETH_DATA_LEN equ 1500 ; rx/tx mac addr + type + vlan + align + slack -RX_NIC_BUFSIZE equ (ETH_DATA_LEN + 64) +RX_NIC_BUFSIZE equ (ETH_DATA_LEN + 64) ; even more slack -RX_ALLOC_BUFSIZE equ (ETH_DATA_LEN + 128) +RX_ALLOC_BUFSIZE equ (ETH_DATA_LEN + 128) -NvRegIrqStatus equ 0x00 -NvRegIrqMask equ 0x04 -NvRegUnknownSetupReg6 equ 0x08 -NvRegPollingInterval equ 0x0c -NvRegMacReset equ 0x3c -NvRegMisc1 equ 0x80 -NvRegTransmitterControl equ 0x84 -NvRegTransmitterStatus equ 0x88 -NvRegPacketFilterFlags equ 0x8c -NvRegOffloadConfig equ 0x90 -NvRegReceiverControl equ 0x94 -NvRegReceiverStatus equ 0x98 -NvRegRandomSeed equ 0x9c -NvRegUnknownSetupReg1 equ 0xA0 -NvRegUnknownSetupReg2 equ 0xA4 -NvRegMacAddrA equ 0xA8 ; MAC address low -NvRegMacAddrB equ 0xAC ; MAC address high -NvRegMulticastAddrA equ 0xB0 -NvRegMulticastAddrB equ 0xB4 -NvRegMulticastMaskA equ 0xB8 -NvRegMulticastMaskB equ 0xBC -NvRegPhyInterface equ 0xC0 -NvRegTxRingPhysAddr equ 0x100 -NvRegRxRingPhysAddr equ 0x104 -NvRegRingSizes equ 0x108 -NvRegUnknownTransmitterReg equ 0x10c -NvRegLinkSpeed equ 0x110 -NvRegUnknownSetupReg5 equ 0x130 -NvRegUnknownSetupReg3 equ 0x13c -NvRegTxRxControl equ 0x144 -NvRegMIIStatus equ 0x180 -NvRegUnknownSetupReg4 equ 0x184 -NvRegAdapterControl equ 0x188 -NvRegMIISpeed equ 0x18c -NvRegMIIControl equ 0x190 -NvRegMIIData equ 0x194 -NvRegWakeUpFlags equ 0x200 -NvRegPowerState equ 0x26c -NvRegPowerState2 equ 0x600 +NvRegIrqStatus equ 0x00 +NvRegIrqMask equ 0x04 +NvRegUnknownSetupReg6 equ 0x08 +NvRegPollingInterval equ 0x0c +NvRegMacReset equ 0x3c +NvRegMisc1 equ 0x80 +NvRegTransmitterControl equ 0x84 +NvRegTransmitterStatus equ 0x88 +NvRegPacketFilterFlags equ 0x8c +NvRegOffloadConfig equ 0x90 +NvRegReceiverControl equ 0x94 +NvRegReceiverStatus equ 0x98 +NvRegRandomSeed equ 0x9c +NvRegUnknownSetupReg1 equ 0xA0 +NvRegUnknownSetupReg2 equ 0xA4 +NvRegMacAddrA equ 0xA8 ; MAC address low +NvRegMacAddrB equ 0xAC ; MAC address high +NvRegMulticastAddrA equ 0xB0 +NvRegMulticastAddrB equ 0xB4 +NvRegMulticastMaskA equ 0xB8 +NvRegMulticastMaskB equ 0xBC +NvRegPhyInterface equ 0xC0 +NvRegTxRingPhysAddr equ 0x100 +NvRegRxRingPhysAddr equ 0x104 +NvRegRingSizes equ 0x108 +NvRegUnknownTransmitterReg equ 0x10c +NvRegLinkSpeed equ 0x110 +NvRegUnknownSetupReg5 equ 0x130 +NvRegUnknownSetupReg3 equ 0x13c +NvRegTxRxControl equ 0x144 +NvRegMIIStatus equ 0x180 +NvRegUnknownSetupReg4 equ 0x184 +NvRegAdapterControl equ 0x188 +NvRegMIISpeed equ 0x18c +NvRegMIIControl equ 0x190 +NvRegMIIData equ 0x194 +NvRegWakeUpFlags equ 0x200 +NvRegPowerState equ 0x26c +NvRegPowerState2 equ 0x600 -NVREG_UNKSETUP1_VAL equ 0x16070f -NVREG_UNKSETUP2_VAL equ 0x16 -NVREG_UNKSETUP3_VAL1 equ 0x200010 -NVREG_UNKSETUP4_VAL equ 8 -NVREG_UNKSETUP5_BIT31 equ (1 shl 31) -NVREG_UNKSETUP6_VAL equ 3 +NVREG_UNKSETUP1_VAL equ 0x16070f +NVREG_UNKSETUP2_VAL equ 0x16 +NVREG_UNKSETUP3_VAL1 equ 0x200010 +NVREG_UNKSETUP4_VAL equ 8 +NVREG_UNKSETUP5_BIT31 equ (1 shl 31) +NVREG_UNKSETUP6_VAL equ 3 -NVREG_TXRXCTL_RXCHECK equ 0x0400 -NVREG_MIISTAT_ERROR equ 0x0001 -NVREG_MIISTAT_MASK equ 0x000f -NVREG_MIISTAT_MASK2 equ 0x000f -NVREG_MIICTL_INUSE equ 0x08000 -NVREG_MIICTL_WRITE equ 0x00400 -NVREG_MIICTL_ADDRSHIFT equ 5 +NVREG_TXRXCTL_RXCHECK equ 0x0400 +NVREG_MIISTAT_ERROR equ 0x0001 +NVREG_MIISTAT_MASK equ 0x000f +NVREG_MIISTAT_MASK2 equ 0x000f +NVREG_MIICTL_INUSE equ 0x08000 +NVREG_MIICTL_WRITE equ 0x00400 +NVREG_MIICTL_ADDRSHIFT equ 5 -NVREG_MIISPEED_BIT8 equ (1 shl 8) -NVREG_MIIDELAY equ 5 +NVREG_MIISPEED_BIT8 equ (1 shl 8) +NVREG_MIIDELAY equ 5 -NVREG_IRQ_RX_ERROR equ 0x0001 -NVREG_IRQ_RX equ 0x0002 -NVREG_IRQ_RX_NOBUF equ 0x0004 -NVREG_IRQ_LINK equ 0x0040 -NVREG_IRQ_TIMER equ 0x0020 -NVREG_IRQMASK_WANTED_2 equ 0x0147 +NVREG_IRQ_RX_ERROR equ 0x0001 +NVREG_IRQ_RX equ 0x0002 +NVREG_IRQ_RX_NOBUF equ 0x0004 +NVREG_IRQ_LINK equ 0x0040 +NVREG_IRQ_TIMER equ 0x0020 +NVREG_IRQMASK_WANTED_2 equ 0x0147 -NVREG_IRQ_RX_ALL equ (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) -NVREG_IRQ_TX_ALL equ 0 ; ??????????? -NVREG_IRQ_OTHER_ALL equ (NVREG_IRQ_LINK or NVREG_IRQ_TIMER) +NVREG_IRQ_RX_ALL equ (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) +NVREG_IRQ_TX_ALL equ 0 ; ??????????? +NVREG_IRQ_OTHER_ALL equ (NVREG_IRQ_LINK or NVREG_IRQ_TIMER) -NVREG_IRQSTAT_MASK equ 0x1ff +NVREG_IRQSTAT_MASK equ 0x1ff -NVREG_TXRXCTL_KICK equ 0x0001 -NVREG_TXRXCTL_BIT1 equ 0x0002 -NVREG_TXRXCTL_BIT2 equ 0x0004 -NVREG_TXRXCTL_IDLE equ 0x0008 -NVREG_TXRXCTL_RESET equ 0x0010 -NVREG_TXRXCTL_RXCHECK equ 0x0400 +NVREG_TXRXCTL_KICK equ 0x0001 +NVREG_TXRXCTL_BIT1 equ 0x0002 +NVREG_TXRXCTL_BIT2 equ 0x0004 +NVREG_TXRXCTL_IDLE equ 0x0008 +NVREG_TXRXCTL_RESET equ 0x0010 +NVREG_TXRXCTL_RXCHECK equ 0x0400 -NVREG_MCASTADDRA_FORCE equ 0x01 +NVREG_MCASTADDRA_FORCE equ 0x01 -NVREG_MAC_RESET_ASSERT equ 0x0F3 +NVREG_MAC_RESET_ASSERT equ 0x0F3 -NVREG_MISC1_HD equ 0x02 -NVREG_MISC1_FORCE equ 0x3b0f3c +NVREG_MISC1_HD equ 0x02 +NVREG_MISC1_FORCE equ 0x3b0f3c -NVREG_PFF_ALWAYS equ 0x7F0008 -NVREG_PFF_PROMISC equ 0x80 -NVREG_PFF_MYADDR equ 0x20 +NVREG_PFF_ALWAYS equ 0x7F0008 +NVREG_PFF_PROMISC equ 0x80 +NVREG_PFF_MYADDR equ 0x20 -NVREG_OFFLOAD_HOMEPHY equ 0x601 -NVREG_OFFLOAD_NORMAL equ RX_NIC_BUFSIZE +NVREG_OFFLOAD_HOMEPHY equ 0x601 +NVREG_OFFLOAD_NORMAL equ RX_NIC_BUFSIZE -NVREG_RNDSEED_MASK equ 0x00ff -NVREG_RNDSEED_FORCE equ 0x7f00 -NVREG_RNDSEED_FORCE2 equ 0x2d00 -NVREG_RNDSEED_FORCE3 equ 0x7400 +NVREG_RNDSEED_MASK equ 0x00ff +NVREG_RNDSEED_FORCE equ 0x7f00 +NVREG_RNDSEED_FORCE2 equ 0x2d00 +NVREG_RNDSEED_FORCE3 equ 0x7400 ; NVREG_POLL_DEFAULT is the interval length of the timer source on the nic ; NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms -NVREG_POLL_DEFAULT equ 970 +NVREG_POLL_DEFAULT equ 970 -NVREG_ADAPTCTL_START equ 0x02 -NVREG_ADAPTCTL_LINKUP equ 0x04 -NVREG_ADAPTCTL_PHYVALID equ 0x40000 -NVREG_ADAPTCTL_RUNNING equ 0x100000 -NVREG_ADAPTCTL_PHYSHIFT equ 24 +NVREG_ADAPTCTL_START equ 0x02 +NVREG_ADAPTCTL_LINKUP equ 0x04 +NVREG_ADAPTCTL_PHYVALID equ 0x40000 +NVREG_ADAPTCTL_RUNNING equ 0x100000 +NVREG_ADAPTCTL_PHYSHIFT equ 24 -NVREG_WAKEUPFLAGS_VAL equ 0x7770 +NVREG_WAKEUPFLAGS_VAL equ 0x7770 -NVREG_POWERSTATE_POWEREDUP equ 0x8000 -NVREG_POWERSTATE_VALID equ 0x0100 -NVREG_POWERSTATE_MASK equ 0x0003 -NVREG_POWERSTATE_D0 equ 0x0000 -NVREG_POWERSTATE_D1 equ 0x0001 -NVREG_POWERSTATE_D2 equ 0x0002 -NVREG_POWERSTATE_D3 equ 0x0003 +NVREG_POWERSTATE_POWEREDUP equ 0x8000 +NVREG_POWERSTATE_VALID equ 0x0100 +NVREG_POWERSTATE_MASK equ 0x0003 +NVREG_POWERSTATE_D0 equ 0x0000 +NVREG_POWERSTATE_D1 equ 0x0001 +NVREG_POWERSTATE_D2 equ 0x0002 +NVREG_POWERSTATE_D3 equ 0x0003 -NVREG_POWERSTATE2_POWERUP_MASK equ 0x0F11 -NVREG_POWERSTATE2_POWERUP_REV_A3 equ 0x0001 +NVREG_POWERSTATE2_POWERUP_MASK equ 0x0F11 +NVREG_POWERSTATE2_POWERUP_REV_A3 equ 0x0001 -NVREG_RCVCTL_START equ 0x01 -NVREG_RCVSTAT_BUSY equ 0x01 +NVREG_RCVCTL_START equ 0x01 +NVREG_RCVSTAT_BUSY equ 0x01 -NVREG_XMITCTL_START equ 0x01 +NVREG_XMITCTL_START equ 0x01 -NVREG_LINKSPEED_FORCE equ 0x10000 -NVREG_LINKSPEED_10 equ 1000 -NVREG_LINKSPEED_100 equ 100 -NVREG_LINKSPEED_1000 equ 50 +NVREG_LINKSPEED_FORCE equ 0x10000 +NVREG_LINKSPEED_10 equ 1000 +NVREG_LINKSPEED_100 equ 100 +NVREG_LINKSPEED_1000 equ 50 -NVREG_RINGSZ_TXSHIFT equ 0 -NVREG_RINGSZ_RXSHIFT equ 16 +NVREG_RINGSZ_TXSHIFT equ 0 +NVREG_RINGSZ_RXSHIFT equ 16 -LPA_1000FULL equ 0x0800 +LPA_1000FULL equ 0x0800 ; Link partner ability register. -LPA_SLCT equ 0x001f ; Same as advertise selector -LPA_10HALF equ 0x0020 ; Can do 10mbps half-duplex -LPA_10FULL equ 0x0040 ; Can do 10mbps full-duplex -LPA_100HALF equ 0x0080 ; Can do 100mbps half-duplex -LPA_100FULL equ 0x0100 ; Can do 100mbps full-duplex -LPA_100BASE4 equ 0x0200 ; Can do 100mbps 4k packets -LPA_RESV equ 0x1c00 ; Unused... -LPA_RFAULT equ 0x2000 ; Link partner faulted -LPA_LPACK equ 0x4000 ; Link partner acked us -LPA_NPAGE equ 0x8000 ; Next page bit +LPA_SLCT equ 0x001f ; Same as advertise selector +LPA_10HALF equ 0x0020 ; Can do 10mbps half-duplex +LPA_10FULL equ 0x0040 ; Can do 10mbps full-duplex +LPA_100HALF equ 0x0080 ; Can do 100mbps half-duplex +LPA_100FULL equ 0x0100 ; Can do 100mbps full-duplex +LPA_100BASE4 equ 0x0200 ; Can do 100mbps 4k packets +LPA_RESV equ 0x1c00 ; Unused... +LPA_RFAULT equ 0x2000 ; Link partner faulted +LPA_LPACK equ 0x4000 ; Link partner acked us +LPA_NPAGE equ 0x8000 ; Next page bit -MII_READ equ (-1) -MII_PHYSID1 equ 0x02 ; PHYS ID 1 -MII_PHYSID2 equ 0x03 ; PHYS ID 2 -MII_BMCR equ 0x00 ; Basic mode control register -MII_BMSR equ 0x01 ; Basic mode status register -MII_ADVERTISE equ 0x04 ; Advertisement control reg -MII_LPA equ 0x05 ; Link partner ability reg -MII_SREVISION equ 0x16 ; Silicon revision -MII_RESV1 equ 0x17 ; Reserved... -MII_NCONFIG equ 0x1c ; Network interface config +MII_READ equ (-1) +MII_PHYSID1 equ 0x02 ; PHYS ID 1 +MII_PHYSID2 equ 0x03 ; PHYS ID 2 +MII_BMCR equ 0x00 ; Basic mode control register +MII_BMSR equ 0x01 ; Basic mode status register +MII_ADVERTISE equ 0x04 ; Advertisement control reg +MII_LPA equ 0x05 ; Link partner ability reg +MII_SREVISION equ 0x16 ; Silicon revision +MII_RESV1 equ 0x17 ; Reserved... +MII_NCONFIG equ 0x1c ; Network interface config ; PHY defines -PHY_OUI_MARVELL equ 0x5043 -PHY_OUI_CICADA equ 0x03f1 -PHYID1_OUI_MASK equ 0x03ff -PHYID1_OUI_SHFT equ 6 -PHYID2_OUI_MASK equ 0xfc00 -PHYID2_OUI_SHFT equ 10 -PHY_INIT1 equ 0x0f000 -PHY_INIT2 equ 0x0e00 -PHY_INIT3 equ 0x01000 -PHY_INIT4 equ 0x0200 -PHY_INIT5 equ 0x0004 -PHY_INIT6 equ 0x02000 -PHY_GIGABIT equ 0x0100 +PHY_OUI_MARVELL equ 0x5043 +PHY_OUI_CICADA equ 0x03f1 +PHYID1_OUI_MASK equ 0x03ff +PHYID1_OUI_SHFT equ 6 +PHYID2_OUI_MASK equ 0xfc00 +PHYID2_OUI_SHFT equ 10 +PHY_INIT1 equ 0x0f000 +PHY_INIT2 equ 0x0e00 +PHY_INIT3 equ 0x01000 +PHY_INIT4 equ 0x0200 +PHY_INIT5 equ 0x0004 +PHY_INIT6 equ 0x02000 +PHY_GIGABIT equ 0x0100 -PHY_TIMEOUT equ 0x1 -PHY_ERROR equ 0x2 +PHY_TIMEOUT equ 0x1 +PHY_ERROR equ 0x2 -PHY_100 equ 0x1 -PHY_1000 equ 0x2 -PHY_HALF equ 0x100 +PHY_100 equ 0x1 +PHY_1000 equ 0x2 +PHY_HALF equ 0x100 -PHY_RGMII equ 0x10000000 +PHY_RGMII equ 0x10000000 ; desc_ver values: ; This field has two purposes: ; - Newer nics uses a different ring layout. The layout is selected by ; comparing np->desc_ver with DESC_VER_xy. ; - It contains bits that are forced on when writing to NvRegTxRxControl. -DESC_VER_1 equ 0x0 -DESC_VER_2 equ (0x02100 or NVREG_TXRXCTL_RXCHECK) +DESC_VER_1 equ 0x0 +DESC_VER_2 equ (0x02100 or NVREG_TXRXCTL_RXCHECK) -MAC_ADDR_LEN equ 6 +MAC_ADDR_LEN equ 6 -NV_TX_LASTPACKET equ (1 shl 16) -NV_TX_RETRYERROR equ (1 shl 19) -NV_TX_LASTPACKET1 equ (1 shl 24) -NV_TX_DEFERRED equ (1 shl 26) -NV_TX_CARRIERLOST equ (1 shl 27) -NV_TX_LATECOLLISION equ (1 shl 28) -NV_TX_UNDERFLOW equ (1 shl 29) -NV_TX_ERROR equ (1 shl 30) -NV_TX_VALID equ (1 shl 31) +NV_TX_LASTPACKET equ (1 shl 16) +NV_TX_RETRYERROR equ (1 shl 19) +NV_TX_LASTPACKET1 equ (1 shl 24) +NV_TX_DEFERRED equ (1 shl 26) +NV_TX_CARRIERLOST equ (1 shl 27) +NV_TX_LATECOLLISION equ (1 shl 28) +NV_TX_UNDERFLOW equ (1 shl 29) +NV_TX_ERROR equ (1 shl 30) +NV_TX_VALID equ (1 shl 31) -NV_TX2_LASTPACKET equ (1 shl 29) -NV_TX2_RETRYERROR equ (1 shl 18) -NV_TX2_LASTPACKET1 equ (1 shl 23) -NV_TX2_DEFERRED equ (1 shl 25) -NV_TX2_CARRIERLOST equ (1 shl 26) -NV_TX2_LATECOLLISION equ (1 shl 27) -NV_TX2_UNDERFLOW equ (1 shl 28) +NV_TX2_LASTPACKET equ (1 shl 29) +NV_TX2_RETRYERROR equ (1 shl 18) +NV_TX2_LASTPACKET1 equ (1 shl 23) +NV_TX2_DEFERRED equ (1 shl 25) +NV_TX2_CARRIERLOST equ (1 shl 26) +NV_TX2_LATECOLLISION equ (1 shl 27) +NV_TX2_UNDERFLOW equ (1 shl 28) ; error and valid are the same for both -NV_TX2_ERROR equ (1 shl 30) -NV_TX2_VALID equ (1 shl 31) +NV_TX2_ERROR equ (1 shl 30) +NV_TX2_VALID equ (1 shl 31) -NV_RX_DESCRIPTORVALID equ (1 shl 16) -NV_RX_AVAIL equ (1 shl 31) +NV_RX_DESCRIPTORVALID equ (1 shl 16) +NV_RX_AVAIL equ (1 shl 31) -NV_RX2_DESCRIPTORVALID equ (1 shl 29) +NV_RX2_DESCRIPTORVALID equ (1 shl 29) -RX_RING equ 4 -TX_RING equ 2 +RX_RING equ 4 +TX_RING equ 2 -FLAG_MASK_V1 equ 0xffff0000 -FLAG_MASK_V2 equ 0xffffc000 -LEN_MASK_V1 equ (0xffffffff xor FLAG_MASK_V1) -LEN_MASK_V2 equ (0xffffffff xor FLAG_MASK_V2) +FLAG_MASK_V1 equ 0xffff0000 +FLAG_MASK_V2 equ 0xffffc000 +LEN_MASK_V1 equ (0xffffffff xor FLAG_MASK_V1) +LEN_MASK_V2 equ (0xffffffff xor FLAG_MASK_V2) ; Miscelaneous hardware related defines: -NV_PCI_REGSZ_VER1 equ 0x270 -NV_PCI_REGSZ_VER2 equ 0x604 +NV_PCI_REGSZ_VER1 equ 0x270 +NV_PCI_REGSZ_VER2 equ 0x604 ; various timeout delays: all in usec -NV_TXRX_RESET_DELAY equ 4 -NV_TXSTOP_DELAY1 equ 10 -NV_TXSTOP_DELAY1MAX equ 500000 -NV_TXSTOP_DELAY2 equ 100 -NV_RXSTOP_DELAY1 equ 10 -NV_RXSTOP_DELAY1MAX equ 500000 -NV_RXSTOP_DELAY2 equ 100 -NV_SETUP5_DELAY equ 5 -NV_SETUP5_DELAYMAX equ 50000 -NV_POWERUP_DELAY equ 5 -NV_POWERUP_DELAYMAX equ 5000 -NV_MIIBUSY_DELAY equ 50 -NV_MIIPHY_DELAY equ 10 -NV_MIIPHY_DELAYMAX equ 10000 -NV_MAC_RESET_DELAY equ 64 -NV_WAKEUPPATTERNS equ 5 -NV_WAKEUPMASKENTRIES equ 4 +NV_TXRX_RESET_DELAY equ 4 +NV_TXSTOP_DELAY1 equ 10 +NV_TXSTOP_DELAY1MAX equ 500000 +NV_TXSTOP_DELAY2 equ 100 +NV_RXSTOP_DELAY1 equ 10 +NV_RXSTOP_DELAY1MAX equ 500000 +NV_RXSTOP_DELAY2 equ 100 +NV_SETUP5_DELAY equ 5 +NV_SETUP5_DELAYMAX equ 50000 +NV_POWERUP_DELAY equ 5 +NV_POWERUP_DELAYMAX equ 5000 +NV_MIIBUSY_DELAY equ 50 +NV_MIIPHY_DELAY equ 10 +NV_MIIPHY_DELAYMAX equ 10000 +NV_MAC_RESET_DELAY equ 64 +NV_WAKEUPPATTERNS equ 5 +NV_WAKEUPMASKENTRIES equ 4 ; Advertisement control register. -ADVERTISE_SLCT equ 0x001f ; Selector bits -ADVERTISE_CSMA equ 0x0001 ; Only selector supported -ADVERTISE_10HALF equ 0x0020 ; Try for 10mbps half-duplex -ADVERTISE_10FULL equ 0x0040 ; Try for 10mbps full-duplex -ADVERTISE_100HALF equ 0x0080 ; Try for 100mbps half-duplex -ADVERTISE_100FULL equ 0x0100 ; Try for 100mbps full-duplex -ADVERTISE_100BASE4 equ 0x0200 ; Try for 100mbps 4k packets -ADVERTISE_RESV equ 0x1c00 ; Unused... -ADVERTISE_RFAULT equ 0x2000 ; Say we can detect faults -ADVERTISE_LPACK equ 0x4000 ; Ack link partners response -ADVERTISE_NPAGE equ 0x8000 ; Next page bit +ADVERTISE_SLCT equ 0x001f ; Selector bits +ADVERTISE_CSMA equ 0x0001 ; Only selector supported +ADVERTISE_10HALF equ 0x0020 ; Try for 10mbps half-duplex +ADVERTISE_10FULL equ 0x0040 ; Try for 10mbps full-duplex +ADVERTISE_100HALF equ 0x0080 ; Try for 100mbps half-duplex +ADVERTISE_100FULL equ 0x0100 ; Try for 100mbps full-duplex +ADVERTISE_100BASE4 equ 0x0200 ; Try for 100mbps 4k packets +ADVERTISE_RESV equ 0x1c00 ; Unused... +ADVERTISE_RFAULT equ 0x2000 ; Say we can detect faults +ADVERTISE_LPACK equ 0x4000 ; Ack link partners response +ADVERTISE_NPAGE equ 0x8000 ; Next page bit -ADVERTISE_FULL equ (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA) -ADVERTISE_ALL equ (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL) +ADVERTISE_FULL equ (ADVERTISE_100FULL or ADVERTISE_10FULL or ADVERTISE_CSMA) +ADVERTISE_ALL equ (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL) -MII_1000BT_CR equ 0x09 -MII_1000BT_SR equ 0x0a -ADVERTISE_1000FULL equ 0x0200 -ADVERTISE_1000HALF equ 0x0100 +MII_1000BT_CR equ 0x09 +MII_1000BT_SR equ 0x0a +ADVERTISE_1000FULL equ 0x0200 +ADVERTISE_1000HALF equ 0x0100 -BMCR_ANRESTART equ 0x0200 ; Auto negotiation restart -BMCR_ANENABLE equ 0x1000 ; Enable auto negotiation -BMCR_SPEED100 equ 0x2000 ; Select 100Mbps -BMCR_LOOPBACK equ 0x4000 ; TXD loopback bits -BMCR_RESET equ 0x8000 ; Reset the DP83840 +BMCR_ANRESTART equ 0x0200 ; Auto negotiation restart +BMCR_ANENABLE equ 0x1000 ; Enable auto negotiation +BMCR_SPEED100 equ 0x2000 ; Select 100Mbps +BMCR_LOOPBACK equ 0x4000 ; TXD loopback bits +BMCR_RESET equ 0x8000 ; Reset the DP83840 ; Basic mode status register. -BMSR_ERCAP equ 0x0001 ; Ext-reg capability -BMSR_JCD equ 0x0002 ; Jabber detected -BMSR_LSTATUS equ 0x0004 ; Link status -BMSR_ANEGCAPABLE equ 0x0008 ; Able to do auto-negotiation -BMSR_RFAULT equ 0x0010 ; Remote fault detected -BMSR_ANEGCOMPLETE equ 0x0020 ; Auto-negotiation complete -BMSR_RESV equ 0x07c0 ; Unused... -BMSR_10HALF equ 0x0800 ; Can do 10mbps, half-duplex -BMSR_10FULL equ 0x1000 ; Can do 10mbps, full-duplex -BMSR_100HALF equ 0x2000 ; Can do 100mbps, half-duplex -BMSR_100FULL equ 0x4000 ; Can do 100mbps, full-duplex -BMSR_100BASE4 equ 0x8000 ; Can do 100mbps, 4k packets +BMSR_ERCAP equ 0x0001 ; Ext-reg capability +BMSR_JCD equ 0x0002 ; Jabber detected +BMSR_LSTATUS equ 0x0004 ; Link status +BMSR_ANEGCAPABLE equ 0x0008 ; Able to do auto-negotiation +BMSR_RFAULT equ 0x0010 ; Remote fault detected +BMSR_ANEGCOMPLETE equ 0x0020 ; Auto-negotiation complete +BMSR_RESV equ 0x07c0 ; Unused... +BMSR_10HALF equ 0x0800 ; Can do 10mbps, half-duplex +BMSR_10FULL equ 0x1000 ; Can do 10mbps, full-duplex +BMSR_100HALF equ 0x2000 ; Can do 100mbps, half-duplex +BMSR_100FULL equ 0x4000 ; Can do 100mbps, full-duplex +BMSR_100BASE4 equ 0x8000 ; Can do 100mbps, 4k packets -ETH_ALEN equ 6 -ETH_HLEN equ (2 * ETH_ALEN + 2) -ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for - ; mininmum 64bytes frame length +ETH_ALEN equ 6 +ETH_HLEN equ (2 * ETH_ALEN + 2) +ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length uglobal -forcedeth_mmio_addr dd 0 ; memory map physical address -forcedeth_mmio_size dd 0 ; size of memory bar -forcedeth_vendor_id dw 0 ; Vendor ID -forcedeth_device_id dw 0 ; Device ID -forcedeth_orig_mac0 dd 0 ; MAC -forcedeth_orig_mac1 dd 0 ; MAC -forcedeth_mapio_addr dd 0 ; mapped IO address -forcedeth_txflags dd 0 ; -forcedeth_desc_ver dd 0 ; -forcedeth_irqmask dd 0 ; IRQ-mask -forcedeth_wolenabled dd 0 ; WOL -forcedeth_in_shutdown dd 0 ; -forcedeth_cur_rx dd 0 ; -forcedeth_refill_rx dd 0 ; -forcedeth_phyaddr dd 0 ; -forcedeth_phy_oui dd 0 ; -forcedeth_gigabit dd 0 ; -forcedeth_needs_mac_reset dd 0 ; -forcedeth_linkspeed dd 0 ; -forcedeth_duplex dd 0 ; -forcedeth_next_tx dd 0 ; next TX descriptor number -forcedeth_nic_tx dd 0 ; ??? d'nt used ??? -forcedeth_packetlen dd 0 ; -forcedeth_nocable dd 0 ; no cable present +forcedeth_mmio_addr dd 0 ; memory map physical address +forcedeth_mmio_size dd 0 ; size of memory bar +forcedeth_vendor_id dw 0 ; Vendor ID +forcedeth_device_id dw 0 ; Device ID +forcedeth_orig_mac0 dd 0 ; MAC +forcedeth_orig_mac1 dd 0 ; MAC +forcedeth_mapio_addr dd 0 ; mapped IO address +forcedeth_txflags dd 0 ; +forcedeth_desc_ver dd 0 ; +forcedeth_irqmask dd 0 ; IRQ-mask +forcedeth_wolenabled dd 0 ; WOL +forcedeth_in_shutdown dd 0 ; +forcedeth_cur_rx dd 0 ; +forcedeth_refill_rx dd 0 ; +forcedeth_phyaddr dd 0 ; +forcedeth_phy_oui dd 0 ; +forcedeth_gigabit dd 0 ; +forcedeth_needs_mac_reset dd 0 ; +forcedeth_linkspeed dd 0 ; +forcedeth_duplex dd 0 ; +forcedeth_next_tx dd 0 ; next TX descriptor number +forcedeth_nic_tx dd 0 ; ??? d'nt used ??? +forcedeth_packetlen dd 0 ; +forcedeth_nocable dd 0 ; no cable present endg -struc forcedeth_TxDesc { - .PacketBuffer dd ? - .FlagLen dd ? +struc forcedeth_TxDesc { + .PacketBuffer dd ? + .FlagLen dd ? } -virtual at 0 - forcedeth_TxDesc forcedeth_TxDesc - sizeof.forcedeth_TxDesc = $ - forcedeth_TxDesc +virtual at 0 + forcedeth_TxDesc forcedeth_TxDesc + sizeof.forcedeth_TxDesc = $ - forcedeth_TxDesc end virtual -struc forcedeth_RxDesc { - .PacketBuffer dd ? - .FlagLen dd ? +struc forcedeth_RxDesc { + .PacketBuffer dd ? + .FlagLen dd ? } -virtual at 0 - forcedeth_RxDesc forcedeth_RxDesc - sizeof.forcedeth_RxDesc = $ - forcedeth_RxDesc +virtual at 0 + forcedeth_RxDesc forcedeth_RxDesc + sizeof.forcedeth_RxDesc = $ - forcedeth_RxDesc end virtual virtual at eth_data_start - ; Define the TX Descriptor - align 256 - forcedeth_tx_ring rb TX_RING * sizeof.forcedeth_TxDesc - ; Create a static buffer of size RX_BUF_SZ for each - ; TX Descriptor. All descriptors point to a - ; part of this buffer - align 256 - forcedeth_txb rb TX_RING * RX_NIC_BUFSIZE - - ; Define the RX Descriptor - align 256 - forcedeth_rx_ring rb RX_RING * sizeof.forcedeth_RxDesc - ; Create a static buffer of size RX_BUF_SZ for each - ; RX Descriptor. All descriptors point to a - ; part of this buffer - align 256 - forcedeth_rxb rb RX_RING * RX_NIC_BUFSIZE + ; Define the TX Descriptor + align 256 + forcedeth_tx_ring rb TX_RING * sizeof.forcedeth_TxDesc + ; Create a static buffer of size RX_BUF_SZ for each + ; TX Descriptor. All descriptors point to a + ; part of this buffer + align 256 + forcedeth_txb rb TX_RING * RX_NIC_BUFSIZE + + ; Define the RX Descriptor + align 256 + forcedeth_rx_ring rb RX_RING * sizeof.forcedeth_RxDesc + ; Create a static buffer of size RX_BUF_SZ for each + ; RX Descriptor. All descriptors point to a + ; part of this buffer + align 256 + forcedeth_rxb rb RX_RING * RX_NIC_BUFSIZE end virtual @@ -462,266 +462,266 @@ end virtual ;*************************************************************************** forcedeth_reset: - ; 1) erase previous misconfiguration - ; 4.1-1: stop adapter: ignored, 4.3 seems to be overkill + ; 1) erase previous misconfiguration + ; 4.1-1: stop adapter: ignored, 4.3 seems to be overkill - ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) - mov edi, dword [forcedeth_mapio_addr] - mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE + ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE - ; writel(0, base + NvRegMulticastAddrB) - mov dword [edi+NvRegMulticastAddrB], 0 - - ; writel(0, base + NvRegMulticastMaskA) - mov dword [edi+NvRegMulticastMaskA], 0 - - ; writel(0, base + NvRegMulticastMaskB) - mov dword [edi+NvRegMulticastMaskB], 0 + ; writel(0, base + NvRegMulticastAddrB) + mov dword [edi+NvRegMulticastAddrB], 0 + + ; writel(0, base + NvRegMulticastMaskA) + mov dword [edi+NvRegMulticastMaskA], 0 + + ; writel(0, base + NvRegMulticastMaskB) + mov dword [edi+NvRegMulticastMaskB], 0 - ; writel(0, base + NvRegPacketFilterFlags) - mov dword [edi+NvRegPacketFilterFlags], 0 - - ; writel(0, base + NvRegTransmitterControl) - mov dword [edi+NvRegTransmitterControl], 0 - - ; writel(0, base + NvRegReceiverControl) - mov dword [edi+NvRegReceiverControl], 0 + ; writel(0, base + NvRegPacketFilterFlags) + mov dword [edi+NvRegPacketFilterFlags], 0 + + ; writel(0, base + NvRegTransmitterControl) + mov dword [edi+NvRegTransmitterControl], 0 + + ; writel(0, base + NvRegReceiverControl) + mov dword [edi+NvRegReceiverControl], 0 - ; writel(0, base + NvRegAdapterControl) - mov dword [edi+NvRegAdapterControl], 0 + ; writel(0, base + NvRegAdapterControl) + mov dword [edi+NvRegAdapterControl], 0 - ; 2) initialize descriptor rings - ; init_ring(nic) - call forcedeth_init_ring + ; 2) initialize descriptor rings + ; init_ring(nic) + call forcedeth_init_ring - ; writel(0, base + NvRegLinkSpeed) - mov dword [edi+NvRegLinkSpeed], 0 - - ; writel(0, base + NvRegUnknownTransmitterReg) - mov dword [edi+NvRegUnknownTransmitterReg], 0 + ; writel(0, base + NvRegLinkSpeed) + mov dword [edi+NvRegLinkSpeed], 0 + + ; writel(0, base + NvRegUnknownTransmitterReg) + mov dword [edi+NvRegUnknownTransmitterReg], 0 - ; txrx_reset(nic) - call forcedeth_txrx_reset - - ; writel(0, base + NvRegUnknownSetupReg6) - mov dword [edi+NvRegUnknownSetupReg6], 0 + ; txrx_reset(nic) + call forcedeth_txrx_reset + + ; writel(0, base + NvRegUnknownSetupReg6) + mov dword [edi+NvRegUnknownSetupReg6], 0 - ; np->in_shutdown = 0 - mov dword [forcedeth_in_shutdown], 0 + ; np->in_shutdown = 0 + mov dword [forcedeth_in_shutdown], 0 - ; 3) set mac address - ; writel(mac[0], base + NvRegMacAddrA) - mov eax, dword [forcedeth_orig_mac0] - mov dword [edi+NvRegMacAddrA], eax - - ; writel(mac[1], base + NvRegMacAddrB) - mov eax, dword [forcedeth_orig_mac1] - mov dword [edi+NvRegMacAddrB], eax + ; 3) set mac address + ; writel(mac[0], base + NvRegMacAddrA) + mov eax, dword [forcedeth_orig_mac0] + mov dword [edi+NvRegMacAddrA], eax + + ; writel(mac[1], base + NvRegMacAddrB) + mov eax, dword [forcedeth_orig_mac1] + mov dword [edi+NvRegMacAddrB], eax - ; 4) give hw rings - ; writel((u32) virt_to_le32desc(&rx_ring[0]), base + NvRegRxRingPhysAddr) - mov eax, forcedeth_rx_ring + ; 4) give hw rings + ; writel((u32) virt_to_le32desc(&rx_ring[0]), base + NvRegRxRingPhysAddr) + mov eax, forcedeth_rx_ring ;DEBUGF 1," K : FORCEDETH: rx_ring at 0x%x\n", eax - sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov dword [edi+NvRegRxRingPhysAddr], eax + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov dword [edi+NvRegRxRingPhysAddr], eax - ; writel((u32) virt_to_le32desc(&tx_ring[0]), base + NvRegTxRingPhysAddr) - mov eax, forcedeth_tx_ring - sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov dword [edi+NvRegTxRingPhysAddr], eax + ; writel((u32) virt_to_le32desc(&tx_ring[0]), base + NvRegTxRingPhysAddr) + mov eax, forcedeth_tx_ring + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov dword [edi+NvRegTxRingPhysAddr], eax - ; writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes) - mov dword [edi+NvRegRingSizes], (((RX_RING - 1) shl NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) shl NVREG_RINGSZ_TXSHIFT)) + ; writel(((RX_RING - 1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) << NVREG_RINGSZ_TXSHIFT), base + NvRegRingSizes) + mov dword [edi+NvRegRingSizes], (((RX_RING - 1) shl NVREG_RINGSZ_RXSHIFT) + ((TX_RING - 1) shl NVREG_RINGSZ_TXSHIFT)) - ; 5) continue setup - ; np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 - mov dword [forcedeth_linkspeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) - - ; np->duplex = 0 - mov dword [forcedeth_duplex], 0 + ; 5) continue setup + ; np->linkspeed = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_linkspeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + + ; np->duplex = 0 + mov dword [forcedeth_duplex], 0 - ; writel(np->linkspeed, base + NvRegLinkSpeed) - mov dword [edi+NvRegLinkSpeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; writel(np->linkspeed, base + NvRegLinkSpeed) + mov dword [edi+NvRegLinkSpeed], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) - ; writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3) - mov dword [edi+NvRegUnknownSetupReg3], NVREG_UNKSETUP3_VAL1 - - ; writel(np->desc_ver, base + NvRegTxRxControl) - mov eax, dword [forcedeth_desc_ver] - mov dword [edi+NvRegTxRxControl], eax - - ; pci_push(base) - call forcedeth_pci_push - - ; writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl) - or eax, NVREG_TXRXCTL_BIT1 - mov dword [edi+NvRegTxRxControl], eax + ; writel(NVREG_UNKSETUP3_VAL1, base + NvRegUnknownSetupReg3) + mov dword [edi+NvRegUnknownSetupReg3], NVREG_UNKSETUP3_VAL1 + + ; writel(np->desc_ver, base + NvRegTxRxControl) + mov eax, dword [forcedeth_desc_ver] + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push + + ; writel(NVREG_TXRXCTL_BIT1 | np->desc_ver, base + NvRegTxRxControl) + or eax, NVREG_TXRXCTL_BIT1 + mov dword [edi+NvRegTxRxControl], eax - ; reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, "open: SetupReg5, Bit 31 remained off\n") - push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; - stdcall forcedeth_reg_delay,NvRegUnknownSetupReg5,NVREG_UNKSETUP5_BIT31,NVREG_UNKSETUP5_BIT31,NV_SETUP5_DELAY,NV_SETUP5_DELAYMAX,0 - pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; + ; reg_delay(NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, "open: SetupReg5, Bit 31 remained off\n") + push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; + stdcall forcedeth_reg_delay, NvRegUnknownSetupReg5, NVREG_UNKSETUP5_BIT31, NVREG_UNKSETUP5_BIT31, NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, 0 + pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; - ; writel(0, base + NvRegUnknownSetupReg4) - mov dword [edi+NvRegUnknownSetupReg4], 0 + ; writel(0, base + NvRegUnknownSetupReg4) + mov dword [edi+NvRegUnknownSetupReg4], 0 - ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) - mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 - + ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 + - ; printf("%d-Mbs Link, %s-Duplex\n", np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100, np->duplex ? "Full" : "Half") + ; printf("%d-Mbs Link, %s-Duplex\n", np->linkspeed & NVREG_LINKSPEED_10 ? 10 : 100, np->duplex ? "Full" : "Half") ;;;;;;;;;;; DEBUGF - ; 6) continue setup - - ; writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1) - mov dword [edi+NvRegMisc1], (NVREG_MISC1_FORCE or NVREG_MISC1_HD) - - ; writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus) - mov eax, dword [edi+NvRegTransmitterStatus] - mov dword [edi+NvRegTransmitterStatus], eax + ; 6) continue setup + + ; writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1) + mov dword [edi+NvRegMisc1], (NVREG_MISC1_FORCE or NVREG_MISC1_HD) + + ; writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus) + mov eax, dword [edi+NvRegTransmitterStatus] + mov dword [edi+NvRegTransmitterStatus], eax - ; writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags) - mov dword [edi+NvRegPacketFilterFlags], NVREG_PFF_ALWAYS + ; writel(NVREG_PFF_ALWAYS, base + NvRegPacketFilterFlags) + mov dword [edi+NvRegPacketFilterFlags], NVREG_PFF_ALWAYS - ; writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig) - mov dword [edi+NvRegOffloadConfig], NVREG_OFFLOAD_NORMAL + ; writel(NVREG_OFFLOAD_NORMAL, base + NvRegOffloadConfig) + mov dword [edi+NvRegOffloadConfig], NVREG_OFFLOAD_NORMAL - ; writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus) - mov eax, dword [edi+NvRegReceiverStatus] - mov dword [edi+NvRegReceiverStatus], eax + ; writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus) + mov eax, dword [edi+NvRegReceiverStatus] + mov dword [edi+NvRegReceiverStatus], eax - ; Get a random number - ; i = random() - push edi - stdcall sys_clock ; eax = 0x00SSMMHH (current system time) - pop edi + ; Get a random number + ; i = random() + push edi + stdcall sys_clock ; eax = 0x00SSMMHH (current system time) + pop edi - ; writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK), base + NvRegRandomSeed) - and eax, NVREG_RNDSEED_MASK - or eax, NVREG_RNDSEED_FORCE - mov dword [edi+NvRegRandomSeed], eax + ; writel(NVREG_RNDSEED_FORCE | (i & NVREG_RNDSEED_MASK), base + NvRegRandomSeed) + and eax, NVREG_RNDSEED_MASK + or eax, NVREG_RNDSEED_FORCE + mov dword [edi+NvRegRandomSeed], eax - ; writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1) - mov dword [edi+NvRegUnknownSetupReg1], NVREG_UNKSETUP1_VAL - - ; writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2) - mov dword [edi+NvRegUnknownSetupReg2], NVREG_UNKSETUP2_VAL - - ; writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval) - mov dword [edi+NvRegPollingInterval], NVREG_POLL_DEFAULT - - ; writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6) - mov dword [edi+NvRegUnknownSetupReg6], NVREG_UNKSETUP6_VAL + ; writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1) + mov dword [edi+NvRegUnknownSetupReg1], NVREG_UNKSETUP1_VAL + + ; writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2) + mov dword [edi+NvRegUnknownSetupReg2], NVREG_UNKSETUP2_VAL + + ; writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval) + mov dword [edi+NvRegPollingInterval], NVREG_POLL_DEFAULT + + ; writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6) + mov dword [edi+NvRegUnknownSetupReg6], NVREG_UNKSETUP6_VAL - ; writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING, - ; base + NvRegAdapterControl) - mov eax, dword [forcedeth_phyaddr] - shl eax, NVREG_ADAPTCTL_PHYSHIFT - or eax, (NVREG_ADAPTCTL_PHYVALID or NVREG_ADAPTCTL_RUNNING) - mov dword [edi+NvRegAdapterControl], eax - - ; writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed) - mov dword [edi+NvRegMIISpeed], (NVREG_MIISPEED_BIT8 or NVREG_MIIDELAY) + ; writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT) | NVREG_ADAPTCTL_PHYVALID | NVREG_ADAPTCTL_RUNNING, + ; base + NvRegAdapterControl) + mov eax, dword [forcedeth_phyaddr] + shl eax, NVREG_ADAPTCTL_PHYSHIFT + or eax, (NVREG_ADAPTCTL_PHYVALID or NVREG_ADAPTCTL_RUNNING) + mov dword [edi+NvRegAdapterControl], eax + + ; writel(NVREG_MIISPEED_BIT8 | NVREG_MIIDELAY, base + NvRegMIISpeed) + mov dword [edi+NvRegMIISpeed], (NVREG_MIISPEED_BIT8 or NVREG_MIIDELAY) - ; writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4) - mov dword [edi+NvRegUnknownSetupReg4], NVREG_UNKSETUP4_VAL + ; writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4) + mov dword [edi+NvRegUnknownSetupReg4], NVREG_UNKSETUP4_VAL - ; writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags) - mov dword [edi+NvRegWakeUpFlags], NVREG_WAKEUPFLAGS_VAL - - ; i = readl(base + NvRegPowerState) - mov eax, dword [edi+NvRegPowerState] + ; writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags) + mov dword [edi+NvRegWakeUpFlags], NVREG_WAKEUPFLAGS_VAL + + ; i = readl(base + NvRegPowerState) + mov eax, dword [edi+NvRegPowerState] - ; if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) - test eax, NVREG_POWERSTATE_POWEREDUP - jnz @f - ; writel(NVREG_POWERSTATE_POWEREDUP | i, base + NvRegPowerState) - or eax, NVREG_POWERSTATE_POWEREDUP - mov dword [edi+NvRegPowerState], eax + ; if ((i & NVREG_POWERSTATE_POWEREDUP) == 0) + test eax, NVREG_POWERSTATE_POWEREDUP + jnz @f + ; writel(NVREG_POWERSTATE_POWEREDUP | i, base + NvRegPowerState) + or eax, NVREG_POWERSTATE_POWEREDUP + mov dword [edi+NvRegPowerState], eax @@: - ; pci_push(base) - call forcedeth_pci_push + ; pci_push(base) + call forcedeth_pci_push - ; nv_udelay(10) - mov esi, 10 - call forcedeth_nv_udelay + ; nv_udelay(10) + mov esi, 10 + call forcedeth_nv_udelay - ; writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState) - mov eax, dword [edi+NvRegPowerState] - or eax, NVREG_POWERSTATE_VALID - mov dword [edi+NvRegPowerState], eax + ; writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState) + mov eax, dword [edi+NvRegPowerState] + or eax, NVREG_POWERSTATE_VALID + mov dword [edi+NvRegPowerState], eax - ; ??? disable all interrupts ??? - ; writel(0, base + NvRegIrqMask) - mov dword [edi+NvRegIrqMask], 0 + ; ??? disable all interrupts ??? + ; writel(0, base + NvRegIrqMask) + mov dword [edi+NvRegIrqMask], 0 -;;; ; ??? Mask RX interrupts -;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_RX_ALL -;;; ; ??? Mask TX interrupts -;;; ;mov dword [edi+NvRegIrqMask], NVREG_IRQ_TX_ALL -;;; ; ??? Mask OTHER interrupts -;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_OTHER_ALL - - ; pci_push(base) - call forcedeth_pci_push - - ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) - mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 - - ; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus) - mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK - - ; pci_push(base) - call forcedeth_pci_push - - - ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) - mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE - - ; writel(0, base + NvRegMulticastAddrB) - mov dword [edi+NvRegMulticastAddrB], 0 - - ; writel(0, base + NvRegMulticastMaskA) - mov dword [edi+NvRegMulticastMaskA], 0 - - ; writel(0, base + NvRegMulticastMaskB) - mov dword [edi+NvRegMulticastMaskB], 0 - - ; writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags) - mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_ALWAYS or NVREG_PFF_MYADDR) - - ; set_multicast(nic) - call forcedeth_set_multicast - - ; One manual link speed update: Interrupts are enabled, future link - ; speed changes cause interrupts and are handled by nv_link_irq(). - - ; miistat = readl(base + NvRegMIIStatus) - mov eax, dword [edi+NvRegMIIStatus] - - ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); - mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK - - ; dprintf(("startup: got 0x%hX.\n", miistat)); -;;; DEBUGF 1," K : FORCEDETH: startup: got 0x%x\n", eax - - - ; ret = update_linkspeed(nic) - call forcedeth_update_linkspeed - push eax +;;; ; ??? Mask RX interrupts +;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_RX_ALL +;;; ; ??? Mask TX interrupts +;;; ;mov dword [edi+NvRegIrqMask], NVREG_IRQ_TX_ALL +;;; ; ??? Mask OTHER interrupts +;;; mov dword [edi+NvRegIrqMask], NVREG_IRQ_OTHER_ALL - ; start_tx(nic) - call forcedeth_start_tx + ; pci_push(base) + call forcedeth_pci_push - pop eax + ; writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus) + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK2 + + ; writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus) + mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK + + ; pci_push(base) + call forcedeth_pci_push + + + ; writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA) + mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE + + ; writel(0, base + NvRegMulticastAddrB) + mov dword [edi+NvRegMulticastAddrB], 0 + + ; writel(0, base + NvRegMulticastMaskA) + mov dword [edi+NvRegMulticastMaskA], 0 + + ; writel(0, base + NvRegMulticastMaskB) + mov dword [edi+NvRegMulticastMaskB], 0 + + ; writel(NVREG_PFF_ALWAYS | NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags) + mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_ALWAYS or NVREG_PFF_MYADDR) + + ; set_multicast(nic) + call forcedeth_set_multicast + + ; One manual link speed update: Interrupts are enabled, future link + ; speed changes cause interrupts and are handled by nv_link_irq(). + + ; miistat = readl(base + NvRegMIIStatus) + mov eax, dword [edi+NvRegMIIStatus] + + ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK + + ; dprintf(("startup: got 0x%hX.\n", miistat)); +;;; DEBUGF 1," K : FORCEDETH: startup: got 0x%x\n", eax + + + ; ret = update_linkspeed(nic) + call forcedeth_update_linkspeed + push eax + + ; start_tx(nic) + call forcedeth_start_tx + + pop eax ; if (ret) { ; //Start Connection netif_carrier_on(dev); @@ -729,25 +729,25 @@ forcedeth_reset: ; printf("no link during initialization.\n"); ; } - ;*** added by shurf (21.09.2008) - mov dword [forcedeth_nocable], 0 - ;*** + ;*** added by shurf (21.09.2008) + mov dword [forcedeth_nocable], 0 + ;*** - test eax, eax - jnz .return - DEBUGF 1," K : FORCEDETH: no link during initialization.\n" + test eax, eax + jnz .return + DEBUGF 1," K : FORCEDETH: no link during initialization.\n" - ;*** added by shurf (21.09.2008) - mov dword [forcedeth_nocable], 1 - ;*** + ;*** added by shurf (21.09.2008) + mov dword [forcedeth_nocable], 1 + ;*** .return: ; Indicate that we have successfully reset the card mov eax, dword [pci_data] mov dword [eth_status], eax - ret - + ret + ;*************************************************************************** @@ -760,486 +760,490 @@ forcedeth_reset: ;*************************************************************************** forcedeth_probe: -; DEBUGF 1," K : FORCEDETH: 0x%x 0x%x, 0x%x\n", [io_addr]:8,[pci_bus]:2,[pci_dev]:2 +; DEBUGF 1," K : FORCEDETH: 0x%x 0x%x, 0x%x\n", [io_addr]:8,[pci_bus]:2,[pci_dev]:2 - mov dword [forcedeth_needs_mac_reset], 0 + mov dword [forcedeth_needs_mac_reset], 0 ; BEGIN of adjust_pci_device() - ; read word from PCI-device - mov al, 1 ;;;;;;;;;;;;;;2 - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_REG_COMMAND - call pci_read_reg - mov bx, ax ; new command - or bx, PCI_COMMAND_MASTER - or bx, PCI_COMMAND_IO - cmp bx, ax - je @f - ; Enabling PCI-device (make card as bus master) - DEBUGF 1," K : FORCEDETH: Updating PCI command 0x%x->0x%x\n", ax, bx - mov cx, bx - mov al, 1 ;;;;;;;;;;;;2 - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_REG_COMMAND - call pci_write_reg + ; read word from PCI-device + mov al, 1 ;;;;;;;;;;;;;;2 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_REG_COMMAND + call pci_read_reg + mov bx, ax ; new command + or bx, PCI_COMMAND_MASTER + or bx, PCI_COMMAND_IO + cmp bx, ax + je @f + ; Enabling PCI-device (make card as bus master) + DEBUGF 1," K : FORCEDETH: Updating PCI command 0x%x->0x%x\n", ax, bx + mov cx, bx + mov al, 1 ;;;;;;;;;;;;2 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_REG_COMMAND + call pci_write_reg - ; Check latency settings + ; Check latency settings @@: - ; Get current latency settings from Latency timer register (byte) - mov al, 0 ;;;;;;;;;1 - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_LATENCY_TIMER - call pci_read_reg + ; Get current latency settings from Latency timer register (byte) + mov al, 0 ;;;;;;;;;1 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_LATENCY_TIMER + call pci_read_reg - ; see if its at least 32 - cmp al, 32 - jge @f - ; set latency to 32 + ; see if its at least 32 + cmp al, 32 + jge @f + ; set latency to 32 DEBUGF 1, "K : FORCEDETH: PCI latency timer (CFLT) is unreasonably low at %d.\n", al DEBUGF 1, "K : FORCEDETH: Setting to 32 clocks.\n" - mov cl, 32 - mov al, 0 ;;;;;;;1 - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_LATENCY_TIMER - call pci_write_reg + mov cl, 32 + mov al, 0 ;;;;;;;1 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_LATENCY_TIMER + call pci_write_reg ; END of adjust_pci_device() @@: ; BEGIN of pci_bar_start (addr = pci_bar_start(pci, PCI_BASE_ADDRESS_0)) - mov al, 2 ; dword - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_BASE_ADDRESS_0 - call pci_read_reg - test eax, PCI_BASE_ADDRESS_SPACE_IO - jz @f - and eax, PCI_BASE_ADDRESS_IO_MASK - jmp .next -@@: push eax - and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK - cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64 - jne .not64 - mov al, 2 ; dword - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_BASE_ADDRESS_0 + 4 - call pci_read_reg - or eax, eax - jz .not64 - DEBUGF 1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n" - or eax, -1 - jmp .next -.not64: - pop eax - and eax, PCI_BASE_ADDRESS_MEM_MASK + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + call pci_read_reg + test eax, PCI_BASE_ADDRESS_SPACE_IO + jz @f + and eax, PCI_BASE_ADDRESS_IO_MASK + jmp .next +@@: + push eax + and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK + cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64 + jne .not64 + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + 4 + call pci_read_reg + or eax, eax + jz .not64 + DEBUGF 1,"K : FORCEDETH: pci_bar_start: Unhandled 64bit BAR\n" + or eax, -1 + jmp .next +.not64: + pop eax + and eax, PCI_BASE_ADDRESS_MEM_MASK .next: ; END of pci_bar_start ; addr = eax - mov dword [forcedeth_mmio_addr], eax + mov dword [forcedeth_mmio_addr], eax - + ; BEGIN of pci_bar_size (sz = pci_bar_size(pci, PCI_BASE_ADDRESS_0)) - ; Save original bar - mov al, 2 ; dword - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_BASE_ADDRESS_0 - call pci_read_reg - mov dword [forcedeth_tmp_start], eax - ; Compute which bits can be set - ; (ecx - value to write) - mov al, 2 ; dword - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_BASE_ADDRESS_0 - mov ecx, (not 0) - call pci_write_reg - mov al, 2 ; dword - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_BASE_ADDRESS_0 - call pci_read_reg - push eax - ; Restore the original size - mov al, 2 ; dword - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_BASE_ADDRESS_0 - mov ecx, dword [forcedeth_tmp_start] - call pci_write_reg - ; Find the significant bits - pop eax - test dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO - jz @f - and eax, PCI_BASE_ADDRESS_IO_MASK - jmp .next2 -@@: and eax, PCI_BASE_ADDRESS_MEM_MASK + ; Save original bar + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + call pci_read_reg + mov dword [forcedeth_tmp_start], eax + ; Compute which bits can be set + ; (ecx - value to write) + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + mov ecx, (not 0) + call pci_write_reg + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + call pci_read_reg + push eax + ; Restore the original size + mov al, 2 ; dword + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_BASE_ADDRESS_0 + mov ecx, dword [forcedeth_tmp_start] + call pci_write_reg + ; Find the significant bits + pop eax + test dword [forcedeth_tmp_start], PCI_BASE_ADDRESS_SPACE_IO + jz @f + and eax, PCI_BASE_ADDRESS_IO_MASK + jmp .next2 +@@: + and eax, PCI_BASE_ADDRESS_MEM_MASK .next2: - ; Find the lowest bit set - mov ecx, eax - sub eax, 1 - not eax - and ecx, eax + ; Find the lowest bit set + mov ecx, eax + sub eax, 1 + not eax + and ecx, eax ; END of pci_bar_start - mov dword [forcedeth_mmio_size], ecx + mov dword [forcedeth_mmio_size], ecx - DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8 + DEBUGF 1," K : FORCEDETH: mmio_addr= 0x%x [mmio_size= 0x%x]\n", [forcedeth_mmio_addr]:8, [forcedeth_mmio_size]:8 - ; Get Vendor and Device ID - mov al, 2 - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_VENDOR_ID - call pci_read_reg - mov word [forcedeth_vendor_id], ax - shr eax, 16 - mov word [forcedeth_device_id], ax + ; Get Vendor and Device ID + mov al, 2 + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_VENDOR_ID + call pci_read_reg + mov word [forcedeth_vendor_id], ax + shr eax, 16 + mov word [forcedeth_device_id], ax - DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 + DEBUGF 1," K : FORCEDETH: vendor_id= 0x%x device_id= 0x%x\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 - ; handle different descriptor versions - mov eax, dword [forcedeth_device_id] - cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_1 - je .ver1 - cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_2 - je .ver1 - cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_3 - je .ver1 - mov dword [forcedeth_desc_ver], DESC_VER_2 - jmp @f -.ver1: mov dword [forcedeth_desc_ver], DESC_VER_1 + ; handle different descriptor versions + mov eax, dword [forcedeth_device_id] + cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_1 + je .ver1 + cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_2 + je .ver1 + cmp eax, PCI_DEVICE_ID_NVIDIA_NVENET_3 + je .ver1 + mov dword [forcedeth_desc_ver], DESC_VER_2 + jmp @f +.ver1: + mov dword [forcedeth_desc_ver], DESC_VER_1 @@: - ; read the mac address - ; map memory - stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE) - test eax, eax - jz .fail + ; read the mac address + ; map memory + stdcall map_io_mem, [forcedeth_mmio_addr], [forcedeth_mmio_size], (PG_SW+PG_NOCACHE) + test eax, eax + jz .fail - mov dword [forcedeth_mapio_addr], eax - mov edi, eax - mov eax, dword [edi+NvRegMacAddrA] - mov dword [forcedeth_orig_mac0], eax - mov edx, dword [edi+NvRegMacAddrB] - mov dword [forcedeth_orig_mac1], edx + mov dword [forcedeth_mapio_addr], eax + mov edi, eax + mov eax, dword [edi+NvRegMacAddrA] + mov dword [forcedeth_orig_mac0], eax + mov edx, dword [edi+NvRegMacAddrB] + mov dword [forcedeth_orig_mac1], edx - ; save MAC-address to global variable node_addr - mov dword [node_addr], eax - mov word [node_addr+4], dx + ; save MAC-address to global variable node_addr + mov dword [node_addr], eax + mov word [node_addr+4], dx - ; reverse if desired - cmp word [forcedeth_device_id], 0x03E5 - jae .no_reverse_mac - mov al, byte [node_addr] - xchg al, byte [node_addr+5] - mov byte [node_addr], al - mov al, byte [node_addr+1] - xchg al, byte [node_addr+4] - mov byte [node_addr+4], al - mov al, byte [node_addr+2] - xchg al, byte [node_addr+3] - mov byte [node_addr+3], al + ; reverse if desired + cmp word [forcedeth_device_id], 0x03E5 + jae .no_reverse_mac + mov al, byte [node_addr] + xchg al, byte [node_addr+5] + mov byte [node_addr], al + mov al, byte [node_addr+1] + xchg al, byte [node_addr+4] + mov byte [node_addr+4], al + mov al, byte [node_addr+2] + xchg al, byte [node_addr+3] + mov byte [node_addr+3], al .no_reverse_mac: -; DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8 -; DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8 - DEBUGF 1," K : FORCEDETH: MAC = %x-%x-%x-%x-%x-%x\n", [node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2, +; DEBUGF 1," K : FORCEDETH: orig_mac0= 0x%x\n", [forcedeth_orig_mac0]:8 +; DEBUGF 1," K : FORCEDETH: orig_mac1= 0x%x\n", [forcedeth_orig_mac1]:8 + DEBUGF 1," K : FORCEDETH: MAC = %x-%x-%x-%x-%x-%x\n", [node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2, - ; disable WOL - mov edi, dword [forcedeth_mapio_addr] - mov dword [edi+NvRegWakeUpFlags], 0 - mov dword [forcedeth_wolenabled], 0 - - mov dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID) - cmp dword [forcedeth_desc_ver], DESC_VER_1 - jne @f - mov dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID) -@@: + ; disable WOL + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegWakeUpFlags], 0 + mov dword [forcedeth_wolenabled], 0 + + mov dword [forcedeth_txflags], (NV_TX2_LASTPACKET or NV_TX2_VALID) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + mov dword [forcedeth_txflags], (NV_TX_LASTPACKET or NV_TX_VALID) +@@: ; BEGIN of switch (pci->dev_id) - cmp word [forcedeth_device_id], 0x01C3 - jne .next_0x0066 - ; nforce - mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) - jmp .end_switch + cmp word [forcedeth_device_id], 0x01C3 + jne .next_0x0066 + ; nforce + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + jmp .end_switch .next_0x0066: - cmp word [forcedeth_device_id], 0x0066 - je @f - cmp word [forcedeth_device_id], 0x00D6 - je @f - jmp .next_0x0086 -@@: - mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) - cmp dword [forcedeth_desc_ver], DESC_VER_1 - jne @f - or dword [forcedeth_txflags], NV_TX_LASTPACKET1 - jmp .end_switch -@@: or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 - jmp .end_switch + cmp word [forcedeth_device_id], 0x0066 + je @f + cmp word [forcedeth_device_id], 0x00D6 + je @f + jmp .next_0x0086 +@@: + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + or dword [forcedeth_txflags], NV_TX_LASTPACKET1 + jmp .end_switch +@@: + or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 + jmp .end_switch .next_0x0086: - cmp word [forcedeth_device_id], 0x0086 - je @f - cmp word [forcedeth_device_id], 0x008c - je @f - cmp word [forcedeth_device_id], 0x00e6 - je @f - cmp word [forcedeth_device_id], 0x00df - je @f - cmp word [forcedeth_device_id], 0x0056 - je @f - cmp word [forcedeth_device_id], 0x0057 - je @f - cmp word [forcedeth_device_id], 0x0037 - je @f - cmp word [forcedeth_device_id], 0x0038 - je @f - jmp .next_0x0268 -@@: - ; np->irqmask = NVREG_IRQMASK_WANTED_2; - ; np->irqmask |= NVREG_IRQ_TIMER; - mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + cmp word [forcedeth_device_id], 0x0086 + je @f + cmp word [forcedeth_device_id], 0x008c + je @f + cmp word [forcedeth_device_id], 0x00e6 + je @f + cmp word [forcedeth_device_id], 0x00df + je @f + cmp word [forcedeth_device_id], 0x0056 + je @f + cmp word [forcedeth_device_id], 0x0057 + je @f + cmp word [forcedeth_device_id], 0x0037 + je @f + cmp word [forcedeth_device_id], 0x0038 + je @f + jmp .next_0x0268 +@@: + ; np->irqmask = NVREG_IRQMASK_WANTED_2; + ; np->irqmask |= NVREG_IRQ_TIMER; + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) - ; if (np->desc_ver == DESC_VER_1) - cmp dword [forcedeth_desc_ver], DESC_VER_1 - jne @f - ; np->tx_flags |= NV_TX_LASTPACKET1; - or dword [forcedeth_txflags], NV_TX_LASTPACKET1 - jmp .end_switch - ; else + ; if (np->desc_ver == DESC_VER_1) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + ; np->tx_flags |= NV_TX_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX_LASTPACKET1 + jmp .end_switch + ; else @@: - ; np->tx_flags |= NV_TX2_LASTPACKET1; - or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 + ; np->tx_flags |= NV_TX2_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 - ; break; - jmp .end_switch + ; break; + jmp .end_switch .next_0x0268: -; cmp word [forcedeth_device_id], 0x0268 -; je @f -; cmp word [forcedeth_device_id], 0x0269 -; je @f -; cmp word [forcedeth_device_id], 0x0372 -; je @f -; cmp word [forcedeth_device_id], 0x0373 -; je @f -; jmp .default_switch +; cmp word [forcedeth_device_id], 0x0268 +; je @f +; cmp word [forcedeth_device_id], 0x0269 +; je @f +; cmp word [forcedeth_device_id], 0x0372 +; je @f +; cmp word [forcedeth_device_id], 0x0373 +; je @f +; jmp .default_switch ;@@: - cmp word [forcedeth_device_id], 0x0268 - jb .default_switch - ; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id); - mov al, 0 ; byte - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, PCI_REVISION_ID - call pci_read_reg - mov ecx, eax ; cl = revision_id + cmp word [forcedeth_device_id], 0x0268 + jb .default_switch + ; pci_read_config_byte(pci, PCI_REVISION_ID, &revision_id); + mov al, 0 ; byte + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, PCI_REVISION_ID + call pci_read_reg + mov ecx, eax ; cl = revision_id - ; take phy and nic out of low power mode - ; powerstate = readl(base + NvRegPowerState2); - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [edi+NvRegPowerState2] ; eax = powerstate - - ; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; - and eax, not NVREG_POWERSTATE2_POWERUP_MASK - - ; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3) - cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12 - je @f - cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13 - je @f - jmp .end_if + ; take phy and nic out of low power mode + ; powerstate = readl(base + NvRegPowerState2); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegPowerState2] ; eax = powerstate + + ; powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; + and eax, not NVREG_POWERSTATE2_POWERUP_MASK + + ; if ((pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_12||pci->dev_id==PCI_DEVICE_ID_NVIDIA_NVENET_13)&&revision_id>=0xA3) + cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_12 + je @f + cmp dword [forcedeth_device_id], PCI_DEVICE_ID_NVIDIA_NVENET_13 + je @f + jmp .end_if @@: - cmp cl, 0xA3 - jl .end_if - ; powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; - or eax, NVREG_POWERSTATE2_POWERUP_REV_A3 + cmp cl, 0xA3 + jl .end_if + ; powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; + or eax, NVREG_POWERSTATE2_POWERUP_REV_A3 .end_if: - ; writel(powerstate, base + NvRegPowerState2); - mov dword [edi+NvRegPowerState2], eax + ; writel(powerstate, base + NvRegPowerState2); + mov dword [edi+NvRegPowerState2], eax - ; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ - ; np->irqmask = NVREG_IRQMASK_WANTED_2; - ; np->irqmask |= NVREG_IRQ_TIMER; - mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) - - ; needs_mac_reset = 1; - mov dword [forcedeth_needs_mac_reset], 1 - - ; if (np->desc_ver == DESC_VER_1) - cmp dword [forcedeth_desc_ver], DESC_VER_1 - jne @f - ; np->tx_flags |= NV_TX_LASTPACKET1; - or dword [forcedeth_txflags], NV_TX_LASTPACKET1 - jmp .end_if2 + ; //DEV_NEED_LASTPACKET1|DEV_IRQMASK_2|DEV_NEED_TIMERIRQ + ; np->irqmask = NVREG_IRQMASK_WANTED_2; + ; np->irqmask |= NVREG_IRQ_TIMER; + mov dword [forcedeth_irqmask], 0 ;;;;;;;;;;;;;;;;(NVREG_IRQMASK_WANTED_2 or NVREG_IRQ_TIMER) + + ; needs_mac_reset = 1; + mov dword [forcedeth_needs_mac_reset], 1 + + ; if (np->desc_ver == DESC_VER_1) + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + ; np->tx_flags |= NV_TX_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX_LASTPACKET1 + jmp .end_if2 @@: - ; else - ; np->tx_flags |= NV_TX2_LASTPACKET1; - or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 + ; else + ; np->tx_flags |= NV_TX2_LASTPACKET1; + or dword [forcedeth_txflags], NV_TX2_LASTPACKET1 .end_if2: - ; break; - jmp .end_switch + ; break; + jmp .end_switch .default_switch: - DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n" - DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n" + DEBUGF 1," K : FORCEDETH: Your card was undefined in this driver.\n" + DEBUGF 1," K : FORCEDETH: Review driver_data in Kolibri driver and send a patch\n" .end_switch: ; END of switch (pci->dev_id) - ; Find a suitable phy - mov dword [forcedeth_tmp_i], 1 + ; Find a suitable phy + mov dword [forcedeth_tmp_i], 1 .for_loop: - ; for (i = 1; i <= 32; i++) - ; phyaddr = i & 0x1f - mov ebx, dword [forcedeth_tmp_i] - and ebx, 0x1f + ; for (i = 1; i <= 32; i++) + ; phyaddr = i & 0x1f + mov ebx, dword [forcedeth_tmp_i] + and ebx, 0x1f - ; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ) + ; id1 = mii_rw(phyaddr, MII_PHYSID1, MII_READ) ;EBX - addr, EAX - miireg, ECX - value - mov eax, MII_PHYSID1 - mov ecx, MII_READ - call forcedeth_mii_rw ; id1 = eax + mov eax, MII_PHYSID1 + mov ecx, MII_READ + call forcedeth_mii_rw ; id1 = eax - ; if (id1 < 0 || id1 == 0xffff) - cmp eax, 0xffffffff - je .continue_for - test eax, 0x80000000 - jnz .continue_for - mov dword [forcedeth_tmp_id1], eax + ; if (id1 < 0 || id1 == 0xffff) + cmp eax, 0xffffffff + je .continue_for + test eax, 0x80000000 + jnz .continue_for + mov dword [forcedeth_tmp_id1], eax - ; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ) - mov eax, MII_PHYSID2 - mov ecx, MII_READ - call forcedeth_mii_rw ; id2 = eax + ; id2 = mii_rw(nic, phyaddr, MII_PHYSID2, MII_READ) + mov eax, MII_PHYSID2 + mov ecx, MII_READ + call forcedeth_mii_rw ; id2 = eax - ; if (id2 < 0 || id2 == 0xffff) - cmp eax, 0xffffffff - je .continue_for - test eax, 0x80000000 - jnz .continue_for - mov dword [forcedeth_tmp_id2], eax + ; if (id2 < 0 || id2 == 0xffff) + cmp eax, 0xffffffff + je .continue_for + test eax, 0x80000000 + jnz .continue_for + mov dword [forcedeth_tmp_id2], eax - jmp .break_for + jmp .break_for .continue_for: - inc dword [forcedeth_tmp_i] - cmp dword [forcedeth_tmp_i], 32 - jle .for_loop - jmp .end_for + inc dword [forcedeth_tmp_i] + cmp dword [forcedeth_tmp_i], 32 + jle .for_loop + jmp .end_for .break_for: -;;;; DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8 +;;;; DEBUGF 1," K : FORCEDETH: id1=0x%x id2=0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8 - ; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT - mov eax, dword [forcedeth_tmp_id1] - and eax, PHYID1_OUI_MASK - shl eax, PHYID1_OUI_SHFT - mov dword [forcedeth_tmp_id1], eax + ; id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT + mov eax, dword [forcedeth_tmp_id1] + and eax, PHYID1_OUI_MASK + shl eax, PHYID1_OUI_SHFT + mov dword [forcedeth_tmp_id1], eax - ; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT - mov eax, dword [forcedeth_tmp_id2] - and eax, PHYID2_OUI_MASK - shr eax, PHYID2_OUI_SHFT - mov dword [forcedeth_tmp_id2], eax + ; id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT + mov eax, dword [forcedeth_tmp_id2] + and eax, PHYID2_OUI_MASK + shr eax, PHYID2_OUI_SHFT + mov dword [forcedeth_tmp_id2], eax - DEBUGF 1," K : FORCEDETH: Found PHY 0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx + DEBUGF 1," K : FORCEDETH: Found PHY 0x%x:0x%x at address 0x%x\n", [forcedeth_tmp_id1]:8, [forcedeth_tmp_id2]:8, ebx - ; np->phyaddr = phyaddr; - mov dword [forcedeth_phyaddr], ebx + ; np->phyaddr = phyaddr; + mov dword [forcedeth_phyaddr], ebx - ; np->phy_oui = id1 | id2; - mov eax, dword [forcedeth_tmp_id1] - or eax, dword [forcedeth_tmp_id2] - mov dword [forcedeth_phy_oui], eax + ; np->phy_oui = id1 | id2; + mov eax, dword [forcedeth_tmp_id1] + or eax, dword [forcedeth_tmp_id2] + mov dword [forcedeth_phy_oui], eax .end_for: - ; if (i == 33) - cmp dword [forcedeth_tmp_i], 33 - jne @f - ; PHY in isolate mode? No phy attached and user wants to - ; test loopback? Very odd, but can be correct. - - DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n" + ; if (i == 33) + cmp dword [forcedeth_tmp_i], 33 + jne @f + ; PHY in isolate mode? No phy attached and user wants to + ; test loopback? Very odd, but can be correct. + + DEBUGF 1," K : FORCEDETH: Could not find a valid PHY.\n" - jmp .next3 + jmp .next3 @@: - ; if (i != 33) - ; reset it - call forcedeth_phy_init + ; if (i != 33) + ; reset it + call forcedeth_phy_init .next3: ; dprintf(("%s: forcedeth.c: subsystem: %hX:%hX bound to %s\n", ; pci->name, pci->vendor, pci->dev_id, pci->name)); - DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 + DEBUGF 1," K : FORCEDETH: subsystem: 0x%x:0x%x bound to forcedeth\n", [forcedeth_vendor_id]:4, [forcedeth_device_id]:4 ; if(needs_mac_reset) mac_reset(nic); - cmp dword [forcedeth_needs_mac_reset], 0 - je @f - call forcedeth_mac_reset + cmp dword [forcedeth_needs_mac_reset], 0 + je @f + call forcedeth_mac_reset @@: - - ; if(!forcedeth_reset(nic)) return 0; // no valid link - call forcedeth_reset - test eax, eax - jnz @f - mov eax, 0 - jmp .return + + ; if(!forcedeth_reset(nic)) return 0; // no valid link + call forcedeth_reset + test eax, eax + jnz @f + mov eax, 0 + jmp .return @@: - ; point to NIC specific routines - ; dev->disable = forcedeth_disable; - ; nic->poll = forcedeth_poll; - ; nic->transmit = forcedeth_transmit; - ; nic->irq = forcedeth_irq; - ;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0 + ; point to NIC specific routines + ; dev->disable = forcedeth_disable; + ; nic->poll = forcedeth_poll; + ; nic->transmit = forcedeth_transmit; + ; nic->irq = forcedeth_irq; + ;;;;;;;;;stdcall attach_int_handler, 11, forcedeth_int_handler, 0 - ; return 1 - mov eax, 1 - jmp .return + ; return 1 + mov eax, 1 + jmp .return .fail: - mov eax, 0 + mov eax, 0 .return: - ret + ret uglobal -forcedeth_tmp_start dd ? -forcedeth_tmp_reg dd ? -forcedeth_tmp_i dd ? -forcedeth_tmp_id1 dd ? -forcedeth_tmp_id2 dd ? -forcedeth_tmp_phyinterface dd ? -forcedeth_tmp_newls dd ? -forcedeth_tmp_newdup dd ? -forcedeth_tmp_retval dd ? -forcedeth_tmp_control_1000 dd ? -forcedeth_tmp_lpa dd ? -forcedeth_tmp_adv dd ? -forcedeth_tmp_len dd ? -forcedeth_tmp_valid dd ? -forcedeth_tmp_nr dd ? -forcedeth_tmp_ptxb dd ? +forcedeth_tmp_start dd ? +forcedeth_tmp_reg dd ? +forcedeth_tmp_i dd ? +forcedeth_tmp_id1 dd ? +forcedeth_tmp_id2 dd ? +forcedeth_tmp_phyinterface dd ? +forcedeth_tmp_newls dd ? +forcedeth_tmp_newdup dd ? +forcedeth_tmp_retval dd ? +forcedeth_tmp_control_1000 dd ? +forcedeth_tmp_lpa dd ? +forcedeth_tmp_adv dd ? +forcedeth_tmp_len dd ? +forcedeth_tmp_valid dd ? +forcedeth_tmp_nr dd ? +forcedeth_tmp_ptxb dd ? endg ;*************************************************************************** @@ -1253,146 +1257,146 @@ endg ;*************************************************************************** forcedeth_poll: - mov word [eth_rx_data_len], 0 + mov word [eth_rx_data_len], 0 - ; ???????????????????????????? - ; ??? Clear events? ??? - mov edi, dword [forcedeth_mapio_addr] - mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK - ; ???????????????????????????? + ; ???????????????????????????? + ; ??? Clear events? ??? + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegIrqStatus], NVREG_IRQSTAT_MASK + ; ???????????????????????????? .top: - ; i = np->cur_rx % RX_RING - mov eax, dword [forcedeth_cur_rx] - and eax, (RX_RING-1) - mov dword [forcedeth_tmp_i], eax + ; i = np->cur_rx % RX_RING + mov eax, dword [forcedeth_cur_rx] + and eax, (RX_RING-1) + mov dword [forcedeth_tmp_i], eax - ; Flags = le32_to_cpu(rx_ring[i].FlagLen) - ; Flags = rx_ring[i].FlagLen - mov cl, sizeof.forcedeth_RxDesc - mul cl - add eax, forcedeth_rx_ring - mov ebx, eax - mov eax, [ebx + forcedeth_RxDesc.FlagLen] + ; Flags = le32_to_cpu(rx_ring[i].FlagLen) + ; Flags = rx_ring[i].FlagLen + mov cl, sizeof.forcedeth_RxDesc + mul cl + add eax, forcedeth_rx_ring + mov ebx, eax + mov eax, [ebx + forcedeth_RxDesc.FlagLen] - ; if (Flags & NV_RX_AVAIL) - test eax, NV_RX_AVAIL - ; return 0; /* still owned by hardware, */ - ; still owned by hardware - jnz .return0 + ; if (Flags & NV_RX_AVAIL) + test eax, NV_RX_AVAIL + ; return 0; /* still owned by hardware, */ + ; still owned by hardware + jnz .return0 -;;;;; DEBUGF 1,"poll: FlagLen = %x\n", eax +;;;;; DEBUGF 1,"poll: FlagLen = %x\n", eax - ; if (np->desc_ver == DESC_VER_1) { - cmp dword [forcedeth_desc_ver], DESC_VER_1 - jne @f - ; if (!(Flags & NV_RX_DESCRIPTORVALID)) - test eax, NV_RX_DESCRIPTORVALID - ; return 0; - jz .return0 - jmp .next - ; } else { + ; if (np->desc_ver == DESC_VER_1) { + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + ; if (!(Flags & NV_RX_DESCRIPTORVALID)) + test eax, NV_RX_DESCRIPTORVALID + ; return 0; + jz .return0 + jmp .next + ; } else { @@: - ; if (!(Flags & NV_RX2_DESCRIPTORVALID)) - test eax, NV_RX2_DESCRIPTORVALID - ; return 0; - jz .return0 - ; } - + ; if (!(Flags & NV_RX2_DESCRIPTORVALID)) + test eax, NV_RX2_DESCRIPTORVALID + ; return 0; + jz .return0 + ; } + .next: - ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) - ; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2); - ; eax = FlagLen - cmp dword [forcedeth_desc_ver], DESC_VER_1 - jne @f - and eax, LEN_MASK_V1 - jmp .next2 + ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) + ; len = rx_ring[i].FlagLen & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2); + ; eax = FlagLen + cmp dword [forcedeth_desc_ver], DESC_VER_1 + jne @f + and eax, LEN_MASK_V1 + jmp .next2 @@: - and eax, LEN_MASK_V2 + and eax, LEN_MASK_V2 .next2: - ; mov dword [forcedeth_tmp_len], eax + ; mov dword [forcedeth_tmp_len], eax - ; valid = 1 - mov dword [forcedeth_tmp_valid], 1 - - ; got a valid packet - forward it to the network core - ; nic->packetlen = len; - mov dword [forcedeth_packetlen], eax - ; - mov word [eth_rx_data_len], ax -;;;;;;;;; DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen] + ; valid = 1 + mov dword [forcedeth_tmp_valid], 1 + + ; got a valid packet - forward it to the network core + ; nic->packetlen = len; + mov dword [forcedeth_packetlen], eax + ; + mov word [eth_rx_data_len], ax +;;;;;;;;; DEBUGF 1,"poll: packet len = 0x%x\n", [forcedeth_packetlen] - ; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen); - ; Copy packet to system buffer (Ether_buffer) - ;???? ecx = (len-4) - mov ecx, eax - push ecx - shr ecx, 2 + ; memcpy(nic->packet, rxb + (i * RX_NIC_BUFSIZE), nic->packetlen); + ; Copy packet to system buffer (Ether_buffer) + ;???? ecx = (len-4) + mov ecx, eax + push ecx + shr ecx, 2 - ; rxb + (i * RX_NIC_BUFSIZE) - mov eax, dword [forcedeth_tmp_i] - mov bx, RX_NIC_BUFSIZE - mul bx - add eax, forcedeth_rxb + ; rxb + (i * RX_NIC_BUFSIZE) + mov eax, dword [forcedeth_tmp_i] + mov bx, RX_NIC_BUFSIZE + mul bx + add eax, forcedeth_rxb - mov esi, eax + mov esi, eax mov edi, Ether_buffer - cld ; set to increment - rep movsd ; mov dword from [esi++] to [edi++] - pop ecx - and ecx, 3 ; copy rest 1-3 bytes - rep movsb + cld ; set to increment + rep movsd ; mov dword from [esi++] to [edi++] + pop ecx + and ecx, 3 ; copy rest 1-3 bytes + rep movsb - ; wmb(); - ; ??? + ; wmb(); + ; ??? - ; np->cur_rx++; - inc dword [forcedeth_cur_rx] + ; np->cur_rx++; + inc dword [forcedeth_cur_rx] - ; if (!valid) - cmp dword [forcedeth_tmp_valid], 0 - jne @f - ; goto top; - jmp .top + ; if (!valid) + cmp dword [forcedeth_tmp_valid], 0 + jne @f + ; goto top; + jmp .top @@: - ; alloc_rx(nic); - call forcedeth_alloc_rx + ; alloc_rx(nic); + call forcedeth_alloc_rx - ; return 1; - jmp .return1 + ; return 1; + jmp .return1 -;;;;; DEBUGF 1,"K : FORCEDETH: poll: ...\n" +;;;;; DEBUGF 1,"K : FORCEDETH: poll: ...\n" .return0: - mov eax, 0 - jmp .return + mov eax, 0 + jmp .return .return1: - mov eax, 1 + mov eax, 1 .return: - ;;push eax + ;;push eax - ; ???????????????????????????????????????????????? - ; ????? clear interrupt mask/status - ; read IRQ status - ;;mov edi, dword [forcedeth_mapio_addr] - ;;mov eax, dword [edi+NvRegIrqStatus] + ; ???????????????????????????????????????????????? + ; ????? clear interrupt mask/status + ; read IRQ status + ;;mov edi, dword [forcedeth_mapio_addr] + ;;mov eax, dword [edi+NvRegIrqStatus] - ; clear events - ;;and eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER) + ; clear events + ;;and eax, not (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF or NVREG_IRQ_LINK or NVREG_IRQ_TIMER) - ; write IRQ status - ;;mov dword [edi+NvRegIrqStatus], eax - ; ???????????????????????????????????????????????? + ; write IRQ status + ;;mov dword [edi+NvRegIrqStatus], eax + ; ???????????????????????????????????????????????? - ;;pop eax - ret + ;;pop eax + ret ;*************************************************************************** @@ -1409,210 +1413,210 @@ forcedeth_poll: ;*************************************************************************** forcedeth_transmit: - ; send the packet to destination + ; send the packet to destination ;pusha -;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx -;DEBUGF 1,"K : FORCEDETH: transmit: packet len = 0x%x\n", ecx -;mov eax, dword [edi] -;DEBUGF 1,"K : FORCEDETH: transmit: dest adr = 0x%x\n", eax -;mov eax, dword [edi+4] -;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2 = 0x%x\n", eax -;mov eax, dword [node_addr] -;DEBUGF 1,"K : FORCEDETH: transmit: src adr = 0x%x\n", eax -;mov eax, dword [node_addr+4] -;DEBUGF 1,"K : FORCEDETH: transmit: src adr2 = 0x%x\n", eax +;DEBUGF 1,"K : FORCEDETH: transmit: packet type = 0x%x\n", ebx +;DEBUGF 1,"K : FORCEDETH: transmit: packet len = 0x%x\n", ecx +;mov eax, dword [edi] +;DEBUGF 1,"K : FORCEDETH: transmit: dest adr = 0x%x\n", eax +;mov eax, dword [edi+4] +;DEBUGF 1,"K : FORCEDETH: transmit: dest adr2 = 0x%x\n", eax +;mov eax, dword [node_addr] +;DEBUGF 1,"K : FORCEDETH: transmit: src adr = 0x%x\n", eax +;mov eax, dword [node_addr+4] +;DEBUGF 1,"K : FORCEDETH: transmit: src adr2 = 0x%x\n", eax ;popa - ; int nr = np->next_tx % TX_RING - mov eax, dword [forcedeth_next_tx] - and eax, (TX_RING-1) - mov dword [forcedeth_tmp_nr], eax - - ; point to the current txb incase multiple tx_rings are used - ; ptxb = txb + (nr * RX_NIC_BUFSIZE) - push ecx - mov cx, RX_NIC_BUFSIZE - mul cx ; AX*CX, result to DX:AX - add eax, forcedeth_txb - mov dword [forcedeth_tmp_ptxb], eax - push esi - mov esi, edi ; dst MAC - mov edi, eax ; packet buffer - cld ; set to increment - - ; copy the packet to ring buffer - ; memcpy(ptxb, d, ETH_ALEN); /* dst */ - movsd - movsw - - ; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ - mov esi, node_addr - movsd - movsw + ; int nr = np->next_tx % TX_RING + mov eax, dword [forcedeth_next_tx] + and eax, (TX_RING-1) + mov dword [forcedeth_tmp_nr], eax + + ; point to the current txb incase multiple tx_rings are used + ; ptxb = txb + (nr * RX_NIC_BUFSIZE) + push ecx + mov cx, RX_NIC_BUFSIZE + mul cx ; AX*CX, result to DX:AX + add eax, forcedeth_txb + mov dword [forcedeth_tmp_ptxb], eax + push esi + mov esi, edi ; dst MAC + mov edi, eax ; packet buffer + cld ; set to increment + + ; copy the packet to ring buffer + ; memcpy(ptxb, d, ETH_ALEN); /* dst */ + movsd + movsw + + ; memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */ + mov esi, node_addr + movsd + movsw - ; nstype = htons((u16) t); /* type */ - ; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* type */ - mov word [edi], bx - add edi, 2 - - ; memcpy(ptxb + ETH_HLEN, p, s); - pop esi - pop ecx - push ecx - shr ecx, 2 ; count in dwords - rep movsd ; copy dwords from [esi+=4] to [edi+=4] - pop ecx - push ecx - and ecx, 3 ; copy rest 1-3 bytes - rep movsb ; copy bytess from [esi++] to [edi++] + ; nstype = htons((u16) t); /* type */ + ; memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2); /* type */ + mov word [edi], bx + add edi, 2 + + ; memcpy(ptxb + ETH_HLEN, p, s); + pop esi + pop ecx + push ecx + shr ecx, 2 ; count in dwords + rep movsd ; copy dwords from [esi+=4] to [edi+=4] + pop ecx + push ecx + and ecx, 3 ; copy rest 1-3 bytes + rep movsb ; copy bytess from [esi++] to [edi++] - ; s += ETH_HLEN; - ; while (s < ETH_ZLEN) /* pad to min length */ - ; ptxb[s++] = '\0'; - ; pad to min length - pop ecx - add ecx, ETH_HLEN - push ecx ; header length + data length - cmp ecx, ETH_ZLEN - jge @f - mov eax, ETH_ZLEN - sub eax, ecx - xchg eax, ecx - mov al, 0 - rep stosb ; copy byte from al to [edi++] + ; s += ETH_HLEN; + ; while (s < ETH_ZLEN) /* pad to min length */ + ; ptxb[s++] = '\0'; + ; pad to min length + pop ecx + add ecx, ETH_HLEN + push ecx ; header length + data length + cmp ecx, ETH_ZLEN + jge @f + mov eax, ETH_ZLEN + sub eax, ecx + xchg eax, ecx + mov al, 0 + rep stosb ; copy byte from al to [edi++] @@: - ; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb); - mov eax, dword [forcedeth_tmp_nr] - mov cl, sizeof.forcedeth_TxDesc - mul cl - add eax, forcedeth_tx_ring - mov ebx, eax - mov eax, dword [forcedeth_tmp_ptxb] - sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov [ebx + forcedeth_TxDesc.PacketBuffer], eax + ; tx_ring[nr].PacketBuffer = (u32) virt_to_le32desc(ptxb); + mov eax, dword [forcedeth_tmp_nr] + mov cl, sizeof.forcedeth_TxDesc + mul cl + add eax, forcedeth_tx_ring + mov ebx, eax + mov eax, dword [forcedeth_tmp_ptxb] + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov [ebx + forcedeth_TxDesc.PacketBuffer], eax -;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax -;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8 +;DEBUGF 1,"K : FORCEDETH: transmit: PacketBuffer = 0x%x\n", eax +;DEBUGF 1,"K : FORCEDETH: transmit: txflags = 0x%x\n", [forcedeth_txflags]:8 - ; wmb(); - ; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags); - pop eax ; header length + data length - mov ecx, dword [forcedeth_txflags] - or eax, ecx - mov [ebx + forcedeth_TxDesc.FlagLen], eax + ; wmb(); + ; tx_ring[nr].FlagLen = cpu_to_le32((s - 1) | np->tx_flags); + pop eax ; header length + data length + mov ecx, dword [forcedeth_txflags] + or eax, ecx + mov [ebx + forcedeth_TxDesc.FlagLen], eax - ; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl); - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [forcedeth_desc_ver] - or eax, NVREG_TXRXCTL_KICK - mov dword [edi+NvRegTxRxControl], eax + ; writel(NVREG_TXRXCTL_KICK | np->desc_ver, base + NvRegTxRxControl); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [forcedeth_desc_ver] + or eax, NVREG_TXRXCTL_KICK + mov dword [edi+NvRegTxRxControl], eax - ; pci_push(base); - call forcedeth_pci_push + ; pci_push(base); + call forcedeth_pci_push - ; np->next_tx++ - inc dword [forcedeth_next_tx] ; may be need to reset? Overflow? + ; np->next_tx++ + inc dword [forcedeth_next_tx]; may be need to reset? Overflow? - ret + ret ;*************************************************************************** ; Function ; forcedeth_cable ; ; Description -; Return AL=0, if cable is not connected -; Returm AL=1, if cable is connected +; Return AL=0, if cable is not connected +; Returm AL=1, if cable is connected ; ;*************************************************************************** forcedeth_cable: - mov al, 1 - cmp dword [forcedeth_nocable], 1 - jne .return - mov al, 0 + mov al, 1 + cmp dword [forcedeth_nocable], 1 + jne .return + mov al, 0 .return: - ret + ret ;*************************************************************************** - - + + ; read/write a register on the PHY. ; Caller must guarantee serialization ; Input: EAX - miireg, EBX - addr, ECX - value ; Output: EAX - retval forcedeth_mii_rw: - push ebx - push eax ; save miireg - ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus) - mov edi, dword [forcedeth_mapio_addr] - mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK + push ebx + push eax ; save miireg + ; writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegMIIStatus], NVREG_MIISTAT_MASK - ; reg = readl(base + NvRegMIIControl) - mov eax, dword [edi+NvRegMIIControl] - test eax, NVREG_MIICTL_INUSE - jz @f - ; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl) - mov dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE - ; nv_udelay(NV_MIIBUSY_DELAY) - mov esi, NV_MIIBUSY_DELAY - call forcedeth_nv_udelay + ; reg = readl(base + NvRegMIIControl) + mov eax, dword [edi+NvRegMIIControl] + test eax, NVREG_MIICTL_INUSE + jz @f + ; writel(NVREG_MIICTL_INUSE, base + NvRegMIIControl) + mov dword [edi+NvRegMIIControl], NVREG_MIICTL_INUSE + ; nv_udelay(NV_MIIBUSY_DELAY) + mov esi, NV_MIIBUSY_DELAY + call forcedeth_nv_udelay @@: - ; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg - pop edx ; restore miireg - mov eax, ebx - shl eax, NVREG_MIICTL_ADDRSHIFT - or eax, edx - mov dword [forcedeth_tmp_reg], eax + ; reg = (addr << NVREG_MIICTL_ADDRSHIFT) | miireg + pop edx ; restore miireg + mov eax, ebx + shl eax, NVREG_MIICTL_ADDRSHIFT + or eax, edx + mov dword [forcedeth_tmp_reg], eax - cmp ecx, MII_READ - je @f - ; writel(value, base + NvRegMIIData) - mov dword [edi+NvRegMIIData], ecx - ; reg |= NVREG_MIICTL_WRITE - or dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE + cmp ecx, MII_READ + je @f + ; writel(value, base + NvRegMIIData) + mov dword [edi+NvRegMIIData], ecx + ; reg |= NVREG_MIICTL_WRITE + or dword [forcedeth_tmp_reg], NVREG_MIICTL_WRITE @@: - ; writel(reg, base + NvRegMIIControl) - mov eax, dword [forcedeth_tmp_reg] - mov dword [edi+NvRegMIIControl], eax + ; writel(reg, base + NvRegMIIControl) + mov eax, dword [forcedeth_tmp_reg] + mov dword [edi+NvRegMIIControl], eax - push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; + push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; - ; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL) - stdcall forcedeth_reg_delay,NvRegMIIControl,NVREG_MIICTL_INUSE,0,NV_MIIPHY_DELAY,NV_MIIPHY_DELAYMAX,0 + ; reg_delay(NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, NULL) + stdcall forcedeth_reg_delay, NvRegMIIControl, NVREG_MIICTL_INUSE, 0, NV_MIIPHY_DELAY, NV_MIIPHY_DELAYMAX, 0 - pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; + pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; - test eax, eax - jz @f -;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx - mov eax, 0xffffffff - jmp .return + test eax, eax + jz @f +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d timed out.\n", edx, ebx + mov eax, 0xffffffff + jmp .return @@: - cmp ecx, MII_READ - je @f - ;it was a write operation - fewer failures are detectable -;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx - mov eax, 0 - jmp .return + cmp ecx, MII_READ + je @f + ;it was a write operation - fewer failures are detectable +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw wrote 0x%x to reg %d at PHY %d\n", ecx, edx, ebx + mov eax, 0 + jmp .return @@: - ; readl(base + NvRegMIIStatus) - mov eax, dword [edi+NvRegMIIStatus] - test eax, NVREG_MIISTAT_ERROR - jz @f -;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx - mov eax, 0xffffffff - jmp .return + ; readl(base + NvRegMIIStatus) + mov eax, dword [edi+NvRegMIIStatus] + test eax, NVREG_MIISTAT_ERROR + jz @f +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw of reg %d at PHY %d failed.\n", edx, ebx + mov eax, 0xffffffff + jmp .return @@: - ; retval = readl(base + NvRegMIIData) - mov eax, dword [edi+NvRegMIIData] -;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax + ; retval = readl(base + NvRegMIIData) + mov eax, dword [edi+NvRegMIIData] +;;;;;;;; DEBUGF 1,"K : FORCEDETH: mii_rw read from reg %d at PHY %d: 0x%x.\n", edx, ebx, eax .return: - pop ebx - ret + pop ebx + ret @@ -1620,84 +1624,84 @@ forcedeth_mii_rw: ; Output: none forcedeth_nv_udelay: - push ebx - cmp dword [forcedeth_in_shutdown], 0 - jne @f - call forcedeth_udelay ; delay on ESI - jmp .return + push ebx + cmp dword [forcedeth_in_shutdown], 0 + jne @f + call forcedeth_udelay ; delay on ESI + jmp .return @@: - + .loop: - cmp esi, 0 - je .return - ; Don't allow an rx_ring overflow to happen - ; while shutting down the NIC it will - ; kill the receive function. + cmp esi, 0 + je .return + ; Don't allow an rx_ring overflow to happen + ; while shutting down the NIC it will + ; kill the receive function. - call forcedeth_drop_rx - mov ebx, 3 ; sleep = 3 - cmp ebx, esi ; if(sleep > delay) - jle @f - mov ebx, esi ; sleep = delay + call forcedeth_drop_rx + mov ebx, 3 ; sleep = 3 + cmp ebx, esi ; if(sleep > delay) + jle @f + mov ebx, esi ; sleep = delay @@: - push esi - mov esi, ebx - ; udelay(sleep) - call forcedeth_udelay ; delay on ESI - pop esi - sub esi, ebx ; delay -= sleep - jmp .loop + push esi + mov esi, ebx + ; udelay(sleep) + call forcedeth_udelay ; delay on ESI + pop esi + sub esi, ebx ; delay -= sleep + jmp .loop .return: - pop ebx - ret + pop ebx + ret ; Input: none ; Output: none forcedeth_drop_rx: - push eax ebx ecx edi + push eax ebx ecx edi - ; events = readl(base + NvRegIrqStatus) - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [edi+NvRegIrqStatus] + ; events = readl(base + NvRegIrqStatus) + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegIrqStatus] - test eax, eax - jz @f - ; writel(events, base + NvRegIrqStatus) - mov dword [edi+NvRegIrqStatus], eax + test eax, eax + jz @f + ; writel(events, base + NvRegIrqStatus) + mov dword [edi+NvRegIrqStatus], eax @@: - ;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF))) - test eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) - jz .return - -.loop: - ; i = np->cur_rx % RX_RING - mov eax, dword [forcedeth_cur_rx] - and eax, (RX_RING-1) - ; //Flags = le32_to_cpu(rx_ring[i].FlagLen) - ; Flags = rx_ring[i].FlagLen - mov cl, sizeof.forcedeth_RxDesc - mul cl - add eax, forcedeth_rx_ring - mov ebx, eax - mov eax, [ebx + forcedeth_RxDesc.FlagLen] - ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) - ; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2) - ; ??? len don't used later !!! ??? - ; ... - test eax, NV_RX_AVAIL - jnz .return ; still owned by hardware, - ; wmb() - ; ??? may be empty function ??? - ; np->cur_rx++ - inc dword [forcedeth_cur_rx] - ; alloc_rx(NULL) - call forcedeth_alloc_rx -.return: - pop edi ecx ebx eax - ret + ;if (!(events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF))) + test eax, (NVREG_IRQ_RX_ERROR or NVREG_IRQ_RX or NVREG_IRQ_RX_NOBUF) + jz .return + +.loop: + ; i = np->cur_rx % RX_RING + mov eax, dword [forcedeth_cur_rx] + and eax, (RX_RING-1) + ; //Flags = le32_to_cpu(rx_ring[i].FlagLen) + ; Flags = rx_ring[i].FlagLen + mov cl, sizeof.forcedeth_RxDesc + mul cl + add eax, forcedeth_rx_ring + mov ebx, eax + mov eax, [ebx + forcedeth_RxDesc.FlagLen] + ; len = nv_descr_getlength(&rx_ring[i], np->desc_ver) + ; > len = Flags & ((np->desc_ver == DESC_VER_1) ? LEN_MASK_V1 : LEN_MASK_V2) + ; ??? len don't used later !!! ??? + ; ... + test eax, NV_RX_AVAIL + jnz .return ; still owned by hardware, + ; wmb() + ; ??? may be empty function ??? + ; np->cur_rx++ + inc dword [forcedeth_cur_rx] + ; alloc_rx(NULL) + call forcedeth_alloc_rx +.return: + pop edi ecx ebx eax + ret ; Fill rx ring entries. @@ -1707,42 +1711,42 @@ forcedeth_drop_rx: ; Output: none forcedeth_alloc_rx: - push eax ebx ecx edx - ; refill_rx = np->refill_rx - mov ecx, dword [forcedeth_refill_rx] + push eax ebx ecx edx + ; refill_rx = np->refill_rx + mov ecx, dword [forcedeth_refill_rx] .loop: - cmp dword [forcedeth_cur_rx], ecx - je .loop_end - ; nr = refill_rx % RX_RING - mov eax, ecx - and eax, (RX_RING-1) ; nr - ; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE] - push ecx - push eax - mov cl, sizeof.forcedeth_RxDesc - mul cl - add eax, forcedeth_rx_ring - mov ebx, eax - pop eax - mov cx, RX_NIC_BUFSIZE - mul cx - pop ecx - add eax, forcedeth_rxb - sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov [ebx + forcedeth_RxDesc.PacketBuffer], eax - ; wmb() - ; ... - ; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL - mov [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL) - inc ecx - jmp .loop - + cmp dword [forcedeth_cur_rx], ecx + je .loop_end + ; nr = refill_rx % RX_RING + mov eax, ecx + and eax, (RX_RING-1) ; nr + ; rx_ring[nr].PacketBuffer = &rxb[nr * RX_NIC_BUFSIZE] + push ecx + push eax + mov cl, sizeof.forcedeth_RxDesc + mul cl + add eax, forcedeth_rx_ring + mov ebx, eax + pop eax + mov cx, RX_NIC_BUFSIZE + mul cx + pop ecx + add eax, forcedeth_rxb + sub eax, OS_BASE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov [ebx + forcedeth_RxDesc.PacketBuffer], eax + ; wmb() + ; ... + ; rx_ring[nr].FlagLen = RX_NIC_BUFSIZE | NV_RX_AVAIL + mov [ebx + forcedeth_RxDesc.FlagLen], (RX_NIC_BUFSIZE or NV_RX_AVAIL) + inc ecx + jmp .loop + .loop_end: - ; np->refill_rx = refill_rx - mov [forcedeth_refill_rx], ecx + ; np->refill_rx = refill_rx + mov [forcedeth_refill_rx], ecx .return: - pop edx ecx ebx eax - ret + pop edx ecx ebx eax + ret ; Delay in millisec @@ -1750,943 +1754,943 @@ forcedeth_alloc_rx: ; Output: none forcedeth_udelay: call delay_ms - ret + ret ; Input: offset:word, mask:dword, target:dword, delay:word, delaymax:word, msg:dword ; Output: EAX - 0|1 -;;;;proc forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword -proc forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword +;;;;proc forcedeth_reg_delay,offset:word,mask:dword,target:dword,delay:word,delaymax:word,msg:dword +proc forcedeth_reg_delay,offset:dword,mask:dword,target:dword,delay:dword,delaymax:dword,msg:dword - push ebx esi edi - ; pci_push(base) - call forcedeth_pci_push + push ebx esi edi + ; pci_push(base) + call forcedeth_pci_push .loop: - ; nv_udelay(delay) - mov esi, dword [delay] - call forcedeth_nv_udelay ; delay in esi - mov eax, dword [delaymax] - sub eax, dword [delay] - mov dword [delaymax], eax - ; if (delaymax < 0) - test dword [delaymax], 0x80000000 - jz @f - ; return 1 - mov eax, 1 - jmp .return + ; nv_udelay(delay) + mov esi, dword [delay] + call forcedeth_nv_udelay ; delay in esi + mov eax, dword [delaymax] + sub eax, dword [delay] + mov dword [delaymax], eax + ; if (delaymax < 0) + test dword [delaymax], 0x80000000 + jz @f + ; return 1 + mov eax, 1 + jmp .return @@: - ; while ((readl(base + offset) & mask) != target) - mov edi, dword [forcedeth_mapio_addr] - mov ebx, dword [offset] - mov eax, dword [edi+ebx] - and eax, dword [mask] - cmp eax, dword [target] - jne .loop - xor eax, eax + ; while ((readl(base + offset) & mask) != target) + mov edi, dword [forcedeth_mapio_addr] + mov ebx, dword [offset] + mov eax, dword [edi+ebx] + and eax, dword [mask] + cmp eax, dword [target] + jne .loop + xor eax, eax .return: - pop edi esi ebx - ret + pop edi esi ebx + ret endp ; Input: none ; Output: none forcedeth_pci_push: - push eax edi - ;force out pending posted writes - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [edi] - pop edi eax - ret + push eax edi + ;force out pending posted writes + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi] + pop edi eax + ret ; Input: none ; Output: EAX - result (0 = OK, other = error) forcedeth_phy_init: - push ebx ecx - - ; set advertise register - ; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); + push ebx ecx + + ; set advertise register + ; reg = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); ; EBX - addr, EAX - miireg, ECX - value - mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_ADVERTISE - mov ecx, MII_READ - call forcedeth_mii_rw ; reg = eax + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_ADVERTISE + mov ecx, MII_READ + call forcedeth_mii_rw ; reg = eax - ; reg |= - ; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | - ; ADVERTISE_100FULL | 0x800 | 0x400); - or eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400) + ; reg |= + ; (ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | + ; ADVERTISE_100FULL | 0x800 | 0x400); + or eax, (ADVERTISE_10HALF or ADVERTISE_10FULL or ADVERTISE_100HALF or ADVERTISE_100FULL or 0x800 or 0x400) - ; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg)) + ; if (mii_rw(nic, np->phyaddr, MII_ADVERTISE, reg)) ; EBX - addr, EAX - miireg, ECX - value - mov ecx, eax ; reg - mov eax, MII_ADVERTISE - call forcedeth_mii_rw ; eax -> return + mov ecx, eax ; reg + mov eax, MII_ADVERTISE + call forcedeth_mii_rw ; eax -> return - test eax, eax - jz @f - ; printf("phy write to advertise failed.\n"); - DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n" + test eax, eax + jz @f + ; printf("phy write to advertise failed.\n"); + DEBUGF 1," K : FORCEDETH: phy write to advertise failed.\n" - ; return PHY_ERROR; - mov eax, PHY_ERROR - jmp .return + ; return PHY_ERROR; + mov eax, PHY_ERROR + jmp .return @@: - ; get phy interface type - ; phyinterface = readl(base + NvRegPhyInterface); - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [edi+NvRegPhyInterface] ; phyinterface = eax - mov dword [forcedeth_tmp_phyinterface], eax + ; get phy interface type + ; phyinterface = readl(base + NvRegPhyInterface); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegPhyInterface] ; phyinterface = eax + mov dword [forcedeth_tmp_phyinterface], eax ;;;;;;;;;;;;;;;;;;;;;;;;; DEBUGF 1," K : FORCEDETH: phy interface type = 0x%x\n", [forcedeth_tmp_phyinterface]:8 ;;;;;;;;;;;;;;;;;;;;;;;;; - ; see if gigabit phy - ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); + ; see if gigabit phy + ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); ; EBX - addr, EAX - miireg, ECX - value - mov eax, MII_BMSR - mov ecx, MII_READ - call forcedeth_mii_rw ; mii_status = eax - - ; if (mii_status & PHY_GIGABIT) - test eax, PHY_GIGABIT - jnz .gigabit - ; np->gigabit = 0; - mov dword [forcedeth_gigabit], 0 - jmp .next_if + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_status = eax + + ; if (mii_status & PHY_GIGABIT) + test eax, PHY_GIGABIT + jnz .gigabit + ; np->gigabit = 0; + mov dword [forcedeth_gigabit], 0 + jmp .next_if .gigabit: - ; np->gigabit = PHY_GIGABIT; - mov dword [forcedeth_gigabit], PHY_GIGABIT + ; np->gigabit = PHY_GIGABIT; + mov dword [forcedeth_gigabit], PHY_GIGABIT - ; mii_control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ); + ; mii_control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ); ; EBX - addr, EAX - miireg, ECX - value - mov eax, MII_1000BT_CR - mov ecx, MII_READ - call forcedeth_mii_rw ; mii_control_1000 = eax - - ; mii_control_1000 &= ~ADVERTISE_1000HALF; - and eax, (not ADVERTISE_1000HALF) + mov eax, MII_1000BT_CR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_control_1000 = eax + + ; mii_control_1000 &= ~ADVERTISE_1000HALF; + and eax, (not ADVERTISE_1000HALF) - ; if (phyinterface & PHY_RGMII) - test dword [forcedeth_tmp_phyinterface], PHY_RGMII - jz @f - ; mii_control_1000 |= ADVERTISE_1000FULL - or eax, ADVERTISE_1000FULL - jmp .next + ; if (phyinterface & PHY_RGMII) + test dword [forcedeth_tmp_phyinterface], PHY_RGMII + jz @f + ; mii_control_1000 |= ADVERTISE_1000FULL + or eax, ADVERTISE_1000FULL + jmp .next @@: - ; mii_control_1000 &= ~ADVERTISE_1000FULL - and eax, (not ADVERTISE_1000FULL) + ; mii_control_1000 &= ~ADVERTISE_1000FULL + and eax, (not ADVERTISE_1000FULL) .next: - ; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000)) + ; if (mii_rw(nic, np->phyaddr, MII_1000BT_CR, mii_control_1000)) ; EBX - addr, EAX - miireg, ECX - value - mov ecx, eax - mov eax, MII_1000BT_CR - call forcedeth_mii_rw ; eax -> return + mov ecx, eax + mov eax, MII_1000BT_CR + call forcedeth_mii_rw ; eax -> return - test eax, eax - jz .next_if + test eax, eax + jz .next_if - ; printf("phy init failed.\n"); - DEBUGF 1," K : FORCEDETH: phy init failed.\n" + ; printf("phy init failed.\n"); + DEBUGF 1," K : FORCEDETH: phy init failed.\n" - ; return PHY_ERROR; - mov eax, PHY_ERROR - jmp .return + ; return PHY_ERROR; + mov eax, PHY_ERROR + jmp .return .next_if: - ; reset the phy - ; if (phy_reset(nic)) - call forcedeth_phy_reset - test eax, eax - jz @f - ; printf("phy reset failed\n") - DEBUGF 1," K : FORCEDETH: phy reset failed.\n" - ; return PHY_ERROR - mov eax, PHY_ERROR - jmp .return + ; reset the phy + ; if (phy_reset(nic)) + call forcedeth_phy_reset + test eax, eax + jz @f + ; printf("phy reset failed\n") + DEBUGF 1," K : FORCEDETH: phy reset failed.\n" + ; return PHY_ERROR + mov eax, PHY_ERROR + jmp .return @@: - ; phy vendor specific configuration - ; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII)) - cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA - jne .next_if2 - test dword [forcedeth_tmp_phyinterface], PHY_RGMII - jz .next_if2 + ; phy vendor specific configuration + ; if ((np->phy_oui == PHY_OUI_CICADA) && (phyinterface & PHY_RGMII)) + cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA + jne .next_if2 + test dword [forcedeth_tmp_phyinterface], PHY_RGMII + jz .next_if2 - ; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ) + ; phy_reserved = mii_rw(nic, np->phyaddr, MII_RESV1, MII_READ) ; EBX - addr, EAX - miireg, ECX - value - mov eax, MII_RESV1 - mov ecx, MII_READ - call forcedeth_mii_rw ; phy_reserved = eax - - ; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2) - and eax, (not (PHY_INIT1 or PHY_INIT2)) - ; phy_reserved |= (PHY_INIT3 | PHY_INIT4) - or eax, (PHY_INIT3 or PHY_INIT4) - - ; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved)) + mov eax, MII_RESV1 + mov ecx, MII_READ + call forcedeth_mii_rw ; phy_reserved = eax + + ; phy_reserved &= ~(PHY_INIT1 | PHY_INIT2) + and eax, (not (PHY_INIT1 or PHY_INIT2)) + ; phy_reserved |= (PHY_INIT3 | PHY_INIT4) + or eax, (PHY_INIT3 or PHY_INIT4) + + ; if (mii_rw(nic, np->phyaddr, MII_RESV1, phy_reserved)) ; EBX - addr, EAX - miireg, ECX - value - mov ecx, eax - mov eax, MII_RESV1 - call forcedeth_mii_rw ; eax -> return - test eax, eax - jz @f - ; printf("phy init failed.\n") - DEBUGF 1," K : FORCEDETH: phy init failed.\n" - ; return PHY_ERROR - mov eax, PHY_ERROR - jmp .return + mov ecx, eax + mov eax, MII_RESV1 + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz @f + ; printf("phy init failed.\n") + DEBUGF 1," K : FORCEDETH: phy init failed.\n" + ; return PHY_ERROR + mov eax, PHY_ERROR + jmp .return @@: - ; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ); + ; phy_reserved = mii_rw(nic, np->phyaddr, MII_NCONFIG, MII_READ); ; EBX - addr, EAX - miireg, ECX - value - mov eax, MII_NCONFIG - mov ecx, MII_READ - call forcedeth_mii_rw ; phy_reserved = eax + mov eax, MII_NCONFIG + mov ecx, MII_READ + call forcedeth_mii_rw ; phy_reserved = eax - ; phy_reserved |= PHY_INIT5 - or eax, PHY_INIT5 - - ; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved)) + ; phy_reserved |= PHY_INIT5 + or eax, PHY_INIT5 + + ; if (mii_rw(nic, np->phyaddr, MII_NCONFIG, phy_reserved)) ; EBX - addr, EAX - miireg, ECX - value - mov ecx, eax - mov eax, MII_NCONFIG - call forcedeth_mii_rw ; eax -> return - test eax, eax - jz .next_if2 - ; printf("phy init failed.\n") - DEBUGF 1," K : FORCEDETH: phy init failed.\n" - ; return PHY_ERROR - mov eax, PHY_ERROR - jmp .return + mov ecx, eax + mov eax, MII_NCONFIG + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz .next_if2 + ; printf("phy init failed.\n") + DEBUGF 1," K : FORCEDETH: phy init failed.\n" + ; return PHY_ERROR + mov eax, PHY_ERROR + jmp .return .next_if2: - ; if (np->phy_oui == PHY_OUI_CICADA) - cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA - jne .restart - - ; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ) + ; if (np->phy_oui == PHY_OUI_CICADA) + cmp dword [forcedeth_phy_oui], PHY_OUI_CICADA + jne .restart + + ; phy_reserved = mii_rw(nic, np->phyaddr, MII_SREVISION, MII_READ) ; EBX - addr, EAX - miireg, ECX - value - mov eax, MII_SREVISION - mov ecx, MII_READ - call forcedeth_mii_rw ; phy_reserved = eax - - ; phy_reserved |= PHY_INIT6 - or eax, PHY_INIT6 - - ; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved)) - mov ecx, eax - mov eax, MII_SREVISION - call forcedeth_mii_rw ; eax -> return - test eax, eax - jz .restart - ; printf("phy init failed.\n"); - DEBUGF 1," K : FORCEDETH: phy init failed.\n" - ; return PHY_ERROR; - jmp .return + mov eax, MII_SREVISION + mov ecx, MII_READ + call forcedeth_mii_rw ; phy_reserved = eax + + ; phy_reserved |= PHY_INIT6 + or eax, PHY_INIT6 + + ; if (mii_rw(nic, np->phyaddr, MII_SREVISION, phy_reserved)) + mov ecx, eax + mov eax, MII_SREVISION + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz .restart + ; printf("phy init failed.\n"); + DEBUGF 1," K : FORCEDETH: phy init failed.\n" + ; return PHY_ERROR; + jmp .return .restart: - ; restart auto negotiation - ; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ) + ; restart auto negotiation + ; mii_control = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ) ; EBX - addr, EAX - miireg, ECX - value - mov eax, MII_BMCR - mov ecx, MII_READ - call forcedeth_mii_rw ; mii_control = eax + mov eax, MII_BMCR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_control = eax - ; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE) - or eax, (BMCR_ANRESTART or BMCR_ANENABLE) - - ; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control)) - mov ecx, eax - mov eax, MII_BMCR - call forcedeth_mii_rw ; eax -> return - test eax, eax - jz .ok + ; mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE) + or eax, (BMCR_ANRESTART or BMCR_ANENABLE) + + ; if (mii_rw(nic, np->phyaddr, MII_BMCR, mii_control)) + mov ecx, eax + mov eax, MII_BMCR + call forcedeth_mii_rw ; eax -> return + test eax, eax + jz .ok - ; return PHY_ERROR; - mov eax, PHY_ERROR - jmp .return + ; return PHY_ERROR; + mov eax, PHY_ERROR + jmp .return .ok: - mov eax, 0 + mov eax, 0 .return: - pop ecx ebx - ret + pop ecx ebx + ret ; Input: none ; Output: EAX - result (0 = OK, other = error) forcedeth_phy_reset: - push ebx ecx edx + push ebx ecx edx - ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); + ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); ; EBX - addr, EAX - miireg, ECX - value - mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_BMCR - mov ecx, MII_READ - call forcedeth_mii_rw ; miicontrol = eax + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMCR + mov ecx, MII_READ + call forcedeth_mii_rw ; miicontrol = eax - ; miicontrol |= BMCR_RESET; - or eax, BMCR_RESET - push eax + ; miicontrol |= BMCR_RESET; + or eax, BMCR_RESET + push eax - ; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol)) + ; if (mii_rw(nic, np->phyaddr, MII_BMCR, miicontrol)) ; EBX - addr, EAX - miireg, ECX - value - mov ecx, eax - mov eax, MII_BMCR - call forcedeth_mii_rw ; miicontrol = eax + mov ecx, eax + mov eax, MII_BMCR + call forcedeth_mii_rw ; miicontrol = eax - test eax, eax - jz @f - pop eax - mov eax, 0xffffffff - jmp .return + test eax, eax + jz @f + pop eax + mov eax, 0xffffffff + jmp .return @@: - pop eax + pop eax - ; wait for 500ms - ; mdelay(500) - mov esi, 500 - call forcedeth_udelay + ; wait for 500ms + ; mdelay(500) + mov esi, 500 + call forcedeth_udelay - ; must wait till reset is deasserted - ; while (miicontrol & BMCR_RESET) { - mov edx, 100 + ; must wait till reset is deasserted + ; while (miicontrol & BMCR_RESET) { + mov edx, 100 .while_loop: - test eax, BMCR_RESET - jz .while_loop_exit + test eax, BMCR_RESET + jz .while_loop_exit - ; mdelay(10); - mov esi, 10 - call forcedeth_udelay + ; mdelay(10); + mov esi, 10 + call forcedeth_udelay - ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); + ; miicontrol = mii_rw(nic, np->phyaddr, MII_BMCR, MII_READ); ; EBX - addr, EAX - miireg, ECX - value - mov eax, MII_BMCR - mov ecx, MII_READ - call forcedeth_mii_rw ; miicontrol = eax + mov eax, MII_BMCR + mov ecx, MII_READ + call forcedeth_mii_rw ; miicontrol = eax - ; FIXME: 100 tries seem excessive - ; if (tries++ > 100) - dec edx - jnz .while_loop - ; return -1; - mov eax, 0xffffffff - jmp .return + ; FIXME: 100 tries seem excessive + ; if (tries++ > 100) + dec edx + jnz .while_loop + ; return -1; + mov eax, 0xffffffff + jmp .return .while_loop_exit: - ; return 0 - mov eax, 0 -.return: - pop edx ecx ebx - ret + ; return 0 + mov eax, 0 +.return: + pop edx ecx ebx + ret ; Input: none ; Output: none forcedeth_mac_reset: - push esi edi + push esi edi - ; dprintf("mac_reset\n") - DEBUGF 1," K : FORCEDETH: mac_reset.\n" + ; dprintf("mac_reset\n") + DEBUGF 1," K : FORCEDETH: mac_reset.\n" - ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [forcedeth_desc_ver] - or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) - mov dword [edi+NvRegTxRxControl], eax + ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [forcedeth_desc_ver] + or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) + mov dword [edi+NvRegTxRxControl], eax - ; pci_push(base) - call forcedeth_pci_push - - ; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset) - mov dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT + ; pci_push(base) + call forcedeth_pci_push + + ; writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset) + mov dword [edi+NvRegMacReset], NVREG_MAC_RESET_ASSERT - ; pci_push(base) - call forcedeth_pci_push + ; pci_push(base) + call forcedeth_pci_push - ; udelay(NV_MAC_RESET_DELAY) - mov esi, NV_MAC_RESET_DELAY - call forcedeth_nv_udelay + ; udelay(NV_MAC_RESET_DELAY) + mov esi, NV_MAC_RESET_DELAY + call forcedeth_nv_udelay - ; writel(0, base + NvRegMacReset) - mov dword [edi+NvRegMacReset], 0 + ; writel(0, base + NvRegMacReset) + mov dword [edi+NvRegMacReset], 0 - ; pci_push(base) - call forcedeth_pci_push - - ; udelay(NV_MAC_RESET_DELAY) - mov esi, NV_MAC_RESET_DELAY - call forcedeth_nv_udelay + ; pci_push(base) + call forcedeth_pci_push + + ; udelay(NV_MAC_RESET_DELAY) + mov esi, NV_MAC_RESET_DELAY + call forcedeth_nv_udelay - ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) - mov eax, dword [forcedeth_desc_ver] - or eax, NVREG_TXRXCTL_BIT2 - mov dword [edi+NvRegTxRxControl], eax - - ; pci_push(base) - call forcedeth_pci_push + ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) + mov eax, dword [forcedeth_desc_ver] + or eax, NVREG_TXRXCTL_BIT2 + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push - pop edi esi - ret + pop edi esi + ret ; Input: none ; Output: none forcedeth_init_ring: - push eax ebx ecx + push eax ebx ecx ; np->next_tx = np->nic_tx = 0 - mov dword[forcedeth_next_tx], 0 - mov dword[forcedeth_nic_tx], 0 + mov dword[forcedeth_next_tx], 0 + mov dword[forcedeth_nic_tx], 0 ; for (i = 0; i < TX_RING; i++) - mov ecx, TX_RING + mov ecx, TX_RING .for_loop: ; tx_ring[i].FlagLen = 0; - mov eax, ecx - dec eax - mov bl, sizeof.forcedeth_TxDesc - mul bl - add eax, forcedeth_tx_ring - mov ebx, eax - mov dword [ebx + forcedeth_TxDesc.FlagLen], 0 - loop .for_loop + mov eax, ecx + dec eax + mov bl, sizeof.forcedeth_TxDesc + mul bl + add eax, forcedeth_tx_ring + mov ebx, eax + mov dword [ebx + forcedeth_TxDesc.FlagLen], 0 + loop .for_loop ; np->cur_rx = RX_RING; - mov dword [forcedeth_cur_rx], RX_RING + mov dword [forcedeth_cur_rx], RX_RING ; np->refill_rx = 0; - mov dword [forcedeth_refill_rx], 0 + mov dword [forcedeth_refill_rx], 0 - ;for (i = 0; i < RX_RING; i++) - mov ecx, RX_RING + ;for (i = 0; i < RX_RING; i++) + mov ecx, RX_RING .for_loop2: ; rx_ring[i].FlagLen = 0; - mov eax, ecx - dec eax - mov bl, sizeof.forcedeth_RxDesc - mul bl - add eax, forcedeth_rx_ring - mov ebx, eax - mov dword [ebx + forcedeth_RxDesc.FlagLen], 0 - loop .for_loop2 + mov eax, ecx + dec eax + mov bl, sizeof.forcedeth_RxDesc + mul bl + add eax, forcedeth_rx_ring + mov ebx, eax + mov dword [ebx + forcedeth_RxDesc.FlagLen], 0 + loop .for_loop2 - ; alloc_rx(nic); - call forcedeth_alloc_rx + ; alloc_rx(nic); + call forcedeth_alloc_rx .return: - pop ecx ebx eax - ret + pop ecx ebx eax + ret ; Input: none ; Output: none forcedeth_txrx_reset: - push eax esi edi + push eax esi edi - ; dprintf(("txrx_reset\n")) - DEBUGF 1," K : FORCEDETH: txrx_reset.\n" + ; dprintf(("txrx_reset\n")) + DEBUGF 1," K : FORCEDETH: txrx_reset.\n" - ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [forcedeth_desc_ver] - or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) - mov dword [edi+NvRegTxRxControl], eax + ; writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->desc_ver, base + NvRegTxRxControl) + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [forcedeth_desc_ver] + or eax, (NVREG_TXRXCTL_BIT2 or NVREG_TXRXCTL_RESET) + mov dword [edi+NvRegTxRxControl], eax - ; pci_push(base) - call forcedeth_pci_push + ; pci_push(base) + call forcedeth_pci_push - ; nv_udelay(NV_TXRX_RESET_DELAY) - mov esi, NV_TXRX_RESET_DELAY - call forcedeth_nv_udelay + ; nv_udelay(NV_TXRX_RESET_DELAY) + mov esi, NV_TXRX_RESET_DELAY + call forcedeth_nv_udelay - ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) - mov eax, dword [forcedeth_desc_ver] - or eax, NVREG_TXRXCTL_BIT2 - mov dword [edi+NvRegTxRxControl], eax - - ; pci_push(base) - call forcedeth_pci_push + ; writel(NVREG_TXRXCTL_BIT2 | np->desc_ver, base + NvRegTxRxControl) + mov eax, dword [forcedeth_desc_ver] + or eax, NVREG_TXRXCTL_BIT2 + mov dword [edi+NvRegTxRxControl], eax + + ; pci_push(base) + call forcedeth_pci_push .return: - pop edi esi eax - ret + pop edi esi eax + ret ; Input: none ; Output: none forcedeth_set_multicast: - push edi + push edi - ; u32 addr[2]; - ; u32 mask[2]; - ; u32 pff; - ; u32 alwaysOff[2]; - ; u32 alwaysOn[2]; - ; - ; memset(addr, 0, sizeof(addr)); - ; memset(mask, 0, sizeof(mask)); - ; - ; pff = NVREG_PFF_MYADDR; - ; - ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0; - ; - ; addr[0] = alwaysOn[0]; - ; addr[1] = alwaysOn[1]; - ; mask[0] = alwaysOn[0] | alwaysOff[0]; - ; mask[1] = alwaysOn[1] | alwaysOff[1]; - ; - ; addr[0] |= NVREG_MCASTADDRA_FORCE; - ; pff |= NVREG_PFF_ALWAYS; - ; stop_rx(); - call forcedeth_stop_rx - ; writel(addr[0], base + NvRegMulticastAddrA); - mov edi, dword [forcedeth_mapio_addr] - mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE - ; writel(addr[1], base + NvRegMulticastAddrB); - mov dword [edi+NvRegMulticastAddrB], 0 - ; writel(mask[0], base + NvRegMulticastMaskA); - mov dword [edi+NvRegMulticastMaskA], 0 - ; writel(mask[1], base + NvRegMulticastMaskB); - mov dword [edi+NvRegMulticastMaskB], 0 - ; writel(pff, base + NvRegPacketFilterFlags); - mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS) - ; start_rx(nic); - call forcedeth_start_rx + ; u32 addr[2]; + ; u32 mask[2]; + ; u32 pff; + ; u32 alwaysOff[2]; + ; u32 alwaysOn[2]; + ; + ; memset(addr, 0, sizeof(addr)); + ; memset(mask, 0, sizeof(mask)); + ; + ; pff = NVREG_PFF_MYADDR; + ; + ; alwaysOn[0] = alwaysOn[1] = alwaysOff[0] = alwaysOff[1] = 0; + ; + ; addr[0] = alwaysOn[0]; + ; addr[1] = alwaysOn[1]; + ; mask[0] = alwaysOn[0] | alwaysOff[0]; + ; mask[1] = alwaysOn[1] | alwaysOff[1]; + ; + ; addr[0] |= NVREG_MCASTADDRA_FORCE; + ; pff |= NVREG_PFF_ALWAYS; + ; stop_rx(); + call forcedeth_stop_rx + ; writel(addr[0], base + NvRegMulticastAddrA); + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegMulticastAddrA], NVREG_MCASTADDRA_FORCE + ; writel(addr[1], base + NvRegMulticastAddrB); + mov dword [edi+NvRegMulticastAddrB], 0 + ; writel(mask[0], base + NvRegMulticastMaskA); + mov dword [edi+NvRegMulticastMaskA], 0 + ; writel(mask[1], base + NvRegMulticastMaskB); + mov dword [edi+NvRegMulticastMaskB], 0 + ; writel(pff, base + NvRegPacketFilterFlags); + mov dword [edi+NvRegPacketFilterFlags], (NVREG_PFF_MYADDR or NVREG_PFF_ALWAYS) + ; start_rx(nic); + call forcedeth_start_rx .return: - pop edi - ret + pop edi + ret ; Input: none ; Output: none forcedeth_start_rx: - push edi + push edi - ; dprintf(("start_rx\n")) - DEBUGF 1," K : FORCEDETH: start_rx.\n" + ; dprintf(("start_rx\n")) + DEBUGF 1," K : FORCEDETH: start_rx.\n" - ; Already running? Stop it. - ; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [edi+NvRegReceiverControl] - test eax, NVREG_RCVCTL_START - jz @f - ; writel(0, base + NvRegReceiverControl) - mov dword [edi+NvRegReceiverControl], 0 - ; pci_push(base) - call forcedeth_pci_push + ; Already running? Stop it. + ; if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegReceiverControl] + test eax, NVREG_RCVCTL_START + jz @f + ; writel(0, base + NvRegReceiverControl) + mov dword [edi+NvRegReceiverControl], 0 + ; pci_push(base) + call forcedeth_pci_push @@: - - ; writel(np->linkspeed, base + NvRegLinkSpeed); - mov eax, dword [forcedeth_linkspeed] - mov dword [edi+NvRegLinkSpeed], eax - ; pci_push(base); - call forcedeth_pci_push - ; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl); - mov dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START - ; pci_push(base); - call forcedeth_pci_push + + ; writel(np->linkspeed, base + NvRegLinkSpeed); + mov eax, dword [forcedeth_linkspeed] + mov dword [edi+NvRegLinkSpeed], eax + ; pci_push(base); + call forcedeth_pci_push + ; writel(NVREG_RCVCTL_START, base + NvRegReceiverControl); + mov dword [edi+NvRegReceiverControl], NVREG_RCVCTL_START + ; pci_push(base); + call forcedeth_pci_push .return: - pop edi - ret + pop edi + ret ; Input: none ; Output: none forcedeth_stop_rx: - push esi edi + push esi edi - ; dprintf(("stop_rx\n")) - DEBUGF 1," K : FORCEDETH: stop_rx.\n" + ; dprintf(("stop_rx\n")) + DEBUGF 1," K : FORCEDETH: stop_rx.\n" - ; writel(0, base + NvRegReceiverControl) - mov edi, dword [forcedeth_mapio_addr] - mov dword [edi+NvRegReceiverControl], 0 + ; writel(0, base + NvRegReceiverControl) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegReceiverControl], 0 - push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; - ; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy"); - stdcall forcedeth_reg_delay,NvRegReceiverStatus,NVREG_RCVSTAT_BUSY,0,NV_RXSTOP_DELAY1,NV_RXSTOP_DELAY1MAX,0 - pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; + push ebx edx edi ;;;;;;;;;;;;;;;;;;;;;; + ; reg_delay(NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, "stop_rx: ReceiverStatus remained busy"); + stdcall forcedeth_reg_delay, NvRegReceiverStatus, NVREG_RCVSTAT_BUSY, 0, NV_RXSTOP_DELAY1, NV_RXSTOP_DELAY1MAX, 0 + pop edi edx ebx ;;;;;;;;;;;;;;;;;;;;;; - ; nv_udelay(NV_RXSTOP_DELAY2) - mov esi, NV_RXSTOP_DELAY2 - call forcedeth_nv_udelay + ; nv_udelay(NV_RXSTOP_DELAY2) + mov esi, NV_RXSTOP_DELAY2 + call forcedeth_nv_udelay - ; writel(0, base + NvRegLinkSpeed) - mov dword [edi+NvRegLinkSpeed], 0 + ; writel(0, base + NvRegLinkSpeed) + mov dword [edi+NvRegLinkSpeed], 0 .return: - pop edi esi - ret + pop edi esi + ret ; Input: none ; Output: EAX forcedeth_update_linkspeed: - push ebx ecx esi edi + push ebx ecx esi edi - ; BMSR_LSTATUS is latched, read it twice: - ; we want the current value. - - ; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) + ; BMSR_LSTATUS is latched, read it twice: + ; we want the current value. + + ; mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) ;EBX - addr, EAX - miireg, ECX - value - mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_BMSR - mov ecx, MII_READ - call forcedeth_mii_rw + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw - ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) + ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ) ;EBX - addr, EAX - miireg, ECX - value - mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_BMSR - mov ecx, MII_READ - call forcedeth_mii_rw ; mii_status = eax - - ; yhlu + mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_status = eax + + ; yhlu - ; for(i=0;i<30;i++) { - mov ecx, 30 + ; for(i=0;i<30;i++) { + mov ecx, 30 .for_loop: - push ecx + push ecx - ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); + ; mii_status = mii_rw(nic, np->phyaddr, MII_BMSR, MII_READ); ;EBX - addr, EAX - miireg, ECX - value - ;mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_BMSR - mov ecx, MII_READ - call forcedeth_mii_rw ; mii_status = eax + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_BMSR + mov ecx, MII_READ + call forcedeth_mii_rw ; mii_status = eax - ; if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break; - test eax, BMSR_LSTATUS - jz @f - test eax, BMSR_ANEGCOMPLETE - jz @f - ; break - pop ecx - jmp .break - + ; if((mii_status & BMSR_LSTATUS) && (mii_status & BMSR_ANEGCOMPLETE)) break; + test eax, BMSR_LSTATUS + jz @f + test eax, BMSR_ANEGCOMPLETE + jz @f + ; break + pop ecx + jmp .break + @@: - ; mdelay(100); - push eax ; ??? - mov esi, 100 - call forcedeth_udelay - pop eax ; ??? + ; mdelay(100); + push eax ; ??? + mov esi, 100 + call forcedeth_udelay + pop eax ; ??? - pop ecx - loop .for_loop + pop ecx + loop .for_loop .break: - ; if (!(mii_status & BMSR_LSTATUS)) { - test eax, BMSR_LSTATUS - jnz @f + ; if (!(mii_status & BMSR_LSTATUS)) { + test eax, BMSR_LSTATUS + jnz @f - ; printf("no link detected by phy - falling back to 10HD.\n") - DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n" + ; printf("no link detected by phy - falling back to 10HD.\n") + DEBUGF 1," K : FORCEDETH: update_linkspeed: no link detected by phy - falling back to 10HD.\n" - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) - ; newdup = 0; - mov dword [forcedeth_tmp_newdup], 0 - ; retval = 0; - mov dword [forcedeth_tmp_retval], 0 + ; newdup = 0; + mov dword [forcedeth_tmp_newdup], 0 + ; retval = 0; + mov dword [forcedeth_tmp_retval], 0 - ; goto set_speed; - jmp .set_speed + ; goto set_speed; + jmp .set_speed @@: - ; check auto negotiation is complete - ; if (!(mii_status & BMSR_ANEGCOMPLETE)) { - test eax, BMSR_ANEGCOMPLETE - jnz @f + ; check auto negotiation is complete + ; if (!(mii_status & BMSR_ANEGCOMPLETE)) { + test eax, BMSR_ANEGCOMPLETE + jnz @f - ; still in autonegotiation - configure nic for 10 MBit HD and wait. - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; still in autonegotiation - configure nic for 10 MBit HD and wait. + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) - ; newdup = 0 - mov dword [forcedeth_tmp_newdup], 0 + ; newdup = 0 + mov dword [forcedeth_tmp_newdup], 0 - ; retval = 0 - mov dword [forcedeth_tmp_retval], 0 + ; retval = 0 + mov dword [forcedeth_tmp_retval], 0 - ; printf("autoneg not completed - falling back to 10HD.\n") - DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n" + ; printf("autoneg not completed - falling back to 10HD.\n") + DEBUGF 1," K : FORCEDETH: update_linkspeed: autoneg not completed - falling back to 10HD.\n" - ; goto set_speed - jmp .set_speed + ; goto set_speed + jmp .set_speed @@: - ; retval = 1 - mov dword [forcedeth_tmp_retval], 1 - - ; if (np->gigabit == PHY_GIGABIT) { - cmp dword [forcedeth_gigabit], PHY_GIGABIT - jne .end_if - ; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ) + ; retval = 1 + mov dword [forcedeth_tmp_retval], 1 + + ; if (np->gigabit == PHY_GIGABIT) { + cmp dword [forcedeth_gigabit], PHY_GIGABIT + jne .end_if + ; control_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_CR, MII_READ) ;EBX - addr, EAX - miireg, ECX - value - ;mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_1000BT_CR - mov ecx, MII_READ - call forcedeth_mii_rw ; control_1000 = eax - mov dword [forcedeth_tmp_control_1000], eax - - ; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ) + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_1000BT_CR + mov ecx, MII_READ + call forcedeth_mii_rw ; control_1000 = eax + mov dword [forcedeth_tmp_control_1000], eax + + ; status_1000 = mii_rw(nic, np->phyaddr, MII_1000BT_SR, MII_READ) ;EBX - addr, EAX - miireg, ECX - value - ;mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_1000BT_SR - mov ecx, MII_READ - call forcedeth_mii_rw ; status_1000 = eax - ;mov dword [forcedeth_tmp_status_1000], eax - - ; if ((control_1000 & ADVERTISE_1000FULL) && - ; (status_1000 & LPA_1000FULL)) { - test eax, LPA_1000FULL - jz .end_if - test dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL - jz .end_if + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_1000BT_SR + mov ecx, MII_READ + call forcedeth_mii_rw ; status_1000 = eax + ;mov dword [forcedeth_tmp_status_1000], eax + + ; if ((control_1000 & ADVERTISE_1000FULL) && + ; (status_1000 & LPA_1000FULL)) { + test eax, LPA_1000FULL + jz .end_if + test dword [forcedeth_tmp_control_1000], ADVERTISE_1000FULL + jz .end_if - ; printf ("update_linkspeed: GBit ethernet detected.\n") - DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n" + ; printf ("update_linkspeed: GBit ethernet detected.\n") + DEBUGF 1," K : FORCEDETH: update_linkspeed: GBit ethernet detected.\n" - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000 - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000) + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_1000 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_1000) - ; newdup = 1 - mov dword [forcedeth_tmp_newdup], 1 + ; newdup = 1 + mov dword [forcedeth_tmp_newdup], 1 - ; goto set_speed - jmp .set_speed + ; goto set_speed + jmp .set_speed .end_if: - ; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); + ; adv = mii_rw(nic, np->phyaddr, MII_ADVERTISE, MII_READ); ;EBX - addr, EAX - miireg, ECX - value - ;mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_ADVERTISE - mov ecx, MII_READ - call forcedeth_mii_rw ; adv = eax - mov dword [forcedeth_tmp_adv], eax + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_ADVERTISE + mov ecx, MII_READ + call forcedeth_mii_rw ; adv = eax + mov dword [forcedeth_tmp_adv], eax - ; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ); + ; lpa = mii_rw(nic, np->phyaddr, MII_LPA, MII_READ); ;EBX - addr, EAX - miireg, ECX - value - ;mov ebx, dword [forcedeth_phyaddr] - mov eax, MII_LPA - mov ecx, MII_READ - call forcedeth_mii_rw ; lpa = eax - mov dword [forcedeth_tmp_lpa], eax + ;mov ebx, dword [forcedeth_phyaddr] + mov eax, MII_LPA + mov ecx, MII_READ + call forcedeth_mii_rw ; lpa = eax + mov dword [forcedeth_tmp_lpa], eax - ; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa)); - DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8 + ; dprintf(("update_linkspeed: PHY advertises 0x%hX, lpa 0x%hX.\n", adv, lpa)); + DEBUGF 1," K : FORCEDETH: update_linkspeed: PHY advertises 0x%x, lpa 0x%x.\n", [forcedeth_tmp_adv]:8, [forcedeth_tmp_lpa]:8 - ; FIXME: handle parallel detection properly, handle gigabit ethernet - ; lpa = lpa & adv - mov eax, dword [forcedeth_tmp_adv] - and dword [forcedeth_tmp_lpa], eax + ; FIXME: handle parallel detection properly, handle gigabit ethernet + ; lpa = lpa & adv + mov eax, dword [forcedeth_tmp_adv] + and dword [forcedeth_tmp_lpa], eax - mov eax, dword [forcedeth_tmp_lpa] + mov eax, dword [forcedeth_tmp_lpa] - ; if (lpa & LPA_100FULL) { - test eax, LPA_100FULL - jz @f - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) - ; newdup = 1 - mov dword [forcedeth_tmp_newdup], 1 - jmp .set_speed + ; if (lpa & LPA_100FULL) { + test eax, LPA_100FULL + jz @f + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) + ; newdup = 1 + mov dword [forcedeth_tmp_newdup], 1 + jmp .set_speed @@: - ; } else if (lpa & LPA_100HALF) { - test eax, LPA_100HALF - jz @f - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) - ; newdup = 0 - mov dword [forcedeth_tmp_newdup], 0 - jmp .set_speed + ; } else if (lpa & LPA_100HALF) { + test eax, LPA_100HALF + jz @f + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_100 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_100) + ; newdup = 0 + mov dword [forcedeth_tmp_newdup], 0 + jmp .set_speed @@: - ; } else if (lpa & LPA_10FULL) { - test eax, LPA_10FULL - jz @f - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) - ; newdup = 1 - mov dword [forcedeth_tmp_newdup], 1 - jmp .set_speed + ; } else if (lpa & LPA_10FULL) { + test eax, LPA_10FULL + jz @f + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; newdup = 1 + mov dword [forcedeth_tmp_newdup], 1 + jmp .set_speed @@: - ; } else if (lpa & LPA_10HALF) { - test eax, LPA_10HALF - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10; - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) - ; newdup = 0; - mov dword [forcedeth_tmp_newdup], 0 - jmp .set_speed + ; } else if (lpa & LPA_10HALF) { + test eax, LPA_10HALF + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10; + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; newdup = 0; + mov dword [forcedeth_tmp_newdup], 0 + jmp .set_speed @@: - ; } else { - ; printf("bad ability %hX - falling back to 10HD.\n", lpa) - DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax + ; } else { + ; printf("bad ability %hX - falling back to 10HD.\n", lpa) + DEBUGF 1," K : FORCEDETH: update_linkspeed: bad ability 0x%x - falling back to 10HD.\n", eax - ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 - mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) - ; newdup = 0 - mov dword [forcedeth_tmp_newdup], 0 - ; } + ; newls = NVREG_LINKSPEED_FORCE | NVREG_LINKSPEED_10 + mov dword [forcedeth_tmp_newls], (NVREG_LINKSPEED_FORCE or NVREG_LINKSPEED_10) + ; newdup = 0 + mov dword [forcedeth_tmp_newdup], 0 + ; } .set_speed: - ; if (np->duplex == newdup && np->linkspeed == newls) - mov eax, dword [forcedeth_tmp_newdup] - cmp eax, dword [forcedeth_duplex] - jne .end_if2 - mov eax, dword [forcedeth_tmp_newls] - cmp eax, dword [forcedeth_linkspeed] - jne .end_if2 - ; return retval; - jmp .return - + ; if (np->duplex == newdup && np->linkspeed == newls) + mov eax, dword [forcedeth_tmp_newdup] + cmp eax, dword [forcedeth_duplex] + jne .end_if2 + mov eax, dword [forcedeth_tmp_newls] + cmp eax, dword [forcedeth_linkspeed] + jne .end_if2 + ; return retval; + jmp .return + .end_if2: - ; dprintf(("changing link setting from %d/%s to %d/%s.\n", - ; np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex")) - DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8 ; !!!!!!!!!!!!!!!!!!!!!!!!!!!! + ; dprintf(("changing link setting from %d/%s to %d/%s.\n", + ; np->linkspeed, np->duplex ? "Full-Duplex": "Half-Duplex", newls, newdup ? "Full-Duplex": "Half-Duplex")) + DEBUGF 1," K : FORCEDETH: update_linkspeed: changing link from %x/XD to %x/XD.\n", [forcedeth_linkspeed]:8, [forcedeth_tmp_newls]:8 ; !!!!!!!!!!!!!!!!!!!!!!!!!!!! - ; np->duplex = newdup - mov eax, dword [forcedeth_tmp_newdup] - mov dword [forcedeth_duplex], eax + ; np->duplex = newdup + mov eax, dword [forcedeth_tmp_newdup] + mov dword [forcedeth_duplex], eax - ; np->linkspeed = newls - mov eax, [forcedeth_tmp_newls] - mov dword [forcedeth_linkspeed], eax + ; np->linkspeed = newls + mov eax, [forcedeth_tmp_newls] + mov dword [forcedeth_linkspeed], eax - ; if (np->gigabit == PHY_GIGABIT) { - cmp dword [forcedeth_gigabit], PHY_GIGABIT - jne .end_if3 + ; if (np->gigabit == PHY_GIGABIT) { + cmp dword [forcedeth_gigabit], PHY_GIGABIT + jne .end_if3 - ; phyreg = readl(base + NvRegRandomSeed); - mov edi, dword [forcedeth_mapio_addr] - mov eax, dword [edi+NvRegRandomSeed] + ; phyreg = readl(base + NvRegRandomSeed); + mov edi, dword [forcedeth_mapio_addr] + mov eax, dword [edi+NvRegRandomSeed] - ; phyreg &= ~(0x3FF00); - and eax, not (0x3FF00) - mov ecx, eax ; phyreg = ecx + ; phyreg &= ~(0x3FF00); + and eax, not (0x3FF00) + mov ecx, eax ; phyreg = ecx - ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) - mov eax, dword [forcedeth_linkspeed] - and eax, 0xFFF - cmp eax, NVREG_LINKSPEED_10 - jne @f - ; phyreg |= NVREG_RNDSEED_FORCE3 - or ecx, NVREG_RNDSEED_FORCE3 - jmp .end_if4 + ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) + mov eax, dword [forcedeth_linkspeed] + and eax, 0xFFF + cmp eax, NVREG_LINKSPEED_10 + jne @f + ; phyreg |= NVREG_RNDSEED_FORCE3 + or ecx, NVREG_RNDSEED_FORCE3 + jmp .end_if4 @@: - ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) - cmp eax, NVREG_LINKSPEED_100 - jne @f - ; phyreg |= NVREG_RNDSEED_FORCE2 - or ecx, NVREG_RNDSEED_FORCE2 - jmp .end_if4 + ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) + cmp eax, NVREG_LINKSPEED_100 + jne @f + ; phyreg |= NVREG_RNDSEED_FORCE2 + or ecx, NVREG_RNDSEED_FORCE2 + jmp .end_if4 @@: - ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) - cmp eax, NVREG_LINKSPEED_1000 - jne .end_if4 - ; phyreg |= NVREG_RNDSEED_FORCE - or ecx, NVREG_RNDSEED_FORCE + ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) + cmp eax, NVREG_LINKSPEED_1000 + jne .end_if4 + ; phyreg |= NVREG_RNDSEED_FORCE + or ecx, NVREG_RNDSEED_FORCE .end_if4: - ; writel(phyreg, base + NvRegRandomSeed) - mov dword [edi+NvRegRandomSeed], ecx + ; writel(phyreg, base + NvRegRandomSeed) + mov dword [edi+NvRegRandomSeed], ecx .end_if3: - ; phyreg = readl(base + NvRegPhyInterface) - mov ecx, dword [edi+NvRegPhyInterface] + ; phyreg = readl(base + NvRegPhyInterface) + mov ecx, dword [edi+NvRegPhyInterface] - ; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000) - and ecx, not (PHY_HALF or PHY_100 or PHY_1000) - - ; if (np->duplex == 0) - cmp dword [forcedeth_duplex], 0 - jne @f - ; phyreg |= PHY_HALF - or ecx, PHY_HALF + ; phyreg &= ~(PHY_HALF | PHY_100 | PHY_1000) + and ecx, not (PHY_HALF or PHY_100 or PHY_1000) + + ; if (np->duplex == 0) + cmp dword [forcedeth_duplex], 0 + jne @f + ; phyreg |= PHY_HALF + or ecx, PHY_HALF @@: - ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) - mov eax, dword [forcedeth_linkspeed] - and eax, 0xFFF - cmp eax, NVREG_LINKSPEED_100 - jne @f - ; phyreg |= PHY_100 - or ecx, PHY_100 - jmp .end_if5 + ; if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) + mov eax, dword [forcedeth_linkspeed] + and eax, 0xFFF + cmp eax, NVREG_LINKSPEED_100 + jne @f + ; phyreg |= PHY_100 + or ecx, PHY_100 + jmp .end_if5 @@: - ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) - cmp eax, NVREG_LINKSPEED_1000 - jne .end_if5 - ; phyreg |= PHY_1000 - or ecx, PHY_1000 + ; else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) + cmp eax, NVREG_LINKSPEED_1000 + jne .end_if5 + ; phyreg |= PHY_1000 + or ecx, PHY_1000 .end_if5: - ; writel(phyreg, base + NvRegPhyInterface) - mov dword [edi+NvRegPhyInterface], ecx + ; writel(phyreg, base + NvRegPhyInterface) + mov dword [edi+NvRegPhyInterface], ecx - ; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1); - cmp dword [forcedeth_duplex], 0 - je @f - mov ecx, 0 - jmp .next + ; writel(NVREG_MISC1_FORCE | (np->duplex ? 0 : NVREG_MISC1_HD), base + NvRegMisc1); + cmp dword [forcedeth_duplex], 0 + je @f + mov ecx, 0 + jmp .next @@: - mov ecx, NVREG_MISC1_HD + mov ecx, NVREG_MISC1_HD .next: - or ecx, NVREG_MISC1_FORCE - mov dword [edi+NvRegMisc1], ecx + or ecx, NVREG_MISC1_FORCE + mov dword [edi+NvRegMisc1], ecx - ; pci_push(base) - call forcedeth_pci_push + ; pci_push(base) + call forcedeth_pci_push - ; writel(np->linkspeed, base + NvRegLinkSpeed) - mov eax, dword [forcedeth_linkspeed] - mov dword [edi+NvRegLinkSpeed], eax + ; writel(np->linkspeed, base + NvRegLinkSpeed) + mov eax, dword [forcedeth_linkspeed] + mov dword [edi+NvRegLinkSpeed], eax - ; pci_push(base) - call forcedeth_pci_push + ; pci_push(base) + call forcedeth_pci_push .return: - ; return retval - mov eax, dword [forcedeth_tmp_retval] - pop edi esi ecx ebx - ret + ; return retval + mov eax, dword [forcedeth_tmp_retval] + pop edi esi ecx ebx + ret - + ; Input: none ; Output: none forcedeth_start_tx: - push edi - ; dprintf(("start_tx\n")) - DEBUGF 1," K : FORCEDETH: start_tx.\n" + push edi + ; dprintf(("start_tx\n")) + DEBUGF 1," K : FORCEDETH: start_tx.\n" - ; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl) - mov edi, dword [forcedeth_mapio_addr] - mov dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START + ; writel(NVREG_XMITCTL_START, base + NvRegTransmitterControl) + mov edi, dword [forcedeth_mapio_addr] + mov dword [edi+NvRegTransmitterControl], NVREG_XMITCTL_START - ; pci_push(base) - call forcedeth_pci_push + ; pci_push(base) + call forcedeth_pci_push .return: - pop edi - ret + pop edi + ret ; Interrupt handler forcedeth_int_handler: - DEBUGF 1," K : FORCEDETH: interrupt handler.\n" + DEBUGF 1," K : FORCEDETH: interrupt handler.\n" - ret - + ret + diff --git a/kernel/trunk/network/eth_drv/drivers/i8255x.inc b/kernel/trunk/network/eth_drv/drivers/i8255x.inc index 3ab4d0628..6abb8dc74 100644 --- a/kernel/trunk/network/eth_drv/drivers/i8255x.inc +++ b/kernel/trunk/network/eth_drv/drivers/i8255x.inc @@ -1,760 +1,794 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ;; -;; I8255X.INC ;; -;; ;; -;; Ethernet driver for Menuet OS ;; -;; ;; -;; Version 0.3 11 August 2003 ;; -;; ;; -;; This driver is based on the eepro100 driver from ;; -;; the etherboot 5.0.6 project. The copyright statement is ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;; remaining parts Copyright 2002 Mike Hibbett, ;; -;; mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;******************************************************************** -; Interface -; I8255x_reset -; I8255x_probe -; I8255x_poll -; I8255x_transmit -; -; These functions are referenced in ethernet.inc -; -;******************************************************************** - - -rxfd_status equ eth_data_start -rxfd_command equ eth_data_start + 2 -rxfd_link equ eth_data_start + 4 -rxfd_rx_buf_addr equ eth_data_start + 8 -rxfd_count equ eth_data_start + 12 -rxfd_size equ eth_data_start + 14 -rxfd_packet equ eth_data_start + 16 - - - -uglobal -eeprom_data: times 16 dd 0 - -align 4 - -lstats: -tx_good_frames: dd 0 -tx_coll16_errs: dd 0 -tx_late_colls: dd 0 -tx_underruns: dd 0 -tx_lost_carrier: dd 0 -tx_deferred: dd 0 -tx_one_colls: dd 0 -tx_multi_colls: dd 0 -tx_total_colls: dd 0 -rx_good_frames: dd 0 -rx_crc_errs: dd 0 -rx_align_errs: dd 0 -rx_resource_errs: dd 0 -rx_overrun_errs: dd 0 -rx_colls_errs: dd 0 -rx_runt_errs: dd 0 -done_marker: dd 0 - -align 4 - -confcmd: -confcmd_status: dw 0 -confcmd_command: dw 0 -confcmd_link: dd 0 -endg - -iglobal -confcmd_data: db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1 - db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2 - db 0x80, 0x3f, 0x05 -endg - -uglobal -align 4 - -txfd: -txfd_status: dw 0 -txfd_command: dw 0 -txfd_link: dd 0 -txfd_tx_desc_addr: dd 0 -txfd_count: dd 0 -txfd_tx_buf_addr0: dd 0 -txfd_tx_buf_size0: dd 0 -txfd_tx_buf_addr1: dd 0 -txfd_tx_buf_size1: dd 0 - -align 4 - -hdr: -hdr_dst_addr: times 6 db 0 -hdr_src_addr: times 6 db 0 -hdr_type: dw 0 -endg - - -;*************************************************************************** -; Function -; wait_for_cmd_done -; -; Description -; waits for the hardware to complete a command -; port address in edx -; -; al destroyed -;*************************************************************************** -wait_for_cmd_done: - in al, dx - cmp al, 0 - jne wait_for_cmd_done - ret - - - -;*************************************************************************** -; Function -; mdio_read -; -; Description -; This probably reads a register in the "physical media interface chip" -; Phy_id in ebx -; location in ecx -; -; Data returned in eax -; -;*************************************************************************** -mdio_read: - mov edx, [io_addr] - add edx, 16 ; SCBCtrlMDI - - mov eax, 0x08000000 - shl ecx, 16 - or eax, ecx - shl ebx, 21 - or eax, ebx - - out dx, eax - -mrlp: - call delay_us - in eax, dx - mov ecx, eax - and ecx, 0x10000000 - jz mrlp - - and eax, 0xffff - ret - - - -;*************************************************************************** -; Function -; mdio_write -; -; Description -; This probably writes a register in the "physical media interface chip" -; Phy_id in ebx -; location in ecx -; data in edx -; Data returned in eax -; -;*************************************************************************** -mdio_write: - mov eax, 0x04000000 - shl ecx, 16 - or eax, ecx - shl ebx, 21 - or eax, ebx - or eax, edx - - mov edx, [io_addr] - add edx, 16 ; SCBCtrlMDI - out dx, eax - -mwlp: - call delay_us - in eax, dx - mov ecx, eax - and ecx, 0x10000000 - jz mwlp - - and eax, 0xffff - ret - - - -;/***********************************************************************/ -;/* I82557 related defines */ -;/***********************************************************************/ - -; Serial EEPROM section. -; A "bit" grungy, but we work our way through bit-by-bit :->. -; EEPROM_Ctrl bits. -EE_SHIFT_CLK equ 0x01 ; EEPROM shift clock. -EE_CS equ 0x02 ; EEPROM chip select. -EE_DATA_WRITE equ 0x04 ; EEPROM chip data in. -EE_DATA_READ equ 0x08 ; EEPROM chip data out. -EE_WRITE_0 equ 0x4802 -EE_WRITE_1 equ 0x4806 -EE_ENB equ 0x4802 - - -; The EEPROM commands include the alway-set leading bit. -EE_READ_CMD equ 6 - -; The SCB accepts the following controls for the Tx and Rx units: -CU_START equ 0x0010 -CU_RESUME equ 0x0020 -CU_STATSADDR equ 0x0040 -CU_SHOWSTATS equ 0x0050 ; Dump statistics counters. -CU_CMD_BASE equ 0x0060 ; Base address to add to add CU commands. -CU_DUMPSTATS equ 0x0070 ; Dump then reset stats counters. - -RX_START equ 0x0001 -RX_RESUME equ 0x0002 -RX_ABORT equ 0x0004 -RX_ADDR_LOAD equ 0x0006 -RX_RESUMENR equ 0x0007 -INT_MASK equ 0x0100 -DRVR_INT equ 0x0200 ; Driver generated interrupt. - - -;*************************************************************************** -; Function -; do_eeprom_cmd -; -; Description -; writes a cmd to the ethernet cards eeprom, by bit bashing -; cmd in ebx -; cmd length in ecx -; return in eax -;*************************************************************************** -do_eeprom_cmd: - mov edx, [io_addr] ; We only require the value in dx - add dx, 14 ; the value SCBeeprom - - mov ax, EE_ENB - out dx, ax - call delay_us - - mov ax, 0x4803 ; EE_ENB | EE_SHIFT_CLK - out dx, ax - call delay_us - - ; dx holds ee_addr - ; ecx holds count - ; eax holds cmd - xor edi, edi ; this will be the receive data - -dec_001: - mov esi, 1 - - dec ecx - shl esi, cl - inc ecx - and esi, ebx - mov eax, EE_WRITE_0 ; I am assuming this doesnt affect the flags.. - cmp esi,0 - jz dec_002 - mov eax, EE_WRITE_1 - -dec_002: - out dx, ax - call delay_us - - or ax, EE_SHIFT_CLK - out dx, ax - call delay_us - - shl edi,1 - - in ax, dx - and ax, EE_DATA_READ - cmp ax,0 - jz dec_003 - inc edi - -dec_003: - loop dec_001 - - mov ax, EE_ENB - out dx, ax - call delay_us - - mov ax, 0x4800 - out dx, ax - call delay_us - - mov eax, edi - - ret - - -;*************************************************************************** -; Function -; I8255x_probe -; Description -; Searches for an ethernet card, enables it and clears the rx buffer -; If a card was found, it enables the ethernet -> TCPIP link -; -;*************************************************************************** -I8255x_probe: - DEBUGF 1," K : Probing i8255x device \n" - mov eax, [io_addr] - - mov ebx, [pci_bus] - mov ecx, [pci_dev] - mov edx, 0x04 ; PCI_COMMAND - call pcibios_read_config_word - - or ax, 0x05 - mov ebx, [pci_bus] - mov ecx, [pci_dev] - mov edx, 0x04 ; PCI_COMMAND - call pcibios_write_config_word - - mov ebx, 0x6000000 - mov ecx, 27 - call do_eeprom_cmd - and eax, 0xffe0000 - cmp eax, 0xffe0000 - je bige - - mov ebx, 0x1800000 - mov ecx, 0x40 - jmp doread - -bige: - mov ebx, 0x6000000 - mov ecx, 0x100 - -doread: - ; do-eeprom-cmd will destroy all registers - ; we have eesize in ecx - ; read_cmd in ebx - - ; Ignore full eeprom - just load the mac address - mov ecx, 0 - -drlp: - push ecx ; save count - push ebx - mov eax, ecx - shl eax, 16 - or ebx, eax - mov ecx, 27 - call do_eeprom_cmd - - pop ebx - pop ecx - - mov edx, ecx - shl edx, 2 - mov esi, eeprom_data - add esi, edx - mov [esi], eax - - inc ecx - cmp ecx, 16 - jne drlp - - ; OK, we have the MAC address. - ; Now reset the card - - mov edx, [io_addr] - add dx, 8 ; SCBPort - xor eax, eax ; The reset cmd == 0 - out dx, eax - - mov esi, 10 - call delay_ms ; Give the card time to warm up. - - mov eax, lstats - mov edx, [io_addr] - add edx, 4 ; SCBPointer - out dx, eax - - mov eax, 0x0140 ; INT_MASK | CU_STATSADDR - mov edx, [io_addr] - add edx, 2 ; SCBCmd - out dx, ax - - call wait_for_cmd_done - - mov eax, 0 - mov edx, [io_addr] - add edx, 4 ; SCBPointer - out dx, eax - - mov eax, 0x0106 ; INT_MASK | RX_ADDR_LOAD - mov edx, [io_addr] - add edx, 2 ; SCBCmd - out dx, ax - - call wait_for_cmd_done - - ; build rxrd structure - mov ax, 0x0001 - mov [rxfd_status], ax - mov ax, 0x0000 - mov [rxfd_command], ax - - mov eax, rxfd_status - sub eax, OS_BASE - mov [rxfd_link], eax - - mov eax, Ether_buffer - sub eax, OS_BASE - mov [rxfd_rx_buf_addr], eax - - mov ax, 0 - mov [rxfd_count], ax - - mov ax, 1528 - mov [rxfd_size], ax - - mov edx, [io_addr] - add edx, 4 ; SCBPointer - - mov eax, rxfd_status - sub eax, OS_BASE - out dx, eax - - mov edx, [io_addr] - add edx, 2 ; SCBCmd - - mov ax, 0x0101 ; INT_MASK | RX_START - out dx, ax - - call wait_for_cmd_done - - ; start the reciver - - mov ax, 0 - mov [rxfd_status], ax - - mov ax, 0xc000 - mov [rxfd_command], ax - - mov edx, [io_addr] - add edx, 4 ; SCBPointer - - mov eax, rxfd_status - sub eax, OS_BASE - out dx, eax - - mov edx, [io_addr] - add edx, 2 ; SCBCmd - - mov ax, 0x0101 ; INT_MASK | RX_START - out dx, ax - - ; Init TX Stuff - - mov edx, [io_addr] - add edx, 4 ; SCBPointer - - mov eax, 0 - out dx, eax - - mov edx, [io_addr] - add edx, 2 ; SCBCmd - - mov ax, 0x0160 ; INT_MASK | CU_CMD_BASE - out dx, ax - - call wait_for_cmd_done - - ; Set TX Base address - - ; First, set up confcmd values - - mov ax, 2 - mov [confcmd_command], ax - mov eax, txfd - sub eax, OS_BASE - mov [confcmd_link], eax - - mov ax, 1 - mov [txfd_command], ax ; CmdIASetup - - mov ax, 0 - mov [txfd_status], ax - - mov eax, confcmd - sub eax, OS_BASE - mov [txfd_link], eax - - - - ; ETH_ALEN is 6 bytes - - mov esi, eeprom_data - mov edi, node_addr - mov ecx, 3 -drp000: - mov eax, [esi] - mov [edi], al - shr eax, 8 - inc edi - mov [edi], al - inc edi - add esi, 4 - loop drp000 - - ; Hard code your MAC address into node_addr at this point, - ; If you cannot read the MAC address from the eeprom in the previous step. - ; You also have to write the mac address into txfd_tx_desc_addr, rather - ; than taking data from eeprom_data - - mov esi, eeprom_data - mov edi, txfd_tx_desc_addr - mov ecx, 3 -drp001: - mov eax, [esi] - mov [edi], al - shr eax, 8 - inc edi - mov [edi], al - inc edi - add esi, 4 - loop drp001 - - - mov esi, eeprom_data + (6 * 4) - mov eax, [esi] - shr eax, 8 - and eax, 0x3f - cmp eax, 4 ; DP83840 - je drp002 - cmp eax, 10 ; DP83840A - je drp002 - jmp drp003 - -drp002: - mov ebx, [esi] - and ebx, 0x1f - push ebx - mov ecx, 23 - call mdio_read - pop ebx - or eax, 0x0422 - mov ecx, 23 - mov edx, eax - call mdio_write - -drp003: - mov ax, 0x4002 ; Cmdsuspend | CmdConfigure - mov [confcmd_command], ax - mov ax, 0 - mov [confcmd_status], ax - mov eax, txfd - mov [confcmd_link], eax - mov ebx, confcmd_data - mov al, 0x88 ; fifo of 8 each - mov [ebx + 1], al - mov al, 0 - mov [ebx + 4], al - mov al, 0x80 - mov [ebx + 5], al - mov al, 0x48 - mov [ebx + 15], al - mov al, 0x80 - mov [ebx + 19], al - mov al, 0x05 - mov [ebx + 21], al - - mov eax, txfd - sub eax, OS_BASE - mov edx, [io_addr] - add edx, 4 ; SCBPointer - out dx, eax - - mov eax, 0x0110 ; INT_MASK | CU_START - mov edx, [io_addr] - add edx, 2 ; SCBCmd - out dx, ax - - call wait_for_cmd_done -jmp skip - - ; wait for thing to start -drp004: - mov ax, [txfd_status] - cmp ax, 0 - je drp004 - -skip: - ; Indicate that we have successfully reset the card - mov eax, [pci_data] - mov [eth_status], eax - -I8255x_exit: - ret - - - -;*************************************************************************** -; Function -; I8255x_reset -; Description -; Place the chip (ie, the ethernet card) into a virgin state -; No inputs -; All registers destroyed -; -;*************************************************************************** -I8255x_reset: - ret - - - -;*************************************************************************** -; Function -; I8255x_poll -; -; Description -; Polls the ethernet card for a received packet -; Received data, if any, ends up in Ether_buffer -; -;*************************************************************************** -I8255x_poll: - mov ax, 0 ; assume no data - mov [eth_rx_data_len], ax - - mov ax, [rxfd_status] - cmp ax, 0 - je i8p_exit - - mov ax, 0 - mov [rxfd_status], ax - - mov ax, 0xc000 - mov [rxfd_command], ax - - mov edx, [io_addr] - add edx, 4 ; SCBPointer - - mov eax, rxfd_status - sub eax, OS_BASE - out dx, eax - - mov edx, [io_addr] - add edx, 2 ; SCBCmd - - mov ax, 0x0101 ; INT_MASK | RX_START - out dx, ax - - call wait_for_cmd_done - - mov esi, rxfd_packet - mov edi, Ether_buffer - mov ecx, 1518 - cld - rep movsb - - mov ax, [rxfd_count] - and ax, 0x3fff - mov [eth_rx_data_len], ax - -i8p_exit: - ret - - - -;*************************************************************************** -; Function -; I8255x_transmit -; -; Description -; Transmits a packet of data via the ethernet card -; Pointer to 48 bit destination address in edi -; Type of packet in bx -; size of packet in ecx -; pointer to packet data in esi -; -;*************************************************************************** -I8255x_transmit: - - mov [hdr_type], bx - - mov eax, [edi] - mov [hdr_dst_addr], eax - mov ax, [edi+4] - mov [hdr_dst_addr+4], ax - - mov eax, [node_addr] - mov [hdr_src_addr], eax - mov ax, [node_addr+4] - mov [hdr_src_addr+4], ax - - mov edx, [io_addr] - in ax, dx - and ax, 0xfc00 - out dx, ax - - xor ax, ax - mov [txfd_status], ax - mov ax, 0x400C ; Cmdsuspend | CmdTx | CmdTxFlex - mov [txfd_command], ax - mov eax, txfd - mov [txfd_link], eax - mov eax, 0x02208000 - mov [txfd_count], eax - mov eax, txfd_tx_buf_addr0 - sub eax, OS_BASE - mov [txfd_tx_desc_addr], eax - mov eax, hdr - sub eax, OS_BASE - mov [txfd_tx_buf_addr0], eax - mov eax, 14 ; sizeof hdr - mov [txfd_tx_buf_size0], eax - - ; Copy the buffer address and size in - mov eax, esi - sub eax, OS_BASE - mov [txfd_tx_buf_addr1], eax - mov eax, ecx - mov [txfd_tx_buf_size1], eax - - mov eax, txfd - sub eax, OS_BASE - mov edx, [io_addr] - add edx, 4 ; SCBPointer - out dx, eax - - mov ax, 0x0110 ; INT_MASK | CU_START - mov edx, [io_addr] - add edx, 2 ; SCBCmd - out dx, ax - - call wait_for_cmd_done - - mov edx, [io_addr] - in ax, dx - -I8t_001: - mov ax, [txfd_status] - cmp ax, 0 - je I8t_001 - - mov edx, [io_addr] - in ax, dx - - ret \ No newline at end of file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; I8255X.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.3 11 August 2003 ;; +;; ;; +;; This driver is based on the eepro100 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2002 Mike Hibbett, ;; +;; mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;******************************************************************** +; Interface +; I8255x_reset +; I8255x_probe +; I8255x_poll +; I8255x_transmit +; +; These functions are referenced in ethernet.inc +; +;******************************************************************** + + +rxfd_status equ eth_data_start +rxfd_command equ eth_data_start + 2 +rxfd_link equ eth_data_start + 4 +rxfd_rx_buf_addr equ eth_data_start + 8 +rxfd_count equ eth_data_start + 12 +rxfd_size equ eth_data_start + 14 +rxfd_packet equ eth_data_start + 16 + + + +uglobal +eeprom_data: + times 16 dd 0 + +align 4 + +lstats: +tx_good_frames: + dd 0 +tx_coll16_errs: + dd 0 +tx_late_colls: + dd 0 +tx_underruns: + dd 0 +tx_lost_carrier: + dd 0 +tx_deferred: + dd 0 +tx_one_colls: + dd 0 +tx_multi_colls: + dd 0 +tx_total_colls: + dd 0 +rx_good_frames: + dd 0 +rx_crc_errs: + dd 0 +rx_align_errs: + dd 0 +rx_resource_errs: + dd 0 +rx_overrun_errs: + dd 0 +rx_colls_errs: + dd 0 +rx_runt_errs: + dd 0 +done_marker: + dd 0 + +align 4 + +confcmd: +confcmd_status: + dw 0 +confcmd_command: + dw 0 +confcmd_link: + dd 0 +endg + +iglobal +confcmd_data: + db 22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1 + db 0, 0x2e, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2 + db 0x80, 0x3f, 0x05 +endg + +uglobal +align 4 + +txfd: +txfd_status: + dw 0 +txfd_command: + dw 0 +txfd_link: + dd 0 +txfd_tx_desc_addr: + dd 0 +txfd_count: + dd 0 +txfd_tx_buf_addr0: + dd 0 +txfd_tx_buf_size0: + dd 0 +txfd_tx_buf_addr1: + dd 0 +txfd_tx_buf_size1: + dd 0 + +align 4 + +hdr: +hdr_dst_addr: + times 6 db 0 +hdr_src_addr: + times 6 db 0 +hdr_type: + dw 0 +endg + + +;*************************************************************************** +; Function +; wait_for_cmd_done +; +; Description +; waits for the hardware to complete a command +; port address in edx +; +; al destroyed +;*************************************************************************** +wait_for_cmd_done: + in al, dx + cmp al, 0 + jne wait_for_cmd_done + ret + + + +;*************************************************************************** +; Function +; mdio_read +; +; Description +; This probably reads a register in the "physical media interface chip" +; Phy_id in ebx +; location in ecx +; +; Data returned in eax +; +;*************************************************************************** +mdio_read: + mov edx, [io_addr] + add edx, 16 ; SCBCtrlMDI + + mov eax, 0x08000000 + shl ecx, 16 + or eax, ecx + shl ebx, 21 + or eax, ebx + + out dx, eax + +mrlp: + call delay_us + in eax, dx + mov ecx, eax + and ecx, 0x10000000 + jz mrlp + + and eax, 0xffff + ret + + + +;*************************************************************************** +; Function +; mdio_write +; +; Description +; This probably writes a register in the "physical media interface chip" +; Phy_id in ebx +; location in ecx +; data in edx +; Data returned in eax +; +;*************************************************************************** +mdio_write: + mov eax, 0x04000000 + shl ecx, 16 + or eax, ecx + shl ebx, 21 + or eax, ebx + or eax, edx + + mov edx, [io_addr] + add edx, 16 ; SCBCtrlMDI + out dx, eax + +mwlp: + call delay_us + in eax, dx + mov ecx, eax + and ecx, 0x10000000 + jz mwlp + + and eax, 0xffff + ret + + + +;/***********************************************************************/ +;/* I82557 related defines */ +;/***********************************************************************/ + +; Serial EEPROM section. +; A "bit" grungy, but we work our way through bit-by-bit :->. +; EEPROM_Ctrl bits. +EE_SHIFT_CLK equ 0x01 ; EEPROM shift clock. +EE_CS equ 0x02 ; EEPROM chip select. +EE_DATA_WRITE equ 0x04 ; EEPROM chip data in. +EE_DATA_READ equ 0x08 ; EEPROM chip data out. +EE_WRITE_0 equ 0x4802 +EE_WRITE_1 equ 0x4806 +EE_ENB equ 0x4802 + + +; The EEPROM commands include the alway-set leading bit. +EE_READ_CMD equ 6 + +; The SCB accepts the following controls for the Tx and Rx units: +CU_START equ 0x0010 +CU_RESUME equ 0x0020 +CU_STATSADDR equ 0x0040 +CU_SHOWSTATS equ 0x0050 ; Dump statistics counters. +CU_CMD_BASE equ 0x0060 ; Base address to add to add CU commands. +CU_DUMPSTATS equ 0x0070 ; Dump then reset stats counters. + +RX_START equ 0x0001 +RX_RESUME equ 0x0002 +RX_ABORT equ 0x0004 +RX_ADDR_LOAD equ 0x0006 +RX_RESUMENR equ 0x0007 +INT_MASK equ 0x0100 +DRVR_INT equ 0x0200 ; Driver generated interrupt. + + +;*************************************************************************** +; Function +; do_eeprom_cmd +; +; Description +; writes a cmd to the ethernet cards eeprom, by bit bashing +; cmd in ebx +; cmd length in ecx +; return in eax +;*************************************************************************** +do_eeprom_cmd: + mov edx, [io_addr]; We only require the value in dx + add dx, 14 ; the value SCBeeprom + + mov ax, EE_ENB + out dx, ax + call delay_us + + mov ax, 0x4803 ; EE_ENB | EE_SHIFT_CLK + out dx, ax + call delay_us + + ; dx holds ee_addr + ; ecx holds count + ; eax holds cmd + xor edi, edi ; this will be the receive data + +dec_001: + mov esi, 1 + + dec ecx + shl esi, cl + inc ecx + and esi, ebx + mov eax, EE_WRITE_0; I am assuming this doesnt affect the flags.. + cmp esi, 0 + jz dec_002 + mov eax, EE_WRITE_1 + +dec_002: + out dx, ax + call delay_us + + or ax, EE_SHIFT_CLK + out dx, ax + call delay_us + + shl edi, 1 + + in ax, dx + and ax, EE_DATA_READ + cmp ax, 0 + jz dec_003 + inc edi + +dec_003: + loop dec_001 + + mov ax, EE_ENB + out dx, ax + call delay_us + + mov ax, 0x4800 + out dx, ax + call delay_us + + mov eax, edi + + ret + + +;*************************************************************************** +; Function +; I8255x_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; +;*************************************************************************** +I8255x_probe: + DEBUGF 1," K : Probing i8255x device \n" + mov eax, [io_addr] + + mov ebx, [pci_bus] + mov ecx, [pci_dev] + mov edx, 0x04 ; PCI_COMMAND + call pcibios_read_config_word + + or ax, 0x05 + mov ebx, [pci_bus] + mov ecx, [pci_dev] + mov edx, 0x04 ; PCI_COMMAND + call pcibios_write_config_word + + mov ebx, 0x6000000 + mov ecx, 27 + call do_eeprom_cmd + and eax, 0xffe0000 + cmp eax, 0xffe0000 + je bige + + mov ebx, 0x1800000 + mov ecx, 0x40 + jmp doread + +bige: + mov ebx, 0x6000000 + mov ecx, 0x100 + +doread: + ; do-eeprom-cmd will destroy all registers + ; we have eesize in ecx + ; read_cmd in ebx + + ; Ignore full eeprom - just load the mac address + mov ecx, 0 + +drlp: + push ecx ; save count + push ebx + mov eax, ecx + shl eax, 16 + or ebx, eax + mov ecx, 27 + call do_eeprom_cmd + + pop ebx + pop ecx + + mov edx, ecx + shl edx, 2 + mov esi, eeprom_data + add esi, edx + mov [esi], eax + + inc ecx + cmp ecx, 16 + jne drlp + + ; OK, we have the MAC address. + ; Now reset the card + + mov edx, [io_addr] + add dx, 8 ; SCBPort + xor eax, eax ; The reset cmd == 0 + out dx, eax + + mov esi, 10 + call delay_ms ; Give the card time to warm up. + + mov eax, lstats + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov eax, 0x0140 ; INT_MASK | CU_STATSADDR + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done + + mov eax, 0 + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov eax, 0x0106 ; INT_MASK | RX_ADDR_LOAD + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done + + ; build rxrd structure + mov ax, 0x0001 + mov [rxfd_status], ax + mov ax, 0x0000 + mov [rxfd_command], ax + + mov eax, rxfd_status + sub eax, OS_BASE + mov [rxfd_link], eax + + mov eax, Ether_buffer + sub eax, OS_BASE + mov [rxfd_rx_buf_addr], eax + + mov ax, 0 + mov [rxfd_count], ax + + mov ax, 1528 + mov [rxfd_size], ax + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, rxfd_status + sub eax, OS_BASE + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0101 ; INT_MASK | RX_START + out dx, ax + + call wait_for_cmd_done + + ; start the reciver + + mov ax, 0 + mov [rxfd_status], ax + + mov ax, 0xc000 + mov [rxfd_command], ax + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, rxfd_status + sub eax, OS_BASE + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0101 ; INT_MASK | RX_START + out dx, ax + + ; Init TX Stuff + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, 0 + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0160 ; INT_MASK | CU_CMD_BASE + out dx, ax + + call wait_for_cmd_done + + ; Set TX Base address + + ; First, set up confcmd values + + mov ax, 2 + mov [confcmd_command], ax + mov eax, txfd + sub eax, OS_BASE + mov [confcmd_link], eax + + mov ax, 1 + mov [txfd_command], ax ; CmdIASetup + + mov ax, 0 + mov [txfd_status], ax + + mov eax, confcmd + sub eax, OS_BASE + mov [txfd_link], eax + + + + ; ETH_ALEN is 6 bytes + + mov esi, eeprom_data + mov edi, node_addr + mov ecx, 3 +drp000: + mov eax, [esi] + mov [edi], al + shr eax, 8 + inc edi + mov [edi], al + inc edi + add esi, 4 + loop drp000 + + ; Hard code your MAC address into node_addr at this point, + ; If you cannot read the MAC address from the eeprom in the previous step. + ; You also have to write the mac address into txfd_tx_desc_addr, rather + ; than taking data from eeprom_data + + mov esi, eeprom_data + mov edi, txfd_tx_desc_addr + mov ecx, 3 +drp001: + mov eax, [esi] + mov [edi], al + shr eax, 8 + inc edi + mov [edi], al + inc edi + add esi, 4 + loop drp001 + + + mov esi, eeprom_data + (6 * 4) + mov eax, [esi] + shr eax, 8 + and eax, 0x3f + cmp eax, 4 ; DP83840 + je drp002 + cmp eax, 10 ; DP83840A + je drp002 + jmp drp003 + +drp002: + mov ebx, [esi] + and ebx, 0x1f + push ebx + mov ecx, 23 + call mdio_read + pop ebx + or eax, 0x0422 + mov ecx, 23 + mov edx, eax + call mdio_write + +drp003: + mov ax, 0x4002 ; Cmdsuspend | CmdConfigure + mov [confcmd_command], ax + mov ax, 0 + mov [confcmd_status], ax + mov eax, txfd + mov [confcmd_link], eax + mov ebx, confcmd_data + mov al, 0x88 ; fifo of 8 each + mov [ebx + 1], al + mov al, 0 + mov [ebx + 4], al + mov al, 0x80 + mov [ebx + 5], al + mov al, 0x48 + mov [ebx + 15], al + mov al, 0x80 + mov [ebx + 19], al + mov al, 0x05 + mov [ebx + 21], al + + mov eax, txfd + sub eax, OS_BASE + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov eax, 0x0110 ; INT_MASK | CU_START + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done + jmp skip + + ; wait for thing to start +drp004: + mov ax, [txfd_status] + cmp ax, 0 + je drp004 + +skip: + ; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax + +I8255x_exit: + ret + + + +;*************************************************************************** +; Function +; I8255x_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; No inputs +; All registers destroyed +; +;*************************************************************************** +I8255x_reset: + ret + + + +;*************************************************************************** +; Function +; I8255x_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; +;*************************************************************************** +I8255x_poll: + mov ax, 0 ; assume no data + mov [eth_rx_data_len], ax + + mov ax, [rxfd_status] + cmp ax, 0 + je i8p_exit + + mov ax, 0 + mov [rxfd_status], ax + + mov ax, 0xc000 + mov [rxfd_command], ax + + mov edx, [io_addr] + add edx, 4 ; SCBPointer + + mov eax, rxfd_status + sub eax, OS_BASE + out dx, eax + + mov edx, [io_addr] + add edx, 2 ; SCBCmd + + mov ax, 0x0101 ; INT_MASK | RX_START + out dx, ax + + call wait_for_cmd_done + + mov esi, rxfd_packet + mov edi, Ether_buffer + mov ecx, 1518 + cld + rep movsb + + mov ax, [rxfd_count] + and ax, 0x3fff + mov [eth_rx_data_len], ax + +i8p_exit: + ret + + + +;*************************************************************************** +; Function +; I8255x_transmit +; +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +;*************************************************************************** +I8255x_transmit: + + mov [hdr_type], bx + + mov eax, [edi] + mov [hdr_dst_addr], eax + mov ax, [edi+4] + mov [hdr_dst_addr+4], ax + + mov eax, [node_addr] + mov [hdr_src_addr], eax + mov ax, [node_addr+4] + mov [hdr_src_addr+4], ax + + mov edx, [io_addr] + in ax, dx + and ax, 0xfc00 + out dx, ax + + xor ax, ax + mov [txfd_status], ax + mov ax, 0x400C ; Cmdsuspend | CmdTx | CmdTxFlex + mov [txfd_command], ax + mov eax, txfd + mov [txfd_link], eax + mov eax, 0x02208000 + mov [txfd_count], eax + mov eax, txfd_tx_buf_addr0 + sub eax, OS_BASE + mov [txfd_tx_desc_addr], eax + mov eax, hdr + sub eax, OS_BASE + mov [txfd_tx_buf_addr0], eax + mov eax, 14; sizeof hdr + mov [txfd_tx_buf_size0], eax + + ; Copy the buffer address and size in + mov eax, esi + sub eax, OS_BASE + mov [txfd_tx_buf_addr1], eax + mov eax, ecx + mov [txfd_tx_buf_size1], eax + + mov eax, txfd + sub eax, OS_BASE + mov edx, [io_addr] + add edx, 4 ; SCBPointer + out dx, eax + + mov ax, 0x0110 ; INT_MASK | CU_START + mov edx, [io_addr] + add edx, 2 ; SCBCmd + out dx, ax + + call wait_for_cmd_done + + mov edx, [io_addr] + in ax, dx + +I8t_001: + mov ax, [txfd_status] + cmp ax, 0 + je I8t_001 + + mov edx, [io_addr] + in ax, dx + + ret diff --git a/kernel/trunk/network/eth_drv/drivers/pcnet32.inc b/kernel/trunk/network/eth_drv/drivers/pcnet32.inc index f328e7105..664633d1c 100644 --- a/kernel/trunk/network/eth_drv/drivers/pcnet32.inc +++ b/kernel/trunk/network/eth_drv/drivers/pcnet32.inc @@ -1,848 +1,848 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; PCNET32.INC ;; -;; ;; -;; Ethernet driver for Menuet OS ;; -;; ;; -;; - Version 1.0 31 July 2004: ;; -;; Initial release ;; -;; ;; -;; - Version 1.01 29 March 2008: ;; -;; Adapted to work with kolibrios flat kernel ;; -;; Debug info is updated, and now uses DEBUGF macro ;; -;; by hidnplayr@kolibrios.org ;; -;; ;; -;; This driver is based on the PCNet32 driver from ;; -;; the etherboot 5.0.6 project. The copyright statement is ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;; remaining parts Copyright 2004 Jarek Pelczar, ;; -;; jpelczar@interia.pl ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -PCNET32_PORT_AUI equ 0x00 -PCNET32_PORT_10BT equ 0x01 -PCNET32_PORT_GPSI equ 0x02 -PCNET32_PORT_MII equ 0x03 -PCNET32_PORT_PORTSEL equ 0x03 -PCNET32_PORT_ASEL equ 0x04 -PCNET32_PORT_100 equ 0x40 -PCNET32_PORT_FD equ 0x80 -PCNET32_DMA_MASK equ 0xffffffff - -PCNET32_LOG_TX_BUFFERS equ 1 -PCNET32_LOG_RX_BUFFERS equ 2 - -PCNET32_TX_RING_SIZE equ (1 shl PCNET32_LOG_TX_BUFFERS) -PCNET32_TX_RING_MOD_MASK equ (PCNET32_TX_RING_SIZE-1) -PCNET32_TX_RING_LEN_BITS equ 0 -PCNET32_RX_RING_SIZE equ (1 shl PCNET32_LOG_RX_BUFFERS) -PCNET32_RX_RING_MOD_MASK equ (PCNET32_RX_RING_SIZE-1) -PCNET32_RX_RING_LEN_BITS equ (PCNET32_LOG_RX_BUFFERS shl 4) -PCNET32_PKT_BUF_SZ equ 1544 -PCNET32_PKT_BUF_SZ_NEG equ 0xf9f8 - -pcnet32_txb equ (eth_data_start) -pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) -pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) -pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) - -virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) -pcnet32_private: -.mode dw ? -.tlen_rlen dw ? -.phys_addr db ?,?,?,?,?,? -.reserved dw ? -.filter dd ?,? -.rx_ring dd ? -.tx_ring dd ? -.cur_rx dd ? -.cur_tx dd ? -.dirty_rx dd ? -.dirty_tx dd ? -.tx_full db ? -.options dd ? -.full_duplex db ? -.chip_version dd ? -.mii db ? -.ltint db ? -.dxsuflo db ? -.fset db ? -.fdx db ? -end virtual - -virtual at 0 -pcnet32_rx_head: -.base dd ? -.buf_length dw ? -.status dw ? -.msg_length dd ? -.reserved dd ? -end virtual - -virtual at 0 -pcnet32_tx_head: -.base dd ? -.length dw ? -.status dw ? -.misc dd ? -.reserved dd ? -end virtual - -uglobal -pcnet32_access: -.read_csr dd ? -.write_csr dd ? -.read_bcr dd ? -.write_bcr dd ? -.read_rap dd ? -.write_rap dd ? -.reset dd ? -endg - -iglobal -pcnet32_options_mapping: -dd PCNET32_PORT_ASEL ; 0 Auto-select -dd PCNET32_PORT_AUI ; 1 BNC/AUI -dd PCNET32_PORT_AUI ; 2 AUI/BNC -dd PCNET32_PORT_ASEL ; 3 not supported -dd PCNET32_PORT_10BT or PCNET32_PORT_FD ; 4 10baseT-FD -dd PCNET32_PORT_ASEL ; 5 not supported -dd PCNET32_PORT_ASEL ; 6 not supported -dd PCNET32_PORT_ASEL ; 7 not supported -dd PCNET32_PORT_ASEL ; 8 not supported -dd PCNET32_PORT_MII ; 9 MII 10baseT -dd PCNET32_PORT_MII or PCNET32_PORT_FD ; 10 MII 10baseT-FD -dd PCNET32_PORT_MII ; 11 MII (autosel) -dd PCNET32_PORT_10BT ; 12 10BaseT -dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx -dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD ; 14 MII 100BaseTx-FD -dd PCNET32_PORT_ASEL ; 15 not supported -endg - -PCNET32_WIO_RDP equ 0x10 -PCNET32_WIO_RAP equ 0x12 -PCNET32_WIO_RESET equ 0x14 -PCNET32_WIO_BDP equ 0x16 -PCNET32_DWIO_RDP equ 0x10 -PCNET32_DWIO_RAP equ 0x14 -PCNET32_DWIO_RESET equ 0x18 -PCNET32_DWIO_BDP equ 0x1C -PCNET32_TOTAL_SIZE equ 0x20 -; ebx - index -; return: -; eax - data -pcnet32_wio_read_csr: - push edx - lea edx,[ebp+PCNET32_WIO_RAP] - mov ax,bx - out dx,ax - lea edx,[ebp+PCNET32_WIO_RDP] - in ax,dx - and eax,0xffff - pop edx - ret -; eax - data -; ebx - index -pcnet32_wio_write_csr: - push edx - lea edx,[ebp+PCNET32_WIO_RAP] - xchg eax,ebx - out dx,ax - xchg eax,ebx - lea edx,[ebp+PCNET32_WIO_RDP] - out dx,ax - pop edx - ret -; ebx - index -; return: -; eax - data -pcnet32_wio_read_bcr: - push edx - lea edx,[ebp+PCNET32_WIO_RAP] - mov ax,bx - out dx,ax - lea edx,[ebp+PCNET32_WIO_BDP] - in ax,dx - and eax,0xffff - pop edx - ret -; eax - data -; ebx - index -pcnet32_wio_write_bcr: - push edx - lea edx,[ebp+PCNET32_WIO_RAP] - xchg eax,ebx - out dx,ax - xchg eax,ebx - lea edx,[ebp+PCNET32_WIO_BDP] - out dx,ax - pop edx - ret -pcnet32_wio_read_rap: - push edx - lea edx,[ebp+PCNET32_WIO_RAP] - in ax,dx - and eax,0xffff - pop edx - ret -; eax - val -pcnet32_wio_write_rap: - push edx - lea edx,[ebp+PCNET32_WIO_RAP] - out dx,ax - pop edx - ret -pcnet32_wio_reset: - push edx - push eax - lea edx,[ebp+PCNET32_WIO_RESET] - in ax,dx - pop eax - pop edx - ret -pcnet32_wio_check: - push edx - mov ax,88 - lea edx,[ebp+PCNET32_WIO_RAP] - out dx,ax - nop - nop - in ax,dx - cmp ax,88 - sete al - pop edx - ret - -iglobal -pcnet32_wio: - dd pcnet32_wio_read_csr - dd pcnet32_wio_write_csr - dd pcnet32_wio_read_bcr - dd pcnet32_wio_write_bcr - dd pcnet32_wio_read_rap - dd pcnet32_wio_write_rap - dd pcnet32_wio_reset -endg - -; ebx - index -; return: -; eax - data -pcnet32_dwio_read_csr: - push edx - lea edx,[ebp+PCNET32_DWIO_RAP] - mov ebx,eax - out dx,eax - lea edx,[ebp+PCNET32_DWIO_RDP] - in eax,dx - and eax,0xffff - pop edx - ret -; ebx - index -; eax - data -pcnet32_dwio_write_csr: - push edx - lea edx,[ebp+PCNET32_DWIO_RAP] - xchg eax,ebx - out dx,eax - lea edx,[ebp+PCNET32_DWIO_RDP] - xchg eax,ebx - out dx,eax - pop edx - ret -; ebx - index -; return: -; eax - data -pcnet32_dwio_read_bcr: - push edx - lea edx,[ebp+PCNET32_DWIO_RAP] - mov ebx,eax - out dx,eax - lea edx,[ebp+PCNET32_DWIO_BDP] - in eax,dx - and eax,0xffff - pop edx - ret -; ebx - index -; eax - data -pcnet32_dwio_write_bcr: - push edx - lea edx,[ebp+PCNET32_DWIO_RAP] - xchg eax,ebx - out dx,eax - lea edx,[ebp+PCNET32_DWIO_BDP] - xchg eax,ebx - out dx,eax - pop edx - ret -pcnet32_dwio_read_rap: - push edx - lea edx,[ebp+PCNET32_DWIO_RAP] - in eax,dx - and eax,0xffff - pop edx - ret -; eax - val -pcnet32_dwio_write_rap: - push edx - lea edx,[ebp+PCNET32_DWIO_RAP] - out dx,eax - pop edx - ret -pcnet32_dwio_reset: - push edx - push eax - lea edx,[ebp+PCNET32_DWIO_RESET] - in eax,dx - pop eax - pop edx - ret -pcnet32_dwio_check: - push edx - lea edx,[PCNET32_DWIO_RAP] - mov eax,88 - out dx,eax - nop - nop - in eax,dx - and eax,0xffff - cmp eax,88 - sete al - pop edx - ret - -iglobal -pcnet32_dwio: - dd pcnet32_dwio_read_csr - dd pcnet32_dwio_write_csr - dd pcnet32_dwio_read_bcr - dd pcnet32_dwio_write_bcr - dd pcnet32_dwio_read_rap - dd pcnet32_dwio_write_rap - dd pcnet32_dwio_reset -endg - - - -pcnet32_init_ring: - mov [pcnet32_private.tx_full],0 - mov [pcnet32_private.cur_rx],0 - mov [pcnet32_private.cur_tx],0 - mov [pcnet32_private.dirty_rx],0 - mov [pcnet32_private.dirty_tx],0 - mov edi,pcnet32_rx_ring - mov ecx,PCNET32_RX_RING_SIZE - mov ebx,pcnet32_rxb - sub ebx,OS_BASE -.rx_init: - mov [edi+pcnet32_rx_head.base],ebx - mov [edi+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG - mov [edi+pcnet32_rx_head.status],word 0x8000 - add ebx,PCNET32_PKT_BUF_SZ -; inc ebx - add edi,16 - loop .rx_init - mov edi,pcnet32_tx_ring - mov ecx,PCNET32_TX_RING_SIZE -.tx_init: - mov [edi+pcnet32_tx_head.base],dword 0 - mov [edi+pcnet32_tx_head.status],word 0 - add edi,16 - loop .tx_init - mov [pcnet32_private.tlen_rlen],(PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) - mov esi,node_addr - mov edi,pcnet32_private.phys_addr - cld - movsd - movsw - mov eax,pcnet32_rx_ring - sub eax,OS_BASE - mov dword [pcnet32_private.rx_ring],eax - - mov eax,pcnet32_tx_ring - sub eax,OS_BASE - mov dword [pcnet32_private.tx_ring],eax - ret - - - -pcnet32_reset: - ; Reset PCNET32 - mov ebp,[io_addr] - call dword [pcnet32_access.reset] - ; set 32bit mode - mov ebx,20 - mov eax,2 - call dword [pcnet32_access.write_bcr] - ; set/reset autoselect bit - mov ebx,2 - call dword [pcnet32_access.read_bcr] - and eax,not 2 - test [pcnet32_private.options],PCNET32_PORT_ASEL - jz .L1 - or eax,2 -.L1: - call dword [pcnet32_access.write_bcr] - ; Handle full duplex setting - cmp byte [pcnet32_private.full_duplex],0 - je .L2 - mov ebx,9 - call dword [pcnet32_access.read_bcr] - and eax,not 3 - test [pcnet32_private.options],PCNET32_PORT_FD - jz .L3 - or eax,1 - cmp [pcnet32_private.options],PCNET32_PORT_FD or PCNET32_PORT_AUI - jne .L4 - or eax,2 - jmp .L4 -.L3: - test [pcnet32_private.options],PCNET32_PORT_ASEL - jz .L4 - cmp [pcnet32_private.chip_version],0x2627 - jne .L4 - or eax,3 -.L4: - mov ebx,9 - call dword [pcnet32_access.write_bcr] -.L2: - ; set/reset GPSI bit - mov ebx,124 - call dword [pcnet32_access.read_csr] - mov ecx,[pcnet32_private.options] - and ecx,PCNET32_PORT_PORTSEL - cmp ecx,PCNET32_PORT_GPSI - jne .L5 - or eax,0x10 -.L5: - call dword [pcnet32_access.write_csr] - cmp [pcnet32_private.mii],0 - je .L6 - test [pcnet32_private.options],PCNET32_PORT_ASEL - jnz .L6 - mov ebx,32 - call dword [pcnet32_access.read_bcr] - and eax,not 0x38 - test [pcnet32_private.options],PCNET32_PORT_FD - jz .L7 - or eax,0x10 -.L7: - test [pcnet32_private.options],PCNET32_PORT_100 - jz .L8 - or eax,0x08 -.L8: - call dword [pcnet32_access.write_bcr] - jmp .L9 -.L6: - test [pcnet32_private.options],PCNET32_PORT_ASEL - jz .L9 - mov ebx,32 -; DEBUGF 1," K : ASEL, enable auto-negotiation\n" - call dword [pcnet32_access.read_bcr] - and eax,not 0x98 - or eax,0x20 - call dword [pcnet32_access.write_bcr] -.L9: - cmp [pcnet32_private.ltint],0 - je .L10 - mov ebx,5 - call dword [pcnet32_access.read_csr] - or eax,(1 shl 14) - call dword [pcnet32_access.write_csr] -.L10: - mov eax,[pcnet32_private.options] - and eax,PCNET32_PORT_PORTSEL - shl eax,7 - mov [pcnet32_private.mode],ax - mov [pcnet32_private.filter],dword 0xffffffff - mov [pcnet32_private.filter+4],dword 0xffffffff - call pcnet32_init_ring - mov ebx,1 - mov eax,pcnet32_private - sub eax,OS_BASE - and eax,0xffff - call dword [pcnet32_access.write_csr] - mov eax,pcnet32_private - sub eax,OS_BASE - mov ebx,2 - shr eax,16 - call dword [pcnet32_access.write_csr] - mov ebx,4 - mov eax,0x0915 - call dword [pcnet32_access.write_csr] - mov ebx,0 - mov eax,1 - call dword [pcnet32_access.write_csr] - mov ecx,100 -.L11: - xor ebx,ebx - call dword [pcnet32_access.read_csr] - test ax,0x100 - jnz .L12 - loop .L11 -.L12: -; DEBUGF 1," K : hardware reset\n" - xor ebx,ebx - mov eax,0x0002 - call dword [pcnet32_access.write_csr] - xor ebx,ebx - call dword [pcnet32_access.read_csr] -; DEBUGF 1," K : PCNET reset complete\n" - ret - - - -pcnet32_adjust_pci_device: - ;*******Get current setting************************ - mov al, 2 ;read a word - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, 0x04 ;from command Register - call pci_read_reg - ;******see if its already set as bus master******** - mov bx, ax - and bx,5 - cmp bx,5 - je pcnet32_adjust_pci_device_Latency - ;******Make card a bus master******* - mov cx, ax ;value to write - mov bh, [pci_dev] - mov al, 2 ;write a word - or cx,5 - mov ah, [pci_bus] - mov bl, 0x04 ;to command register - call pci_write_reg - ;******Check latency setting*********** -pcnet32_adjust_pci_device_Latency: - ;*******Get current latency setting************************ -; mov al, 1 ;read a byte -; mov bh, [pci_dev] -; mov ah, [pci_bus] -; mov bl, 0x0D ;from Lantency Timer Register -; call pci_read_reg - ;******see if its aat least 64 clocks******** -; cmp ax,64 -; jge pcnet32_adjust_pci_device_Done - ;******Set latency to 32 clocks******* -; mov cx, 64 ;value to write -; mov bh, [pci_dev] -; mov al, 1 ;write a byte -; mov ah, [pci_bus] -; mov bl, 0x0D ;to Lantency Timer Register -; call pci_write_reg - ;******Check latency setting*********** -pcnet32_adjust_pci_device_Done: - ret - - - - -pcnet32_probe: - mov ebp,[io_addr] - call pcnet32_wio_reset - xor ebx,ebx - call pcnet32_wio_read_csr - cmp eax,4 - jne .try_dwio - call pcnet32_wio_check - and al,al - jz .try_dwio -; DEBUGF 1," K : Using WIO\n" - mov esi,pcnet32_wio - jmp .L1 -.try_dwio: - call pcnet32_dwio_reset - xor ebx,ebx - call pcnet32_dwio_read_csr - cmp eax,4 - jne .no_dev - call pcnet32_dwio_check - and al,al - jz .no_dev -; DEBUGF 1," K : Using DWIO\n" - mov esi,pcnet32_dwio - jmp .L1 -.no_dev: - DEBUGF 1," K : PCNET32 not found\n" - ret -.L1: - mov edi,pcnet32_access - mov ecx,7 - cld - rep movsd - mov ebx,88 - call dword [pcnet32_access.read_csr] - mov ecx,eax - mov ebx,89 - call dword [pcnet32_access.read_csr] - shl eax,16 - or eax,ecx - mov ecx,eax - and ecx,0xfff - cmp ecx,3 - jne .no_dev - shr eax,12 - and eax,0xffff - mov [pcnet32_private.chip_version],eax -; DEBUGF 1," K : PCNET32 chip version OK\n" - mov [pcnet32_private.fdx],0 - mov [pcnet32_private.mii],0 - mov [pcnet32_private.fset],0 - mov [pcnet32_private.dxsuflo],0 - mov [pcnet32_private.ltint],0 - mov eax,[pcnet32_private.chip_version] - cmp eax,0x2420 - je .L2 - cmp eax,0x2430 - je .L3 - cmp eax,0x2621 - je .L4 - cmp eax,0x2623 - je .L5 - cmp eax,0x2624 - je .L6 - cmp eax,0x2625 - je .L7 - cmp eax,0x2626 - je .L8 - cmp eax,0x2627 - je .L9 - DEBUGF 1," K : Invalid chip rev\n" - jmp .no_dev -.L2: -; DEBUGF 1," K : PCnet/PCI 79C970\n" - jmp .L10 -.L3: -; DEBUGF 1," K : PCnet/PCI 79C970\n" - jmp .L10 -.L4: -; DEBUGF 1," K : PCnet/PCI II 79C970A\n" - mov [pcnet32_private.fdx],1 - jmp .L10 -.L5: -; DEBUGF 1," K : PCnet/FAST 79C971\n" - mov [pcnet32_private.fdx],1 - mov [pcnet32_private.mii],1 - mov [pcnet32_private.fset],1 - mov [pcnet32_private.ltint],1 - jmp .L10 -.L6: -; DEBUGF 1," K : PCnet/FAST+ 79C972\n" - mov [pcnet32_private.fdx],1 - mov [pcnet32_private.mii],1 - mov [pcnet32_private.fset],1 - jmp .L10 -.L7: -; DEBUGF 1," K : PCnet/FAST III 79C973\n" - mov [pcnet32_private.fdx],1 - mov [pcnet32_private.mii],1 - jmp .L10 -.L8: -; DEBUGF 1," K : PCnet/Home 79C978\n" - mov [pcnet32_private.fdx],1 - mov ebx,49 - call dword [pcnet32_access.read_bcr] - call dword [pcnet32_access.write_bcr] - jmp .L10 -.L9: -; DEBUGF 1," K : PCnet/FAST III 79C975\n" - mov [pcnet32_private.fdx],1 - mov [pcnet32_private.mii],1 -.L10: - cmp [pcnet32_private.fset],1 - jne .L11 - mov ebx,18 - call dword [pcnet32_access.read_bcr] - or eax,0x800 - call dword [pcnet32_access.write_bcr] - mov ebx,80 - call dword [pcnet32_access.read_csr] - and eax,0xc00 - or eax,0xc00 - call dword [pcnet32_access.write_csr] - mov [pcnet32_private.dxsuflo],1 - mov [pcnet32_private.ltint],1 -.L11: - ; read MAC - mov edi,node_addr - mov edx,ebp - mov ecx,6 -.Lmac: - in al,dx - stosb - inc edx - loop .Lmac -; DEBUGF 1," K : MAC read\n" - call pcnet32_adjust_pci_device -; DEBUGF 1," K : PCI done\n" - mov eax,PCNET32_PORT_ASEL - mov [pcnet32_private.options],eax - mov [pcnet32_private.mode],word 0x0003 - mov [pcnet32_private.tlen_rlen],word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) - mov esi,node_addr - mov edi,pcnet32_private.phys_addr - cld - movsd - movsw - mov [pcnet32_private.filter],dword 0 - mov [pcnet32_private.filter+4],dword 0 - mov eax,pcnet32_rx_ring - sub eax,OS_BASE - mov dword [pcnet32_private.rx_ring],eax - - mov eax,pcnet32_tx_ring - sub eax,OS_BASE - mov dword [pcnet32_private.tx_ring],eax -; DEBUGF 1," K : Switching to 32\n" - mov ebx,20 - mov eax,2 - call dword [pcnet32_access.write_bcr] - mov ebx,1 - mov eax,(pcnet32_private and 0xffff) - call dword [pcnet32_access.write_csr] - mov ebx,2 - mov eax,(pcnet32_private shr 16) and 0xffff - call dword [pcnet32_access.write_csr] - mov ebx,0 - mov eax,1 - call dword [pcnet32_access.write_csr] - mov esi,1 - call delay_ms - call pcnet32_reset - mov eax, [pci_data] - mov [eth_status], eax - ret - - - -pcnet32_poll: - xor ax,ax - mov [eth_rx_data_len],ax - mov eax,[pcnet32_private.cur_rx] - and eax,PCNET32_RX_RING_MOD_MASK - mov ebx,eax - imul esi,eax,PCNET32_PKT_BUF_SZ - add esi,pcnet32_rxb - shl ebx,4 - add ebx,pcnet32_rx_ring - mov cx,[ebx+pcnet32_rx_head.status] - test cx,0x8000 - jnz .L1 - cmp ch,3 - jne .L1 - mov ecx,[ebx+pcnet32_rx_head.msg_length] - and ecx,0xfff - sub ecx,4 - mov [eth_rx_data_len],cx -; DEBUGF 1," K : PCNETRX: %ub\n",cx - push ecx - shr ecx,2 - mov edi,Ether_buffer - cld - rep movsd - pop ecx - and ecx,3 - rep movsb - mov [ebx+pcnet32_rx_head.buf_length],word PCNET32_PKT_BUF_SZ_NEG - or [ebx+pcnet32_rx_head.status],word 0x8000 - inc [pcnet32_private.cur_rx] -.L1: - ret - - - - -; Pointer to 48 bit destination address in edi -; Type of packet in bx -; size of packet in ecx -; pointer to packet data in esi -pcnet32_xmit: - push edi - push esi - push ebx - push ecx -; DEBUGF 1," K : PCNETTX\n" - mov esi,edi - mov edi,[pcnet32_private.cur_tx] - imul edi,PCNET32_PKT_BUF_SZ - add edi,pcnet32_txb ; edi=ptxb - mov eax,edi - cld ; copy MAC - movsd - movsw - mov esi,node_addr - cld - movsd - movsw - mov [edi],bx - add edi,2 - mov esi,[esp+8] - mov ecx,[esp] - push ecx - shr ecx,2 - cld - rep movsd - pop ecx - and ecx,3 - rep movsb -; mov ecx,[esp] -; add ecx,14 ; ETH_HLEN -; xor eax,eax -; pad to min length (60=ETH_ZLEN) -; cmp ecx,60 -; jae .L1 -; sub ecx,60 -; cld -; rep stosb -;.L1: - mov edi,pcnet32_tx_ring+0 ; entry=0 - mov ecx,[esp] - add ecx,14 - cmp cx,60 - jae .L1 - mov cx,60 -.L1: - neg cx - mov [edi+pcnet32_tx_head.length],cx - mov [edi+pcnet32_tx_head.misc],dword 0 - sub eax,OS_BASE - mov [edi+pcnet32_tx_head.base],eax - mov [edi+pcnet32_tx_head.status],word 0x8300 - ; trigger an immediate send poll - mov ebx,0 - mov eax,0x0008 ; 0x0048 - mov ebp,[io_addr] - call dword [pcnet32_access.write_csr] - mov dword [pcnet32_private.cur_tx],0 - ; wait for TX to complete - mov ecx,[timer_ticks];[0xfdf0] - add ecx,100 -.L2: - mov ax,[edi+pcnet32_tx_head.status] - test ax,0x8000 - jz .L3 - cmp ecx,[timer_ticks];[0xfdf0] - jb .L4 - mov esi,10 - call delay_ms - jnz .L2 -.L4: - DEBUGF 1," K : PCNET: Send timeout\n" -.L3: - mov dword [edi+pcnet32_tx_head.base],0 - pop ecx - pop ebx - pop esi - pop edi - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; PCNET32.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; - Version 1.0 31 July 2004: ;; +;; Initial release ;; +;; ;; +;; - Version 1.01 29 March 2008: ;; +;; Adapted to work with kolibrios flat kernel ;; +;; Debug info is updated, and now uses DEBUGF macro ;; +;; by hidnplayr@kolibrios.org ;; +;; ;; +;; This driver is based on the PCNet32 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2004 Jarek Pelczar, ;; +;; jpelczar@interia.pl ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +PCNET32_PORT_AUI equ 0x00 +PCNET32_PORT_10BT equ 0x01 +PCNET32_PORT_GPSI equ 0x02 +PCNET32_PORT_MII equ 0x03 +PCNET32_PORT_PORTSEL equ 0x03 +PCNET32_PORT_ASEL equ 0x04 +PCNET32_PORT_100 equ 0x40 +PCNET32_PORT_FD equ 0x80 +PCNET32_DMA_MASK equ 0xffffffff + +PCNET32_LOG_TX_BUFFERS equ 1 +PCNET32_LOG_RX_BUFFERS equ 2 + +PCNET32_TX_RING_SIZE equ (1 shl PCNET32_LOG_TX_BUFFERS) +PCNET32_TX_RING_MOD_MASK equ (PCNET32_TX_RING_SIZE-1) +PCNET32_TX_RING_LEN_BITS equ 0 +PCNET32_RX_RING_SIZE equ (1 shl PCNET32_LOG_RX_BUFFERS) +PCNET32_RX_RING_MOD_MASK equ (PCNET32_RX_RING_SIZE-1) +PCNET32_RX_RING_LEN_BITS equ (PCNET32_LOG_RX_BUFFERS shl 4) +PCNET32_PKT_BUF_SZ equ 1544 +PCNET32_PKT_BUF_SZ_NEG equ 0xf9f8 + +pcnet32_txb equ (eth_data_start) +pcnet32_rxb equ ((pcnet32_txb+(PCNET32_PKT_BUF_SZ*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) +pcnet32_tx_ring equ ((pcnet32_rxb+(PCNET32_PKT_BUF_SZ*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) +pcnet32_rx_ring equ ((pcnet32_tx_ring+(16*PCNET32_TX_RING_SIZE)+0xf) and 0xfffffff0) + +virtual at ((pcnet32_rx_ring+(16*PCNET32_RX_RING_SIZE)+0xf) and 0xfffffff0) +pcnet32_private: +.mode dw ? +.tlen_rlen dw ? +.phys_addr db ?,?,?,?,?,? +.reserved dw ? +.filter dd ?,? +.rx_ring dd ? +.tx_ring dd ? +.cur_rx dd ? +.cur_tx dd ? +.dirty_rx dd ? +.dirty_tx dd ? +.tx_full db ? +.options dd ? +.full_duplex db ? +.chip_version dd ? +.mii db ? +.ltint db ? +.dxsuflo db ? +.fset db ? +.fdx db ? +end virtual + +virtual at 0 +pcnet32_rx_head: +.base dd ? +.buf_length dw ? +.status dw ? +.msg_length dd ? +.reserved dd ? +end virtual + +virtual at 0 +pcnet32_tx_head: +.base dd ? +.length dw ? +.status dw ? +.misc dd ? +.reserved dd ? +end virtual + +uglobal +pcnet32_access: +.read_csr dd ? +.write_csr dd ? +.read_bcr dd ? +.write_bcr dd ? +.read_rap dd ? +.write_rap dd ? +.reset dd ? +endg + +iglobal +pcnet32_options_mapping: +dd PCNET32_PORT_ASEL ; 0 Auto-select +dd PCNET32_PORT_AUI ; 1 BNC/AUI +dd PCNET32_PORT_AUI ; 2 AUI/BNC +dd PCNET32_PORT_ASEL ; 3 not supported +dd PCNET32_PORT_10BT or PCNET32_PORT_FD ; 4 10baseT-FD +dd PCNET32_PORT_ASEL ; 5 not supported +dd PCNET32_PORT_ASEL ; 6 not supported +dd PCNET32_PORT_ASEL ; 7 not supported +dd PCNET32_PORT_ASEL ; 8 not supported +dd PCNET32_PORT_MII ; 9 MII 10baseT +dd PCNET32_PORT_MII or PCNET32_PORT_FD ; 10 MII 10baseT-FD +dd PCNET32_PORT_MII ; 11 MII (autosel) +dd PCNET32_PORT_10BT ; 12 10BaseT +dd PCNET32_PORT_MII or PCNET32_PORT_100 ; 13 MII 100BaseTx +dd PCNET32_PORT_MII or PCNET32_PORT_100 or PCNET32_PORT_FD ; 14 MII 100BaseTx-FD +dd PCNET32_PORT_ASEL ; 15 not supported +endg + +PCNET32_WIO_RDP equ 0x10 +PCNET32_WIO_RAP equ 0x12 +PCNET32_WIO_RESET equ 0x14 +PCNET32_WIO_BDP equ 0x16 +PCNET32_DWIO_RDP equ 0x10 +PCNET32_DWIO_RAP equ 0x14 +PCNET32_DWIO_RESET equ 0x18 +PCNET32_DWIO_BDP equ 0x1C +PCNET32_TOTAL_SIZE equ 0x20 +; ebx - index +; return: +; eax - data +pcnet32_wio_read_csr: + push edx + lea edx, [ebp+PCNET32_WIO_RAP] + mov ax, bx + out dx, ax + lea edx, [ebp+PCNET32_WIO_RDP] + in ax, dx + and eax, 0xffff + pop edx + ret +; eax - data +; ebx - index +pcnet32_wio_write_csr: + push edx + lea edx, [ebp+PCNET32_WIO_RAP] + xchg eax, ebx + out dx, ax + xchg eax, ebx + lea edx, [ebp+PCNET32_WIO_RDP] + out dx, ax + pop edx + ret +; ebx - index +; return: +; eax - data +pcnet32_wio_read_bcr: + push edx + lea edx, [ebp+PCNET32_WIO_RAP] + mov ax, bx + out dx, ax + lea edx, [ebp+PCNET32_WIO_BDP] + in ax, dx + and eax, 0xffff + pop edx + ret +; eax - data +; ebx - index +pcnet32_wio_write_bcr: + push edx + lea edx, [ebp+PCNET32_WIO_RAP] + xchg eax, ebx + out dx, ax + xchg eax, ebx + lea edx, [ebp+PCNET32_WIO_BDP] + out dx, ax + pop edx + ret +pcnet32_wio_read_rap: + push edx + lea edx, [ebp+PCNET32_WIO_RAP] + in ax, dx + and eax, 0xffff + pop edx + ret +; eax - val +pcnet32_wio_write_rap: + push edx + lea edx, [ebp+PCNET32_WIO_RAP] + out dx, ax + pop edx + ret +pcnet32_wio_reset: + push edx + push eax + lea edx, [ebp+PCNET32_WIO_RESET] + in ax, dx + pop eax + pop edx + ret +pcnet32_wio_check: + push edx + mov ax, 88 + lea edx, [ebp+PCNET32_WIO_RAP] + out dx, ax + nop + nop + in ax, dx + cmp ax, 88 + sete al + pop edx + ret + +iglobal +pcnet32_wio: + dd pcnet32_wio_read_csr + dd pcnet32_wio_write_csr + dd pcnet32_wio_read_bcr + dd pcnet32_wio_write_bcr + dd pcnet32_wio_read_rap + dd pcnet32_wio_write_rap + dd pcnet32_wio_reset +endg + +; ebx - index +; return: +; eax - data +pcnet32_dwio_read_csr: + push edx + lea edx, [ebp+PCNET32_DWIO_RAP] + mov ebx, eax + out dx, eax + lea edx, [ebp+PCNET32_DWIO_RDP] + in eax, dx + and eax, 0xffff + pop edx + ret +; ebx - index +; eax - data +pcnet32_dwio_write_csr: + push edx + lea edx, [ebp+PCNET32_DWIO_RAP] + xchg eax, ebx + out dx, eax + lea edx, [ebp+PCNET32_DWIO_RDP] + xchg eax, ebx + out dx, eax + pop edx + ret +; ebx - index +; return: +; eax - data +pcnet32_dwio_read_bcr: + push edx + lea edx, [ebp+PCNET32_DWIO_RAP] + mov ebx, eax + out dx, eax + lea edx, [ebp+PCNET32_DWIO_BDP] + in eax, dx + and eax, 0xffff + pop edx + ret +; ebx - index +; eax - data +pcnet32_dwio_write_bcr: + push edx + lea edx, [ebp+PCNET32_DWIO_RAP] + xchg eax, ebx + out dx, eax + lea edx, [ebp+PCNET32_DWIO_BDP] + xchg eax, ebx + out dx, eax + pop edx + ret +pcnet32_dwio_read_rap: + push edx + lea edx, [ebp+PCNET32_DWIO_RAP] + in eax, dx + and eax, 0xffff + pop edx + ret +; eax - val +pcnet32_dwio_write_rap: + push edx + lea edx, [ebp+PCNET32_DWIO_RAP] + out dx, eax + pop edx + ret +pcnet32_dwio_reset: + push edx + push eax + lea edx, [ebp+PCNET32_DWIO_RESET] + in eax, dx + pop eax + pop edx + ret +pcnet32_dwio_check: + push edx + lea edx, [PCNET32_DWIO_RAP] + mov eax, 88 + out dx, eax + nop + nop + in eax, dx + and eax, 0xffff + cmp eax, 88 + sete al + pop edx + ret + +iglobal +pcnet32_dwio: + dd pcnet32_dwio_read_csr + dd pcnet32_dwio_write_csr + dd pcnet32_dwio_read_bcr + dd pcnet32_dwio_write_bcr + dd pcnet32_dwio_read_rap + dd pcnet32_dwio_write_rap + dd pcnet32_dwio_reset +endg + + + +pcnet32_init_ring: + mov [pcnet32_private.tx_full], 0 + mov [pcnet32_private.cur_rx], 0 + mov [pcnet32_private.cur_tx], 0 + mov [pcnet32_private.dirty_rx], 0 + mov [pcnet32_private.dirty_tx], 0 + mov edi, pcnet32_rx_ring + mov ecx, PCNET32_RX_RING_SIZE + mov ebx, pcnet32_rxb + sub ebx, OS_BASE +.rx_init: + mov [edi+pcnet32_rx_head.base], ebx + mov [edi+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG + mov [edi+pcnet32_rx_head.status], word 0x8000 + add ebx, PCNET32_PKT_BUF_SZ +; inc ebx + add edi, 16 + loop .rx_init + mov edi, pcnet32_tx_ring + mov ecx, PCNET32_TX_RING_SIZE +.tx_init: + mov [edi+pcnet32_tx_head.base], dword 0 + mov [edi+pcnet32_tx_head.status], word 0 + add edi, 16 + loop .tx_init + mov [pcnet32_private.tlen_rlen], (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) + mov esi, node_addr + mov edi, pcnet32_private.phys_addr + cld + movsd + movsw + mov eax, pcnet32_rx_ring + sub eax, OS_BASE + mov dword [pcnet32_private.rx_ring], eax + + mov eax, pcnet32_tx_ring + sub eax, OS_BASE + mov dword [pcnet32_private.tx_ring], eax + ret + + + +pcnet32_reset: + ; Reset PCNET32 + mov ebp, [io_addr] + call dword [pcnet32_access.reset] + ; set 32bit mode + mov ebx, 20 + mov eax, 2 + call dword [pcnet32_access.write_bcr] + ; set/reset autoselect bit + mov ebx, 2 + call dword [pcnet32_access.read_bcr] + and eax, not 2 + test [pcnet32_private.options], PCNET32_PORT_ASEL + jz .L1 + or eax, 2 +.L1: + call dword [pcnet32_access.write_bcr] + ; Handle full duplex setting + cmp byte [pcnet32_private.full_duplex], 0 + je .L2 + mov ebx, 9 + call dword [pcnet32_access.read_bcr] + and eax, not 3 + test [pcnet32_private.options], PCNET32_PORT_FD + jz .L3 + or eax, 1 + cmp [pcnet32_private.options], PCNET32_PORT_FD or PCNET32_PORT_AUI + jne .L4 + or eax, 2 + jmp .L4 +.L3: + test [pcnet32_private.options], PCNET32_PORT_ASEL + jz .L4 + cmp [pcnet32_private.chip_version], 0x2627 + jne .L4 + or eax, 3 +.L4: + mov ebx, 9 + call dword [pcnet32_access.write_bcr] +.L2: + ; set/reset GPSI bit + mov ebx, 124 + call dword [pcnet32_access.read_csr] + mov ecx, [pcnet32_private.options] + and ecx, PCNET32_PORT_PORTSEL + cmp ecx, PCNET32_PORT_GPSI + jne .L5 + or eax, 0x10 +.L5: + call dword [pcnet32_access.write_csr] + cmp [pcnet32_private.mii], 0 + je .L6 + test [pcnet32_private.options], PCNET32_PORT_ASEL + jnz .L6 + mov ebx, 32 + call dword [pcnet32_access.read_bcr] + and eax, not 0x38 + test [pcnet32_private.options], PCNET32_PORT_FD + jz .L7 + or eax, 0x10 +.L7: + test [pcnet32_private.options], PCNET32_PORT_100 + jz .L8 + or eax, 0x08 +.L8: + call dword [pcnet32_access.write_bcr] + jmp .L9 +.L6: + test [pcnet32_private.options], PCNET32_PORT_ASEL + jz .L9 + mov ebx, 32 +; DEBUGF 1," K : ASEL, enable auto-negotiation\n" + call dword [pcnet32_access.read_bcr] + and eax, not 0x98 + or eax, 0x20 + call dword [pcnet32_access.write_bcr] +.L9: + cmp [pcnet32_private.ltint], 0 + je .L10 + mov ebx, 5 + call dword [pcnet32_access.read_csr] + or eax, (1 shl 14) + call dword [pcnet32_access.write_csr] +.L10: + mov eax, [pcnet32_private.options] + and eax, PCNET32_PORT_PORTSEL + shl eax, 7 + mov [pcnet32_private.mode], ax + mov [pcnet32_private.filter], dword 0xffffffff + mov [pcnet32_private.filter+4], dword 0xffffffff + call pcnet32_init_ring + mov ebx, 1 + mov eax, pcnet32_private + sub eax, OS_BASE + and eax, 0xffff + call dword [pcnet32_access.write_csr] + mov eax, pcnet32_private + sub eax, OS_BASE + mov ebx, 2 + shr eax, 16 + call dword [pcnet32_access.write_csr] + mov ebx, 4 + mov eax, 0x0915 + call dword [pcnet32_access.write_csr] + mov ebx, 0 + mov eax, 1 + call dword [pcnet32_access.write_csr] + mov ecx, 100 +.L11: + xor ebx, ebx + call dword [pcnet32_access.read_csr] + test ax, 0x100 + jnz .L12 + loop .L11 +.L12: +; DEBUGF 1," K : hardware reset\n" + xor ebx, ebx + mov eax, 0x0002 + call dword [pcnet32_access.write_csr] + xor ebx, ebx + call dword [pcnet32_access.read_csr] +; DEBUGF 1," K : PCNET reset complete\n" + ret + + + +pcnet32_adjust_pci_device: + ;*******Get current setting************************ + mov al, 2 ;read a word + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x04 ;from command Register + call pci_read_reg + ;******see if its already set as bus master******** + mov bx, ax + and bx, 5 + cmp bx, 5 + je pcnet32_adjust_pci_device_Latency + ;******Make card a bus master******* + mov cx, ax ;value to write + mov bh, [pci_dev] + mov al, 2 ;write a word + or cx, 5 + mov ah, [pci_bus] + mov bl, 0x04 ;to command register + call pci_write_reg + ;******Check latency setting*********** +pcnet32_adjust_pci_device_Latency: + ;*******Get current latency setting************************ +; mov al, 1 ;read a byte +; mov bh, [pci_dev] +; mov ah, [pci_bus] +; mov bl, 0x0D ;from Lantency Timer Register +; call pci_read_reg + ;******see if its aat least 64 clocks******** +; cmp ax,64 +; jge pcnet32_adjust_pci_device_Done + ;******Set latency to 32 clocks******* +; mov cx, 64 ;value to write +; mov bh, [pci_dev] +; mov al, 1 ;write a byte +; mov ah, [pci_bus] +; mov bl, 0x0D ;to Lantency Timer Register +; call pci_write_reg + ;******Check latency setting*********** +pcnet32_adjust_pci_device_Done: + ret + + + + +pcnet32_probe: + mov ebp, [io_addr] + call pcnet32_wio_reset + xor ebx, ebx + call pcnet32_wio_read_csr + cmp eax, 4 + jne .try_dwio + call pcnet32_wio_check + and al, al + jz .try_dwio +; DEBUGF 1," K : Using WIO\n" + mov esi, pcnet32_wio + jmp .L1 +.try_dwio: + call pcnet32_dwio_reset + xor ebx, ebx + call pcnet32_dwio_read_csr + cmp eax, 4 + jne .no_dev + call pcnet32_dwio_check + and al, al + jz .no_dev +; DEBUGF 1," K : Using DWIO\n" + mov esi, pcnet32_dwio + jmp .L1 +.no_dev: + DEBUGF 1," K : PCNET32 not found\n" + ret +.L1: + mov edi, pcnet32_access + mov ecx, 7 + cld + rep movsd + mov ebx, 88 + call dword [pcnet32_access.read_csr] + mov ecx, eax + mov ebx, 89 + call dword [pcnet32_access.read_csr] + shl eax, 16 + or eax, ecx + mov ecx, eax + and ecx, 0xfff + cmp ecx, 3 + jne .no_dev + shr eax, 12 + and eax, 0xffff + mov [pcnet32_private.chip_version], eax +; DEBUGF 1," K : PCNET32 chip version OK\n" + mov [pcnet32_private.fdx], 0 + mov [pcnet32_private.mii], 0 + mov [pcnet32_private.fset], 0 + mov [pcnet32_private.dxsuflo], 0 + mov [pcnet32_private.ltint], 0 + mov eax, [pcnet32_private.chip_version] + cmp eax, 0x2420 + je .L2 + cmp eax, 0x2430 + je .L3 + cmp eax, 0x2621 + je .L4 + cmp eax, 0x2623 + je .L5 + cmp eax, 0x2624 + je .L6 + cmp eax, 0x2625 + je .L7 + cmp eax, 0x2626 + je .L8 + cmp eax, 0x2627 + je .L9 + DEBUGF 1," K : Invalid chip rev\n" + jmp .no_dev +.L2: +; DEBUGF 1," K : PCnet/PCI 79C970\n" + jmp .L10 +.L3: +; DEBUGF 1," K : PCnet/PCI 79C970\n" + jmp .L10 +.L4: +; DEBUGF 1," K : PCnet/PCI II 79C970A\n" + mov [pcnet32_private.fdx], 1 + jmp .L10 +.L5: +; DEBUGF 1," K : PCnet/FAST 79C971\n" + mov [pcnet32_private.fdx], 1 + mov [pcnet32_private.mii], 1 + mov [pcnet32_private.fset], 1 + mov [pcnet32_private.ltint], 1 + jmp .L10 +.L6: +; DEBUGF 1," K : PCnet/FAST+ 79C972\n" + mov [pcnet32_private.fdx], 1 + mov [pcnet32_private.mii], 1 + mov [pcnet32_private.fset], 1 + jmp .L10 +.L7: +; DEBUGF 1," K : PCnet/FAST III 79C973\n" + mov [pcnet32_private.fdx], 1 + mov [pcnet32_private.mii], 1 + jmp .L10 +.L8: +; DEBUGF 1," K : PCnet/Home 79C978\n" + mov [pcnet32_private.fdx], 1 + mov ebx, 49 + call dword [pcnet32_access.read_bcr] + call dword [pcnet32_access.write_bcr] + jmp .L10 +.L9: +; DEBUGF 1," K : PCnet/FAST III 79C975\n" + mov [pcnet32_private.fdx], 1 + mov [pcnet32_private.mii], 1 +.L10: + cmp [pcnet32_private.fset], 1 + jne .L11 + mov ebx, 18 + call dword [pcnet32_access.read_bcr] + or eax, 0x800 + call dword [pcnet32_access.write_bcr] + mov ebx, 80 + call dword [pcnet32_access.read_csr] + and eax, 0xc00 + or eax, 0xc00 + call dword [pcnet32_access.write_csr] + mov [pcnet32_private.dxsuflo], 1 + mov [pcnet32_private.ltint], 1 +.L11: + ; read MAC + mov edi, node_addr + mov edx, ebp + mov ecx, 6 +.Lmac: + in al, dx + stosb + inc edx + loop .Lmac +; DEBUGF 1," K : MAC read\n" + call pcnet32_adjust_pci_device +; DEBUGF 1," K : PCI done\n" + mov eax, PCNET32_PORT_ASEL + mov [pcnet32_private.options], eax + mov [pcnet32_private.mode], word 0x0003 + mov [pcnet32_private.tlen_rlen], word (PCNET32_TX_RING_LEN_BITS or PCNET32_RX_RING_LEN_BITS) + mov esi, node_addr + mov edi, pcnet32_private.phys_addr + cld + movsd + movsw + mov [pcnet32_private.filter], dword 0 + mov [pcnet32_private.filter+4], dword 0 + mov eax, pcnet32_rx_ring + sub eax, OS_BASE + mov dword [pcnet32_private.rx_ring], eax + + mov eax, pcnet32_tx_ring + sub eax, OS_BASE + mov dword [pcnet32_private.tx_ring], eax +; DEBUGF 1," K : Switching to 32\n" + mov ebx, 20 + mov eax, 2 + call dword [pcnet32_access.write_bcr] + mov ebx, 1 + mov eax, (pcnet32_private and 0xffff) + call dword [pcnet32_access.write_csr] + mov ebx, 2 + mov eax, (pcnet32_private shr 16) and 0xffff + call dword [pcnet32_access.write_csr] + mov ebx, 0 + mov eax, 1 + call dword [pcnet32_access.write_csr] + mov esi, 1 + call delay_ms + call pcnet32_reset + mov eax, [pci_data] + mov [eth_status], eax + ret + + + +pcnet32_poll: + xor ax, ax + mov [eth_rx_data_len], ax + mov eax, [pcnet32_private.cur_rx] + and eax, PCNET32_RX_RING_MOD_MASK + mov ebx, eax + imul esi, eax, PCNET32_PKT_BUF_SZ + add esi, pcnet32_rxb + shl ebx, 4 + add ebx, pcnet32_rx_ring + mov cx, [ebx+pcnet32_rx_head.status] + test cx, 0x8000 + jnz .L1 + cmp ch, 3 + jne .L1 + mov ecx, [ebx+pcnet32_rx_head.msg_length] + and ecx, 0xfff + sub ecx, 4 + mov [eth_rx_data_len], cx +; DEBUGF 1," K : PCNETRX: %ub\n",cx + push ecx + shr ecx, 2 + mov edi, Ether_buffer + cld + rep movsd + pop ecx + and ecx, 3 + rep movsb + mov [ebx+pcnet32_rx_head.buf_length], word PCNET32_PKT_BUF_SZ_NEG + or [ebx+pcnet32_rx_head.status], word 0x8000 + inc [pcnet32_private.cur_rx] +.L1: + ret + + + + +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +pcnet32_xmit: + push edi + push esi + push ebx + push ecx +; DEBUGF 1," K : PCNETTX\n" + mov esi, edi + mov edi, [pcnet32_private.cur_tx] + imul edi, PCNET32_PKT_BUF_SZ + add edi, pcnet32_txb; edi=ptxb + mov eax, edi + cld ; copy MAC + movsd + movsw + mov esi, node_addr + cld + movsd + movsw + mov [edi], bx + add edi, 2 + mov esi, [esp+8] + mov ecx, [esp] + push ecx + shr ecx, 2 + cld + rep movsd + pop ecx + and ecx, 3 + rep movsb +; mov ecx,[esp] +; add ecx,14 ; ETH_HLEN +; xor eax,eax +; pad to min length (60=ETH_ZLEN) +; cmp ecx,60 +; jae .L1 +; sub ecx,60 +; cld +; rep stosb +;.L1: + mov edi, pcnet32_tx_ring+0; entry=0 + mov ecx, [esp] + add ecx, 14 + cmp cx, 60 + jae .L1 + mov cx, 60 +.L1: + neg cx + mov [edi+pcnet32_tx_head.length], cx + mov [edi+pcnet32_tx_head.misc], dword 0 + sub eax, OS_BASE + mov [edi+pcnet32_tx_head.base], eax + mov [edi+pcnet32_tx_head.status], word 0x8300 + ; trigger an immediate send poll + mov ebx, 0 + mov eax, 0x0008; 0x0048 + mov ebp, [io_addr] + call dword [pcnet32_access.write_csr] + mov dword [pcnet32_private.cur_tx], 0 + ; wait for TX to complete + mov ecx, [timer_ticks];[0xfdf0] + add ecx, 100 +.L2: + mov ax, [edi+pcnet32_tx_head.status] + test ax, 0x8000 + jz .L3 + cmp ecx, [timer_ticks];[0xfdf0] + jb .L4 + mov esi, 10 + call delay_ms + jnz .L2 +.L4: + DEBUGF 1," K : PCNET: Send timeout\n" +.L3: + mov dword [edi+pcnet32_tx_head.base], 0 + pop ecx + pop ebx + pop esi + pop edi + ret diff --git a/kernel/trunk/network/eth_drv/drivers/r6040.inc b/kernel/trunk/network/eth_drv/drivers/r6040.inc index cf0e2d6f1..7480fce93 100644 --- a/kernel/trunk/network/eth_drv/drivers/r6040.inc +++ b/kernel/trunk/network/eth_drv/drivers/r6040.inc @@ -1,813 +1,813 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; R6040 driver for KolibriOS ;; -;; ;; -;; based on R6040.c from linux ;; -;; ;; -;; Written by Asper (asper.85@mail.ru) ;; -;; and hidnplayr (hidnplayr@gmail.com) ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - - -;******************************************************************** -; Interface -; r6040_reset -; r6040_probe -; r6040_poll -; r6040_transmit -; -; These functions are referenced in ethernet.inc -; -;******************************************************************** - -;; A few user-configurable values. - -TX_RING_SIZE equ 4 -RX_RING_SIZE equ 4 - -; ethernet address length -ETH_ALEN equ 6 -ETH_HLEN equ (2 * ETH_ALEN + 2) -ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for - ; mininmum 64bytes frame length -; system timer frequency -HZ equ 1000 - -; max time out delay time -W_MAX_TIMEOUT equ 0x0FFF - -;; Size of the in-memory receive ring. -RX_BUF_LEN_IDX equ 3 ;; 0==8K, 1==16K, 2==32K, 3==64K -RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX) - -;-; Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). -;-TX_BUF_SIZE equ 1536 -;-RX_BUF_SIZE equ 1536 - -;; PCI Tuning Parameters -; Threshold is bytes transferred to chip before transmission starts. -TX_FIFO_THRESH equ 256 ;; In bytes, rounded down to 32 byte units. - -;; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. -RX_FIFO_THRESH equ 4 ;; Rx buffer level before first PCI xfer. -RX_DMA_BURST equ 4 ;; Maximum PCI burst, '4' is 256 bytes -TX_DMA_BURST equ 4 - -;; Operational parameters that usually are not changed. -PHY1_ADDR equ 1 ;For MAC1 -PHY2_ADDR equ 3 ;For MAC2 -PHY_MODE equ 0x3100 ;PHY CHIP Register 0 -PHY_CAP equ 0x01E1 ;PHY CHIP Register 4 - -;; Time in jiffies before concluding the transmitter is hung. -TX_TIMEOUT equ ((6000*HZ)/1000) - -R6040_IO_SIZE equ 256 ; RDC MAC I/O Size -MAX_MAC equ 2 ; MAX RDC MAC - -;************************************************************************** -; RDC R6040 Register Definitions -;************************************************************************** -MCR0 equ 0x00 ;Control register 0 -MCR1 equ 0x01 ;Control register 1 -MAC_RST equ 0x0001 ;Reset the MAC -MBCR equ 0x08 ;Bus control -MT_ICR equ 0x0C ;TX interrupt control -MR_ICR equ 0x10 ;RX interrupt control -MTPR equ 0x14 ;TX poll command register -MR_BSR equ 0x18 ;RX buffer size -MR_DCR equ 0x1A ;RX descriptor control -MLSR equ 0x1C ;Last status -MMDIO equ 0x20 ;MDIO control register -MDIO_WRITE equ 0x4000 ;MDIO write -MDIO_READ equ 0x2000 ;MDIO read -MMRD equ 0x24 ;MDIO read data register -MMWD equ 0x28 ;MDIO write data register -MTD_SA0 equ 0x2C ;TX descriptor start address 0 -MTD_SA1 equ 0x30 ;TX descriptor start address 1 -MRD_SA0 equ 0x34 ;RX descriptor start address 0 -MRD_SA1 equ 0x38 ;RX descriptor start address 1 -MISR equ 0x3C ;Status register -MIER equ 0x40 ;INT enable register -MSK_INT equ 0x0000 ;Mask off interrupts -RX_FINISH equ 0x0001 ;RX finished -RX_NO_DESC equ 0x0002 ;No RX descriptor available -RX_FIFO_FULL equ 0x0004 ;RX FIFO full -RX_EARLY equ 0x0008 ;RX early -TX_FINISH equ 0x0010 ;TX finished -TX_EARLY equ 0x0080 ;TX early -EVENT_OVRFL equ 0x0100 ;Event counter overflow -LINK_CHANGED equ 0x0200 ;PHY link changed -ME_CISR equ 0x44 ;Event counter INT status -ME_CIER equ 0x48 ;Event counter INT enable -MR_CNT equ 0x50 ;Successfully received packet counter -ME_CNT0 equ 0x52 ;Event counter 0 -ME_CNT1 equ 0x54 ;Event counter 1 -ME_CNT2 equ 0x56 ;Event counter 2 -ME_CNT3 equ 0x58 ;Event counter 3 -MT_CNT equ 0x5A ;Successfully transmit packet counter -ME_CNT4 equ 0x5C ;Event counter 4 -MP_CNT equ 0x5E ;Pause frame counter register -MAR0 equ 0x60 ;Hash table 0 -MAR1 equ 0x62 ;Hash table 1 -MAR2 equ 0x64 ;Hash table 2 -MAR3 equ 0x66 ;Hash table 3 -MID_0L equ 0x68 ;Multicast address MID0 Low -MID_0M equ 0x6A ;Multicast address MID0 Medium -MID_0H equ 0x6C ;Multicast address MID0 High -MID_1L equ 0x70 ;MID1 Low -MID_1M equ 0x72 ;MID1 Medium -MID_1H equ 0x74 ;MID1 High -MID_2L equ 0x78 ;MID2 Low -MID_2M equ 0x7A ;MID2 Medium -MID_2H equ 0x7C ;MID2 High -MID_3L equ 0x80 ;MID3 Low -MID_3M equ 0x82 ;MID3 Medium -MID_3H equ 0x84 ;MID3 High -PHY_CC equ 0x88 ;PHY status change configuration register -PHY_ST equ 0x8A ;PHY status register -MAC_SM equ 0xAC ;MAC status machine -MAC_ID equ 0xBE ;Identifier register - -MAX_BUF_SIZE equ 0x600 ;1536 - -MBCR_DEFAULT equ 0x012A ;MAC Bus Control Register -MCAST_MAX equ 3 ;Max number multicast addresses to filter - -;Descriptor status -DSC_OWNER_MAC equ 0x8000 ;MAC is the owner of this descriptor -DSC_RX_OK equ 0x4000 ;RX was successfull -DSC_RX_ERR equ 0x0800 ;RX PHY error -DSC_RX_ERR_DRI equ 0x0400 ;RX dribble packet -DSC_RX_ERR_BUF equ 0x0200 ;RX length exceeds buffer size -DSC_RX_ERR_LONG equ 0x0100 ;RX length > maximum packet length -DSC_RX_ERR_RUNT equ 0x0080 ;RX packet length < 64 byte -DSC_RX_ERR_CRC equ 0x0040 ;RX CRC error -DSC_RX_BCAST equ 0x0020 ;RX broadcast (no error) -DSC_RX_MCAST equ 0x0010 ;RX multicast (no error) -DSC_RX_MCH_HIT equ 0x0008 ;RX multicast hit in hash table (no error) -DSC_RX_MIDH_HIT equ 0x0004 ;RX MID table hit (no error) -DSC_RX_IDX_MID_MASK equ 3 ;RX mask for the index of matched MIDx - -;PHY settings -ICPLUS_PHY_ID equ 0x0243 - -RX_INTS equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH -TX_INTS equ TX_FINISH -INT_MASK equ RX_INTS or TX_INTS - - -r6040_txb equ (eth_data_start) -r6040_rxb equ ((r6040_txb+(MAX_BUF_SIZE*TX_RING_SIZE)+32) and 0xfffffff0) -r6040_tx_ring equ ((r6040_rxb+(MAX_BUF_SIZE*RX_RING_SIZE)+32) and 0xfffffff0) -r6040_rx_ring equ ((r6040_tx_ring+(r6040_x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0) - -virtual at ((r6040_rx_ring+(r6040_x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0) -r6040_private: - .rx_ring dd ? - .tx_ring dd ? - .cur_rx dw ? - .cur_tx dw ? - .phy_addr dw ? - .phy_mode dw ? - .mcr0 dw ? - .mcr1 dw ? - .switch_sig dw ? -end virtual - -virtual at 0 -r6040_x_head: - .status dw ? ;0-1 - .len dw ? ;2-3 - .buf dd ? ;4-7 - .ndesc dd ? ;8-B - .rev1 dd ? ;C-F - .vbufp dd ? ;10-13 - .vndescp dd ? ;14-17 - .skb_ptr dd ? ;18-1B - .rev2 dd ? ;1C-1F - .sizeof: -end virtual - - - -; Read a word data from PHY Chip -proc r6040_phy_read stdcall, phy_addr:dword, reg:dword - push ecx edx - mov eax, [phy_addr] - shl eax, 8 - add eax, [reg] - add eax, MDIO_READ - mov edx, [io_addr] - add edx, MMDIO - out dx, ax - ;Wait for the read bit to be cleared. - mov ecx, 2048 ;limit - xor eax, eax - .read: - in ax, dx - test ax, MDIO_READ - jz @f - dec ecx - test ecx, ecx - jnz .read - @@: - mov edx, [io_addr] - add edx, MMRD - in ax, dx - and eax, 0xFFFF - pop edx ecx - ret -endp - -; Write a word data to PHY Chip -proc r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword - push eax ecx edx - mov eax, [val] - mov edx, [io_addr] - add edx, MMWD - out dx, ax - ;Write the command to the MDIO bus - mov eax, [phy_addr] - shl eax, 8 - add eax, [reg] - add eax, MDIO_WRITE - mov edx, [io_addr] - add edx, MMDIO - out dx, ax - ;Wait for the write bit to be cleared. - mov ecx, 2048 ;limit - xor eax, eax - .write: - in ax, dx - test ax, MDIO_WRITE - jz @f - dec ecx - test ecx, ecx - jnz .write - @@: - pop edx ecx eax - ret -endp - -macro r6040_mdio_write reg, val { - stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg -} - -macro r6040_mdio_write reg, val { - stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val -} - - -proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword - push eax ecx esi - mov ecx, [size] - test ecx, ecx - jz .out - - mov esi, [desc_ring] - mov eax, esi - .next_desc: - add eax, r6040_x_head.sizeof - OS_BASE - mov [esi+r6040_x_head.ndesc], eax - add eax, OS_BASE - mov [esi+r6040_x_head.vndescp], eax - mov esi, eax - dec ecx - jnz .next_desc - - sub esi, r6040_x_head.sizeof - mov eax, [desc_ring] - mov [esi+r6040_x_head.vndescp], eax - sub eax, OS_BASE - mov [esi+r6040_x_head.ndesc], eax - .out: - pop esi ecx eax - ret -endp - - - - -r6040_init_rxbufs: - - stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE - - ; Allocate skbs for the rx descriptors - mov esi, r6040_rx_ring - mov ebx, r6040_rxb - mov ecx, RX_RING_SIZE - mov eax, r6040_rx_ring - .next_desc: - mov [esi+r6040_x_head.skb_ptr], ebx - mov [esi+r6040_x_head.buf], ebx - sub [esi+r6040_x_head.buf], OS_BASE - mov [esi+r6040_x_head.status], DSC_OWNER_MAC - - mov eax, [esi+r6040_x_head.vndescp] - mov esi, eax - - add ebx, MAX_BUF_SIZE - dec ecx - jnz .next_desc - - xor eax, eax - .out: - - ret - - -r6040_probe: - - DEBUGF 1, "Probing r6040\n" - - call adjust_pci_device - - - ; If PHY status change register is still set to zero - ; it means the bootloader didn't initialize it - mov edx, [io_addr] - add edx, PHY_CC - in ax, dx - test ax, ax - jnz @f - mov eax, 0x9F07 - out dx, ax - @@: - ; Set MAC address - mov ecx, 3 - mov edi, node_addr - mov edx, [io_addr] - add edx, MID_0L - .mac: - in ax, dx - stosw - add edx, 2 - dec ecx - jnz .mac - ; Some bootloaders/BIOSes do not initialize - ; MAC address, warn about that - and eax, 0xFF - or eax, [node_addr] - test eax, eax - jnz @f - DEBUGF 1, "K : MAC address not initialized\n" ;, generating random" - ;Asper: Add here generate function call! - ; Temporary workaround: init by constant adress - mov dword [node_addr], 0x00006000 - mov word [node_addr+4], 0x0001 - @@: - ; Init RDC private data - mov [r6040_private.mcr0], 0x1002 - ;mov [r6040_private.phy_addr], 1 ; Asper: Only one network card is supported now. - mov [r6040_private.switch_sig], 0 - - ; Check the vendor ID on the PHY, if 0xFFFF assume none attached - stdcall r6040_phy_read, 1, 2 - cmp ax, 0xFFFF - jne @f - DEBUGF 1, "K : Failed to detect an attached PHY\n" ;, generating random" - mov eax, -1 - ret - @@: - - ; Set MAC address - call r6040_mac_address - - - ; Initialize and alloc RX/TX buffers - stdcall r6040_init_ring_desc, r6040_tx_ring, TX_RING_SIZE - call r6040_init_rxbufs ;r6040_alloc_rxbufs - test eax, eax - jnz .out - - ; Read the PHY ID - mov [r6040_private.phy_mode], 0x8000 - stdcall r6040_phy_read, 0, 2 - mov [r6040_private.switch_sig], ax - cmp ax, ICPLUS_PHY_ID - jne @f - stdcall r6040_phy_write, 29, 31, 0x175C ; Enable registers - jmp .phy_readen - @@: - - ; PHY Mode Check - movzx eax, [r6040_private.phy_addr] - stdcall r6040_phy_write, eax, 4, PHY_CAP - stdcall r6040_phy_write, eax, 0, PHY_MODE -; if PHY_MODE = 0x3100 - call r6040_phy_mode_chk - mov [r6040_private.phy_mode], ax - jmp .phy_readen -; end if -; if not (PHY_MODE and 0x0100) - mov [r6040_private.phy_mode], 0 -; end if - .phy_readen: - - ; Set duplex mode - mov ax, [r6040_private.phy_mode] - or [r6040_private.mcr0], ax - - ; improve performance (by RDC guys) - stdcall r6040_phy_read, 30, 17 - or ax, 0x4000 - stdcall r6040_phy_write, 30, 17, eax - - stdcall r6040_phy_read, 30, 17 - xor ax, -1 - or ax, 0x2000 - xor ax, -1 - stdcall r6040_phy_write, 30, 17, eax - - stdcall r6040_phy_write, 0, 19, 0x0000 - stdcall r6040_phy_write, 0, 30, 0x01F0 - - ; Initialize all Mac registers - call r6040_reset - - xor eax, eax - .out: - ret - - - - - - -align 4 -r6040_reset: - - DEBUGF 1, "Resetting r6040\n" - - push eax ecx edx - ; Mask off Interrupt - mov eax, MSK_INT - mov edx, [io_addr] - add edx, MIER - out dx, ax - - ;Reset RDC MAC - mov eax, MAC_RST - mov edx, [io_addr] - add edx, MCR1 - out dx, ax - - mov ecx, 2048 ;limit - .read: - in ax, dx - test ax, 0x1 - jnz @f - dec ecx - test ecx, ecx - jnz .read - @@: - ;Reset internal state machine - mov ax, 2 - mov edx, [io_addr] - add edx, MAC_SM - out dx, ax - xor ax, ax - out dx, ax - mov esi, 5 - call delay_ms - - ;MAC Bus Control Register - mov ax, MBCR_DEFAULT - mov edx, [io_addr] - add edx, MBCR - out dx, ax - - ;Buffer Size Register - mov ax, MAX_BUF_SIZE - mov edx, [io_addr] - add edx, MR_BSR - out dx, ax - - ;Write TX ring start address - mov eax, r6040_tx_ring - OS_BASE ;Asper: Maybe we can just write dword? Hidnplayr: better use word, as described in datasheet. - mov edx, [io_addr] - add edx, MTD_SA0 - out dx, ax - shr eax, 16 - add edx, MTD_SA1 - MTD_SA0 - out dx, ax - - ;Write RX ring start address - mov eax, r6040_rx_ring - OS_BASE ;Asper: Maybe we can just write dword? - mov edx, [io_addr] - add edx, MRD_SA0 - out dx, ax - shr eax, 16 - add edx, MRD_SA1 - MRD_SA0 - out dx, ax - - ;Set interrupt waiting time and packet numbers - xor ax, ax - mov edx, [io_addr] - add edx, MT_ICR - out dx, ax - - ;Asper: ~ Disable ints ;Enable interrupts - ;mov ax, MSK_INT ;INT_MASK ;Asper ~ - ;mov edx, [io_addr] - ;add edx, MIER - ;out dx, ax - - ;Enable TX and RX - mov ax, [r6040_private.mcr0] - or ax, 0x0002 - mov edx, [io_addr] - out dx, ax - - ;Let TX poll the descriptors - ;we may got called by r6040_tx_timeout which has left - ;some unset tx buffers - xor ax, ax - inc ax - mov edx, [io_addr] - add edx, MTPR - out dx, ax - - pop edx ecx eax - - DEBUGF 1, "reset ok!\n" - - ; Indicate that we have successfully reset the card - mov eax, [pci_data] - mov [eth_status], eax - ret - - - -proc r6040_tx_timeout - push eax edx - ;... - inc [stats.tx_errors] - ;Reset MAC and re-init all registers - call r6040_init_mac_regs - pop edx eax - ret -endp - -proc r6040_get_stats - push eax edx - mov edx, [io_addr] - add edx, ME_CNT1 - in al, dx - add [stats.rx_crc_errors], al - mov edx, [io_addr] - add edx, ME_CNT0 - in al, dx - add [stats.multicast], al - pop edx eax - ret -endp - -;... - -proc r6040_phy_mode_chk - push ebx - ;PHY Link Status Check - movzx eax, [r6040_private.phy_addr] - stdcall r6040_phy_read, eax, 1 - test eax, 0x4 - jnz @f - mov eax, 0x8000 ;Link Failed, full duplex - @@: - ;PHY Chip Auto-Negotiation Status - movzx eax, [r6040_private.phy_addr] - stdcall r6040_phy_read, eax, 1 - test eax, 0x0020 - jz .force_mode - ;Auto Negotuiation Mode - movzx eax, [r6040_private.phy_addr] - stdcall r6040_phy_read, eax, 5 - mov ebx, eax - movzx eax, [r6040_private.phy_addr] - stdcall r6040_phy_read, eax, 4 - and eax, ebx - test eax, 0x140 - jz .ret_0 - jmp .ret_0x8000 - .force_mode: - ;Force Mode - movzx eax, [r6040_private.phy_addr] - stdcall r6040_phy_read, eax, 0 - test eax, 0x100 - jz .ret_0 - .ret_0x8000: - mov eax, 0x8000 - pop ebx - ret - .ret_0: - xor eax, eax - pop ebx - ret -endp - - - -;*************************************************************************** -; Function -; r6040_rx -; Description -; polls card to see if there is a packet waiting -; -; Currently only supports one descriptor per packet, if packet is fragmented -; between multiple descriptors you will lose part of the packet -;*************************************************************************** -r6040_poll: - push ebx ecx esi edi - - xor eax, eax - mov [eth_rx_data_len], ax - - movzx eax, [r6040_private.cur_rx] - mov ebx, eax - shl ebx, 5 - - mov cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status - test cx, DSC_OWNER_MAC - jnz .out - - test cx, DSC_RX_ERR ; Global error status set - jz .no_dsc_rx_err - ;... - jmp .out - - .no_dsc_rx_err: - ; Packet successfully received - movzx ecx, [ebx+r6040_rx_ring+r6040_x_head.len] - and ecx, 0xFFF - sub ecx, 4 ; Do not count the CRC - mov [eth_rx_data_len], cx - mov esi, [ebx+r6040_rx_ring+r6040_x_head.skb_ptr] - - push ecx - shr ecx, 2 - mov edi, Ether_buffer - cld - rep movsd - pop ecx - and ecx, 3 - rep movsb - - or [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC - - inc [r6040_private.cur_rx] - and [r6040_private.cur_rx], RX_RING_SIZE-1 - - xor eax, eax - .out: - pop edi esi ecx ebx - ret - - - -;*************************************************************************** -; Function -; r6040_transmit -; Description -; Transmits a packet of data via the ethernet card -; Pointer to 48 bit destination address in edi -; Type of packet in bx -; size of packet in ecx -; pointer to packet data in esi -; -;*************************************************************************** -r6040_transmit: - cmp ecx, MAX_BUF_SIZE - jg .out ; packet is too long - - push edi esi ebx ecx - - movzx eax, [r6040_private.cur_tx] - shl eax, 5 - -; DEBUGF 1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax - - test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 ; check if buffer is available - jz .l3 - - push ecx esi - mov ecx, [timer_ticks] - add ecx, 100 - .l2: - test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 - jz .l5 - cmp ecx, [timer_ticks] - jb .l4 - mov esi, 10 - call delay_ms - jmp .l2 - - .l4: - pop esi ecx - DEBUGF 1,"R6040: Send timeout\n" - jmp .out - - .l5: - pop esi ecx - .l3: - push eax - - mov esi, edi - -; point to the current tx buffer - movzx edi, [r6040_private.cur_tx] - imul edi, MAX_BUF_SIZE - add edi, r6040_txb - lea eax, [edi - OS_BASE] ; real buffer address in eax - -; copy destination address - movsd - movsw -; copy source address - mov esi, node_addr - movsd - movsw -; copy packet type - mov [edi], bx - add edi, 2 - - mov esi, [esp+8+4] - mov ecx, [esp+4] -; copy the packet data - push ecx - shr ecx,2 - rep movsd - pop ecx - and ecx,3 - rep movsb - - pop edi - - mov ecx, [esp] - add ecx, ETH_HLEN - cmp cx, ETH_ZLEN - jae @f - mov cx, ETH_ZLEN - @@: - - mov [r6040_tx_ring + edi + r6040_x_head.len], cx - mov [r6040_tx_ring + edi + r6040_x_head.buf], eax - mov [r6040_tx_ring + edi + r6040_x_head.status], 0x8000 - - ; Trigger the MAC to check the TX descriptor - mov ax, 0x01 - mov edx, [io_addr] - add edx, MTPR - out dx, ax - - inc [r6040_private.cur_tx] - and [r6040_private.cur_tx], TX_RING_SIZE-1 - xor eax, eax - - pop ecx ebx esi edi - .out: - ret - - - -r6040_mac_address: - push eax ecx edx esi edi - ; MAC operation register - mov ax, 1 - mov edx, [io_addr] - add edx, MCR1 - out dx, ax - ; Reset MAC - mov ax, 2 - mov edx, [io_addr] - add edx, MAC_SM - out dx, ax - ; Reset internal state machine - xor ax, ax - out dx, ax - mov esi, 5 - call delay_ms - - ; Restore MAC Address - mov ecx, 3 - mov edi, node_addr - mov edx, [io_addr] - add edx, MID_0L - .mac: - in ax, dx - stosw - add edx, 2 - dec ecx - jnz .mac - - pop edi esi edx ecx eax - ret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; R6040 driver for KolibriOS ;; +;; ;; +;; based on R6040.c from linux ;; +;; ;; +;; Written by Asper (asper.85@mail.ru) ;; +;; and hidnplayr (hidnplayr@gmail.com) ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +;******************************************************************** +; Interface +; r6040_reset +; r6040_probe +; r6040_poll +; r6040_transmit +; +; These functions are referenced in ethernet.inc +; +;******************************************************************** + +;; A few user-configurable values. + +TX_RING_SIZE equ 4 +RX_RING_SIZE equ 4 + +; ethernet address length +ETH_ALEN equ 6 +ETH_HLEN equ (2 * ETH_ALEN + 2) +ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length +; system timer frequency +HZ equ 1000 + +; max time out delay time +W_MAX_TIMEOUT equ 0x0FFF + +;; Size of the in-memory receive ring. +RX_BUF_LEN_IDX equ 3 ;; 0==8K, 1==16K, 2==32K, 3==64K +RX_BUF_LEN equ (8192 << RX_BUF_LEN_IDX) + +;-; Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). +;-TX_BUF_SIZE equ 1536 +;-RX_BUF_SIZE equ 1536 + +;; PCI Tuning Parameters +; Threshold is bytes transferred to chip before transmission starts. +TX_FIFO_THRESH equ 256 ;; In bytes, rounded down to 32 byte units. + +;; The following settings are log_2(bytes)-4: 0 == 16 bytes .. 6==1024. +RX_FIFO_THRESH equ 4 ;; Rx buffer level before first PCI xfer. +RX_DMA_BURST equ 4 ;; Maximum PCI burst, '4' is 256 bytes +TX_DMA_BURST equ 4 + +;; Operational parameters that usually are not changed. +PHY1_ADDR equ 1 ;For MAC1 +PHY2_ADDR equ 3 ;For MAC2 +PHY_MODE equ 0x3100 ;PHY CHIP Register 0 +PHY_CAP equ 0x01E1 ;PHY CHIP Register 4 + +;; Time in jiffies before concluding the transmitter is hung. +TX_TIMEOUT equ ((6000*HZ)/1000) + +R6040_IO_SIZE equ 256 ; RDC MAC I/O Size +MAX_MAC equ 2 ; MAX RDC MAC + +;************************************************************************** +; RDC R6040 Register Definitions +;************************************************************************** +MCR0 equ 0x00 ;Control register 0 +MCR1 equ 0x01 ;Control register 1 +MAC_RST equ 0x0001 ;Reset the MAC +MBCR equ 0x08 ;Bus control +MT_ICR equ 0x0C ;TX interrupt control +MR_ICR equ 0x10 ;RX interrupt control +MTPR equ 0x14 ;TX poll command register +MR_BSR equ 0x18 ;RX buffer size +MR_DCR equ 0x1A ;RX descriptor control +MLSR equ 0x1C ;Last status +MMDIO equ 0x20 ;MDIO control register +MDIO_WRITE equ 0x4000 ;MDIO write +MDIO_READ equ 0x2000 ;MDIO read +MMRD equ 0x24 ;MDIO read data register +MMWD equ 0x28 ;MDIO write data register +MTD_SA0 equ 0x2C ;TX descriptor start address 0 +MTD_SA1 equ 0x30 ;TX descriptor start address 1 +MRD_SA0 equ 0x34 ;RX descriptor start address 0 +MRD_SA1 equ 0x38 ;RX descriptor start address 1 +MISR equ 0x3C ;Status register +MIER equ 0x40 ;INT enable register +MSK_INT equ 0x0000 ;Mask off interrupts +RX_FINISH equ 0x0001 ;RX finished +RX_NO_DESC equ 0x0002 ;No RX descriptor available +RX_FIFO_FULL equ 0x0004 ;RX FIFO full +RX_EARLY equ 0x0008 ;RX early +TX_FINISH equ 0x0010 ;TX finished +TX_EARLY equ 0x0080 ;TX early +EVENT_OVRFL equ 0x0100 ;Event counter overflow +LINK_CHANGED equ 0x0200 ;PHY link changed +ME_CISR equ 0x44 ;Event counter INT status +ME_CIER equ 0x48 ;Event counter INT enable +MR_CNT equ 0x50 ;Successfully received packet counter +ME_CNT0 equ 0x52 ;Event counter 0 +ME_CNT1 equ 0x54 ;Event counter 1 +ME_CNT2 equ 0x56 ;Event counter 2 +ME_CNT3 equ 0x58 ;Event counter 3 +MT_CNT equ 0x5A ;Successfully transmit packet counter +ME_CNT4 equ 0x5C ;Event counter 4 +MP_CNT equ 0x5E ;Pause frame counter register +MAR0 equ 0x60 ;Hash table 0 +MAR1 equ 0x62 ;Hash table 1 +MAR2 equ 0x64 ;Hash table 2 +MAR3 equ 0x66 ;Hash table 3 +MID_0L equ 0x68 ;Multicast address MID0 Low +MID_0M equ 0x6A ;Multicast address MID0 Medium +MID_0H equ 0x6C ;Multicast address MID0 High +MID_1L equ 0x70 ;MID1 Low +MID_1M equ 0x72 ;MID1 Medium +MID_1H equ 0x74 ;MID1 High +MID_2L equ 0x78 ;MID2 Low +MID_2M equ 0x7A ;MID2 Medium +MID_2H equ 0x7C ;MID2 High +MID_3L equ 0x80 ;MID3 Low +MID_3M equ 0x82 ;MID3 Medium +MID_3H equ 0x84 ;MID3 High +PHY_CC equ 0x88 ;PHY status change configuration register +PHY_ST equ 0x8A ;PHY status register +MAC_SM equ 0xAC ;MAC status machine +MAC_ID equ 0xBE ;Identifier register + +MAX_BUF_SIZE equ 0x600 ;1536 + +MBCR_DEFAULT equ 0x012A ;MAC Bus Control Register +MCAST_MAX equ 3 ;Max number multicast addresses to filter + +;Descriptor status +DSC_OWNER_MAC equ 0x8000 ;MAC is the owner of this descriptor +DSC_RX_OK equ 0x4000 ;RX was successfull +DSC_RX_ERR equ 0x0800 ;RX PHY error +DSC_RX_ERR_DRI equ 0x0400 ;RX dribble packet +DSC_RX_ERR_BUF equ 0x0200 ;RX length exceeds buffer size +DSC_RX_ERR_LONG equ 0x0100 ;RX length > maximum packet length +DSC_RX_ERR_RUNT equ 0x0080 ;RX packet length < 64 byte +DSC_RX_ERR_CRC equ 0x0040 ;RX CRC error +DSC_RX_BCAST equ 0x0020 ;RX broadcast (no error) +DSC_RX_MCAST equ 0x0010 ;RX multicast (no error) +DSC_RX_MCH_HIT equ 0x0008 ;RX multicast hit in hash table (no error) +DSC_RX_MIDH_HIT equ 0x0004 ;RX MID table hit (no error) +DSC_RX_IDX_MID_MASK equ 3 ;RX mask for the index of matched MIDx + +;PHY settings +ICPLUS_PHY_ID equ 0x0243 + +RX_INTS equ RX_FIFO_FULL or RX_NO_DESC or RX_FINISH +TX_INTS equ TX_FINISH +INT_MASK equ RX_INTS or TX_INTS + + +r6040_txb equ (eth_data_start) +r6040_rxb equ ((r6040_txb+(MAX_BUF_SIZE*TX_RING_SIZE)+32) and 0xfffffff0) +r6040_tx_ring equ ((r6040_rxb+(MAX_BUF_SIZE*RX_RING_SIZE)+32) and 0xfffffff0) +r6040_rx_ring equ ((r6040_tx_ring+(r6040_x_head.sizeof*TX_RING_SIZE)+32) and 0xfffffff0) + +virtual at ((r6040_rx_ring+(r6040_x_head.sizeof*RX_RING_SIZE)+32) and 0xfffffff0) +r6040_private: + .rx_ring dd ? + .tx_ring dd ? + .cur_rx dw ? + .cur_tx dw ? + .phy_addr dw ? + .phy_mode dw ? + .mcr0 dw ? + .mcr1 dw ? + .switch_sig dw ? +end virtual + +virtual at 0 +r6040_x_head: + .status dw ? ;0-1 + .len dw ? ;2-3 + .buf dd ? ;4-7 + .ndesc dd ? ;8-B + .rev1 dd ? ;C-F + .vbufp dd ? ;10-13 + .vndescp dd ? ;14-17 + .skb_ptr dd ? ;18-1B + .rev2 dd ? ;1C-1F + .sizeof: +end virtual + + + +; Read a word data from PHY Chip +proc r6040_phy_read stdcall, phy_addr:dword, reg:dword + push ecx edx + mov eax, [phy_addr] + shl eax, 8 + add eax, [reg] + add eax, MDIO_READ + mov edx, [io_addr] + add edx, MMDIO + out dx, ax + ;Wait for the read bit to be cleared. + mov ecx, 2048 ;limit + xor eax, eax + .read: + in ax, dx + test ax, MDIO_READ + jz @f + dec ecx + test ecx, ecx + jnz .read + @@: + mov edx, [io_addr] + add edx, MMRD + in ax, dx + and eax, 0xFFFF + pop edx ecx + ret +endp + +; Write a word data to PHY Chip +proc r6040_phy_write stdcall, phy_addr:dword, reg:dword, val:dword + push eax ecx edx + mov eax, [val] + mov edx, [io_addr] + add edx, MMWD + out dx, ax + ;Write the command to the MDIO bus + mov eax, [phy_addr] + shl eax, 8 + add eax, [reg] + add eax, MDIO_WRITE + mov edx, [io_addr] + add edx, MMDIO + out dx, ax + ;Wait for the write bit to be cleared. + mov ecx, 2048 ;limit + xor eax, eax + .write: + in ax, dx + test ax, MDIO_WRITE + jz @f + dec ecx + test ecx, ecx + jnz .write + @@: + pop edx ecx eax + ret +endp + +macro r6040_mdio_write reg, val { + stdcall r6040_phy_read, [io_addr], [r6040_private.phy_addr], reg +} + +macro r6040_mdio_write reg, val { + stdcall r6040_phy_write, [io_addr], [r6040_private.phy_addr], reg, val +} + + +proc r6040_init_ring_desc stdcall, desc_ring:dword, size:dword + push eax ecx esi + mov ecx, [size] + test ecx, ecx + jz .out + + mov esi, [desc_ring] + mov eax, esi + .next_desc: + add eax, r6040_x_head.sizeof - OS_BASE + mov [esi+r6040_x_head.ndesc], eax + add eax, OS_BASE + mov [esi+r6040_x_head.vndescp], eax + mov esi, eax + dec ecx + jnz .next_desc + + sub esi, r6040_x_head.sizeof + mov eax, [desc_ring] + mov [esi+r6040_x_head.vndescp], eax + sub eax, OS_BASE + mov [esi+r6040_x_head.ndesc], eax + .out: + pop esi ecx eax + ret +endp + + + + +r6040_init_rxbufs: + + stdcall r6040_init_ring_desc, r6040_rx_ring, RX_RING_SIZE + + ; Allocate skbs for the rx descriptors + mov esi, r6040_rx_ring + mov ebx, r6040_rxb + mov ecx, RX_RING_SIZE + mov eax, r6040_rx_ring + .next_desc: + mov [esi+r6040_x_head.skb_ptr], ebx + mov [esi+r6040_x_head.buf], ebx + sub [esi+r6040_x_head.buf], OS_BASE + mov [esi+r6040_x_head.status], DSC_OWNER_MAC + + mov eax, [esi+r6040_x_head.vndescp] + mov esi, eax + + add ebx, MAX_BUF_SIZE + dec ecx + jnz .next_desc + + xor eax, eax + .out: + + ret + + +r6040_probe: + + DEBUGF 1, "Probing r6040\n" + + call adjust_pci_device + + + ; If PHY status change register is still set to zero + ; it means the bootloader didn't initialize it + mov edx, [io_addr] + add edx, PHY_CC + in ax, dx + test ax, ax + jnz @f + mov eax, 0x9F07 + out dx, ax + @@: + ; Set MAC address + mov ecx, 3 + mov edi, node_addr + mov edx, [io_addr] + add edx, MID_0L + .mac: + in ax, dx + stosw + add edx, 2 + dec ecx + jnz .mac + ; Some bootloaders/BIOSes do not initialize + ; MAC address, warn about that + and eax, 0xFF + or eax, [node_addr] + test eax, eax + jnz @f + DEBUGF 1, "K : MAC address not initialized\n" ;, generating random" + ;Asper: Add here generate function call! + ; Temporary workaround: init by constant adress + mov dword [node_addr], 0x00006000 + mov word [node_addr+4], 0x0001 + @@: + ; Init RDC private data + mov [r6040_private.mcr0], 0x1002 + ;mov [r6040_private.phy_addr], 1 ; Asper: Only one network card is supported now. + mov [r6040_private.switch_sig], 0 + + ; Check the vendor ID on the PHY, if 0xFFFF assume none attached + stdcall r6040_phy_read, 1, 2 + cmp ax, 0xFFFF + jne @f + DEBUGF 1, "K : Failed to detect an attached PHY\n" ;, generating random" + mov eax, -1 + ret + @@: + + ; Set MAC address + call r6040_mac_address + + + ; Initialize and alloc RX/TX buffers + stdcall r6040_init_ring_desc, r6040_tx_ring, TX_RING_SIZE + call r6040_init_rxbufs ;r6040_alloc_rxbufs + test eax, eax + jnz .out + + ; Read the PHY ID + mov [r6040_private.phy_mode], 0x8000 + stdcall r6040_phy_read, 0, 2 + mov [r6040_private.switch_sig], ax + cmp ax, ICPLUS_PHY_ID + jne @f + stdcall r6040_phy_write, 29, 31, 0x175C ; Enable registers + jmp .phy_readen + @@: + + ; PHY Mode Check + movzx eax, [r6040_private.phy_addr] + stdcall r6040_phy_write, eax, 4, PHY_CAP + stdcall r6040_phy_write, eax, 0, PHY_MODE +; if PHY_MODE = 0x3100 + call r6040_phy_mode_chk + mov [r6040_private.phy_mode], ax + jmp .phy_readen +; end if +; if not (PHY_MODE and 0x0100) + mov [r6040_private.phy_mode], 0 +; end if + .phy_readen: + + ; Set duplex mode + mov ax, [r6040_private.phy_mode] + or [r6040_private.mcr0], ax + + ; improve performance (by RDC guys) + stdcall r6040_phy_read, 30, 17 + or ax, 0x4000 + stdcall r6040_phy_write, 30, 17, eax + + stdcall r6040_phy_read, 30, 17 + xor ax, -1 + or ax, 0x2000 + xor ax, -1 + stdcall r6040_phy_write, 30, 17, eax + + stdcall r6040_phy_write, 0, 19, 0x0000 + stdcall r6040_phy_write, 0, 30, 0x01F0 + + ; Initialize all Mac registers + call r6040_reset + + xor eax, eax + .out: + ret + + + + + + +align 4 +r6040_reset: + + DEBUGF 1, "Resetting r6040\n" + + push eax ecx edx + ; Mask off Interrupt + mov eax, MSK_INT + mov edx, [io_addr] + add edx, MIER + out dx, ax + + ;Reset RDC MAC + mov eax, MAC_RST + mov edx, [io_addr] + add edx, MCR1 + out dx, ax + + mov ecx, 2048 ;limit + .read: + in ax, dx + test ax, 0x1 + jnz @f + dec ecx + test ecx, ecx + jnz .read + @@: + ;Reset internal state machine + mov ax, 2 + mov edx, [io_addr] + add edx, MAC_SM + out dx, ax + xor ax, ax + out dx, ax + mov esi, 5 + call delay_ms + + ;MAC Bus Control Register + mov ax, MBCR_DEFAULT + mov edx, [io_addr] + add edx, MBCR + out dx, ax + + ;Buffer Size Register + mov ax, MAX_BUF_SIZE + mov edx, [io_addr] + add edx, MR_BSR + out dx, ax + + ;Write TX ring start address + mov eax, r6040_tx_ring - OS_BASE ;Asper: Maybe we can just write dword? Hidnplayr: better use word, as described in datasheet. + mov edx, [io_addr] + add edx, MTD_SA0 + out dx, ax + shr eax, 16 + add edx, MTD_SA1 - MTD_SA0 + out dx, ax + + ;Write RX ring start address + mov eax, r6040_rx_ring - OS_BASE ;Asper: Maybe we can just write dword? + mov edx, [io_addr] + add edx, MRD_SA0 + out dx, ax + shr eax, 16 + add edx, MRD_SA1 - MRD_SA0 + out dx, ax + + ;Set interrupt waiting time and packet numbers + xor ax, ax + mov edx, [io_addr] + add edx, MT_ICR + out dx, ax + + ;Asper: ~ Disable ints ;Enable interrupts + ;mov ax, MSK_INT ;INT_MASK ;Asper ~ + ;mov edx, [io_addr] + ;add edx, MIER + ;out dx, ax + + ;Enable TX and RX + mov ax, [r6040_private.mcr0] + or ax, 0x0002 + mov edx, [io_addr] + out dx, ax + + ;Let TX poll the descriptors + ;we may got called by r6040_tx_timeout which has left + ;some unset tx buffers + xor ax, ax + inc ax + mov edx, [io_addr] + add edx, MTPR + out dx, ax + + pop edx ecx eax + + DEBUGF 1, "reset ok!\n" + + ; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax + ret + + + +proc r6040_tx_timeout + push eax edx + ;... + inc [stats.tx_errors] + ;Reset MAC and re-init all registers + call r6040_init_mac_regs + pop edx eax + ret +endp + +proc r6040_get_stats + push eax edx + mov edx, [io_addr] + add edx, ME_CNT1 + in al, dx + add [stats.rx_crc_errors], al + mov edx, [io_addr] + add edx, ME_CNT0 + in al, dx + add [stats.multicast], al + pop edx eax + ret +endp + +;... + +proc r6040_phy_mode_chk + push ebx + ;PHY Link Status Check + movzx eax, [r6040_private.phy_addr] + stdcall r6040_phy_read, eax, 1 + test eax, 0x4 + jnz @f + mov eax, 0x8000 ;Link Failed, full duplex + @@: + ;PHY Chip Auto-Negotiation Status + movzx eax, [r6040_private.phy_addr] + stdcall r6040_phy_read, eax, 1 + test eax, 0x0020 + jz .force_mode + ;Auto Negotuiation Mode + movzx eax, [r6040_private.phy_addr] + stdcall r6040_phy_read, eax, 5 + mov ebx, eax + movzx eax, [r6040_private.phy_addr] + stdcall r6040_phy_read, eax, 4 + and eax, ebx + test eax, 0x140 + jz .ret_0 + jmp .ret_0x8000 + .force_mode: + ;Force Mode + movzx eax, [r6040_private.phy_addr] + stdcall r6040_phy_read, eax, 0 + test eax, 0x100 + jz .ret_0 + .ret_0x8000: + mov eax, 0x8000 + pop ebx + ret + .ret_0: + xor eax, eax + pop ebx + ret +endp + + + +;*************************************************************************** +; Function +; r6040_rx +; Description +; polls card to see if there is a packet waiting +; +; Currently only supports one descriptor per packet, if packet is fragmented +; between multiple descriptors you will lose part of the packet +;*************************************************************************** +r6040_poll: + push ebx ecx esi edi + + xor eax, eax + mov [eth_rx_data_len], ax + + movzx eax, [r6040_private.cur_rx] + mov ebx, eax + shl ebx, 5 + + mov cx, [ebx+r6040_rx_ring+r6040_x_head.status] ; Read the descriptor status + test cx, DSC_OWNER_MAC + jnz .out + + test cx, DSC_RX_ERR ; Global error status set + jz .no_dsc_rx_err + ;... + jmp .out + + .no_dsc_rx_err: + ; Packet successfully received + movzx ecx, [ebx+r6040_rx_ring+r6040_x_head.len] + and ecx, 0xFFF + sub ecx, 4 ; Do not count the CRC + mov [eth_rx_data_len], cx + mov esi, [ebx+r6040_rx_ring+r6040_x_head.skb_ptr] + + push ecx + shr ecx, 2 + mov edi, Ether_buffer + cld + rep movsd + pop ecx + and ecx, 3 + rep movsb + + or [ebx+r6040_rx_ring+r6040_x_head.status], DSC_OWNER_MAC + + inc [r6040_private.cur_rx] + and [r6040_private.cur_rx], RX_RING_SIZE-1 + + xor eax, eax + .out: + pop edi esi ecx ebx + ret + + + +;*************************************************************************** +; Function +; r6040_transmit +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +;*************************************************************************** +r6040_transmit: + cmp ecx, MAX_BUF_SIZE + jg .out ; packet is too long + + push edi esi ebx ecx + + movzx eax, [r6040_private.cur_tx] + shl eax, 5 + +; DEBUGF 1,"R6040: TX buffer status: 0x%x, eax=%u\n", [eax + r6040_tx_ring + r6040_x_head.status]:4, eax + + test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 ; check if buffer is available + jz .l3 + + push ecx esi + mov ecx, [timer_ticks] + add ecx, 100 + .l2: + test [r6040_tx_ring + eax + r6040_x_head.status], 0x8000 + jz .l5 + cmp ecx, [timer_ticks] + jb .l4 + mov esi, 10 + call delay_ms + jmp .l2 + + .l4: + pop esi ecx + DEBUGF 1,"R6040: Send timeout\n" + jmp .out + + .l5: + pop esi ecx + .l3: + push eax + + mov esi, edi + +; point to the current tx buffer + movzx edi, [r6040_private.cur_tx] + imul edi, MAX_BUF_SIZE + add edi, r6040_txb + lea eax, [edi - OS_BASE] ; real buffer address in eax + +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 + + mov esi, [esp+8+4] + mov ecx, [esp+4] +; copy the packet data + push ecx + shr ecx, 2 + rep movsd + pop ecx + and ecx, 3 + rep movsb + + pop edi + + mov ecx, [esp] + add ecx, ETH_HLEN + cmp cx, ETH_ZLEN + jae @f + mov cx, ETH_ZLEN + @@: + + mov [r6040_tx_ring + edi + r6040_x_head.len], cx + mov [r6040_tx_ring + edi + r6040_x_head.buf], eax + mov [r6040_tx_ring + edi + r6040_x_head.status], 0x8000 + + ; Trigger the MAC to check the TX descriptor + mov ax, 0x01 + mov edx, [io_addr] + add edx, MTPR + out dx, ax + + inc [r6040_private.cur_tx] + and [r6040_private.cur_tx], TX_RING_SIZE-1 + xor eax, eax + + pop ecx ebx esi edi + .out: + ret + + + +r6040_mac_address: + push eax ecx edx esi edi + ; MAC operation register + mov ax, 1 + mov edx, [io_addr] + add edx, MCR1 + out dx, ax + ; Reset MAC + mov ax, 2 + mov edx, [io_addr] + add edx, MAC_SM + out dx, ax + ; Reset internal state machine + xor ax, ax + out dx, ax + mov esi, 5 + call delay_ms + + ; Restore MAC Address + mov ecx, 3 + mov edi, node_addr + mov edx, [io_addr] + add edx, MID_0L + .mac: + in ax, dx + stosw + add edx, 2 + dec ecx + jnz .mac + + pop edi esi edx ecx eax + ret + diff --git a/kernel/trunk/network/eth_drv/drivers/rtl8029.inc b/kernel/trunk/network/eth_drv/drivers/rtl8029.inc index 6b66b54ed..320fc432b 100644 --- a/kernel/trunk/network/eth_drv/drivers/rtl8029.inc +++ b/kernel/trunk/network/eth_drv/drivers/rtl8029.inc @@ -1,959 +1,976 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; RTL8029.INC ;; -;; ;; -;; Ethernet driver for Menuet OS ;; -;; ;; -;; Version 0.2 31 July 2002 ;; -;; ;; -;; This driver is based on the ns8390 driver from ;; -;; the etherboot 5.0.6 project. The copyright statement is ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;; remaining parts Copyright 2002 Mike Hibbett, ;; -;; mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;; While this implementation handles only PCI bus RTL8029 ;; -;; hardware, it can be easily adapted to other NE2000 clone ;; -;; products. I just dont have any to try! ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;******************************************************************** -; Interface -; rtl8029_reset -; rtl8029_probe -; rtl8029_poll -; rtl8029_transmit -; -;******************************************************************** - - - - -;************************************************************************** -; 8390 Register Definitions -;************************************************************************** -D8390_P0_COMMAND equ 0x00 -D8390_P0_PSTART equ 0x01 -D8390_P0_PSTOP equ 0x02 -D8390_P0_BOUND equ 0x03 -D8390_P0_TSR equ 0x04 -D8390_P0_TPSR equ 0x04 -D8390_P0_TBCR0 equ 0x05 -D8390_P0_TBCR1 equ 0x06 -D8390_P0_ISR equ 0x07 -D8390_P0_RSAR0 equ 0x08 -D8390_P0_RSAR1 equ 0x09 -D8390_P0_RBCR0 equ 0x0A -D8390_P0_RBCR1 equ 0x0B -D8390_P0_RSR equ 0x0C -D8390_P0_RCR equ 0x0C -D8390_P0_TCR equ 0x0D -D8390_P0_DCR equ 0x0E -D8390_P0_IMR equ 0x0F -D8390_P1_COMMAND equ 0x00 -D8390_P1_PAR0 equ 0x01 -D8390_P1_PAR1 equ 0x02 -D8390_P1_PAR2 equ 0x03 -D8390_P1_PAR3 equ 0x04 -D8390_P1_PAR4 equ 0x05 -D8390_P1_PAR5 equ 0x06 -D8390_P1_CURR equ 0x07 -D8390_P1_MAR0 equ 0x08 - -D8390_COMMAND_PS0 equ 0x0 ; Page 0 select -D8390_COMMAND_PS1 equ 0x40 ; Page 1 select -D8390_COMMAND_PS2 equ 0x80 ; Page 2 select -D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control -D8390_COMMAND_RD1 equ 0x10 -D8390_COMMAND_RD0 equ 0x08 -D8390_COMMAND_TXP equ 0x04 ; transmit packet -D8390_COMMAND_STA equ 0x02 ; start -D8390_COMMAND_STP equ 0x01 ; stop - -D8390_COMMAND_RD2_STA equ 0x22 -D8390_COMMAND_RD2_STP equ 0x21 -D8390_COMMAND_RD1_STA equ 0x12 -D8390_COMMAND_RD0_STA equ 0x0A -D8390_COMMAND_PS0_RD2_STP equ 0x21 -D8390_COMMAND_PS1_RD2_STP equ 0x61 -D8390_COMMAND_PS0_RD2_STA equ 0x22 -D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26 - -D8390_RCR_MON equ 0x20 ; monitor mode - -D8390_DCR_FT1 equ 0x40 -D8390_DCR_LS equ 0x08 ; Loopback select -D8390_DCR_WTS equ 0x01 ; Word transfer select - -D8390_DCR_FT1_LS equ 0x48 -D8390_DCR_WTS_FT1_LS equ 0x49 - -D8390_ISR_PRX equ 0x01 ; successful recv -D8390_ISR_PTX equ 0x02 ; successful xmit -D8390_ISR_RXE equ 0x04 ; receive error -D8390_ISR_TXE equ 0x08 ; transmit error -D8390_ISR_OVW equ 0x10 ; Overflow -D8390_ISR_CNT equ 0x20 ; Counter overflow -D8390_ISR_RDC equ 0x40 ; Remote DMA complete -D8390_ISR_RST equ 0x80 ; reset - -D8390_RSTAT_PRX equ 0x01 ; successful recv -D8390_RSTAT_CRC equ 0x02 ; CRC error -D8390_RSTAT_FAE equ 0x04 ; Frame alignment error -D8390_RSTAT_OVER equ 0x08 ; FIFO overrun - -D8390_TXBUF_SIZE equ 6 -D8390_RXBUF_END equ 32 -D8390_PAGE_SIZE equ 256 - -ETH_ALEN equ 6 -ETH_HLEN equ 14 -ETH_ZLEN equ 60 -ETH_FRAME_LEN equ 1514 - -FLAG_PIO equ 0x01 -FLAG_16BIT equ 0x02 -ASIC_PIO equ 0 - -VENDOR_NONE equ 0 -VENDOR_WD equ 1 -VENDOR_NOVELL equ 2 -VENDOR_3COM equ 3 - -NE_ASIC_OFFSET equ 0x10 -NE_RESET equ 0x0F ; Used to reset card -NE_DATA equ 0x00 ; Used to read/write NIC mem - -MEM_8192 equ 32 -MEM_16384 equ 64 -MEM_32768 equ 128 - -ISA_MAX_ADDR equ 0x400 - -uglobal -eth_flags: db 0 -eth_vendor: db 0 -eth_nic_base: dw 0 -eth_asic_base: dw 0 -eth_memsize: db 0 -eth_rx_start: db 0 -eth_tx_start: db 0 -eth_bmem: dd 0 -eth_rmem: dd 0 -romdata: db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -endg - -iglobal -test_data: db 'NE*000 memory',0 -test_buffer: db ' ',0 -endg - -uglobal -eth_type: dw 0 -pkthdr: db 0,0,0,0 ; status, next, (short) len -pktoff: dw 0 -eth_rx_data_ptr: dd 0 -eth_tmp_len: dw 0 -endg - - - -;*************************************************************************** -; Function -; eth_pio_read -; -; Description -; Read a frame from the ethernet card via Programmed I/O -; src in ebx -; cnt in ecx -; dst in edi -;*************************************************************************** -eth_pio_read: - mov al, [eth_flags] - and al, FLAG_16BIT - cmp al, 0 - je epr_001 - - inc ecx - and ecx, 0xFFFFFFFE - -epr_001: - mov al, D8390_COMMAND_RD2_STA - mov dx, [eth_nic_base] - add dx, D8390_P0_COMMAND - out dx, al - - mov al, cl - mov dx, [eth_nic_base] - add dx, D8390_P0_RBCR0 - out dx, al - - mov al, ch - mov dx, [eth_nic_base] - add dx, D8390_P0_RBCR1 - out dx, al - - mov al, bl - mov dx, [eth_nic_base] - add dx, D8390_P0_RSAR0 - out dx, al - - mov al, bh - mov dx, [eth_nic_base] - add dx, D8390_P0_RSAR1 - out dx, al - - mov al, D8390_COMMAND_RD0_STA - mov dx, [eth_nic_base] - add dx, D8390_P0_COMMAND - out dx, al - - mov dx, [eth_asic_base] - add dx, ASIC_PIO - - mov al, [eth_flags] - and al, FLAG_16BIT - cmp al, 0 - je epr_003 - - shr ecx, 1 - -epr_002: - ; 2 bytes at a time - in ax, dx - mov [edi], ax - add edi, 2 - loop epr_002 - ret - -epr_003: - ; 1 byte at a time - in al, dx - mov [edi], al - inc edi - loop epr_003 - ret - - - - -;*************************************************************************** -; Function -; eth_pio_write -; -; Description -; writes a frame to the ethernet card via Programmed I/O -; dst in ebx -; cnt in ecx -; src in esi -;*************************************************************************** -eth_pio_write: - mov al, [eth_flags] - and al, FLAG_16BIT - cmp al, 0 - je epw_001 - - inc ecx - and ecx, 0xFFFFFFFE - -epw_001: - mov al, D8390_COMMAND_RD2_STA - mov dx, [eth_nic_base] - add dx, D8390_P0_COMMAND - out dx, al - - mov al, D8390_ISR_RDC - mov dx, [eth_nic_base] - add dx, D8390_P0_ISR - out dx, al - - - mov al, cl - mov dx, [eth_nic_base] - add dx, D8390_P0_RBCR0 - out dx, al - - mov al, ch - mov dx, [eth_nic_base] - add dx, D8390_P0_RBCR1 - out dx, al - - mov al, bl - mov dx, [eth_nic_base] - add dx, D8390_P0_RSAR0 - out dx, al - - mov al, bh - mov dx, [eth_nic_base] - add dx, D8390_P0_RSAR1 - out dx, al - - mov al, D8390_COMMAND_RD1_STA - mov dx, [eth_nic_base] - add dx, D8390_P0_COMMAND - out dx, al - - mov dx, [eth_asic_base] - add dx, ASIC_PIO - - mov al, [eth_flags] - and al, FLAG_16BIT - cmp al, 0 - je epw_003 - - shr ecx, 1 - -epw_002: - ; 2 bytes at a time - mov ax, [esi] - add esi, 2 - out dx, ax - - loop epw_002 - jmp epw_004 - -epw_003: - ; 1 byte at a time - mov al, [esi] - inc esi - out dx, al - loop epw_003 - -epw_004: - mov dx, [eth_nic_base] - add dx, D8390_P0_ISR - -epw_005: - in al, dx - and al, D8390_ISR_RDC - cmp al, D8390_ISR_RDC - jne epw_005 - - ret - - - -;*************************************************************************** -; Function -; rtl8029_reset -; Description -; Place the chip (ie, the ethernet card) into a virgin state -; No inputs -; All registers destroyed -; -;*************************************************************************** -rtl8029_reset: - mov bx, [eth_nic_base] - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_PS0_RD2_STP - out dx, al - - mov dx, bx - add dx, D8390_P0_DCR - mov al, [eth_flags] - and al, FLAG_16BIT - cmp al, FLAG_16BIT - jne nsr_001 - - mov al, 0x49 - jmp nsr_002 - -nsr_001: - mov al, 0x48 - -nsr_002: - out dx, al - - xor al, al - - mov dx, bx - add dx, D8390_P0_RBCR0 - out dx, al - - mov dx, bx - add dx, D8390_P0_RBCR1 - out dx, al - - mov dx, bx - add dx, D8390_P0_RCR - mov al, 0x20 - out dx, al - - mov dx, bx - add dx, D8390_P0_TCR - mov al, 2 - out dx, al - - mov dx, bx - add dx, D8390_P0_TPSR - mov al, [eth_tx_start] - out dx, al - - mov dx, bx - add dx, D8390_P0_PSTART - mov al, [eth_rx_start] - out dx, al - - mov dx, bx - add dx, D8390_P0_PSTOP - mov al, [eth_memsize] - out dx, al - - mov dx, bx - add dx, D8390_P0_BOUND - mov al, [eth_memsize] - dec al - out dx, al - - mov dx, bx - add dx, D8390_P0_ISR - mov al, 0xff - out dx, al - - mov dx, bx - add dx, D8390_P0_IMR - xor al, al - out dx, al - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_PS1_RD2_STP - out dx, al - - mov dx, bx - add dx, D8390_P1_PAR0 - mov esi, node_addr - mov ecx, ETH_ALEN - -nsr_003: - mov al, [esi] - out dx, al - - inc esi - inc dx - loop nsr_003 - - mov dx, bx - add dx, D8390_P1_MAR0 - mov ecx, ETH_ALEN - - mov al, 0xff - -nsr_004: - out dx, al - inc dx - loop nsr_004 - - mov dx, bx - add dx, D8390_P1_CURR - mov al, [eth_rx_start] - out dx, al - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_PS0_RD2_STA - out dx, al - - mov dx, bx - add dx, D8390_P0_ISR - mov al, 0xff - out dx, al - - mov dx, bx - add dx, D8390_P0_TCR - mov al, 0 - out dx, al - - mov dx, bx - add dx, D8390_P0_RCR - mov al, 4 - out dx, al - - ret - - - -;*************************************************************************** -; Function -; rtl8029_probe -; Description -; Searches for an ethernet card, enables it and clears the rx buffer -; If a card was found, it enables the ethernet -> TCPIP link -; -;*************************************************************************** -rtl8029_probe: - mov eax, [io_addr] - mov [eth_nic_base], ax ; The IO address space is 16 bit only - - mov al, VENDOR_NONE - mov [eth_vendor], al - - mov al, [eth_vendor] - cmp al, VENDOR_NONE - - jne ep_check_have_vendor - xor eax, eax - mov [eth_bmem], eax - - mov al, FLAG_PIO - mov [eth_flags], al - - mov ax, [eth_nic_base] - add ax, NE_ASIC_OFFSET - mov [eth_asic_base], ax - - mov al, MEM_16384 - mov [eth_memsize], al - - mov al, 32 - mov [eth_tx_start], al - - add al, D8390_TXBUF_SIZE - mov [eth_rx_start], al - - mov dx, [eth_asic_base] - add dx, NE_RESET - - in al, dx - out dx, al - - in al, 0x84 - - mov bx, [eth_nic_base] - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_RD2_STP - out dx, al - - mov dx, bx - add dx, D8390_P0_RCR - mov al, D8390_RCR_MON - out dx, al - - mov dx, bx - add dx, D8390_P0_DCR - mov al, D8390_DCR_FT1_LS - out dx, al - - mov dx, bx - add dx, D8390_P0_PSTART - mov al, MEM_8192 - out dx, al - - mov dx, bx - add dx, D8390_P0_PSTOP - mov al, MEM_16384 - out dx, al - - mov esi, test_data - mov ebx, 8192 - mov ecx, 14 - call eth_pio_write - - mov ebx, 8192 - mov ecx, 14 - mov edi, test_buffer - call eth_pio_read - - mov esi, test_buffer - mov edi, test_data - mov ecx, 13 - cld - rep cmpsb - - je ep_set_vendor - - mov al, [eth_flags] - or al, FLAG_16BIT - mov [eth_flags], al - - mov al, MEM_32768 - mov [eth_memsize], al - - mov al, 64 - mov [eth_tx_start], al - - add al, D8390_TXBUF_SIZE - mov [eth_rx_start], al - - mov bx, [eth_nic_base] - - mov dx, bx - add dx, D8390_P0_DCR - mov al, D8390_DCR_WTS_FT1_LS - out dx, al - - mov dx, bx - add dx, D8390_P0_PSTART - mov al, MEM_16384 - out dx, al - - mov dx, bx - add dx, D8390_P0_PSTOP - mov al, MEM_32768 - out dx, al - - mov esi, test_data - mov ebx, 16384 - mov ecx, 14 - call eth_pio_write - - mov ebx, 16384 - mov ecx, 14 - mov edi, test_buffer - call eth_pio_read - - mov esi, test_buffer - mov edi, test_data - mov ecx, 13 - cld - rep cmpsb - -ep_set_vendor: - ; this bit is odd - probably left over from my hacking - mov ax, [eth_nic_base] - cmp ax, 0 - je rtl8029_exit - cmp ax, ISA_MAX_ADDR - jbe ep_001 - mov al, [eth_flags] - or al, FLAG_16BIT - mov [eth_flags], al - -ep_001: - mov al, VENDOR_NOVELL - mov [eth_vendor], al - - mov ebx, 0 - mov ecx, 16 - mov edi, romdata - call eth_pio_read - - - mov ecx, ETH_ALEN - mov esi, romdata - mov edi, node_addr - - mov bl, [eth_flags] - and bl, FLAG_16BIT - -ep_002: - mov al, [esi] - mov [edi], al - - inc edi - inc esi - cmp bl, FLAG_16BIT - jne ep_003 - - inc esi - -ep_003: - loop ep_002 - -ep_check_have_vendor: - mov al, [eth_vendor] - cmp al, VENDOR_NONE - je rtl8029_exit - - cmp al, VENDOR_3COM - je ep_reset_card - - mov eax, [eth_bmem] - mov [eth_rmem], eax - -ep_reset_card: - ; Reset the card - call rtl8029_reset - - ; Indicate that we have successfully reset the card - mov eax, [pci_data] - mov [eth_status], eax - -rtl8029_exit: - ret - - - -;*************************************************************************** -; Function -; rtl8029_poll -; -; Description -; Polls the ethernet card for a received packet -; Received data, if any, ends up in Ether_buffer -; -;*************************************************************************** -rtl8029_poll: - mov eax, Ether_buffer - mov [eth_rx_data_ptr], eax - - mov bx, [eth_nic_base] - - mov dx, bx - add dx, D8390_P0_RSR - in al, dx - - and al, D8390_RSTAT_PRX - cmp al, D8390_RSTAT_PRX - jne nsp_exit - - mov dx, bx - add dx, D8390_P0_BOUND - in al, dx - inc al - - cmp al, [eth_memsize] - jb nsp_001 - - mov al, [eth_rx_start] - -nsp_001: - mov ch, al - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_PS1 - out dx, al - - mov dx, bx - add dx, D8390_P1_CURR - in al, dx ; get current page - mov cl, al - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_PS0 - out dx, al - - cmp cl, [eth_memsize] - jb nsp_002 - - mov cl, [eth_rx_start] - -nsp_002: - cmp cl, ch - je nsp_exit - - xor ax, ax - mov ah, ch - - mov [pktoff], ax - - mov al, [eth_flags] - and al, FLAG_PIO - cmp al, FLAG_PIO - jne nsp_003 - - movzx ebx, word [pktoff] - mov edi, pkthdr - mov ecx, 4 - call eth_pio_read - jmp nsp_004 - -nsp_003: - mov edi, [eth_rmem] - movzx eax, word [pktoff] - add edi, eax - mov eax, [edi] - mov [pkthdr], eax - -nsp_004: - mov ax, [pktoff] - add ax, 4 - mov [pktoff], ax - - mov ax, [pkthdr + 2] - sub ax, 4 - - mov [eth_tmp_len], ax - - cmp ax, ETH_ZLEN - jb nsp_exit - - cmp ax, ETH_FRAME_LEN - ja nsp_exit - - mov al, [pkthdr] - and al, D8390_RSTAT_PRX - cmp al, D8390_RSTAT_PRX - jne nsp_exit - - ; Right, we can now get the data - - mov ax, [eth_tmp_len] - mov [eth_rx_data_len], ax - - xor ebx, ebx - mov bh, [eth_memsize] - sub bx, [pktoff] - - cmp [eth_tmp_len], bx - jbe nsp_005 - - mov al, [eth_flags] - and al, FLAG_PIO - cmp al, FLAG_PIO - jne nsp_006 - - push ebx - mov ecx, ebx - xor ebx, ebx - mov bx, [pktoff] - mov edi, [eth_rx_data_ptr] - call eth_pio_read - pop ebx - jmp nsp_007 - -nsp_006: - ; Not implemented, as we are using PIO mode on this card - -nsp_007: - xor ax, ax - mov ah, [eth_rx_start] - mov [pktoff], ax - - mov eax, [eth_rx_data_ptr] - add eax, ebx - mov [eth_rx_data_ptr], eax - - mov ax, [eth_tmp_len] - sub ax, bx - mov [eth_tmp_len], ax - -nsp_005: - mov al, [eth_flags] - and al, FLAG_PIO - cmp al, FLAG_PIO - jne nsp_008 - - xor ebx, ebx - mov bx, [pktoff] - xor ecx, ecx - mov cx, [eth_tmp_len] - mov edi, [eth_rx_data_ptr] - call eth_pio_read - jmp nsp_009 - -nsp_008: - ; Not implemented, as we are using PIO mode on this card - -nsp_009: - mov al, [pkthdr+1] - cmp al, [eth_rx_start] - jne nsp_010 - - mov al, [eth_memsize] - -nsp_010: - mov dx, [eth_nic_base] - add dx, D8390_P0_BOUND - dec al - out dx, al - -nsp_exit: - ret - - - -;*************************************************************************** -; Function -; rtl8029_transmit -; -; Description -; Transmits a packet of data via the ethernet card -; Pointer to 48 bit destination address in edi -; Type of packet in bx -; size of packet in ecx -; pointer to packet data in esi -; -;*************************************************************************** -rtl8029_transmit: - mov [eth_type], bx - - pusha - - mov esi, edi - xor bx, bx - mov bh, [eth_tx_start] - mov ecx, ETH_ALEN - call eth_pio_write - - mov esi, node_addr - xor bx, bx - mov bh, [eth_tx_start] - add bx, ETH_ALEN - mov ecx, ETH_ALEN - call eth_pio_write - - mov esi, eth_type - xor bx, bx - mov bh, [eth_tx_start] - add bx, ETH_ALEN - add bx, ETH_ALEN - mov ecx, 2 - call eth_pio_write - - popa - - xor bx, bx - mov bh, [eth_tx_start] - add bx, ETH_HLEN - push ecx - call eth_pio_write - pop ecx - - add ecx, ETH_HLEN - cmp ecx, ETH_ZLEN - jae nst_001 - - mov ecx, ETH_ZLEN - -nst_001: - push ecx - - mov bx, [eth_nic_base] - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_PS0_RD2_STA - out dx, al - - mov dx, bx - add dx, D8390_P0_TPSR - mov al, [eth_tx_start] - out dx, al - - pop ecx - - mov dx, bx - add dx, D8390_P0_TBCR0 - mov al, cl - out dx, al - - mov dx, bx - add dx, D8390_P0_TBCR1 - mov al, ch - out dx, al - - mov dx, bx - add dx, D8390_P0_COMMAND - mov al, D8390_COMMAND_PS0_TXP_RD2_STA - out dx, al - - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; RTL8029.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.2 31 July 2002 ;; +;; ;; +;; This driver is based on the ns8390 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2002 Mike Hibbett, ;; +;; mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; While this implementation handles only PCI bus RTL8029 ;; +;; hardware, it can be easily adapted to other NE2000 clone ;; +;; products. I just dont have any to try! ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;******************************************************************** +; Interface +; rtl8029_reset +; rtl8029_probe +; rtl8029_poll +; rtl8029_transmit +; +;******************************************************************** + + + + +;************************************************************************** +; 8390 Register Definitions +;************************************************************************** +D8390_P0_COMMAND equ 0x00 +D8390_P0_PSTART equ 0x01 +D8390_P0_PSTOP equ 0x02 +D8390_P0_BOUND equ 0x03 +D8390_P0_TSR equ 0x04 +D8390_P0_TPSR equ 0x04 +D8390_P0_TBCR0 equ 0x05 +D8390_P0_TBCR1 equ 0x06 +D8390_P0_ISR equ 0x07 +D8390_P0_RSAR0 equ 0x08 +D8390_P0_RSAR1 equ 0x09 +D8390_P0_RBCR0 equ 0x0A +D8390_P0_RBCR1 equ 0x0B +D8390_P0_RSR equ 0x0C +D8390_P0_RCR equ 0x0C +D8390_P0_TCR equ 0x0D +D8390_P0_DCR equ 0x0E +D8390_P0_IMR equ 0x0F +D8390_P1_COMMAND equ 0x00 +D8390_P1_PAR0 equ 0x01 +D8390_P1_PAR1 equ 0x02 +D8390_P1_PAR2 equ 0x03 +D8390_P1_PAR3 equ 0x04 +D8390_P1_PAR4 equ 0x05 +D8390_P1_PAR5 equ 0x06 +D8390_P1_CURR equ 0x07 +D8390_P1_MAR0 equ 0x08 + +D8390_COMMAND_PS0 equ 0x0 ; Page 0 select +D8390_COMMAND_PS1 equ 0x40 ; Page 1 select +D8390_COMMAND_PS2 equ 0x80 ; Page 2 select +D8390_COMMAND_RD2 equ 0x20 ; Remote DMA control +D8390_COMMAND_RD1 equ 0x10 +D8390_COMMAND_RD0 equ 0x08 +D8390_COMMAND_TXP equ 0x04 ; transmit packet +D8390_COMMAND_STA equ 0x02 ; start +D8390_COMMAND_STP equ 0x01 ; stop + +D8390_COMMAND_RD2_STA equ 0x22 +D8390_COMMAND_RD2_STP equ 0x21 +D8390_COMMAND_RD1_STA equ 0x12 +D8390_COMMAND_RD0_STA equ 0x0A +D8390_COMMAND_PS0_RD2_STP equ 0x21 +D8390_COMMAND_PS1_RD2_STP equ 0x61 +D8390_COMMAND_PS0_RD2_STA equ 0x22 +D8390_COMMAND_PS0_TXP_RD2_STA equ 0x26 + +D8390_RCR_MON equ 0x20 ; monitor mode + +D8390_DCR_FT1 equ 0x40 +D8390_DCR_LS equ 0x08 ; Loopback select +D8390_DCR_WTS equ 0x01 ; Word transfer select + +D8390_DCR_FT1_LS equ 0x48 +D8390_DCR_WTS_FT1_LS equ 0x49 + +D8390_ISR_PRX equ 0x01 ; successful recv +D8390_ISR_PTX equ 0x02 ; successful xmit +D8390_ISR_RXE equ 0x04 ; receive error +D8390_ISR_TXE equ 0x08 ; transmit error +D8390_ISR_OVW equ 0x10 ; Overflow +D8390_ISR_CNT equ 0x20 ; Counter overflow +D8390_ISR_RDC equ 0x40 ; Remote DMA complete +D8390_ISR_RST equ 0x80 ; reset + +D8390_RSTAT_PRX equ 0x01 ; successful recv +D8390_RSTAT_CRC equ 0x02 ; CRC error +D8390_RSTAT_FAE equ 0x04 ; Frame alignment error +D8390_RSTAT_OVER equ 0x08 ; FIFO overrun + +D8390_TXBUF_SIZE equ 6 +D8390_RXBUF_END equ 32 +D8390_PAGE_SIZE equ 256 + +ETH_ALEN equ 6 +ETH_HLEN equ 14 +ETH_ZLEN equ 60 +ETH_FRAME_LEN equ 1514 + +FLAG_PIO equ 0x01 +FLAG_16BIT equ 0x02 +ASIC_PIO equ 0 + +VENDOR_NONE equ 0 +VENDOR_WD equ 1 +VENDOR_NOVELL equ 2 +VENDOR_3COM equ 3 + +NE_ASIC_OFFSET equ 0x10 +NE_RESET equ 0x0F ; Used to reset card +NE_DATA equ 0x00 ; Used to read/write NIC mem + +MEM_8192 equ 32 +MEM_16384 equ 64 +MEM_32768 equ 128 + +ISA_MAX_ADDR equ 0x400 + +uglobal +eth_flags: + db 0 +eth_vendor: + db 0 +eth_nic_base: + dw 0 +eth_asic_base: + dw 0 +eth_memsize: + db 0 +eth_rx_start: + db 0 +eth_tx_start: + db 0 +eth_bmem: + dd 0 +eth_rmem: + dd 0 +romdata: + db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +endg + +iglobal +test_data: + db 'NE*000 memory',0 +test_buffer: + db ' ',0 +endg + +uglobal +eth_type: + dw 0 +pkthdr: + db 0,0,0,0 ; status, next, (short) len +pktoff: + dw 0 +eth_rx_data_ptr: + dd 0 +eth_tmp_len: + dw 0 +endg + + + +;*************************************************************************** +; Function +; eth_pio_read +; +; Description +; Read a frame from the ethernet card via Programmed I/O +; src in ebx +; cnt in ecx +; dst in edi +;*************************************************************************** +eth_pio_read: + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epr_001 + + inc ecx + and ecx, 0xFFFFFFFE + +epr_001: + mov al, D8390_COMMAND_RD2_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov al, cl + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR0 + out dx, al + + mov al, ch + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR1 + out dx, al + + mov al, bl + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR0 + out dx, al + + mov al, bh + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR1 + out dx, al + + mov al, D8390_COMMAND_RD0_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov dx, [eth_asic_base] + add dx, ASIC_PIO + + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epr_003 + + shr ecx, 1 + +epr_002: + ; 2 bytes at a time + in ax, dx + mov [edi], ax + add edi, 2 + loop epr_002 + ret + +epr_003: + ; 1 byte at a time + in al, dx + mov [edi], al + inc edi + loop epr_003 + ret + + + + +;*************************************************************************** +; Function +; eth_pio_write +; +; Description +; writes a frame to the ethernet card via Programmed I/O +; dst in ebx +; cnt in ecx +; src in esi +;*************************************************************************** +eth_pio_write: + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epw_001 + + inc ecx + and ecx, 0xFFFFFFFE + +epw_001: + mov al, D8390_COMMAND_RD2_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov al, D8390_ISR_RDC + mov dx, [eth_nic_base] + add dx, D8390_P0_ISR + out dx, al + + + mov al, cl + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR0 + out dx, al + + mov al, ch + mov dx, [eth_nic_base] + add dx, D8390_P0_RBCR1 + out dx, al + + mov al, bl + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR0 + out dx, al + + mov al, bh + mov dx, [eth_nic_base] + add dx, D8390_P0_RSAR1 + out dx, al + + mov al, D8390_COMMAND_RD1_STA + mov dx, [eth_nic_base] + add dx, D8390_P0_COMMAND + out dx, al + + mov dx, [eth_asic_base] + add dx, ASIC_PIO + + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, 0 + je epw_003 + + shr ecx, 1 + +epw_002: + ; 2 bytes at a time + mov ax, [esi] + add esi, 2 + out dx, ax + + loop epw_002 + jmp epw_004 + +epw_003: + ; 1 byte at a time + mov al, [esi] + inc esi + out dx, al + loop epw_003 + +epw_004: + mov dx, [eth_nic_base] + add dx, D8390_P0_ISR + +epw_005: + in al, dx + and al, D8390_ISR_RDC + cmp al, D8390_ISR_RDC + jne epw_005 + + ret + + + +;*************************************************************************** +; Function +; rtl8029_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; No inputs +; All registers destroyed +; +;*************************************************************************** +rtl8029_reset: + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_RD2_STP + out dx, al + + mov dx, bx + add dx, D8390_P0_DCR + mov al, [eth_flags] + and al, FLAG_16BIT + cmp al, FLAG_16BIT + jne nsr_001 + + mov al, 0x49 + jmp nsr_002 + +nsr_001: + mov al, 0x48 + +nsr_002: + out dx, al + + xor al, al + + mov dx, bx + add dx, D8390_P0_RBCR0 + out dx, al + + mov dx, bx + add dx, D8390_P0_RBCR1 + out dx, al + + mov dx, bx + add dx, D8390_P0_RCR + mov al, 0x20 + out dx, al + + mov dx, bx + add dx, D8390_P0_TCR + mov al, 2 + out dx, al + + mov dx, bx + add dx, D8390_P0_TPSR + mov al, [eth_tx_start] + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTART + mov al, [eth_rx_start] + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTOP + mov al, [eth_memsize] + out dx, al + + mov dx, bx + add dx, D8390_P0_BOUND + mov al, [eth_memsize] + dec al + out dx, al + + mov dx, bx + add dx, D8390_P0_ISR + mov al, 0xff + out dx, al + + mov dx, bx + add dx, D8390_P0_IMR + xor al, al + out dx, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS1_RD2_STP + out dx, al + + mov dx, bx + add dx, D8390_P1_PAR0 + mov esi, node_addr + mov ecx, ETH_ALEN + +nsr_003: + mov al, [esi] + out dx, al + + inc esi + inc dx + loop nsr_003 + + mov dx, bx + add dx, D8390_P1_MAR0 + mov ecx, ETH_ALEN + + mov al, 0xff + +nsr_004: + out dx, al + inc dx + loop nsr_004 + + mov dx, bx + add dx, D8390_P1_CURR + mov al, [eth_rx_start] + out dx, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_RD2_STA + out dx, al + + mov dx, bx + add dx, D8390_P0_ISR + mov al, 0xff + out dx, al + + mov dx, bx + add dx, D8390_P0_TCR + mov al, 0 + out dx, al + + mov dx, bx + add dx, D8390_P0_RCR + mov al, 4 + out dx, al + + ret + + + +;*************************************************************************** +; Function +; rtl8029_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; +;*************************************************************************** +rtl8029_probe: + mov eax, [io_addr] + mov [eth_nic_base], ax ; The IO address space is 16 bit only + + mov al, VENDOR_NONE + mov [eth_vendor], al + + mov al, [eth_vendor] + cmp al, VENDOR_NONE + + jne ep_check_have_vendor + xor eax, eax + mov [eth_bmem], eax + + mov al, FLAG_PIO + mov [eth_flags], al + + mov ax, [eth_nic_base] + add ax, NE_ASIC_OFFSET + mov [eth_asic_base], ax + + mov al, MEM_16384 + mov [eth_memsize], al + + mov al, 32 + mov [eth_tx_start], al + + add al, D8390_TXBUF_SIZE + mov [eth_rx_start], al + + mov dx, [eth_asic_base] + add dx, NE_RESET + + in al, dx + out dx, al + + in al, 0x84 + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_RD2_STP + out dx, al + + mov dx, bx + add dx, D8390_P0_RCR + mov al, D8390_RCR_MON + out dx, al + + mov dx, bx + add dx, D8390_P0_DCR + mov al, D8390_DCR_FT1_LS + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTART + mov al, MEM_8192 + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTOP + mov al, MEM_16384 + out dx, al + + mov esi, test_data + mov ebx, 8192 + mov ecx, 14 + call eth_pio_write + + mov ebx, 8192 + mov ecx, 14 + mov edi, test_buffer + call eth_pio_read + + mov esi, test_buffer + mov edi, test_data + mov ecx, 13 + cld + rep cmpsb + + je ep_set_vendor + + mov al, [eth_flags] + or al, FLAG_16BIT + mov [eth_flags], al + + mov al, MEM_32768 + mov [eth_memsize], al + + mov al, 64 + mov [eth_tx_start], al + + add al, D8390_TXBUF_SIZE + mov [eth_rx_start], al + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_DCR + mov al, D8390_DCR_WTS_FT1_LS + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTART + mov al, MEM_16384 + out dx, al + + mov dx, bx + add dx, D8390_P0_PSTOP + mov al, MEM_32768 + out dx, al + + mov esi, test_data + mov ebx, 16384 + mov ecx, 14 + call eth_pio_write + + mov ebx, 16384 + mov ecx, 14 + mov edi, test_buffer + call eth_pio_read + + mov esi, test_buffer + mov edi, test_data + mov ecx, 13 + cld + rep cmpsb + +ep_set_vendor: + ; this bit is odd - probably left over from my hacking + mov ax, [eth_nic_base] + cmp ax, 0 + je rtl8029_exit + cmp ax, ISA_MAX_ADDR + jbe ep_001 + mov al, [eth_flags] + or al, FLAG_16BIT + mov [eth_flags], al + +ep_001: + mov al, VENDOR_NOVELL + mov [eth_vendor], al + + mov ebx, 0 + mov ecx, 16 + mov edi, romdata + call eth_pio_read + + + mov ecx, ETH_ALEN + mov esi, romdata + mov edi, node_addr + + mov bl, [eth_flags] + and bl, FLAG_16BIT + +ep_002: + mov al, [esi] + mov [edi], al + + inc edi + inc esi + cmp bl, FLAG_16BIT + jne ep_003 + + inc esi + +ep_003: + loop ep_002 + +ep_check_have_vendor: + mov al, [eth_vendor] + cmp al, VENDOR_NONE + je rtl8029_exit + + cmp al, VENDOR_3COM + je ep_reset_card + + mov eax, [eth_bmem] + mov [eth_rmem], eax + +ep_reset_card: + ; Reset the card + call rtl8029_reset + + ; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax + +rtl8029_exit: + ret + + + +;*************************************************************************** +; Function +; rtl8029_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; +;*************************************************************************** +rtl8029_poll: + mov eax, Ether_buffer + mov [eth_rx_data_ptr], eax + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_RSR + in al, dx + + and al, D8390_RSTAT_PRX + cmp al, D8390_RSTAT_PRX + jne nsp_exit + + mov dx, bx + add dx, D8390_P0_BOUND + in al, dx + inc al + + cmp al, [eth_memsize] + jb nsp_001 + + mov al, [eth_rx_start] + +nsp_001: + mov ch, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS1 + out dx, al + + mov dx, bx + add dx, D8390_P1_CURR + in al, dx ; get current page + mov cl, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0 + out dx, al + + cmp cl, [eth_memsize] + jb nsp_002 + + mov cl, [eth_rx_start] + +nsp_002: + cmp cl, ch + je nsp_exit + + xor ax, ax + mov ah, ch + + mov [pktoff], ax + + mov al, [eth_flags] + and al, FLAG_PIO + cmp al, FLAG_PIO + jne nsp_003 + + movzx ebx, word [pktoff] + mov edi, pkthdr + mov ecx, 4 + call eth_pio_read + jmp nsp_004 + +nsp_003: + mov edi, [eth_rmem] + movzx eax, word [pktoff] + add edi, eax + mov eax, [edi] + mov [pkthdr], eax + +nsp_004: + mov ax, [pktoff] + add ax, 4 + mov [pktoff], ax + + mov ax, [pkthdr + 2] + sub ax, 4 + + mov [eth_tmp_len], ax + + cmp ax, ETH_ZLEN + jb nsp_exit + + cmp ax, ETH_FRAME_LEN + ja nsp_exit + + mov al, [pkthdr] + and al, D8390_RSTAT_PRX + cmp al, D8390_RSTAT_PRX + jne nsp_exit + + ; Right, we can now get the data + + mov ax, [eth_tmp_len] + mov [eth_rx_data_len], ax + + xor ebx, ebx + mov bh, [eth_memsize] + sub bx, [pktoff] + + cmp [eth_tmp_len], bx + jbe nsp_005 + + mov al, [eth_flags] + and al, FLAG_PIO + cmp al, FLAG_PIO + jne nsp_006 + + push ebx + mov ecx, ebx + xor ebx, ebx + mov bx, [pktoff] + mov edi, [eth_rx_data_ptr] + call eth_pio_read + pop ebx + jmp nsp_007 + +nsp_006: + ; Not implemented, as we are using PIO mode on this card + +nsp_007: + xor ax, ax + mov ah, [eth_rx_start] + mov [pktoff], ax + + mov eax, [eth_rx_data_ptr] + add eax, ebx + mov [eth_rx_data_ptr], eax + + mov ax, [eth_tmp_len] + sub ax, bx + mov [eth_tmp_len], ax + +nsp_005: + mov al, [eth_flags] + and al, FLAG_PIO + cmp al, FLAG_PIO + jne nsp_008 + + xor ebx, ebx + mov bx, [pktoff] + xor ecx, ecx + mov cx, [eth_tmp_len] + mov edi, [eth_rx_data_ptr] + call eth_pio_read + jmp nsp_009 + +nsp_008: + ; Not implemented, as we are using PIO mode on this card + +nsp_009: + mov al, [pkthdr+1] + cmp al, [eth_rx_start] + jne nsp_010 + + mov al, [eth_memsize] + +nsp_010: + mov dx, [eth_nic_base] + add dx, D8390_P0_BOUND + dec al + out dx, al + +nsp_exit: + ret + + + +;*************************************************************************** +; Function +; rtl8029_transmit +; +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +;*************************************************************************** +rtl8029_transmit: + mov [eth_type], bx + + pusha + + mov esi, edi + xor bx, bx + mov bh, [eth_tx_start] + mov ecx, ETH_ALEN + call eth_pio_write + + mov esi, node_addr + xor bx, bx + mov bh, [eth_tx_start] + add bx, ETH_ALEN + mov ecx, ETH_ALEN + call eth_pio_write + + mov esi, eth_type + xor bx, bx + mov bh, [eth_tx_start] + add bx, ETH_ALEN + add bx, ETH_ALEN + mov ecx, 2 + call eth_pio_write + + popa + + xor bx, bx + mov bh, [eth_tx_start] + add bx, ETH_HLEN + push ecx + call eth_pio_write + pop ecx + + add ecx, ETH_HLEN + cmp ecx, ETH_ZLEN + jae nst_001 + + mov ecx, ETH_ZLEN + +nst_001: + push ecx + + mov bx, [eth_nic_base] + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_RD2_STA + out dx, al + + mov dx, bx + add dx, D8390_P0_TPSR + mov al, [eth_tx_start] + out dx, al + + pop ecx + + mov dx, bx + add dx, D8390_P0_TBCR0 + mov al, cl + out dx, al + + mov dx, bx + add dx, D8390_P0_TBCR1 + mov al, ch + out dx, al + + mov dx, bx + add dx, D8390_P0_COMMAND + mov al, D8390_COMMAND_PS0_TXP_RD2_STA + out dx, al + + ret diff --git a/kernel/trunk/network/eth_drv/drivers/rtl8139.inc b/kernel/trunk/network/eth_drv/drivers/rtl8139.inc index a6af3f899..d5117c252 100644 --- a/kernel/trunk/network/eth_drv/drivers/rtl8139.inc +++ b/kernel/trunk/network/eth_drv/drivers/rtl8139.inc @@ -1,621 +1,624 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; RTL8139.INC ;; -;; ;; -;; Ethernet driver for Menuet OS ;; -;; ;; -;; Version 0.2 11 August 2003 ;; -;; ;; -;; Driver for chips of RealTek 8139 family ;; -;; References: ;; -;; www.realtek.com.hw - data sheets ;; -;; rtl8139.c - linux driver ;; -;; 8139too.c - linux driver ;; -;; ethernet driver template by Mike Hibbett ;; -;; ;; -;; The copyright statement is ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;; Copyright 2003 Endre Kozma, ;; -;; endre.kozma@axelero.hu ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;; 10.01.2007 Bugfix for l8139_transmit from Paolo Franchetti ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - - ETH_ALEN equ 6 - ETH_HLEN equ (2 * ETH_ALEN + 2) - ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for - ; mininmum 64bytes frame length - - PCI_REG_COMMAND equ 0x04 ; command register - PCI_BIT_PIO equ 0 ; bit0: io space control - PCI_BIT_MMIO equ 1 ; bit1: memory space control - PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master - - RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0 - RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4 - RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor - RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor - RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address - RTL8139_REG_COMMAND equ 0x37 ; command register - RTL8139_REG_CAPR equ 0x38 ; current address of packet read - RTL8139_REG_IMR equ 0x3c ; interrupt mask register - RTL8139_REG_ISR equ 0x3e ; interrupt status register - RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register - RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0 - RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1 - RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2 - RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3 - RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0 - RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0 - RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1 - RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2 - RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3 - RTL8139_REG_MPC equ 0x4c ; missed packet counter - RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register - RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1 - RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4 - RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register - RTL8139_REG_BMCR equ 0x62 ; basic mode control register - RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register - -; 5.1 packet header - RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes - RTL8139_BIT_LONG equ 3 ; total packet length > 4k - RTL8139_BIT_CRC equ 2 ; crc error occured - RTL8139_BIT_FAE equ 1 ; frame alignment error occured - RTL8139_BIT_ROK equ 0 ; received packet is ok -; 5.4 command register - RTL8139_BIT_RST equ 4 ; reset bit - RTL8139_BIT_RE equ 3 ; receiver enabled - RTL8139_BIT_TE equ 2 ; transmitter enabled - RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored -; 5.6 interrupt status register - RTL8139_BIT_ISR_TOK equ 2 ; transmit ok - RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt - RTL8139_BIT_ISR_ROK equ 0 ; receive ok -; 5.7 transmit configyration register - RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst - RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16) -; 5.8 receive configuration register - RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold - RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator - RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst - RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping - RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356 - RTL8139_BIT_AER equ 5 ; accept error packets - RTL8139_BIT_AR equ 4 ; accept runt packets - RTL8139_BIT_AB equ 3 ; accept broadcast packets - RTL8139_BIT_AM equ 2 ; accept multicast packets - RTL8139_BIT_APM equ 1 ; accept physical match packets - RTL8139_BIT_AAP equ 0 ; accept all packets -; 5.9 93C46/93C56 command register - RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1 - RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0 - RTL8139_BIT_93C46_EECS equ 3 ; chip select - RTL8139_BIT_93C46_EESK equ 2 ; serial data clock - RTL8139_BIT_93C46_EEDI equ 1 ; serial data input - RTL8139_BIT_93C46_EEDO equ 0 ; serial data output -; 5.11 configuration register 1 - RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1 - RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips - RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips - RTL8139_BIT_PMEn equ 0 ; power management enabled -; 5.14 configuration register 4 - RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4 -; 6.2 transmit status register - RTL8139_BIT_ERTXTH equ 16 ; early TX threshold - RTL8139_BIT_TOK equ 15 ; transmit ok - RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed -; 6.18 basic mode control register - RTL8139_BIT_ANE equ 12 ; auto negotiation enable -; 6.20 auto negotiation advertisement register - RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex - RTL8139_BIT_TX equ 7 ; 100base-T - RTL8139_BIT_10FD equ 6 ; 10base-T full duplex - RTL8139_BIT_10 equ 5 ; 10base-T - RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001 -; RX/TX buffer size - RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k - RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN) - MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC - RTL8139_NUM_TX_DESC equ 4 - RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC) - RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16) - RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128 - ; 4==256 5==512 6==1024 7==2048 - RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256 - RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128 - ; 4==256 5==512 6==1024 7==unlimited - RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128 - ; 4==256 5==512 6==1024 7==no threshold - RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \ - or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \ - or (1 shl RTL8139_BIT_NOWRAP) \ - or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \ - or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \ - or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \ - or (1 shl RTL8139_BIT_AM)) - RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout - - EE_93C46_REG_ETH_ID equ 7 ; MAC offset - EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address - EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address - EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address - EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress - - VER_RTL8139 equ 1100000b - VER_RTL8139A equ 1110000b -; VER_RTL8139AG equ 1110100b - VER_RTL8139B equ 1111000b - VER_RTL8130 equ VER_RTL8139B - VER_RTL8139C equ 1110100b - VER_RTL8100 equ 1111010b - VER_RTL8100B equ 1110101b - VER_RTL8139D equ VER_RTL8100B - VER_RTL8139CP equ 1110110b - VER_RTL8101 equ 1110111b - - IDX_RTL8139 equ 0 - IDX_RTL8139A equ 1 - IDX_RTL8139B equ 2 - IDX_RTL8139C equ 3 - IDX_RTL8100 equ 4 - IDX_RTL8139D equ 5 - IDX_RTL8139D equ 6 - IDX_RTL8101 equ 7 - - -; These two must be 4 byte aligned ( which they are ) -rtl8139_rx_buff equ eth_data_start -rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE) - -uglobal - align 4 -rtl8139_rx_buff_offset: dd 0 -curr_tx_desc dd 0 -endg - -iglobal -hw_ver_array: db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C - db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101 -HW_VER_ARRAY_SIZE = $-hw_ver_array -endg - -uglobal -hw_ver_id: db 0 -endg - -;*************************************************************************** -; Function -; rtl8139_probe -; Description -; Searches for an ethernet card, enables it and clears the rx buffer -; If a card was found, it enables the ethernet -> TCPIP link -; Destroyed registers -; eax, ebx, ecx, edx -; -;*************************************************************************** -rtl8139_probe: -; enable the device - mov al, 2 - mov ah, [pci_bus] - mov bh, [pci_dev] - mov bl, PCI_REG_COMMAND - call pci_read_reg - mov cx, ax - or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) - and cl, not (1 shl PCI_BIT_MMIO) - mov al, 2 - mov ah, [pci_bus] - mov bh, [pci_dev] - mov bl, PCI_REG_COMMAND - call pci_write_reg -; get chip version - mov edx, [io_addr] - add edx, RTL8139_REG_TXCONFIG_2 - in ax, dx - shr ah, 2 - shr ax, 6 - and al, 01111111b - mov ecx, HW_VER_ARRAY_SIZE-1 -.chip_ver_loop: - cmp al, [hw_ver_array+ecx] - je .chip_ver_found - dec ecx - jns .chip_ver_loop - xor cl, cl ; default RTL8139 -.chip_ver_found: - mov [hw_ver_id], cl -; wake up the chip - mov edx, [io_addr] - add edx, RTL8139_REG_HLTCLK - mov al, 'R' ; run the clock - out dx, al -; unlock config and BMCR registers - add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK - mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) - out dx, al -; enable power management - add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR - in al, dx - cmp byte [hw_ver_id], IDX_RTL8139B - jl .old_chip -; set LWAKE pin to active high (default value). -; it is for Wake-On-LAN functionality of some motherboards. -; this signal is used to inform the motherboard to execute a wake-up process. -; only at newer chips. - or al, (1 shl RTL8139_BIT_PMEn) - and al, not (1 shl RTL8139_BIT_LWACT) - out dx, al - add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1 - in al, dx - and al, not (1 shl RTL8139_BIT_LWPTN) - out dx, al - jmp .finish_wake_up -.old_chip: -; wake up older chips - and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN)) - out dx, al -.finish_wake_up: -; lock config and BMCR registers - xor al, al - mov edx, [io_addr] - add edx, RTL8139_REG_9346CR - out dx, al -;*************************************************************************** -; Function -; rt8139_reset -; Description -; Place the chip (ie, the ethernet card) into a virgin state -; Destroyed registers -; eax, ebx, ecx, edx -; -;*************************************************************************** -rtl8139_reset: - mov edx, [io_addr] - add edx, RTL8139_REG_COMMAND - mov al, 1 shl RTL8139_BIT_RST - out dx, al - mov cx, 1000 ; wait no longer for the reset -.wait_for_reset: - in al, dx - test al, 1 shl RTL8139_BIT_RST - jz .reset_completed ; RST remains 1 during reset - dec cx - jns .wait_for_reset -.reset_completed: -; get MAC (hardware address) - mov ecx, 2 -.mac_read_loop: - lea eax, [EE_93C46_REG_ETH_ID+ecx] - push ecx - call rtl8139_read_eeprom - pop ecx - mov [node_addr+ecx*2], ax - dec ecx - jns .mac_read_loop -; unlock config and BMCR registers - mov edx, [io_addr] - add edx, RTL8139_REG_9346CR - mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) - out dx, al -; initialize multicast registers (no filtering) - mov eax, 0xffffffff - add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR - out dx, eax - add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0 - out dx, eax -; enable Rx/Tx - mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE) - add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4 - out dx, al -; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold -; accept broadcast packets, accept physical match packets - mov eax, RTL8139_RX_CONFIG - add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND - out dx, eax -; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144 - mov eax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \ - or (RTL8139_TXRR shl RTL8139_BIT_TXRR) - add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG - out dx, eax -; enable auto negotiation - add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG - in ax, dx - or ax, (1 shl RTL8139_BIT_ANE) - out dx, ax -; set auto negotiation advertisement - add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR - in ax, dx - or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \ - or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \ - or (1 shl RTL8139_BIT_TXFD) - out dx, ax -; lock config and BMCR registers - xor eax, eax - add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR - out dx, al -; init RX/TX pointers - mov [rtl8139_rx_buff_offset], eax - mov [curr_tx_desc], eax -; clear missing packet counter - add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR - out dx, eax -; disable all interrupts - add edx, RTL8139_REG_IMR - RTL8139_REG_MPC - out dx, ax -; set RxBuffer address, init RX buffer offset, init TX ring - mov eax, rtl8139_rx_buff ; simba - sub eax,OS_BASE - add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR - out dx, eax -; Indicate that we have successfully reset the card - mov eax, [pci_data] - mov [eth_status], eax - ret - -;*************************************************************************** -; Function -; rtl8139_read_eeprom -; Description -; reads eeprom type 93c46 and 93c56 -; Parameters -; al - word to be read (6bit in case of 93c46 and 8bit otherwise) -; Return value -; ax - word read in -; Destroyed register(s) -; eax, cx, ebx, edx -; -;*************************************************************************** -rtl8139_read_eeprom: - movzx ebx, al - mov edx, [io_addr] - add edx, RTL8139_REG_RXCONFIG - in al, dx - test al, (1 shl RTL8139_BIT_9356SEL) - jz .type_93c46 -; and bl, 01111111b ; don't care first bit - or bx, EE_93C56_READ_CMD ; it contains start bit - mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter - jmp .read_eeprom -.type_93c46: - and bl, 00111111b - or bx, EE_93C46_READ_CMD ; it contains start bit - mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter -.read_eeprom: - add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0 -; mov al, (1 shl RTL8139_BIT_93C46_EEM1) -; out dx, al - mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ - or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom - out dx, al -.cmd_loop: - mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) - bt bx, cx - jnc .zero_bit - or al, (1 shl RTL8139_BIT_93C46_EEDI) -.zero_bit: - out dx, al -; push eax -; in eax, dx ; eeprom delay -; pop eax - or al, (1 shl RTL8139_BIT_93C46_EESK) - out dx, al -; in eax, dx ; eeprom delay - dec cx - jns .cmd_loop -; in eax, dx ; eeprom delay - mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) - out dx, al - mov cl, 0xf -.read_loop: - shl ebx, 1 - mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ - or (1 shl RTL8139_BIT_93C46_EECS) \ - or (1 shl RTL8139_BIT_93C46_EESK) - out dx, al -; in eax, dx ; eeprom delay - in al, dx - and al, (1 shl RTL8139_BIT_93C46_EEDO) - jz .dont_set - inc ebx -.dont_set: - mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ - or (1 shl RTL8139_BIT_93C46_EECS) - out dx, al -; in eax, dx ; eeprom delay - dec cl - jns .read_loop - xor al, al - out dx, al - mov ax, bx - ret - -;*************************************************************************** -; Function -; rtl8139_transmit -; Description -; Transmits a packet of data via the ethernet card -; Pointer to 48 bit destination address in edi -; Type of packet in bx -; Size of packet in ecx -; Pointer to packet data in esi -; Destroyed registers -; eax, edx, esi, edi -; ToDo -; for waiting of timeout the rtl8139 internal timer -; should be used -; -;*************************************************************************** -rtl8139_transmit: - cmp ecx, MAX_ETH_FRAME_SIZE - jg .finish ; packet is too long - push ecx -; check descriptor - mov ecx, [curr_tx_desc] - mov edx, [io_addr] - lea edx, [edx+ecx*4+RTL8139_REG_TSD0] - push edx ebx - in ax, dx - test ax, 0x1fff ; or no size given - jz .send_packet - and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) - cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) - jz .send_packet -; wait for timeout - mov ebx, RTL8139_TX_TIMEOUT - mov eax, 0x5 ; delay x/100 secs - int 0x40 - in ax, dx - and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) - cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) - jz .send_packet -; chip hung, reset it - call rtl8139_reset -; reset the card -.send_packet: -; calculate tx_buffer address - pop ebx - push esi - mov eax, MAX_ETH_FRAME_SIZE - mul dword [curr_tx_desc] - mov esi, edi - lea edi, [rtl8139_tx_buff+eax] - mov eax, edi - cld -; copy destination address - movsd - movsw -; copy source address - mov esi, node_addr - movsd - movsw -; copy packet type - mov [edi], bx - add edi, 2 -; copy the packet data - pop esi edx ecx - push ecx - shr ecx, 2 - rep movsd - pop ecx - push ecx - and ecx, 3 - rep movsb -; set address - sub eax,OS_BASE - add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0 - out dx, eax -; set size and early threshold - pop eax ; pick up the size - add eax, ETH_HLEN - cmp eax, ETH_ZLEN - jnc .no_pad - mov eax, ETH_ZLEN -.no_pad: - or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH) - add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0 - out dx, eax -; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ... - inc dword [curr_tx_desc] - and dword [curr_tx_desc], 3 -.finish: - ret - -;*************************************************************************** -; Function -; rtl8139_poll -; -; Description -; Polls the ethernet card for a received packet -; Received data, if any, ends up in Ether_buffer -; Destroyed register(s) -; eax, edx, ecx -; -;*************************************************************************** -rtl8139_poll: - mov word [eth_rx_data_len], 0 - mov edx, [io_addr] - add edx, RTL8139_REG_COMMAND - in al, dx - test al, (1 shl RTL8139_BIT_BUFE) - jnz .finish -; new packet received copy it from rx_buffer into Ether_buffer - mov eax, rtl8139_rx_buff - add eax, [rtl8139_rx_buff_offset] -; check if packet is ok - test byte [eax], (1 shl RTL8139_BIT_ROK) - jz .reset_rx -; packet is ok copy it into the Ether_buffer - movzx ecx, word [eax+2] ; packet length - sub ecx, 4 ; don't copy CRC - mov word [eth_rx_data_len], cx - push ecx - shr ecx, 2 ; first copy dword-wise - lea esi, [eax+4] ; don't copy the packet header - mov edi, Ether_buffer - cld - rep movsd ; copy the dwords - pop ecx - and ecx, 3 - rep movsb ; copy the rest bytes -; update rtl8139_rx_buff_offset - movzx eax, word [eax+2] ; packet length - add eax, [rtl8139_rx_buff_offset] - add eax, 4+3 ; packet header is 4 bytes long + dword alignment - and eax, not 3 ; dword alignment - cmp eax, RTL8139_RX_BUFFER_SIZE - jl .no_wrap - sub eax, RTL8139_RX_BUFFER_SIZE -.no_wrap: - mov [rtl8139_rx_buff_offset], eax -; update CAPR register - sub eax, 0x10 ; value 0x10 is a constant for CAPR - add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND - out dx, ax -.finish: -; clear active interrupt sources - mov edx, [io_addr] - add edx, RTL8139_REG_ISR - in ax, dx - out dx, ax - ret -.reset_rx: - in al, dx ; read command register - push eax - and al, not (1 shl RTL8139_BIT_RE) - out dx, al - pop eax - out dx, al - add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND - mov ax, RTL8139_RX_CONFIG - out dx, ax - ret - -rtl8139_cable: - pusha - mov edx, [io_addr] - add edx, 0x58 - in al,dx - test al,1 SHL 2 - jnz .notconnected - popa - xor al,al - inc al - ret - .notconnected: - popa - xor al,al - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; RTL8139.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.2 11 August 2003 ;; +;; ;; +;; Driver for chips of RealTek 8139 family ;; +;; References: ;; +;; www.realtek.com.hw - data sheets ;; +;; rtl8139.c - linux driver ;; +;; 8139too.c - linux driver ;; +;; ethernet driver template by Mike Hibbett ;; +;; ;; +;; The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; Copyright 2003 Endre Kozma, ;; +;; endre.kozma@axelero.hu ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; 10.01.2007 Bugfix for l8139_transmit from Paolo Franchetti ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + + ETH_ALEN equ 6 + ETH_HLEN equ (2 * ETH_ALEN + 2) + ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length + + PCI_REG_COMMAND equ 0x04 ; command register + PCI_BIT_PIO equ 0 ; bit0: io space control + PCI_BIT_MMIO equ 1 ; bit1: memory space control + PCI_BIT_MASTER equ 2 ; bit2: device acts as a PCI master + + RTL8139_REG_MAR0 equ 0x08 ; multicast filter register 0 + RTL8139_REG_MAR4 equ 0x0c ; multicast filter register 4 + RTL8139_REG_TSD0 equ 0x10 ; transmit status of descriptor + RTL8139_REG_TSAD0 equ 0x20 ; transmit start address of descriptor + RTL8139_REG_RBSTART equ 0x30 ; RxBuffer start address + RTL8139_REG_COMMAND equ 0x37 ; command register + RTL8139_REG_CAPR equ 0x38 ; current address of packet read + RTL8139_REG_IMR equ 0x3c ; interrupt mask register + RTL8139_REG_ISR equ 0x3e ; interrupt status register + RTL8139_REG_TXCONFIG equ 0x40 ; transmit configuration register + RTL8139_REG_TXCONFIG_0 equ 0x40 ; transmit configuration register 0 + RTL8139_REG_TXCONFIG_1 equ 0x41 ; transmit configuration register 1 + RTL8139_REG_TXCONFIG_2 equ 0x42 ; transmit configuration register 2 + RTL8139_REG_TXCONFIG_3 equ 0x43 ; transmit configuration register 3 + RTL8139_REG_RXCONFIG equ 0x44 ; receive configuration register 0 + RTL8139_REG_RXCONFIG_0 equ 0x44 ; receive configuration register 0 + RTL8139_REG_RXCONFIG_1 equ 0x45 ; receive configuration register 1 + RTL8139_REG_RXCONFIG_2 equ 0x46 ; receive configuration register 2 + RTL8139_REG_RXCONFIG_3 equ 0x47 ; receive configuration register 3 + RTL8139_REG_MPC equ 0x4c ; missed packet counter + RTL8139_REG_9346CR equ 0x50 ; serial eeprom 93C46 command register + RTL8139_REG_CONFIG1 equ 0x52 ; configuration register 1 + RTL8139_REG_CONFIG4 equ 0x5a ; configuration register 4 + RTL8139_REG_HLTCLK equ 0x5b ; undocumented halt clock register + RTL8139_REG_BMCR equ 0x62 ; basic mode control register + RTL8139_REG_ANAR equ 0x66 ; auto negotiation advertisement register + +; 5.1 packet header + RTL8139_BIT_RUNT equ 4 ; total packet length < 64 bytes + RTL8139_BIT_LONG equ 3 ; total packet length > 4k + RTL8139_BIT_CRC equ 2 ; crc error occured + RTL8139_BIT_FAE equ 1 ; frame alignment error occured + RTL8139_BIT_ROK equ 0 ; received packet is ok +; 5.4 command register + RTL8139_BIT_RST equ 4 ; reset bit + RTL8139_BIT_RE equ 3 ; receiver enabled + RTL8139_BIT_TE equ 2 ; transmitter enabled + RTL8139_BIT_BUFE equ 0 ; rx buffer is empty, no packet stored +; 5.6 interrupt status register + RTL8139_BIT_ISR_TOK equ 2 ; transmit ok + RTL8139_BIT_ISR_RER equ 1 ; receive error interrupt + RTL8139_BIT_ISR_ROK equ 0 ; receive ok +; 5.7 transmit configyration register + RTL8139_BIT_TX_MXDMA equ 8 ; Max DMA burst size per Tx DMA burst + RTL8139_BIT_TXRR equ 4 ; Tx Retry count 16+(TXRR*16) +; 5.8 receive configuration register + RTL8139_BIT_RXFTH equ 13 ; Rx fifo threshold + RTL8139_BIT_RBLEN equ 11 ; Ring buffer length indicator + RTL8139_BIT_RX_MXDMA equ 8 ; Max DMA burst size per Rx DMA burst + RTL8139_BIT_NOWRAP equ 7 ; transfered data wrapping + RTL8139_BIT_9356SEL equ 6 ; eeprom selector 9346/9356 + RTL8139_BIT_AER equ 5 ; accept error packets + RTL8139_BIT_AR equ 4 ; accept runt packets + RTL8139_BIT_AB equ 3 ; accept broadcast packets + RTL8139_BIT_AM equ 2 ; accept multicast packets + RTL8139_BIT_APM equ 1 ; accept physical match packets + RTL8139_BIT_AAP equ 0 ; accept all packets +; 5.9 93C46/93C56 command register + RTL8139_BIT_93C46_EEM1 equ 7 ; RTL8139 eeprom operating mode1 + RTL8139_BIT_93C46_EEM0 equ 6 ; RTL8139 eeprom operating mode0 + RTL8139_BIT_93C46_EECS equ 3 ; chip select + RTL8139_BIT_93C46_EESK equ 2 ; serial data clock + RTL8139_BIT_93C46_EEDI equ 1 ; serial data input + RTL8139_BIT_93C46_EEDO equ 0 ; serial data output +; 5.11 configuration register 1 + RTL8139_BIT_LWACT equ 4 ; see RTL8139_REG_CONFIG1 + RTL8139_BIT_SLEEP equ 1 ; sleep bit at older chips + RTL8139_BIT_PWRDWN equ 0 ; power down bit at older chips + RTL8139_BIT_PMEn equ 0 ; power management enabled +; 5.14 configuration register 4 + RTL8139_BIT_LWPTN equ 2 ; see RTL8139_REG_CONFIG4 +; 6.2 transmit status register + RTL8139_BIT_ERTXTH equ 16 ; early TX threshold + RTL8139_BIT_TOK equ 15 ; transmit ok + RTL8139_BIT_OWN equ 13 ; tx DMA operation is completed +; 6.18 basic mode control register + RTL8139_BIT_ANE equ 12 ; auto negotiation enable +; 6.20 auto negotiation advertisement register + RTL8139_BIT_TXFD equ 8 ; 100base-T full duplex + RTL8139_BIT_TX equ 7 ; 100base-T + RTL8139_BIT_10FD equ 6 ; 10base-T full duplex + RTL8139_BIT_10 equ 5 ; 10base-T + RTL8139_BIT_SELECTOR equ 0 ; binary encoded selector CSMA/CD=00001 +; RX/TX buffer size + RTL8139_RBLEN equ 0 ; 0==8K 1==16k 2==32k 3==64k + RTL8139_RX_BUFFER_SIZE equ (8192 shl RTL8139_RBLEN) + MAX_ETH_FRAME_SIZE equ 1516 ; exactly 1514 wthout CRC + RTL8139_NUM_TX_DESC equ 4 + RTL8139_TX_BUFFER_SIZE equ (MAX_ETH_FRAME_SIZE * RTL8139_NUM_TX_DESC) + RTL8139_TXRR equ 8 ; total retries = 16+(TXRR*16) + RTL8139_TX_MXDMA equ 6 ; 0==16 1==32 2==64 3==128 + ; 4==256 5==512 6==1024 7==2048 + RTL8139_ERTXTH equ 8 ; in unit of 32 bytes e.g:(8*32)=256 + RTL8139_RX_MXDMA equ 7 ; 0==16 1==32 2==64 3==128 + ; 4==256 5==512 6==1024 7==unlimited + RTL8139_RXFTH equ 7 ; 0==16 1==32 2==64 3==128 + ; 4==256 5==512 6==1024 7==no threshold + RTL8139_RX_CONFIG equ ((RTL8139_RBLEN shl RTL8139_BIT_RBLEN) \ + or (RTL8139_RX_MXDMA shl RTL8139_BIT_RX_MXDMA) \ + or (1 shl RTL8139_BIT_NOWRAP) \ + or (RTL8139_RXFTH shl RTL8139_BIT_RXFTH) \ + or (1 shl RTL8139_BIT_AB) or (1 shl RTL8139_BIT_APM) \ + or (1 shl RTL8139_BIT_AER) or (1 shl RTL8139_BIT_AR) \ + or (1 shl RTL8139_BIT_AM)) + RTL8139_TX_TIMEOUT equ 30 ; 300 milliseconds timeout + + EE_93C46_REG_ETH_ID equ 7 ; MAC offset + EE_93C46_READ_CMD equ (6 shl 6) ; 110b + 6bit address + EE_93C56_READ_CMD equ (6 shl 8) ; 110b + 8bit address + EE_93C46_CMD_LENGTH equ 9 ; start bit + cmd + 6bit address + EE_93C56_CMD_LENGTH equ 11 ; start bit + cmd + 8bit ddress + + VER_RTL8139 equ 1100000b + VER_RTL8139A equ 1110000b +; VER_RTL8139AG equ 1110100b + VER_RTL8139B equ 1111000b + VER_RTL8130 equ VER_RTL8139B + VER_RTL8139C equ 1110100b + VER_RTL8100 equ 1111010b + VER_RTL8100B equ 1110101b + VER_RTL8139D equ VER_RTL8100B + VER_RTL8139CP equ 1110110b + VER_RTL8101 equ 1110111b + + IDX_RTL8139 equ 0 + IDX_RTL8139A equ 1 + IDX_RTL8139B equ 2 + IDX_RTL8139C equ 3 + IDX_RTL8100 equ 4 + IDX_RTL8139D equ 5 + IDX_RTL8139D equ 6 + IDX_RTL8101 equ 7 + + +; These two must be 4 byte aligned ( which they are ) +rtl8139_rx_buff equ eth_data_start +rtl8139_tx_buff equ rtl8139_rx_buff + (RTL8139_RX_BUFFER_SIZE + MAX_ETH_FRAME_SIZE) + +uglobal + align 4 +rtl8139_rx_buff_offset: + dd 0 +curr_tx_desc dd 0 +endg + +iglobal +hw_ver_array: + db VER_RTL8139, VER_RTL8139A, VER_RTL8139B, VER_RTL8139C + db VER_RTL8100, VER_RTL8139D, VER_RTL8139CP, VER_RTL8101 +HW_VER_ARRAY_SIZE = $-hw_ver_array +endg + +uglobal +hw_ver_id: + db 0 +endg + +;*************************************************************************** +; Function +; rtl8139_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; Destroyed registers +; eax, ebx, ecx, edx +; +;*************************************************************************** +rtl8139_probe: +; enable the device + mov al, 2 + mov ah, [pci_bus] + mov bh, [pci_dev] + mov bl, PCI_REG_COMMAND + call pci_read_reg + mov cx, ax + or cl, (1 shl PCI_BIT_MASTER) or (1 shl PCI_BIT_PIO) + and cl, not (1 shl PCI_BIT_MMIO) + mov al, 2 + mov ah, [pci_bus] + mov bh, [pci_dev] + mov bl, PCI_REG_COMMAND + call pci_write_reg +; get chip version + mov edx, [io_addr] + add edx, RTL8139_REG_TXCONFIG_2 + in ax, dx + shr ah, 2 + shr ax, 6 + and al, 01111111b + mov ecx, HW_VER_ARRAY_SIZE-1 +.chip_ver_loop: + cmp al, [hw_ver_array+ecx] + je .chip_ver_found + dec ecx + jns .chip_ver_loop + xor cl, cl ; default RTL8139 +.chip_ver_found: + mov [hw_ver_id], cl +; wake up the chip + mov edx, [io_addr] + add edx, RTL8139_REG_HLTCLK + mov al, 'R' ; run the clock + out dx, al +; unlock config and BMCR registers + add edx, RTL8139_REG_9346CR - RTL8139_REG_HLTCLK + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) + out dx, al +; enable power management + add edx, RTL8139_REG_CONFIG1 - RTL8139_REG_9346CR + in al, dx + cmp byte [hw_ver_id], IDX_RTL8139B + jl .old_chip +; set LWAKE pin to active high (default value). +; it is for Wake-On-LAN functionality of some motherboards. +; this signal is used to inform the motherboard to execute a wake-up process. +; only at newer chips. + or al, (1 shl RTL8139_BIT_PMEn) + and al, not (1 shl RTL8139_BIT_LWACT) + out dx, al + add edx, RTL8139_REG_CONFIG4 - RTL8139_REG_CONFIG1 + in al, dx + and al, not (1 shl RTL8139_BIT_LWPTN) + out dx, al + jmp .finish_wake_up +.old_chip: +; wake up older chips + and al, not ((1 shl RTL8139_BIT_SLEEP) or (1 shl RTL8139_BIT_PWRDWN)) + out dx, al +.finish_wake_up: +; lock config and BMCR registers + xor al, al + mov edx, [io_addr] + add edx, RTL8139_REG_9346CR + out dx, al +;*************************************************************************** +; Function +; rt8139_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; Destroyed registers +; eax, ebx, ecx, edx +; +;*************************************************************************** +rtl8139_reset: + mov edx, [io_addr] + add edx, RTL8139_REG_COMMAND + mov al, 1 shl RTL8139_BIT_RST + out dx, al + mov cx, 1000 ; wait no longer for the reset +.wait_for_reset: + in al, dx + test al, 1 shl RTL8139_BIT_RST + jz .reset_completed ; RST remains 1 during reset + dec cx + jns .wait_for_reset +.reset_completed: +; get MAC (hardware address) + mov ecx, 2 +.mac_read_loop: + lea eax, [EE_93C46_REG_ETH_ID+ecx] + push ecx + call rtl8139_read_eeprom + pop ecx + mov [node_addr+ecx*2], ax + dec ecx + jns .mac_read_loop +; unlock config and BMCR registers + mov edx, [io_addr] + add edx, RTL8139_REG_9346CR + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EEM0) + out dx, al +; initialize multicast registers (no filtering) + mov eax, 0xffffffff + add edx, RTL8139_REG_MAR0 - RTL8139_REG_9346CR + out dx, eax + add edx, RTL8139_REG_MAR4 - RTL8139_REG_MAR0 + out dx, eax +; enable Rx/Tx + mov al, (1 shl RTL8139_BIT_RE) or (1 shl RTL8139_BIT_TE) + add edx, RTL8139_REG_COMMAND - RTL8139_REG_MAR4 + out dx, al +; 32k Rxbuffer, unlimited dma burst, no wrapping, no rx threshold +; accept broadcast packets, accept physical match packets + mov eax, RTL8139_RX_CONFIG + add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND + out dx, eax +; 1024 bytes DMA burst, total retries = 16 + 8 * 16 = 144 + mov eax, (RTL8139_TX_MXDMA shl RTL8139_BIT_TX_MXDMA) \ + or (RTL8139_TXRR shl RTL8139_BIT_TXRR) + add edx, RTL8139_REG_TXCONFIG - RTL8139_REG_RXCONFIG + out dx, eax +; enable auto negotiation + add edx, RTL8139_REG_BMCR - RTL8139_REG_TXCONFIG + in ax, dx + or ax, (1 shl RTL8139_BIT_ANE) + out dx, ax +; set auto negotiation advertisement + add edx, RTL8139_REG_ANAR - RTL8139_REG_BMCR + in ax, dx + or ax, (1 shl RTL8139_BIT_SELECTOR) or (1 shl RTL8139_BIT_10) \ + or (1 shl RTL8139_BIT_10FD) or (1 shl RTL8139_BIT_TX) \ + or (1 shl RTL8139_BIT_TXFD) + out dx, ax +; lock config and BMCR registers + xor eax, eax + add edx, RTL8139_REG_9346CR - RTL8139_REG_ANAR + out dx, al +; init RX/TX pointers + mov [rtl8139_rx_buff_offset], eax + mov [curr_tx_desc], eax +; clear missing packet counter + add edx, RTL8139_REG_MPC - RTL8139_REG_9346CR + out dx, eax +; disable all interrupts + add edx, RTL8139_REG_IMR - RTL8139_REG_MPC + out dx, ax +; set RxBuffer address, init RX buffer offset, init TX ring + mov eax, rtl8139_rx_buff ; simba + sub eax, OS_BASE + add edx, RTL8139_REG_RBSTART - RTL8139_REG_IMR + out dx, eax +; Indicate that we have successfully reset the card + mov eax, [pci_data] + mov [eth_status], eax + ret + +;*************************************************************************** +; Function +; rtl8139_read_eeprom +; Description +; reads eeprom type 93c46 and 93c56 +; Parameters +; al - word to be read (6bit in case of 93c46 and 8bit otherwise) +; Return value +; ax - word read in +; Destroyed register(s) +; eax, cx, ebx, edx +; +;*************************************************************************** +rtl8139_read_eeprom: + movzx ebx, al + mov edx, [io_addr] + add edx, RTL8139_REG_RXCONFIG + in al, dx + test al, (1 shl RTL8139_BIT_9356SEL) + jz .type_93c46 +; and bl, 01111111b ; don't care first bit + or bx, EE_93C56_READ_CMD ; it contains start bit + mov cx, EE_93C56_CMD_LENGTH-1 ; cmd_loop counter + jmp .read_eeprom +.type_93c46: + and bl, 00111111b + or bx, EE_93C46_READ_CMD ; it contains start bit + mov cx, EE_93C46_CMD_LENGTH-1 ; cmd_loop counter +.read_eeprom: + add edx, RTL8139_REG_9346CR - RTL8139_REG_RXCONFIG_0 +; mov al, (1 shl RTL8139_BIT_93C46_EEM1) +; out dx, al + mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ + or (1 shl RTL8139_BIT_93C46_EECS) ; wake up the eeprom + out dx, al +.cmd_loop: + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) + bt bx, cx + jnc .zero_bit + or al, (1 shl RTL8139_BIT_93C46_EEDI) +.zero_bit: + out dx, al +; push eax +; in eax, dx ; eeprom delay +; pop eax + or al, (1 shl RTL8139_BIT_93C46_EESK) + out dx, al +; in eax, dx ; eeprom delay + dec cx + jns .cmd_loop +; in eax, dx ; eeprom delay + mov al, (1 shl RTL8139_BIT_93C46_EEM1) or (1 shl RTL8139_BIT_93C46_EECS) + out dx, al + mov cl, 0xf +.read_loop: + shl ebx, 1 + mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ + or (1 shl RTL8139_BIT_93C46_EECS) \ + or (1 shl RTL8139_BIT_93C46_EESK) + out dx, al +; in eax, dx ; eeprom delay + in al, dx + and al, (1 shl RTL8139_BIT_93C46_EEDO) + jz .dont_set + inc ebx +.dont_set: + mov al, (1 shl RTL8139_BIT_93C46_EEM1) \ + or (1 shl RTL8139_BIT_93C46_EECS) + out dx, al +; in eax, dx ; eeprom delay + dec cl + jns .read_loop + xor al, al + out dx, al + mov ax, bx + ret + +;*************************************************************************** +; Function +; rtl8139_transmit +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; Size of packet in ecx +; Pointer to packet data in esi +; Destroyed registers +; eax, edx, esi, edi +; ToDo +; for waiting of timeout the rtl8139 internal timer +; should be used +; +;*************************************************************************** +rtl8139_transmit: + cmp ecx, MAX_ETH_FRAME_SIZE + jg .finish ; packet is too long + push ecx +; check descriptor + mov ecx, [curr_tx_desc] + mov edx, [io_addr] + lea edx, [edx+ecx*4+RTL8139_REG_TSD0] + push edx ebx + in ax, dx + test ax, 0x1fff ; or no size given + jz .send_packet + and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + jz .send_packet +; wait for timeout + mov ebx, RTL8139_TX_TIMEOUT + mov eax, 0x5 ; delay x/100 secs + int 0x40 + in ax, dx + and ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + cmp ax, (1 shl RTL8139_BIT_TOK) or (1 shl RTL8139_BIT_OWN) + jz .send_packet +; chip hung, reset it + call rtl8139_reset +; reset the card +.send_packet: +; calculate tx_buffer address + pop ebx + push esi + mov eax, MAX_ETH_FRAME_SIZE + mul dword [curr_tx_desc] + mov esi, edi + lea edi, [rtl8139_tx_buff+eax] + mov eax, edi + cld +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 +; copy the packet data + pop esi edx ecx + push ecx + shr ecx, 2 + rep movsd + pop ecx + push ecx + and ecx, 3 + rep movsb +; set address + sub eax, OS_BASE + add edx, RTL8139_REG_TSAD0 - RTL8139_REG_TSD0 + out dx, eax +; set size and early threshold + pop eax ; pick up the size + add eax, ETH_HLEN + cmp eax, ETH_ZLEN + jnc .no_pad + mov eax, ETH_ZLEN +.no_pad: + or eax, (RTL8139_ERTXTH shl RTL8139_BIT_ERTXTH) + add edx, RTL8139_REG_TSD0 - RTL8139_REG_TSAD0 + out dx, eax +; get next descriptor 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, ... + inc dword [curr_tx_desc] + and dword [curr_tx_desc], 3 +.finish: + ret + +;*************************************************************************** +; Function +; rtl8139_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Destroyed register(s) +; eax, edx, ecx +; +;*************************************************************************** +rtl8139_poll: + mov word [eth_rx_data_len], 0 + mov edx, [io_addr] + add edx, RTL8139_REG_COMMAND + in al, dx + test al, (1 shl RTL8139_BIT_BUFE) + jnz .finish +; new packet received copy it from rx_buffer into Ether_buffer + mov eax, rtl8139_rx_buff + add eax, [rtl8139_rx_buff_offset] +; check if packet is ok + test byte [eax], (1 shl RTL8139_BIT_ROK) + jz .reset_rx +; packet is ok copy it into the Ether_buffer + movzx ecx, word [eax+2] ; packet length + sub ecx, 4 ; don't copy CRC + mov word [eth_rx_data_len], cx + push ecx + shr ecx, 2 ; first copy dword-wise + lea esi, [eax+4] ; don't copy the packet header + mov edi, Ether_buffer + cld + rep movsd ; copy the dwords + pop ecx + and ecx, 3 + rep movsb ; copy the rest bytes +; update rtl8139_rx_buff_offset + movzx eax, word [eax+2] ; packet length + add eax, [rtl8139_rx_buff_offset] + add eax, 4+3 ; packet header is 4 bytes long + dword alignment + and eax, not 3 ; dword alignment + cmp eax, RTL8139_RX_BUFFER_SIZE + jl .no_wrap + sub eax, RTL8139_RX_BUFFER_SIZE +.no_wrap: + mov [rtl8139_rx_buff_offset], eax +; update CAPR register + sub eax, 0x10 ; value 0x10 is a constant for CAPR + add edx, RTL8139_REG_CAPR - RTL8139_REG_COMMAND + out dx, ax +.finish: +; clear active interrupt sources + mov edx, [io_addr] + add edx, RTL8139_REG_ISR + in ax, dx + out dx, ax + ret +.reset_rx: + in al, dx ; read command register + push eax + and al, not (1 shl RTL8139_BIT_RE) + out dx, al + pop eax + out dx, al + add edx, RTL8139_REG_RXCONFIG - RTL8139_REG_COMMAND + mov ax, RTL8139_RX_CONFIG + out dx, ax + ret + +rtl8139_cable: + pusha + mov edx, [io_addr] + add edx, 0x58 + in al, dx + test al, 1 SHL 2 + jnz .notconnected + popa + xor al, al + inc al + ret + .notconnected: + popa + xor al, al + ret diff --git a/kernel/trunk/network/eth_drv/drivers/rtl8169.inc b/kernel/trunk/network/eth_drv/drivers/rtl8169.inc index 498fd1545..d6dbae851 100644 --- a/kernel/trunk/network/eth_drv/drivers/rtl8169.inc +++ b/kernel/trunk/network/eth_drv/drivers/rtl8169.inc @@ -1,1219 +1,1239 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; RTL8169.INC ;; -;; ;; -;; Ethernet driver for Menuet OS ;; -;; ;; -;; Version 0.1 11 February 2007 ;; -;; ;; -;; Driver for chips of RealTek 8169 family ;; -;; References: ;; -;; r8169.c - linux driver (etherboot project) ;; -;; ethernet driver template by Mike Hibbett ;; -;; ;; -;; The copyright statement is ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;; Copyright 2007 mike.dld, ;; -;; mike.dld@gmail.com ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - - ETH_ALEN equ 6 - ETH_HLEN equ (2 * ETH_ALEN + 2) - ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for - ; mininmum 64bytes frame length - - RTL8169_REG_MAC0 equ 0x0 ; Ethernet hardware address - RTL8169_REG_MAR0 equ 0x8 ; Multicast filter - RTL8169_REG_TxDescStartAddr equ 0x20 - RTL8169_REG_TxHDescStartAddr equ 0x28 - RTL8169_REG_FLASH equ 0x30 - RTL8169_REG_ERSR equ 0x36 - RTL8169_REG_ChipCmd equ 0x37 - RTL8169_REG_TxPoll equ 0x38 - RTL8169_REG_IntrMask equ 0x3C - RTL8169_REG_IntrStatus equ 0x3E - RTL8169_REG_TxConfig equ 0x40 - RTL8169_REG_RxConfig equ 0x44 - RTL8169_REG_RxMissed equ 0x4C - RTL8169_REG_Cfg9346 equ 0x50 - RTL8169_REG_Config0 equ 0x51 - RTL8169_REG_Config1 equ 0x52 - RTL8169_REG_Config2 equ 0x53 - RTL8169_REG_Config3 equ 0x54 - RTL8169_REG_Config4 equ 0x55 - RTL8169_REG_Config5 equ 0x56 - RTL8169_REG_MultiIntr equ 0x5C - RTL8169_REG_PHYAR equ 0x60 - RTL8169_REG_TBICSR equ 0x64 - RTL8169_REG_TBI_ANAR equ 0x68 - RTL8169_REG_TBI_LPAR equ 0x6A - RTL8169_REG_PHYstatus equ 0x6C - RTL8169_REG_RxMaxSize equ 0xDA - RTL8169_REG_CPlusCmd equ 0xE0 - RTL8169_REG_RxDescStartAddr equ 0xE4 - RTL8169_REG_ETThReg equ 0xEC - RTL8169_REG_FuncEvent equ 0xF0 - RTL8169_REG_FuncEventMask equ 0xF4 - RTL8169_REG_FuncPresetState equ 0xF8 - RTL8169_REG_FuncForceEvent equ 0xFC - - ; InterruptStatusBits - RTL8169_ISB_SYSErr equ 0x8000 - RTL8169_ISB_PCSTimeout equ 0x4000 - RTL8169_ISB_SWInt equ 0x0100 - RTL8169_ISB_TxDescUnavail equ 0x80 - RTL8169_ISB_RxFIFOOver equ 0x40 - RTL8169_ISB_LinkChg equ 0x20 - RTL8169_ISB_RxOverflow equ 0x10 - RTL8169_ISB_TxErr equ 0x08 - RTL8169_ISB_TxOK equ 0x04 - RTL8169_ISB_RxErr equ 0x02 - RTL8169_ISB_RxOK equ 0x01 - - ; RxStatusDesc - RTL8169_SD_RxRES equ 0x00200000 - RTL8169_SD_RxCRC equ 0x00080000 - RTL8169_SD_RxRUNT equ 0x00100000 - RTL8169_SD_RxRWT equ 0x00400000 - - ; ChipCmdBits - RTL8169_CMD_Reset equ 0x10 - RTL8169_CMD_RxEnb equ 0x08 - RTL8169_CMD_TxEnb equ 0x04 - RTL8169_CMD_RxBufEmpty equ 0x01 - - ; Cfg9346Bits - RTL8169_CFG_9346_Lock equ 0x00 - RTL8169_CFG_9346_Unlock equ 0xC0 - - ; rx_mode_bits - RTL8169_RXM_AcceptErr equ 0x20 - RTL8169_RXM_AcceptRunt equ 0x10 - RTL8169_RXM_AcceptBroadcast equ 0x08 - RTL8169_RXM_AcceptMulticast equ 0x04 - RTL8169_RXM_AcceptMyPhys equ 0x02 - RTL8169_RXM_AcceptAllPhys equ 0x01 - - ; RxConfigBits - RTL8169_RXC_FIFOShift equ 13 - RTL8169_RXC_DMAShift equ 8 - - ; TxConfigBits - RTL8169_TXC_InterFrameGapShift equ 24 - RTL8169_TXC_DMAShift equ 8 ; DMA burst value (0-7) is shift this many bits - - ; rtl8169_PHYstatus - RTL8169_PHYS_TBI_Enable equ 0x80 - RTL8169_PHYS_TxFlowCtrl equ 0x40 - RTL8169_PHYS_RxFlowCtrl equ 0x20 - RTL8169_PHYS_1000bpsF equ 0x10 - RTL8169_PHYS_100bps equ 0x08 - RTL8169_PHYS_10bps equ 0x04 - RTL8169_PHYS_LinkStatus equ 0x02 - RTL8169_PHYS_FullDup equ 0x01 - - ; GIGABIT_PHY_registers - RTL8169_PHY_CTRL_REG equ 0 - RTL8169_PHY_STAT_REG equ 1 - RTL8169_PHY_AUTO_NEGO_REG equ 4 - RTL8169_PHY_1000_CTRL_REG equ 9 - - ; GIGABIT_PHY_REG_BIT - RTL8169_PHY_Restart_Auto_Nego equ 0x0200 - RTL8169_PHY_Enable_Auto_Nego equ 0x1000 - - ; PHY_STAT_REG = 1; - RTL8169_PHY_Auto_Neco_Comp equ 0x0020 - - ; PHY_AUTO_NEGO_REG = 4; - RTL8169_PHY_Cap_10_Half equ 0x0020 - RTL8169_PHY_Cap_10_Full equ 0x0040 - RTL8169_PHY_Cap_100_Half equ 0x0080 - RTL8169_PHY_Cap_100_Full equ 0x0100 - - ; PHY_1000_CTRL_REG = 9; - RTL8169_PHY_Cap_1000_Full equ 0x0200 - RTL8169_PHY_Cap_1000_Half equ 0x0100 - - RTL8169_PHY_Cap_PAUSE equ 0x0400 - RTL8169_PHY_Cap_ASYM_PAUSE equ 0x0800 - - RTL8169_PHY_Cap_Null equ 0x0 - - ; _MediaType - RTL8169_MT_10_Half equ 0x01 - RTL8169_MT_10_Full equ 0x02 - RTL8169_MT_100_Half equ 0x04 - RTL8169_MT_100_Full equ 0x08 - RTL8169_MT_1000_Full equ 0x10 - - ; _TBICSRBit - RTL8169_TBI_LinkOK equ 0x02000000 - - ; _DescStatusBit - RTL8169_DSB_OWNbit equ 0x80000000 - RTL8169_DSB_EORbit equ 0x40000000 - RTL8169_DSB_FSbit equ 0x20000000 - RTL8169_DSB_LSbit equ 0x10000000 - -; MAC address length -MAC_ADDR_LEN equ 6 - -; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4) -MAX_ETH_FRAME_SIZE equ 1536 - -TX_FIFO_THRESH equ 256 ; In bytes - -RX_FIFO_THRESH equ 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer -RX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 -TX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 -ETTh equ 0x3F ; 0x3F means NO threshold - -EarlyTxThld equ 0x3F ; 0x3F means NO early transmit -RxPacketMaxSize equ 0x0800 ; Maximum size supported is 16K-1 -InterFrameGap equ 0x03 ; 3 means InterFrameGap = the shortest one - -NUM_TX_DESC equ 1 ; Number of Tx descriptor registers -NUM_RX_DESC equ 4 ; Number of Rx descriptor registers -RX_BUF_SIZE equ 1536 ; Rx Buffer size - -HZ equ 1000 - -RTL_MIN_IO_SIZE equ 0x80 -TX_TIMEOUT equ (6*HZ) - -RTL8169_TIMER_EXPIRE_TIME equ 100 - -ETH_HDR_LEN equ 14 -DEFAULT_MTU equ 1500 -DEFAULT_RX_BUF_LEN equ 1536 - - -;#ifdef RTL8169_JUMBO_FRAME_SUPPORT -;#define MAX_JUMBO_FRAME_MTU ( 10000 ) -;#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN ) -;#else -MAX_RX_SKBDATA_SIZE equ 1600 -;#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT - -;#ifdef RTL8169_USE_IO -;!!!#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg)) -macro RTL_W8 reg,val8 { - if ~reg eq dx - mov dx,word[rtl8169_tpc.mmio_addr] - add dx,reg - end if - if ~val8 eq al - mov al,val8 - end if - out dx,al -} -;!!!#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg)) -macro RTL_W16 reg,val16 { - if ~reg eq dx - mov dx,word[rtl8169_tpc.mmio_addr] - add dx,reg - end if - if ~val16 eq ax - mov ax,val16 - end if - out dx,ax -} -;!!!#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg)) -macro RTL_W32 reg,val32 { - if ~reg eq dx - mov dx,word[rtl8169_tpc.mmio_addr] - add dx,reg - end if - if ~val32 eq eax - mov eax,val32 - end if - out dx,eax -} -;!!!#define RTL_R8(reg) inb (ioaddr + (reg)) -macro RTL_R8 reg { - if ~reg eq dx - mov dx,word[rtl8169_tpc.mmio_addr] - add dx,reg - end if - in al,dx -} -;!!!#define RTL_R16(reg) inw (ioaddr + (reg)) -macro RTL_R16 reg { - if ~reg eq dx - mov dx,word[rtl8169_tpc.mmio_addr] - add dx,reg - end if - in ax,dx -} -;!!!#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg))) -macro RTL_R32 reg { - if ~reg eq dx - mov dx,word[rtl8169_tpc.mmio_addr] - add dx,reg - end if - in eax,dx -} -;#else -; write/read MMIO register -;#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -;#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -;#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -;#define RTL_R8(reg) readb (ioaddr + (reg)) -;#define RTL_R16(reg) readw (ioaddr + (reg)) -;#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) -;#endif - -MCFG_METHOD_01 equ 0x01 -MCFG_METHOD_02 equ 0x02 -MCFG_METHOD_03 equ 0x03 -MCFG_METHOD_04 equ 0x04 -MCFG_METHOD_05 equ 0x05 -MCFG_METHOD_11 equ 0x0b -MCFG_METHOD_12 equ 0x0c -MCFG_METHOD_13 equ 0x0d -MCFG_METHOD_14 equ 0x0e -MCFG_METHOD_15 equ 0x0f - -PCFG_METHOD_1 equ 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000 -PCFG_METHOD_2 equ 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001 -PCFG_METHOD_3 equ 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002 - -PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space -PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space -PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering -PCI_LATENCY_TIMER equ 0x0d ; 8 bits -PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles -PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate -PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping -PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking -PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping -PCI_COMMAND_SERR equ 0x100 ; Enable SERR -PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes - -struc rtl8169_TxDesc { - .status dd ? - .vlan_tag dd ? - .buf_addr dd ? - .buf_Haddr dd ? -} -virtual at 0 - rtl8169_TxDesc rtl8169_TxDesc - sizeof.rtl8169_TxDesc = $ - rtl8169_TxDesc -end virtual - -struc rtl8169_RxDesc { - .status dd ? - .vlan_tag dd ? - .buf_addr dd ? - .buf_Haddr dd ? -} -virtual at 0 - rtl8169_RxDesc rtl8169_RxDesc - sizeof.rtl8169_RxDesc = $ - rtl8169_RxDesc -end virtual - -virtual at eth_data_start - -; Define the TX Descriptor -align 256 -rtl8169_tx_ring rb NUM_TX_DESC * sizeof.rtl8169_TxDesc - -; Create a static buffer of size RX_BUF_SZ for each -; TX Descriptor. All descriptors point to a -; part of this buffer -align 256 -rtl8169_txb rb NUM_TX_DESC * RX_BUF_SIZE - -; Define the RX Descriptor -align 256 -rtl8169_rx_ring rb NUM_RX_DESC * sizeof.rtl8169_RxDesc - -; Create a static buffer of size RX_BUF_SZ for each -; RX Descriptor All descriptors point to a -; part of this buffer -align 256 -rtl8169_rxb rb NUM_RX_DESC * RX_BUF_SIZE - -rtl8169_tpc: - .mmio_addr dd ? ; memory map physical address - .chipset dd ? - .pcfg dd ? - .mcfg dd ? - .cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt - .cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt - .TxDescArrays dd ? ; Index of Tx Descriptor buffer - .RxDescArrays dd ? ; Index of Rx Descriptor buffer - .TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer - .RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer - .RxBufferRing rd NUM_RX_DESC ; Index of Rx Buffer array - .Tx_skbuff rd NUM_TX_DESC - -end virtual - -rtl8169_intr_mask = RTL8169_ISB_LinkChg or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxFIFOOver or RTL8169_ISB_TxErr or RTL8169_ISB_TxOK or RTL8169_ISB_RxErr or RTL8169_ISB_RxOK -rtl8169_rx_config = (RX_FIFO_THRESH shl RTL8169_RXC_FIFOShift) or (RX_DMA_BURST shl RTL8169_RXC_DMAShift) or 0x0000000E - -iglobal - -;static struct { -; const char *name; -; u8 mcfg; /* depend on RTL8169 docs */ -; u32 RxConfigMask; /* should clear the bits supported by this chip */ -;} -rtl_chip_info dd \ - MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169 - MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s - MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s - MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb - MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc - MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E - MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E - MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139 - MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139 - MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139 - -mac_info dd \ - 0x38800000, MCFG_METHOD_15, \ - 0x38000000, MCFG_METHOD_12, \ - 0x34000000, MCFG_METHOD_13, \ - 0x30800000, MCFG_METHOD_14, \ - 0x30000000, MCFG_METHOD_11, \ - 0x18000000, MCFG_METHOD_05, \ - 0x10000000, MCFG_METHOD_04, \ - 0x04000000, MCFG_METHOD_03, \ - 0x00800000, MCFG_METHOD_02, \ - 0x00000000, MCFG_METHOD_01 ; catch-all - -endg - -PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space -PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space -PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering -PCI_LATENCY_TIMER equ 0x0d ; 8 bits -PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles -PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate -PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping -PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking -PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping -PCI_COMMAND_SERR equ 0x100 ; Enable SERR -PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes - -PCI_VENDOR_ID equ 0x00 ; 16 bits -PCI_DEVICE_ID equ 0x02 ; 16 bits -PCI_COMMAND equ 0x04 ; 16 bits - -PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits -PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits -PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits -PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits -PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits -PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits - -PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 -PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address -PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] -PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address - -PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) -PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) -PCI_BASE_ADDRESS_SPACE_IO equ 0x01 -PCI_ROM_ADDRESS equ 0x30 ; 32 bits - -proc CONFIG_CMD,where:byte - movzx eax,byte[pci_bus] - shl eax,8 - mov al,[pci_dev] - shl eax,8 - mov al,[where] - and al,not 3 - or eax,0x80000000 - ret -endp - -proc pci_read_config_byte,where:dword - push edx - stdcall CONFIG_CMD,[where] - mov dx,0xCF8 - out dx,eax - mov edx,[where] - and edx,3 - add edx,0xCFC - in al,dx - pop edx - ret -endp - -proc pci_read_config_word,where:dword - push edx - stdcall CONFIG_CMD,[where] - mov dx,0xCF8 - out dx,eax - mov edx,[where] - and edx,2 - add edx,0xCFC - in ax,dx - pop edx - ret -endp - -proc pci_read_config_dword,where:dword - push edx - stdcall CONFIG_CMD,[where] - mov edx,0xCF8 - out dx,eax - mov edx,0xCFC - in eax,dx - pop edx - ret -endp - -proc pci_write_config_byte,where:dword,value:byte - push edx - stdcall CONFIG_CMD,[where] - mov dx,0xCF8 - out dx,eax - mov edx,[where] - and edx,3 - add edx,0xCFC - mov al,[value] - out dx,al - pop edx - ret -endp - -proc pci_write_config_word,where:dword,value:word - push edx - stdcall CONFIG_CMD,[where] - mov dx,0xCF8 - out dx,eax - mov edx,[where] - and edx,2 - add edx,0xCFC - mov ax,[value] - out dx,ax - pop edx - ret -endp - -proc pci_write_config_dword,where:dword,value:dword - push edx - stdcall CONFIG_CMD,[where] - mov edx,0xCF8 - out dx,eax - mov edx,0xCFC - mov eax,[value] - out dx,eax - pop edx - ret -endp - -; Set device to be a busmaster in case BIOS neglected to do so. -; Also adjust PCI latency timer to a reasonable value, 32. -proc adjust_pci_device - -; DEBUGF 1,"K : adjust_pci_device\n" - - stdcall pci_read_config_word,PCI_COMMAND - mov bx,ax - or bx,PCI_COMMAND_MASTER or PCI_COMMAND_IO - cmp ax,bx - je @f -; DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 - stdcall pci_write_config_word,PCI_COMMAND,ebx - @@: - stdcall pci_read_config_byte,PCI_LATENCY_TIMER - cmp al,32 - jae @f -; DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al - stdcall pci_write_config_byte,PCI_LATENCY_TIMER,32 - @@: - ret -endp - -; Find the start of a pci resource -proc pci_bar_start,index:dword - stdcall pci_read_config_dword,[index] - test eax,PCI_BASE_ADDRESS_SPACE_IO - jz @f - and eax,PCI_BASE_ADDRESS_IO_MASK - jmp .exit - @@: push eax - and eax,PCI_BASE_ADDRESS_MEM_TYPE_MASK - cmp eax,PCI_BASE_ADDRESS_MEM_TYPE_64 - jne .not64 - mov eax,[index] - add eax,4 - stdcall pci_read_config_dword,eax - or eax,eax - jz .not64 -; DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" - add esp,4 - or eax,-1 - ret - .not64: - pop eax - and eax,PCI_BASE_ADDRESS_MEM_MASK - .exit: - ret -endp - -proc rtl8169_init_board - -; DEBUGF 1,"K : rtl8169_init_board\n" - - call adjust_pci_device - - stdcall pci_bar_start,PCI_BASE_ADDRESS_0 - mov [rtl8169_tpc.mmio_addr],eax - ; Soft reset the chip - RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset - - ; Check that the chip has finished the reset - mov ecx,1000 - @@: RTL_R8 RTL8169_REG_ChipCmd - test al,RTL8169_CMD_Reset - jz @f - stdcall udelay,10 - loop @b - @@: - ; identify config method - RTL_R32 RTL8169_REG_TxConfig - and eax,0x7c800000 -; DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax - mov esi,mac_info-8 - @@: add esi,8 - mov ecx,eax - and ecx,[esi] - cmp ecx,[esi] - jne @b - mov eax,[esi+4] - mov [rtl8169_tpc.mcfg],eax - - mov [rtl8169_tpc.pcfg],PCFG_METHOD_3 - stdcall RTL8169_READ_GMII_REG,3 - and al,0x0f - or al,al - jnz @f - mov [rtl8169_tpc.pcfg],PCFG_METHOD_1 - jmp .pconf - @@: dec al - jnz .pconf - mov [rtl8169_tpc.pcfg],PCFG_METHOD_2 - .pconf: - - ; identify chip attached to board - mov ecx,10 - mov eax,[rtl8169_tpc.mcfg] - @@: dec ecx - js @f - cmp eax,[rtl_chip_info+ecx*8] - jne @b - mov [rtl8169_tpc.chipset],ecx - jmp .match - @@: - ; if unknown chip, assume array element #0, original RTL-8169 in this case -; DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" - RTL_R32 RTL8169_REG_TxConfig -; DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax - - mov [rtl8169_tpc.chipset],0 - - xor eax,eax - inc eax - ret - - .match: - xor eax,eax - ret -endp - -proc rtl8169_hw_PHY_config - -; DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] - -; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); - - cmp [rtl8169_tpc.mcfg],MCFG_METHOD_04 - jne .not_4 -; stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 -; stdcall RTL8169_WRITE_GMII_REG,0x1b,0x841e -; stdcall RTL8169_WRITE_GMII_REG,0x0e,0x7bfb -; stdcall RTL8169_WRITE_GMII_REG,0x09,0x273a - stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0002 - stdcall RTL8169_WRITE_GMII_REG,0x01,0x90D0 - stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0000 - jmp .exit - .not_4: - cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 - je @f - cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 - jne .not_2_or_3 - @@: stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 - stdcall RTL8169_WRITE_GMII_REG,0x15,0x1000 - stdcall RTL8169_WRITE_GMII_REG,0x18,0x65C7 - stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 - stdcall RTL8169_WRITE_GMII_REG,0x03,0x00A1 - stdcall RTL8169_WRITE_GMII_REG,0x02,0x0008 - stdcall RTL8169_WRITE_GMII_REG,0x01,0x1020 - stdcall RTL8169_WRITE_GMII_REG,0x00,0x1000 - stdcall RTL8169_WRITE_GMII_REG,0x04,0x0800 - stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 - stdcall RTL8169_WRITE_GMII_REG,0x04,0x7000 - stdcall RTL8169_WRITE_GMII_REG,0x03,0xFF41 - stdcall RTL8169_WRITE_GMII_REG,0x02,0xDE60 - stdcall RTL8169_WRITE_GMII_REG,0x01,0x0140 - stdcall RTL8169_WRITE_GMII_REG,0x00,0x0077 - stdcall RTL8169_WRITE_GMII_REG,0x04,0x7800 - stdcall RTL8169_WRITE_GMII_REG,0x04,0x7000 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xA000 - stdcall RTL8169_WRITE_GMII_REG,0x03,0xDF01 - stdcall RTL8169_WRITE_GMII_REG,0x02,0xDF20 - stdcall RTL8169_WRITE_GMII_REG,0x01,0xFF95 - stdcall RTL8169_WRITE_GMII_REG,0x00,0xFA00 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xA800 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xA000 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xB000 - stdcall RTL8169_WRITE_GMII_REG,0x03,0xFF41 - stdcall RTL8169_WRITE_GMII_REG,0x02,0xDE20 - stdcall RTL8169_WRITE_GMII_REG,0x01,0x0140 - stdcall RTL8169_WRITE_GMII_REG,0x00,0x00BB - stdcall RTL8169_WRITE_GMII_REG,0x04,0xB800 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xB000 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xF000 - stdcall RTL8169_WRITE_GMII_REG,0x03,0xDF01 - stdcall RTL8169_WRITE_GMII_REG,0x02,0xDF20 - stdcall RTL8169_WRITE_GMII_REG,0x01,0xFF95 - stdcall RTL8169_WRITE_GMII_REG,0x00,0xBF00 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xF800 - stdcall RTL8169_WRITE_GMII_REG,0x04,0xF000 - stdcall RTL8169_WRITE_GMII_REG,0x04,0x0000 - stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0000 - stdcall RTL8169_WRITE_GMII_REG,0x0B,0x0000 - jmp .exit - .not_2_or_3: -; DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", tpc->mcfg); -; DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] - .exit: - ret -endp - -;proc pci_write_config_byte -; ret -;endp - -proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword - -;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] - - movzx eax,[RegAddr] - shl eax,16 - or eax,[value] - or eax,0x80000000 - RTL_W32 RTL8169_REG_PHYAR,eax - stdcall udelay,1 ;;;1000 - - mov ecx,2000 - ; Check if the RTL8169 has completed writing to the specified MII register - @@: RTL_R32 RTL8169_REG_PHYAR - test eax,0x80000000 - jz .exit - stdcall udelay,1 ;;;100 - loop @b - .exit: - ret -endp - -proc RTL8169_READ_GMII_REG,RegAddr:byte - -;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 - - push ecx - movzx eax,[RegAddr] - shl eax,16 -; or eax,0x0 - RTL_W32 RTL8169_REG_PHYAR,eax - stdcall udelay,1 ;;;1000 - - mov ecx,2000 - ; Check if the RTL8169 has completed retrieving data from the specified MII register - @@: RTL_R32 RTL8169_REG_PHYAR - test eax,0x80000000 - jnz .exit - stdcall udelay,1 ;;;100 - loop @b - - or eax,-1 - pop ecx - ret - .exit: - RTL_R32 RTL8169_REG_PHYAR - and eax,0xFFFF - pop ecx - ret -endp - -proc rtl8169_set_rx_mode - -; DEBUGF 1,"K : rtl8169_set_rx_mode\n" - - ; IFF_ALLMULTI - ; Too many to filter perfectly -- accept all multicasts - RTL_R32 RTL8169_REG_RxConfig - mov ecx,[rtl8169_tpc.chipset] - and eax,[rtl_chip_info + ecx * 8 + 4] ; RxConfigMask - or eax,rtl8169_rx_config or (RTL8169_RXM_AcceptBroadcast or RTL8169_RXM_AcceptMulticast or RTL8169_RXM_AcceptMyPhys) - RTL_W32 RTL8169_REG_RxConfig,eax - - ; Multicast hash filter - RTL_W32 RTL8169_REG_MAR0 + 0,0xffffffff - RTL_W32 RTL8169_REG_MAR0 + 4,0xffffffff - ret -endp - -proc rtl8169_init_ring - -; DEBUGF 1,"K : rtl8169_init_ring\n" - - xor eax,eax - mov [rtl8169_tpc.cur_rx],eax - mov [rtl8169_tpc.cur_tx],eax - - mov edi,[rtl8169_tpc.TxDescArray] - mov ecx,(NUM_TX_DESC * sizeof.rtl8169_TxDesc) / 4 - cld - rep stosd - mov edi,[rtl8169_tpc.RxDescArray] - mov ecx,(NUM_RX_DESC * sizeof.rtl8169_RxDesc) / 4 - rep stosd - - mov edi,rtl8169_tpc.Tx_skbuff - mov eax,rtl8169_txb - mov ecx,NUM_TX_DESC - @@: stosd - inc eax ; add eax,RX_BUF_SIZE ??? - loop @b - -;!!! for (i = 0; i < NUM_RX_DESC; i++) { -;!!! if (i == (NUM_RX_DESC - 1)) -;!!! tpc->RxDescArray[i].status = (OWNbit | EORbit) | RX_BUF_SIZE; -;!!! else -;!!! tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE; -;!!! tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; -;!!! tpc->RxDescArray[i].buf_addr = virt_to_bus(tpc->RxBufferRing[i]); -;!!! } - mov esi,rtl8169_tpc.RxBufferRing - mov edi,[rtl8169_tpc.RxDescArray] - mov eax,rtl8169_rxb - mov ecx,NUM_RX_DESC - @@: mov [esi],eax - mov [edi+rtl8169_RxDesc.buf_addr],eax - sub [edi+rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 - mov [edi+rtl8169_RxDesc.status],RTL8169_DSB_OWNbit or RX_BUF_SIZE - add esi,4 - add edi,sizeof.rtl8169_RxDesc - add eax,RX_BUF_SIZE - loop @b - - or [edi - sizeof.rtl8169_RxDesc + rtl8169_RxDesc.status],RTL8169_DSB_EORbit - - ret -endp - -proc rtl8169_hw_start - -; DEBUGF 1,"K : rtl8169_hw_start\n" - - ; Soft reset the chip - RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset - ; Check that the chip has finished the reset - mov ecx,1000 - @@: RTL_R8 RTL8169_REG_ChipCmd - and al,RTL8169_CMD_Reset - jz @f - stdcall udelay,10 - loop @b - @@: - RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Unlock - RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_TxEnb or RTL8169_CMD_RxEnb - RTL_W8 RTL8169_REG_ETThReg,ETTh - ; For gigabit rtl8169 - RTL_W16 RTL8169_REG_RxMaxSize,RxPacketMaxSize - ; Set Rx Config register - RTL_R32 RTL8169_REG_RxConfig - mov ecx,[rtl8169_tpc.chipset] - and eax,[rtl_chip_info + ecx * 8 + 4] ; RxConfigMask - or eax,rtl8169_rx_config - RTL_W32 RTL8169_REG_RxConfig,eax - ; Set DMA burst size and Interframe Gap Time - RTL_W32 RTL8169_REG_TxConfig,(TX_DMA_BURST shl RTL8169_TXC_DMAShift) or (InterFrameGap shl RTL8169_TXC_InterFrameGapShift) - RTL_R16 RTL8169_REG_CPlusCmd - RTL_W16 RTL8169_REG_CPlusCmd,ax - - RTL_R16 RTL8169_REG_CPlusCmd - or ax,1 shl 3 - cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 - jne @f - cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 - jne @f - or ax,1 shl 14 -; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n" - jmp .set - @@:;DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3\n" - .set: RTL_W16 RTL8169_REG_CPlusCmd,ax - -; RTL_W16 0xE2,0x1517 -; RTL_W16 0xE2,0x152a -; RTL_W16 0xE2,0x282a - RTL_W16 0xE2,0x0000 - - MOV [rtl8169_tpc.cur_rx],0 - push eax ; shurf 28.09.2008 - mov eax, [rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 - sub eax, OS_BASE ; shurf 28.09.2008 - RTL_W32 RTL8169_REG_TxDescStartAddr,eax ;[rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 - mov eax, [rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 - sub eax, OS_BASE ; shurf 28.09.2008 - RTL_W32 RTL8169_REG_RxDescStartAddr,eax ;[rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 - pop eax ; shurf 28.09.2008 - RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Lock - stdcall udelay,10 - RTL_W32 RTL8169_REG_RxMissed,0 - call rtl8169_set_rx_mode - ; no early-rx interrupts - RTL_R16 RTL8169_REG_MultiIntr - and ax,0xF000 - RTL_W16 RTL8169_REG_MultiIntr,ax - RTL_W16 RTL8169_REG_IntrMask,0 ; rtl8169_intr_mask - ret -endp - -proc udelay,msec:dword - push esi - mov esi,[msec] - call delay_ms - pop esi - ret -endp - -;*************************************************************************** -; Function -; rtl8169_probe -; Description -; Searches for an ethernet card, enables it and clears the rx buffer -; If a card was found, it enables the ethernet -> TCPIP link -; Destroyed registers -; eax, ebx, ecx, edx -; -;*************************************************************************** -proc rtl8169_probe - -; DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 - - call rtl8169_init_board - - mov ecx,MAC_ADDR_LEN - mov edx,[rtl8169_tpc.mmio_addr] - add edx,RTL8169_REG_MAC0 - xor ebx,ebx - ; Get MAC address. FIXME: read EEPROM - @@: RTL_R8 dx - mov [node_addr+ebx],al - inc edx - inc ebx - loop @b - -; DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 - - ; Config PHY - stdcall rtl8169_hw_PHY_config -; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" - RTL_W8 0x82,0x01 - cmp [rtl8169_tpc.mcfg],MCFG_METHOD_03 - jae @f -; DEBUGF 1,"K : Set PCI Latency=0x40\n" -; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40 - @@: - cmp [rtl8169_tpc.mcfg],MCFG_METHOD_02 - jne @f -; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" - RTL_W8 0x82,0x01 -; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n" - stdcall RTL8169_WRITE_GMII_REG,0x0b,0x0000 ; w 0x0b 15 0 0 - @@: - ; if TBI is not enabled - RTL_R8 RTL8169_REG_PHYstatus - test al,RTL8169_PHYS_TBI_Enable - jz .tbi_dis - stdcall RTL8169_READ_GMII_REG,RTL8169_PHY_AUTO_NEGO_REG - ; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged - and eax,0x0C1F - or eax,RTL8169_PHY_Cap_10_Half or RTL8169_PHY_Cap_10_Full or RTL8169_PHY_Cap_100_Half or RTL8169_PHY_Cap_100_Full - stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_AUTO_NEGO_REG,eax - ; enable 1000 Full Mode - stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_1000_CTRL_REG,RTL8169_PHY_Cap_1000_Full or RTL8169_PHY_Cap_1000_Half ; rtl8168 - ; Enable auto-negotiation and restart auto-nigotiation - stdcall RTL8169_WRITE_GMII_REG,RTL8169_PHY_CTRL_REG,RTL8169_PHY_Enable_Auto_Nego or RTL8169_PHY_Restart_Auto_Nego - stdcall udelay,100 - mov ecx,10000 - ; wait for auto-negotiation process - @@: dec ecx - jz @f - stdcall RTL8169_READ_GMII_REG,RTL8169_PHY_STAT_REG - stdcall udelay,100 - test eax,RTL8169_PHY_Auto_Neco_Comp - jz @b - RTL_R8 RTL8169_REG_PHYstatus - jmp @f - .tbi_dis: - stdcall udelay,100 - @@: - call rtl8169_reset - ret -endp - -;*************************************************************************** -; Function -; rt8169_reset -; Description -; Place the chip (ie, the ethernet card) into a virgin state -; Destroyed registers -; eax, ebx, ecx, edx -; -;*************************************************************************** -proc rtl8169_reset - -; DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 - - mov [rtl8169_tpc.TxDescArrays],rtl8169_tx_ring - ; Tx Desscriptor needs 256 bytes alignment - mov [rtl8169_tpc.TxDescArray],rtl8169_tx_ring - - mov [rtl8169_tpc.RxDescArrays],rtl8169_rx_ring - ; Rx Desscriptor needs 256 bytes alignment - mov [rtl8169_tpc.RxDescArray],rtl8169_rx_ring - - call rtl8169_init_ring - call rtl8169_hw_start - ; Construct a perfect filter frame with the mac address as first match - ; and broadcast for all others - mov edi,rtl8169_txb - or al,-1 - mov ecx,192 - cld - rep stosb - - mov esi,node_addr - mov edi,rtl8169_txb - movsd - movsw - - mov eax,[pci_data] - mov [eth_status],eax - ret -endp - -;*************************************************************************** -; Function -; rtl8169_transmit -; Description -; Transmits a packet of data via the ethernet card -; d - edi - Pointer to 48 bit destination address -; t - bx - Type of packet -; s - ecx - size of packet -; p - esi - pointer to packet data -; Destroyed registers -; eax, edx, esi, edi -; -;*************************************************************************** -proc rtl8169_transmit - -; DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi - - push ecx edx esi - mov eax,MAX_ETH_FRAME_SIZE - mul [rtl8169_tpc.cur_tx] - mov esi,edi - ; point to the current txb incase multiple tx_rings are used - mov edi,[rtl8169_tpc.Tx_skbuff + eax * 4] - mov eax,edi - cld -; copy destination address - movsd - movsw -; copy source address - mov esi,node_addr - movsd - movsw -; copy packet type - mov [edi],bx - add edi,2 -; copy the packet data - pop esi edx ecx - push ecx - shr ecx,2 - rep movsd - pop ecx - push ecx - and ecx,3 - rep movsb - -;!!! s += ETH_HLEN; -;!!! s &= 0x0FFF; -;!!! while (s < ETH_ZLEN) -;!!! ptxb[s++] = '\0'; - mov edi,eax - pop ecx - push eax - add ecx,ETH_HLEN - and ecx,0x0FFF - xor al,al - add edi,ecx - @@: cmp ecx,ETH_ZLEN - jae @f - stosb - inc ecx - jmp @b - @@: pop eax - - mov ebx,eax - mov eax,sizeof.rtl8169_TxDesc - mul [rtl8169_tpc.cur_tx] - add eax,[rtl8169_tpc.TxDescArray] - xchg eax,ebx - mov [ebx + rtl8169_TxDesc.buf_addr],eax - sub [ebx + rtl8169_TxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 - - mov eax,ecx - cmp eax,ETH_ZLEN - jae @f - mov eax,ETH_ZLEN - @@: or eax,RTL8169_DSB_OWNbit or RTL8169_DSB_FSbit or RTL8169_DSB_LSbit - cmp [rtl8169_tpc.cur_tx],NUM_TX_DESC - 1 - jne @f - or eax,RTL8169_DSB_EORbit - @@: mov [ebx + rtl8169_TxDesc.status],eax - - RTL_W8 RTL8169_REG_TxPoll,0x40 ; set polling bit - - inc [rtl8169_tpc.cur_tx] - and [rtl8169_tpc.cur_tx],NUM_TX_DESC - 1 - -;!!! to = currticks() + TX_TIMEOUT; -;!!! while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ - mov ecx,TX_TIMEOUT / 10 - @@: test [ebx + rtl8169_TxDesc.status],RTL8169_DSB_OWNbit - jnz @f - stdcall udelay,10 - loop @b -; DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" - @@: - - ret -endp - -;*************************************************************************** -; Function -; rtl8169_poll -; -; Description -; Polls the ethernet card for a received packet -; Received data, if any, ends up in Ether_buffer -; Destroyed register(s) -; eax, edx, ecx -; -;*************************************************************************** -proc rtl8169_poll - -; DEBUGF 1,"K : rtl8169_poll\n" ;: 0x%x : none\n",[io_addr]:8 - - mov word[eth_rx_data_len],0 - - mov eax,sizeof.rtl8169_RxDesc - mul [rtl8169_tpc.cur_rx] - add eax,[rtl8169_tpc.RxDescArray] - mov ebx,eax - -; DEBUGF 1,"K : rtl8169_RxDesc.status = 0x%x\n",[ebx + rtl8169_RxDesc.status] - - test [ebx + rtl8169_RxDesc.status],RTL8169_DSB_OWNbit ; 0x80000600 - jnz .exit - -; DEBUGF 1,"K : rtl8169_tpc.cur_rx = %u\n",[rtl8169_tpc.cur_rx] - - ; h/w no longer present (hotplug?) or major error, bail - RTL_R16 RTL8169_REG_IntrStatus - -; DEBUGF 1,"K : IntrStatus = 0x%x\n",ax - - cmp ax,0xFFFF - je .exit - - push eax - and ax,not (RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK) - RTL_W16 RTL8169_REG_IntrStatus,ax - - mov eax,[ebx + rtl8169_RxDesc.status] - -; DEBUGF 1,"K : RxDesc.status = 0x%x\n",eax - - test eax,RTL8169_SD_RxRES - jnz .else - and eax,0x00001FFF -; jz .exit.pop - add eax,-4 - mov [eth_rx_data_len],ax - -; DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax - - push eax - mov ecx,eax - shr ecx,2 - mov eax,[rtl8169_tpc.cur_rx] - mov edx,[rtl8169_tpc.RxBufferRing + eax * 4] - mov esi,edx - mov edi,Ether_buffer - cld - rep movsd - pop ecx - and ecx,3 - rep movsb - - mov eax,RTL8169_DSB_OWNbit or RX_BUF_SIZE - cmp [rtl8169_tpc.cur_rx],NUM_RX_DESC - 1 - jne @f - or eax,RTL8169_DSB_EORbit - @@: mov [ebx + rtl8169_RxDesc.status],eax - - mov [ebx + rtl8169_RxDesc.buf_addr],edx - sub [ebx + rtl8169_RxDesc.buf_addr],OS_BASE ; shurf 28.09.2008 - jmp @f - .else: -; DEBUGF 1,"K : rtl8169_poll: Rx Error\n" - ; FIXME: shouldn't I reset the status on an error - @@: - inc [rtl8169_tpc.cur_rx] - and [rtl8169_tpc.cur_rx],NUM_RX_DESC - 1 - .exit.pop: - pop eax - and ax,RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK - RTL_W16 RTL8169_REG_IntrStatus,ax - .exit: - ret -endp - -proc rtl8169_cable - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; RTL8169.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.1 11 February 2007 ;; +;; ;; +;; Driver for chips of RealTek 8169 family ;; +;; References: ;; +;; r8169.c - linux driver (etherboot project) ;; +;; ethernet driver template by Mike Hibbett ;; +;; ;; +;; The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; Copyright 2007 mike.dld, ;; +;; mike.dld@gmail.com ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + + ETH_ALEN equ 6 + ETH_HLEN equ (2 * ETH_ALEN + 2) + ETH_ZLEN equ 60 ; 60 + 4bytes auto payload for + ; mininmum 64bytes frame length + + RTL8169_REG_MAC0 equ 0x0 ; Ethernet hardware address + RTL8169_REG_MAR0 equ 0x8 ; Multicast filter + RTL8169_REG_TxDescStartAddr equ 0x20 + RTL8169_REG_TxHDescStartAddr equ 0x28 + RTL8169_REG_FLASH equ 0x30 + RTL8169_REG_ERSR equ 0x36 + RTL8169_REG_ChipCmd equ 0x37 + RTL8169_REG_TxPoll equ 0x38 + RTL8169_REG_IntrMask equ 0x3C + RTL8169_REG_IntrStatus equ 0x3E + RTL8169_REG_TxConfig equ 0x40 + RTL8169_REG_RxConfig equ 0x44 + RTL8169_REG_RxMissed equ 0x4C + RTL8169_REG_Cfg9346 equ 0x50 + RTL8169_REG_Config0 equ 0x51 + RTL8169_REG_Config1 equ 0x52 + RTL8169_REG_Config2 equ 0x53 + RTL8169_REG_Config3 equ 0x54 + RTL8169_REG_Config4 equ 0x55 + RTL8169_REG_Config5 equ 0x56 + RTL8169_REG_MultiIntr equ 0x5C + RTL8169_REG_PHYAR equ 0x60 + RTL8169_REG_TBICSR equ 0x64 + RTL8169_REG_TBI_ANAR equ 0x68 + RTL8169_REG_TBI_LPAR equ 0x6A + RTL8169_REG_PHYstatus equ 0x6C + RTL8169_REG_RxMaxSize equ 0xDA + RTL8169_REG_CPlusCmd equ 0xE0 + RTL8169_REG_RxDescStartAddr equ 0xE4 + RTL8169_REG_ETThReg equ 0xEC + RTL8169_REG_FuncEvent equ 0xF0 + RTL8169_REG_FuncEventMask equ 0xF4 + RTL8169_REG_FuncPresetState equ 0xF8 + RTL8169_REG_FuncForceEvent equ 0xFC + + ; InterruptStatusBits + RTL8169_ISB_SYSErr equ 0x8000 + RTL8169_ISB_PCSTimeout equ 0x4000 + RTL8169_ISB_SWInt equ 0x0100 + RTL8169_ISB_TxDescUnavail equ 0x80 + RTL8169_ISB_RxFIFOOver equ 0x40 + RTL8169_ISB_LinkChg equ 0x20 + RTL8169_ISB_RxOverflow equ 0x10 + RTL8169_ISB_TxErr equ 0x08 + RTL8169_ISB_TxOK equ 0x04 + RTL8169_ISB_RxErr equ 0x02 + RTL8169_ISB_RxOK equ 0x01 + + ; RxStatusDesc + RTL8169_SD_RxRES equ 0x00200000 + RTL8169_SD_RxCRC equ 0x00080000 + RTL8169_SD_RxRUNT equ 0x00100000 + RTL8169_SD_RxRWT equ 0x00400000 + + ; ChipCmdBits + RTL8169_CMD_Reset equ 0x10 + RTL8169_CMD_RxEnb equ 0x08 + RTL8169_CMD_TxEnb equ 0x04 + RTL8169_CMD_RxBufEmpty equ 0x01 + + ; Cfg9346Bits + RTL8169_CFG_9346_Lock equ 0x00 + RTL8169_CFG_9346_Unlock equ 0xC0 + + ; rx_mode_bits + RTL8169_RXM_AcceptErr equ 0x20 + RTL8169_RXM_AcceptRunt equ 0x10 + RTL8169_RXM_AcceptBroadcast equ 0x08 + RTL8169_RXM_AcceptMulticast equ 0x04 + RTL8169_RXM_AcceptMyPhys equ 0x02 + RTL8169_RXM_AcceptAllPhys equ 0x01 + + ; RxConfigBits + RTL8169_RXC_FIFOShift equ 13 + RTL8169_RXC_DMAShift equ 8 + + ; TxConfigBits + RTL8169_TXC_InterFrameGapShift equ 24 + RTL8169_TXC_DMAShift equ 8 ; DMA burst value (0-7) is shift this many bits + + ; rtl8169_PHYstatus + RTL8169_PHYS_TBI_Enable equ 0x80 + RTL8169_PHYS_TxFlowCtrl equ 0x40 + RTL8169_PHYS_RxFlowCtrl equ 0x20 + RTL8169_PHYS_1000bpsF equ 0x10 + RTL8169_PHYS_100bps equ 0x08 + RTL8169_PHYS_10bps equ 0x04 + RTL8169_PHYS_LinkStatus equ 0x02 + RTL8169_PHYS_FullDup equ 0x01 + + ; GIGABIT_PHY_registers + RTL8169_PHY_CTRL_REG equ 0 + RTL8169_PHY_STAT_REG equ 1 + RTL8169_PHY_AUTO_NEGO_REG equ 4 + RTL8169_PHY_1000_CTRL_REG equ 9 + + ; GIGABIT_PHY_REG_BIT + RTL8169_PHY_Restart_Auto_Nego equ 0x0200 + RTL8169_PHY_Enable_Auto_Nego equ 0x1000 + + ; PHY_STAT_REG = 1; + RTL8169_PHY_Auto_Neco_Comp equ 0x0020 + + ; PHY_AUTO_NEGO_REG = 4; + RTL8169_PHY_Cap_10_Half equ 0x0020 + RTL8169_PHY_Cap_10_Full equ 0x0040 + RTL8169_PHY_Cap_100_Half equ 0x0080 + RTL8169_PHY_Cap_100_Full equ 0x0100 + + ; PHY_1000_CTRL_REG = 9; + RTL8169_PHY_Cap_1000_Full equ 0x0200 + RTL8169_PHY_Cap_1000_Half equ 0x0100 + + RTL8169_PHY_Cap_PAUSE equ 0x0400 + RTL8169_PHY_Cap_ASYM_PAUSE equ 0x0800 + + RTL8169_PHY_Cap_Null equ 0x0 + + ; _MediaType + RTL8169_MT_10_Half equ 0x01 + RTL8169_MT_10_Full equ 0x02 + RTL8169_MT_100_Half equ 0x04 + RTL8169_MT_100_Full equ 0x08 + RTL8169_MT_1000_Full equ 0x10 + + ; _TBICSRBit + RTL8169_TBI_LinkOK equ 0x02000000 + + ; _DescStatusBit + RTL8169_DSB_OWNbit equ 0x80000000 + RTL8169_DSB_EORbit equ 0x40000000 + RTL8169_DSB_FSbit equ 0x20000000 + RTL8169_DSB_LSbit equ 0x10000000 + +; MAC address length +MAC_ADDR_LEN equ 6 + +; max supported gigabit ethernet frame size -- must be at least (dev->mtu+14+4) +MAX_ETH_FRAME_SIZE equ 1536 + +TX_FIFO_THRESH equ 256 ; In bytes + +RX_FIFO_THRESH equ 7 ; 7 means NO threshold, Rx buffer level before first PCI xfer +RX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 +TX_DMA_BURST equ 7 ; Maximum PCI burst, '6' is 1024 +ETTh equ 0x3F ; 0x3F means NO threshold + +EarlyTxThld equ 0x3F ; 0x3F means NO early transmit +RxPacketMaxSize equ 0x0800 ; Maximum size supported is 16K-1 +InterFrameGap equ 0x03 ; 3 means InterFrameGap = the shortest one + +NUM_TX_DESC equ 1 ; Number of Tx descriptor registers +NUM_RX_DESC equ 4 ; Number of Rx descriptor registers +RX_BUF_SIZE equ 1536 ; Rx Buffer size + +HZ equ 1000 + +RTL_MIN_IO_SIZE equ 0x80 +TX_TIMEOUT equ (6*HZ) + +RTL8169_TIMER_EXPIRE_TIME equ 100 + +ETH_HDR_LEN equ 14 +DEFAULT_MTU equ 1500 +DEFAULT_RX_BUF_LEN equ 1536 + + +;#ifdef RTL8169_JUMBO_FRAME_SUPPORT +;#define MAX_JUMBO_FRAME_MTU ( 10000 ) +;#define MAX_RX_SKBDATA_SIZE ( MAX_JUMBO_FRAME_MTU + ETH_HDR_LEN ) +;#else +MAX_RX_SKBDATA_SIZE equ 1600 +;#endif //end #ifdef RTL8169_JUMBO_FRAME_SUPPORT + +;#ifdef RTL8169_USE_IO +;!!!#define RTL_W8(reg, val8) outb ((val8), ioaddr + (reg)) +macro RTL_W8 reg,val8 { + if ~reg eq dx + mov dx, word[rtl8169_tpc.mmio_addr] + add dx, reg + end if + if ~val8 eq al + mov al, val8 + end if + out dx, al +} +;!!!#define RTL_W16(reg, val16) outw ((val16), ioaddr + (reg)) +macro RTL_W16 reg,val16 { + if ~reg eq dx + mov dx, word[rtl8169_tpc.mmio_addr] + add dx, reg + end if + if ~val16 eq ax + mov ax, val16 + end if + out dx, ax +} +;!!!#define RTL_W32(reg, val32) outl ((val32), ioaddr + (reg)) +macro RTL_W32 reg,val32 { + if ~reg eq dx + mov dx, word[rtl8169_tpc.mmio_addr] + add dx, reg + end if + if ~val32 eq eax + mov eax, val32 + end if + out dx, eax +} +;!!!#define RTL_R8(reg) inb (ioaddr + (reg)) +macro RTL_R8 reg { + if ~reg eq dx + mov dx, word[rtl8169_tpc.mmio_addr] + add dx, reg + end if + in al, dx +} +;!!!#define RTL_R16(reg) inw (ioaddr + (reg)) +macro RTL_R16 reg { + if ~reg eq dx + mov dx, word[rtl8169_tpc.mmio_addr] + add dx, reg + end if + in ax, dx +} +;!!!#define RTL_R32(reg) ((unsigned long) inl (ioaddr + (reg))) +macro RTL_R32 reg { + if ~reg eq dx + mov dx, word[rtl8169_tpc.mmio_addr] + add dx, reg + end if + in eax, dx +} +;#else +; write/read MMIO register +;#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) +;#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) +;#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) +;#define RTL_R8(reg) readb (ioaddr + (reg)) +;#define RTL_R16(reg) readw (ioaddr + (reg)) +;#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg))) +;#endif + +MCFG_METHOD_01 equ 0x01 +MCFG_METHOD_02 equ 0x02 +MCFG_METHOD_03 equ 0x03 +MCFG_METHOD_04 equ 0x04 +MCFG_METHOD_05 equ 0x05 +MCFG_METHOD_11 equ 0x0b +MCFG_METHOD_12 equ 0x0c +MCFG_METHOD_13 equ 0x0d +MCFG_METHOD_14 equ 0x0e +MCFG_METHOD_15 equ 0x0f + +PCFG_METHOD_1 equ 0x01 ; PHY Reg 0x03 bit0-3 == 0x0000 +PCFG_METHOD_2 equ 0x02 ; PHY Reg 0x03 bit0-3 == 0x0001 +PCFG_METHOD_3 equ 0x03 ; PHY Reg 0x03 bit0-3 == 0x0002 + +PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space +PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space +PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering +PCI_LATENCY_TIMER equ 0x0d ; 8 bits +PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles +PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate +PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping +PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking +PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping +PCI_COMMAND_SERR equ 0x100 ; Enable SERR +PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes + +struc rtl8169_TxDesc { + .status dd ? + .vlan_tag dd ? + .buf_addr dd ? + .buf_Haddr dd ? +} +virtual at 0 + rtl8169_TxDesc rtl8169_TxDesc + sizeof.rtl8169_TxDesc = $ - rtl8169_TxDesc +end virtual + +struc rtl8169_RxDesc { + .status dd ? + .vlan_tag dd ? + .buf_addr dd ? + .buf_Haddr dd ? +} +virtual at 0 + rtl8169_RxDesc rtl8169_RxDesc + sizeof.rtl8169_RxDesc = $ - rtl8169_RxDesc +end virtual + +virtual at eth_data_start + +; Define the TX Descriptor +align 256 +rtl8169_tx_ring rb NUM_TX_DESC * sizeof.rtl8169_TxDesc + +; Create a static buffer of size RX_BUF_SZ for each +; TX Descriptor. All descriptors point to a +; part of this buffer +align 256 +rtl8169_txb rb NUM_TX_DESC * RX_BUF_SIZE + +; Define the RX Descriptor +align 256 +rtl8169_rx_ring rb NUM_RX_DESC * sizeof.rtl8169_RxDesc + +; Create a static buffer of size RX_BUF_SZ for each +; RX Descriptor All descriptors point to a +; part of this buffer +align 256 +rtl8169_rxb rb NUM_RX_DESC * RX_BUF_SIZE + +rtl8169_tpc: + .mmio_addr dd ? ; memory map physical address + .chipset dd ? + .pcfg dd ? + .mcfg dd ? + .cur_rx dd ? ; Index into the Rx descriptor buffer of next Rx pkt + .cur_tx dd ? ; Index into the Tx descriptor buffer of next Rx pkt + .TxDescArrays dd ? ; Index of Tx Descriptor buffer + .RxDescArrays dd ? ; Index of Rx Descriptor buffer + .TxDescArray dd ? ; Index of 256-alignment Tx Descriptor buffer + .RxDescArray dd ? ; Index of 256-alignment Rx Descriptor buffer + .RxBufferRing rd NUM_RX_DESC ; Index of Rx Buffer array + .Tx_skbuff rd NUM_TX_DESC + +end virtual + +rtl8169_intr_mask = RTL8169_ISB_LinkChg or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxFIFOOver or RTL8169_ISB_TxErr or RTL8169_ISB_TxOK or RTL8169_ISB_RxErr or RTL8169_ISB_RxOK +rtl8169_rx_config = (RX_FIFO_THRESH shl RTL8169_RXC_FIFOShift) or (RX_DMA_BURST shl RTL8169_RXC_DMAShift) or 0x0000000E + +iglobal + +;static struct { +; const char *name; +; u8 mcfg; /* depend on RTL8169 docs */ +; u32 RxConfigMask; /* should clear the bits supported by this chip */ +;} +rtl_chip_info dd \ + MCFG_METHOD_01, 0xff7e1880, \ ; RTL8169 + MCFG_METHOD_02, 0xff7e1880, \ ; RTL8169s/8110s + MCFG_METHOD_03, 0xff7e1880, \ ; RTL8169s/8110s + MCFG_METHOD_04, 0xff7e1880, \ ; RTL8169sb/8110sb + MCFG_METHOD_05, 0xff7e1880, \ ; RTL8169sc/8110sc + MCFG_METHOD_11, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E + MCFG_METHOD_12, 0xff7e1880, \ ; RTL8168b/8111b // PCI-E + MCFG_METHOD_13, 0xff7e1880, \ ; RTL8101e // PCI-E 8139 + MCFG_METHOD_14, 0xff7e1880, \ ; RTL8100e // PCI-E 8139 + MCFG_METHOD_15, 0xff7e1880 ; RTL8100e // PCI-E 8139 + +mac_info dd \ + 0x38800000, MCFG_METHOD_15, \ + 0x38000000, MCFG_METHOD_12, \ + 0x34000000, MCFG_METHOD_13, \ + 0x30800000, MCFG_METHOD_14, \ + 0x30000000, MCFG_METHOD_11, \ + 0x18000000, MCFG_METHOD_05, \ + 0x10000000, MCFG_METHOD_04, \ + 0x04000000, MCFG_METHOD_03, \ + 0x00800000, MCFG_METHOD_02, \ + 0x00000000, MCFG_METHOD_01 ; catch-all + +endg + +PCI_COMMAND_IO equ 0x1 ; Enable response in I/O space +PCI_COMMAND_MEM equ 0x2 ; Enable response in mem space +PCI_COMMAND_MASTER equ 0x4 ; Enable bus mastering +PCI_LATENCY_TIMER equ 0x0d ; 8 bits +PCI_COMMAND_SPECIAL equ 0x8 ; Enable response to special cycles +PCI_COMMAND_INVALIDATE equ 0x10 ; Use memory write and invalidate +PCI_COMMAND_VGA_PALETTE equ 0x20 ; Enable palette snooping +PCI_COMMAND_PARITY equ 0x40 ; Enable parity checking +PCI_COMMAND_WAIT equ 0x80 ; Enable address/data stepping +PCI_COMMAND_SERR equ 0x100 ; Enable SERR +PCI_COMMAND_FAST_BACK equ 0x200 ; Enable back-to-back writes + +PCI_VENDOR_ID equ 0x00 ; 16 bits +PCI_DEVICE_ID equ 0x02 ; 16 bits +PCI_COMMAND equ 0x04 ; 16 bits + +PCI_BASE_ADDRESS_0 equ 0x10 ; 32 bits +PCI_BASE_ADDRESS_1 equ 0x14 ; 32 bits +PCI_BASE_ADDRESS_2 equ 0x18 ; 32 bits +PCI_BASE_ADDRESS_3 equ 0x1c ; 32 bits +PCI_BASE_ADDRESS_4 equ 0x20 ; 32 bits +PCI_BASE_ADDRESS_5 equ 0x24 ; 32 bits + +PCI_BASE_ADDRESS_MEM_TYPE_MASK equ 0x06 +PCI_BASE_ADDRESS_MEM_TYPE_32 equ 0x00 ; 32 bit address +PCI_BASE_ADDRESS_MEM_TYPE_1M equ 0x02 ; Below 1M [obsolete] +PCI_BASE_ADDRESS_MEM_TYPE_64 equ 0x04 ; 64 bit address + +PCI_BASE_ADDRESS_IO_MASK equ (not 0x03) +PCI_BASE_ADDRESS_MEM_MASK equ (not 0x0f) +PCI_BASE_ADDRESS_SPACE_IO equ 0x01 +PCI_ROM_ADDRESS equ 0x30 ; 32 bits + +proc CONFIG_CMD,where:byte + movzx eax, byte[pci_bus] + shl eax, 8 + mov al, [pci_dev] + shl eax, 8 + mov al, [where] + and al, not 3 + or eax, 0x80000000 + ret +endp + +proc pci_read_config_byte,where:dword + push edx + stdcall CONFIG_CMD, [where] + mov dx, 0xCF8 + out dx, eax + mov edx, [where] + and edx, 3 + add edx, 0xCFC + in al, dx + pop edx + ret +endp + +proc pci_read_config_word,where:dword + push edx + stdcall CONFIG_CMD, [where] + mov dx, 0xCF8 + out dx, eax + mov edx, [where] + and edx, 2 + add edx, 0xCFC + in ax, dx + pop edx + ret +endp + +proc pci_read_config_dword,where:dword + push edx + stdcall CONFIG_CMD, [where] + mov edx, 0xCF8 + out dx, eax + mov edx, 0xCFC + in eax, dx + pop edx + ret +endp + +proc pci_write_config_byte,where:dword,value:byte + push edx + stdcall CONFIG_CMD, [where] + mov dx, 0xCF8 + out dx, eax + mov edx, [where] + and edx, 3 + add edx, 0xCFC + mov al, [value] + out dx, al + pop edx + ret +endp + +proc pci_write_config_word,where:dword,value:word + push edx + stdcall CONFIG_CMD, [where] + mov dx, 0xCF8 + out dx, eax + mov edx, [where] + and edx, 2 + add edx, 0xCFC + mov ax, [value] + out dx, ax + pop edx + ret +endp + +proc pci_write_config_dword,where:dword,value:dword + push edx + stdcall CONFIG_CMD, [where] + mov edx, 0xCF8 + out dx, eax + mov edx, 0xCFC + mov eax, [value] + out dx, eax + pop edx + ret +endp + +; Set device to be a busmaster in case BIOS neglected to do so. +; Also adjust PCI latency timer to a reasonable value, 32. +proc adjust_pci_device + +; DEBUGF 1,"K : adjust_pci_device\n" + + stdcall pci_read_config_word, PCI_COMMAND + mov bx, ax + or bx, PCI_COMMAND_MASTER or PCI_COMMAND_IO + cmp ax, bx + je @f +; DEBUGF 1,"K : adjust_pci_device: The PCI BIOS has not enabled this device!\nK : Updating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",ax,bx,[pci_bus]:2,[pci_dev]:2 + stdcall pci_write_config_word, PCI_COMMAND, ebx + @@: + stdcall pci_read_config_byte, PCI_LATENCY_TIMER + cmp al, 32 + jae @f +; DEBUGF 1,"K : adjust_pci_device: PCI latency timer (CFLT) is unreasonably low at %d.\nK : Setting to 32 clocks.\n",al + stdcall pci_write_config_byte, PCI_LATENCY_TIMER, 32 + @@: + ret +endp + +; Find the start of a pci resource +proc pci_bar_start,index:dword + stdcall pci_read_config_dword, [index] + test eax, PCI_BASE_ADDRESS_SPACE_IO + jz @f + and eax, PCI_BASE_ADDRESS_IO_MASK + jmp .exit + @@: + push eax + and eax, PCI_BASE_ADDRESS_MEM_TYPE_MASK + cmp eax, PCI_BASE_ADDRESS_MEM_TYPE_64 + jne .not64 + mov eax, [index] + add eax, 4 + stdcall pci_read_config_dword, eax + or eax, eax + jz .not64 +; DEBUGF 1,"K : pci_bar_start: Unhandled 64bit BAR\n" + add esp, 4 + or eax, -1 + ret + .not64: + pop eax + and eax, PCI_BASE_ADDRESS_MEM_MASK + .exit: + ret +endp + +proc rtl8169_init_board + +; DEBUGF 1,"K : rtl8169_init_board\n" + + call adjust_pci_device + + stdcall pci_bar_start, PCI_BASE_ADDRESS_0 + mov [rtl8169_tpc.mmio_addr], eax + ; Soft reset the chip + RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset + + ; Check that the chip has finished the reset + mov ecx, 1000 + @@: + RTL_R8 RTL8169_REG_ChipCmd + test al, RTL8169_CMD_Reset + jz @f + stdcall udelay, 10 + loop @b + @@: + ; identify config method + RTL_R32 RTL8169_REG_TxConfig + and eax, 0x7c800000 +; DEBUGF 1,"K : rtl8169_init_board: TxConfig & 0x7c800000 = 0x%x\n",eax + mov esi, mac_info-8 + @@: + add esi, 8 + mov ecx, eax + and ecx, [esi] + cmp ecx, [esi] + jne @b + mov eax, [esi+4] + mov [rtl8169_tpc.mcfg], eax + + mov [rtl8169_tpc.pcfg], PCFG_METHOD_3 + stdcall RTL8169_READ_GMII_REG, 3 + and al, 0x0f + or al, al + jnz @f + mov [rtl8169_tpc.pcfg], PCFG_METHOD_1 + jmp .pconf + @@: + dec al + jnz .pconf + mov [rtl8169_tpc.pcfg], PCFG_METHOD_2 + .pconf: + + ; identify chip attached to board + mov ecx, 10 + mov eax, [rtl8169_tpc.mcfg] + @@: + dec ecx + js @f + cmp eax, [rtl_chip_info+ecx*8] + jne @b + mov [rtl8169_tpc.chipset], ecx + jmp .match + @@: + ; if unknown chip, assume array element #0, original RTL-8169 in this case +; DEBUGF 1,"K : rtl8169_init_board: PCI device: unknown chip version, assuming RTL-8169\n" + RTL_R32 RTL8169_REG_TxConfig +; DEBUGF 1,"K : rtl8169_init_board: PCI device: TxConfig = 0x%x\n",eax + + mov [rtl8169_tpc.chipset], 0 + + xor eax, eax + inc eax + ret + + .match: + xor eax, eax + ret +endp + +proc rtl8169_hw_PHY_config + +; DEBUGF 1,"K : rtl8169_hw_PHY_config: priv.mcfg=%d, priv.pcfg=%d\n",[rtl8169_tpc.mcfg],[rtl8169_tpc.pcfg] + +; DBG_PRINT("priv->mcfg=%d, priv->pcfg=%d\n", tpc->mcfg, tpc->pcfg); + + cmp [rtl8169_tpc.mcfg], MCFG_METHOD_04 + jne .not_4 +; stdcall RTL8169_WRITE_GMII_REG,0x1F,0x0001 +; stdcall RTL8169_WRITE_GMII_REG,0x1b,0x841e +; stdcall RTL8169_WRITE_GMII_REG,0x0e,0x7bfb +; stdcall RTL8169_WRITE_GMII_REG,0x09,0x273a + stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0002 + stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x90D0 + stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0000 + jmp .exit + .not_4: + cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02 + je @f + cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03 + jne .not_2_or_3 + @@: + stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0001 + stdcall RTL8169_WRITE_GMII_REG, 0x15, 0x1000 + stdcall RTL8169_WRITE_GMII_REG, 0x18, 0x65C7 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000 + stdcall RTL8169_WRITE_GMII_REG, 0x03, 0x00A1 + stdcall RTL8169_WRITE_GMII_REG, 0x02, 0x0008 + stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x1020 + stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x1000 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0800 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7000 + stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xFF41 + stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDE60 + stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x0140 + stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x0077 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7800 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x7000 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA000 + stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xDF01 + stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDF20 + stdcall RTL8169_WRITE_GMII_REG, 0x01, 0xFF95 + stdcall RTL8169_WRITE_GMII_REG, 0x00, 0xFA00 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA800 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xA000 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB000 + stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xFF41 + stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDE20 + stdcall RTL8169_WRITE_GMII_REG, 0x01, 0x0140 + stdcall RTL8169_WRITE_GMII_REG, 0x00, 0x00BB + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB800 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xB000 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF000 + stdcall RTL8169_WRITE_GMII_REG, 0x03, 0xDF01 + stdcall RTL8169_WRITE_GMII_REG, 0x02, 0xDF20 + stdcall RTL8169_WRITE_GMII_REG, 0x01, 0xFF95 + stdcall RTL8169_WRITE_GMII_REG, 0x00, 0xBF00 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF800 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0xF000 + stdcall RTL8169_WRITE_GMII_REG, 0x04, 0x0000 + stdcall RTL8169_WRITE_GMII_REG, 0x1F, 0x0000 + stdcall RTL8169_WRITE_GMII_REG, 0x0B, 0x0000 + jmp .exit + .not_2_or_3: +; DBG_PRINT("tpc->mcfg=%d. Discard hw PHY config.\n", tpc->mcfg); +; DEBUGF 1,"K : tpc.mcfg=%d, discard hw PHY config\n",[rtl8169_tpc.mcfg] + .exit: + ret +endp + +;proc pci_write_config_byte +; ret +;endp + +proc RTL8169_WRITE_GMII_REG,RegAddr:byte,value:dword + +;;; DEBUGF 1,"K : RTL8169_WRITE_GMII_REG: 0x%x 0x%x\n",[RegAddr]:2,[value] + + movzx eax, [RegAddr] + shl eax, 16 + or eax, [value] + or eax, 0x80000000 + RTL_W32 RTL8169_REG_PHYAR,eax + stdcall udelay, 1 ;;;1000 + + mov ecx, 2000 + ; Check if the RTL8169 has completed writing to the specified MII register + @@: + RTL_R32 RTL8169_REG_PHYAR + test eax, 0x80000000 + jz .exit + stdcall udelay, 1 ;;;100 + loop @b + .exit: + ret +endp + +proc RTL8169_READ_GMII_REG,RegAddr:byte + +;;; DEBUGF 1,"K : RTL8169_READ_GMII_REG: 0x%x\n",[RegAddr]:2 + + push ecx + movzx eax, [RegAddr] + shl eax, 16 +; or eax,0x0 + RTL_W32 RTL8169_REG_PHYAR,eax + stdcall udelay, 1 ;;;1000 + + mov ecx, 2000 + ; Check if the RTL8169 has completed retrieving data from the specified MII register + @@: + RTL_R32 RTL8169_REG_PHYAR + test eax, 0x80000000 + jnz .exit + stdcall udelay, 1 ;;;100 + loop @b + + or eax, -1 + pop ecx + ret + .exit: + RTL_R32 RTL8169_REG_PHYAR + and eax, 0xFFFF + pop ecx + ret +endp + +proc rtl8169_set_rx_mode + +; DEBUGF 1,"K : rtl8169_set_rx_mode\n" + + ; IFF_ALLMULTI + ; Too many to filter perfectly -- accept all multicasts + RTL_R32 RTL8169_REG_RxConfig + mov ecx, [rtl8169_tpc.chipset] + and eax, [rtl_chip_info + ecx * 8 + 4]; RxConfigMask + or eax, rtl8169_rx_config or (RTL8169_RXM_AcceptBroadcast or RTL8169_RXM_AcceptMulticast or RTL8169_RXM_AcceptMyPhys) + RTL_W32 RTL8169_REG_RxConfig,eax + + ; Multicast hash filter + RTL_W32 RTL8169_REG_MAR0 + 0,0xffffffff + RTL_W32 RTL8169_REG_MAR0 + 4,0xffffffff + ret +endp + +proc rtl8169_init_ring + +; DEBUGF 1,"K : rtl8169_init_ring\n" + + xor eax, eax + mov [rtl8169_tpc.cur_rx], eax + mov [rtl8169_tpc.cur_tx], eax + + mov edi, [rtl8169_tpc.TxDescArray] + mov ecx, (NUM_TX_DESC * sizeof.rtl8169_TxDesc) / 4 + cld + rep stosd + mov edi, [rtl8169_tpc.RxDescArray] + mov ecx, (NUM_RX_DESC * sizeof.rtl8169_RxDesc) / 4 + rep stosd + + mov edi, rtl8169_tpc.Tx_skbuff + mov eax, rtl8169_txb + mov ecx, NUM_TX_DESC + @@: + stosd + inc eax ; add eax,RX_BUF_SIZE ??? + loop @b + +;!!! for (i = 0; i < NUM_RX_DESC; i++) { +;!!! if (i == (NUM_RX_DESC - 1)) +;!!! tpc->RxDescArray[i].status = (OWNbit | EORbit) | RX_BUF_SIZE; +;!!! else +;!!! tpc->RxDescArray[i].status = OWNbit | RX_BUF_SIZE; +;!!! tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE]; +;!!! tpc->RxDescArray[i].buf_addr = virt_to_bus(tpc->RxBufferRing[i]); +;!!! } + mov esi, rtl8169_tpc.RxBufferRing + mov edi, [rtl8169_tpc.RxDescArray] + mov eax, rtl8169_rxb + mov ecx, NUM_RX_DESC + @@: + mov [esi], eax + mov [edi+rtl8169_RxDesc.buf_addr], eax + sub [edi+rtl8169_RxDesc.buf_addr], OS_BASE ; shurf 28.09.2008 + mov [edi+rtl8169_RxDesc.status], RTL8169_DSB_OWNbit or RX_BUF_SIZE + add esi, 4 + add edi, sizeof.rtl8169_RxDesc + add eax, RX_BUF_SIZE + loop @b + + or [edi - sizeof.rtl8169_RxDesc + rtl8169_RxDesc.status], RTL8169_DSB_EORbit + + ret +endp + +proc rtl8169_hw_start + +; DEBUGF 1,"K : rtl8169_hw_start\n" + + ; Soft reset the chip + RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_Reset + ; Check that the chip has finished the reset + mov ecx, 1000 + @@: + RTL_R8 RTL8169_REG_ChipCmd + and al, RTL8169_CMD_Reset + jz @f + stdcall udelay, 10 + loop @b + @@: + RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Unlock + RTL_W8 RTL8169_REG_ChipCmd,RTL8169_CMD_TxEnb or RTL8169_CMD_RxEnb + RTL_W8 RTL8169_REG_ETThReg,ETTh + ; For gigabit rtl8169 + RTL_W16 RTL8169_REG_RxMaxSize,RxPacketMaxSize + ; Set Rx Config register + RTL_R32 RTL8169_REG_RxConfig + mov ecx, [rtl8169_tpc.chipset] + and eax, [rtl_chip_info + ecx * 8 + 4]; RxConfigMask + or eax, rtl8169_rx_config + RTL_W32 RTL8169_REG_RxConfig,eax + ; Set DMA burst size and Interframe Gap Time + RTL_W32 RTL8169_REG_TxConfig,(TX_DMA_BURST shl RTL8169_TXC_DMAShift) or (InterFrameGap shl RTL8169_TXC_InterFrameGapShift) + RTL_R16 RTL8169_REG_CPlusCmd + RTL_W16 RTL8169_REG_CPlusCmd,ax + + RTL_R16 RTL8169_REG_CPlusCmd + or ax, 1 shl 3 + cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02 + jne @f + cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03 + jne @f + or ax, 1 shl 14 +; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14\n" + jmp .set + @@:;DEBUGF 1,"K : Set MAC Reg C+CR Offset 0xE0: bit-3\n" + .set: + RTL_W16 RTL8169_REG_CPlusCmd,ax + +; RTL_W16 0xE2,0x1517 +; RTL_W16 0xE2,0x152a +; RTL_W16 0xE2,0x282a + RTL_W16 0xE2,0x0000 + + MOV [rtl8169_tpc.cur_rx],0 + push eax ; shurf 28.09.2008 + mov eax, [rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 + sub eax, OS_BASE ; shurf 28.09.2008 + RTL_W32 RTL8169_REG_TxDescStartAddr,eax ;[rtl8169_tpc.TxDescArray] ; shurf 28.09.2008 + mov eax, [rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 + sub eax, OS_BASE ; shurf 28.09.2008 + RTL_W32 RTL8169_REG_RxDescStartAddr,eax ;[rtl8169_tpc.RxDescArray] ; shurf 28.09.2008 + pop eax ; shurf 28.09.2008 + RTL_W8 RTL8169_REG_Cfg9346,RTL8169_CFG_9346_Lock + stdcall udelay, 10 + RTL_W32 RTL8169_REG_RxMissed,0 + call rtl8169_set_rx_mode + ; no early-rx interrupts + RTL_R16 RTL8169_REG_MultiIntr + and ax, 0xF000 + RTL_W16 RTL8169_REG_MultiIntr,ax + RTL_W16 RTL8169_REG_IntrMask,0 ; rtl8169_intr_mask + ret +endp + +proc udelay,msec:dword + push esi + mov esi, [msec] + call delay_ms + pop esi + ret +endp + +;*************************************************************************** +; Function +; rtl8169_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +; Destroyed registers +; eax, ebx, ecx, edx +; +;*************************************************************************** +proc rtl8169_probe + +; DEBUGF 1,"K : rtl8169_probe: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 + + call rtl8169_init_board + + mov ecx, MAC_ADDR_LEN + mov edx, [rtl8169_tpc.mmio_addr] + add edx, RTL8169_REG_MAC0 + xor ebx, ebx + ; Get MAC address. FIXME: read EEPROM + @@: + RTL_R8 dx + mov [node_addr+ebx], al + inc edx + inc ebx + loop @b + +; DEBUGF 1,"K : rtl8169_probe: MAC = %x-%x-%x-%x-%x-%x\n",[node_addr+0]:2,[node_addr+1]:2,[node_addr+2]:2,[node_addr+3]:2,[node_addr+4]:2,[node_addr+5]:2 + + ; Config PHY + stdcall rtl8169_hw_PHY_config +; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" + RTL_W8 0x82,0x01 + cmp [rtl8169_tpc.mcfg], MCFG_METHOD_03 + jae @f +; DEBUGF 1,"K : Set PCI Latency=0x40\n" +; stdcall pci_write_config_byte,PCI_LATENCY_TIMER,0x40 + @@: + cmp [rtl8169_tpc.mcfg], MCFG_METHOD_02 + jne @f +; DEBUGF 1,"K : Set MAC Reg C+CR Offset 0x82h = 0x01h\n" + RTL_W8 0x82,0x01 +; DEBUGF 1,"K : Set PHY Reg 0x0bh = 0x00h\n" + stdcall RTL8169_WRITE_GMII_REG, 0x0b, 0x0000 ; w 0x0b 15 0 0 + @@: + ; if TBI is not enabled + RTL_R8 RTL8169_REG_PHYstatus + test al, RTL8169_PHYS_TBI_Enable + jz .tbi_dis + stdcall RTL8169_READ_GMII_REG, RTL8169_PHY_AUTO_NEGO_REG + ; enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged + and eax, 0x0C1F + or eax, RTL8169_PHY_Cap_10_Half or RTL8169_PHY_Cap_10_Full or RTL8169_PHY_Cap_100_Half or RTL8169_PHY_Cap_100_Full + stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_AUTO_NEGO_REG, eax + ; enable 1000 Full Mode + stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_1000_CTRL_REG, RTL8169_PHY_Cap_1000_Full or RTL8169_PHY_Cap_1000_Half; rtl8168 + ; Enable auto-negotiation and restart auto-nigotiation + stdcall RTL8169_WRITE_GMII_REG, RTL8169_PHY_CTRL_REG, RTL8169_PHY_Enable_Auto_Nego or RTL8169_PHY_Restart_Auto_Nego + stdcall udelay, 100 + mov ecx, 10000 + ; wait for auto-negotiation process + @@: + dec ecx + jz @f + stdcall RTL8169_READ_GMII_REG, RTL8169_PHY_STAT_REG + stdcall udelay, 100 + test eax, RTL8169_PHY_Auto_Neco_Comp + jz @b + RTL_R8 RTL8169_REG_PHYstatus + jmp @f + .tbi_dis: + stdcall udelay, 100 + @@: + call rtl8169_reset + ret +endp + +;*************************************************************************** +; Function +; rt8169_reset +; Description +; Place the chip (ie, the ethernet card) into a virgin state +; Destroyed registers +; eax, ebx, ecx, edx +; +;*************************************************************************** +proc rtl8169_reset + +; DEBUGF 1,"K : rtl8169_reset: 0x%x : 0x%x 0x%x\n",[io_addr]:8,[pci_bus]:2,[pci_dev]:2 + + mov [rtl8169_tpc.TxDescArrays], rtl8169_tx_ring + ; Tx Desscriptor needs 256 bytes alignment + mov [rtl8169_tpc.TxDescArray], rtl8169_tx_ring + + mov [rtl8169_tpc.RxDescArrays], rtl8169_rx_ring + ; Rx Desscriptor needs 256 bytes alignment + mov [rtl8169_tpc.RxDescArray], rtl8169_rx_ring + + call rtl8169_init_ring + call rtl8169_hw_start + ; Construct a perfect filter frame with the mac address as first match + ; and broadcast for all others + mov edi, rtl8169_txb + or al, -1 + mov ecx, 192 + cld + rep stosb + + mov esi, node_addr + mov edi, rtl8169_txb + movsd + movsw + + mov eax, [pci_data] + mov [eth_status], eax + ret +endp + +;*************************************************************************** +; Function +; rtl8169_transmit +; Description +; Transmits a packet of data via the ethernet card +; d - edi - Pointer to 48 bit destination address +; t - bx - Type of packet +; s - ecx - size of packet +; p - esi - pointer to packet data +; Destroyed registers +; eax, edx, esi, edi +; +;*************************************************************************** +proc rtl8169_transmit + +; DEBUGF 1,"K : rtl8169_transmit\n" ;: 0x%x : 0x%x 0x%x 0x%x 0x%x\n",[io_addr]:8,edi,bx,ecx,esi + + push ecx edx esi + mov eax, MAX_ETH_FRAME_SIZE + mul [rtl8169_tpc.cur_tx] + mov esi, edi + ; point to the current txb incase multiple tx_rings are used + mov edi, [rtl8169_tpc.Tx_skbuff + eax * 4] + mov eax, edi + cld +; copy destination address + movsd + movsw +; copy source address + mov esi, node_addr + movsd + movsw +; copy packet type + mov [edi], bx + add edi, 2 +; copy the packet data + pop esi edx ecx + push ecx + shr ecx, 2 + rep movsd + pop ecx + push ecx + and ecx, 3 + rep movsb + +;!!! s += ETH_HLEN; +;!!! s &= 0x0FFF; +;!!! while (s < ETH_ZLEN) +;!!! ptxb[s++] = '\0'; + mov edi, eax + pop ecx + push eax + add ecx, ETH_HLEN + and ecx, 0x0FFF + xor al, al + add edi, ecx + @@: + cmp ecx, ETH_ZLEN + jae @f + stosb + inc ecx + jmp @b + @@: + pop eax + + mov ebx, eax + mov eax, sizeof.rtl8169_TxDesc + mul [rtl8169_tpc.cur_tx] + add eax, [rtl8169_tpc.TxDescArray] + xchg eax, ebx + mov [ebx + rtl8169_TxDesc.buf_addr], eax + sub [ebx + rtl8169_TxDesc.buf_addr], OS_BASE ; shurf 28.09.2008 + + mov eax, ecx + cmp eax, ETH_ZLEN + jae @f + mov eax, ETH_ZLEN + @@: + or eax, RTL8169_DSB_OWNbit or RTL8169_DSB_FSbit or RTL8169_DSB_LSbit + cmp [rtl8169_tpc.cur_tx], NUM_TX_DESC - 1 + jne @f + or eax, RTL8169_DSB_EORbit + @@: + mov [ebx + rtl8169_TxDesc.status], eax + + RTL_W8 RTL8169_REG_TxPoll,0x40 ; set polling bit + + inc [rtl8169_tpc.cur_tx] + and [rtl8169_tpc.cur_tx], NUM_TX_DESC - 1 + +;!!! to = currticks() + TX_TIMEOUT; +;!!! while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */ + mov ecx, TX_TIMEOUT / 10 + @@: + test [ebx + rtl8169_TxDesc.status], RTL8169_DSB_OWNbit + jnz @f + stdcall udelay, 10 + loop @b +; DEBUGF 1,"K : rtl8169_transmit: TX Time Out\n" + @@: + + ret +endp + +;*************************************************************************** +; Function +; rtl8169_poll +; +; Description +; Polls the ethernet card for a received packet +; Received data, if any, ends up in Ether_buffer +; Destroyed register(s) +; eax, edx, ecx +; +;*************************************************************************** +proc rtl8169_poll + +; DEBUGF 1,"K : rtl8169_poll\n" ;: 0x%x : none\n",[io_addr]:8 + + mov word[eth_rx_data_len], 0 + + mov eax, sizeof.rtl8169_RxDesc + mul [rtl8169_tpc.cur_rx] + add eax, [rtl8169_tpc.RxDescArray] + mov ebx, eax + +; DEBUGF 1,"K : rtl8169_RxDesc.status = 0x%x\n",[ebx + rtl8169_RxDesc.status] + + test [ebx + rtl8169_RxDesc.status], RTL8169_DSB_OWNbit; 0x80000600 + jnz .exit + +; DEBUGF 1,"K : rtl8169_tpc.cur_rx = %u\n",[rtl8169_tpc.cur_rx] + + ; h/w no longer present (hotplug?) or major error, bail + RTL_R16 RTL8169_REG_IntrStatus + +; DEBUGF 1,"K : IntrStatus = 0x%x\n",ax + + cmp ax, 0xFFFF + je .exit + + push eax + and ax, not (RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK) + RTL_W16 RTL8169_REG_IntrStatus,ax + + mov eax, [ebx + rtl8169_RxDesc.status] + +; DEBUGF 1,"K : RxDesc.status = 0x%x\n",eax + + test eax, RTL8169_SD_RxRES + jnz .else + and eax, 0x00001FFF +; jz .exit.pop + add eax, -4 + mov [eth_rx_data_len], ax + +; DEBUGF 1,"K : rtl8169_poll: data length = %u\n",ax + + push eax + mov ecx, eax + shr ecx, 2 + mov eax, [rtl8169_tpc.cur_rx] + mov edx, [rtl8169_tpc.RxBufferRing + eax * 4] + mov esi, edx + mov edi, Ether_buffer + cld + rep movsd + pop ecx + and ecx, 3 + rep movsb + + mov eax, RTL8169_DSB_OWNbit or RX_BUF_SIZE + cmp [rtl8169_tpc.cur_rx], NUM_RX_DESC - 1 + jne @f + or eax, RTL8169_DSB_EORbit + @@: + mov [ebx + rtl8169_RxDesc.status], eax + + mov [ebx + rtl8169_RxDesc.buf_addr], edx + sub [ebx + rtl8169_RxDesc.buf_addr], OS_BASE ; shurf 28.09.2008 + jmp @f + .else: +; DEBUGF 1,"K : rtl8169_poll: Rx Error\n" + ; FIXME: shouldn't I reset the status on an error + @@: + inc [rtl8169_tpc.cur_rx] + and [rtl8169_tpc.cur_rx], NUM_RX_DESC - 1 + .exit.pop: + pop eax + and ax, RTL8169_ISB_RxFIFOOver or RTL8169_ISB_RxOverflow or RTL8169_ISB_RxOK + RTL_W16 RTL8169_REG_IntrStatus,ax + .exit: + ret +endp + +proc rtl8169_cable + ret +endp diff --git a/kernel/trunk/network/eth_drv/drivers/sis900.inc b/kernel/trunk/network/eth_drv/drivers/sis900.inc index 8f160e0c7..52cd31e01 100644 --- a/kernel/trunk/network/eth_drv/drivers/sis900.inc +++ b/kernel/trunk/network/eth_drv/drivers/sis900.inc @@ -1,1158 +1,1166 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; SIS900.INC ;; -;; ;; -;; Ethernet driver for Menuet OS ;; -;; ;; -;; Version 0.4 26 April 2004 ;; -;; ;; -;; This driver is based on the SIS900 driver from ;; -;; the etherboot 5.0.6 project. The copyright statement is ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;; remaining parts Copyright 2004 Jason Delozier, ;; -;; cordata51@hotmail.com ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;; Updates: ;; -;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;******************************************************************** -; Interface -; SIS900_reset -; SIS900_probe -; SIS900_poll -; SIS900_transmit -; -;******************************************************************** -;******************************************************************** -; Comments: -; Known to work with the following SIS900 ethernet cards: -; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91 -; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x90 -; -; If your card is not listed, try it and let me know if it -; functions properly and it will be aded to the list. If not -; we may be able to add support for it. -; -; How To Use: -; Add the following lines to Ethernet.inc in their appropriate locations -; -; include "Sis900.INC" -; dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, -; SIS900_transmit -; dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, -; SIS900_transmit ;untested -; -; ToDo: -; - Enable MII interface for reading speed -; and duplex settings. -; -; - Update Poll routine to support packet fragmentation. -; -; - Add additional support for other sis900 based cards -; -;******************************************************************** - -; comment the next line out if you don't want debug info printed -; on the debug board. This option adds a lot of bytes to the driver -; so it's worth to comment it out. -; SIS900_DEBUG equ 1 - - -;* buffers and descriptors -cur_rx db 0 -NUM_RX_DESC equ 4 ;* Number of RX descriptors * -NUM_TX_DESC equ 1 ;* Number of TX descriptors * -RX_BUFF_SZ equ 1520 ;* Buffer size for each Rx buffer * -TX_BUFF_SZ equ 1516 ;* Buffer size for each Tx buffer * - -uglobal -align 4 -txd: times (3 * NUM_TX_DESC) dd 0 -rxd: times (3 * NUM_RX_DESC) dd 0 -endg - -txb equ eth_data_start -rxb equ txb + (NUM_TX_DESC * TX_BUFF_SZ) -SIS900_ETH_ALEN equ 6 ;* Size of Ethernet address * -SIS900_ETH_HLEN equ 14 ;* Size of ethernet header * -SIS900_ETH_ZLEN equ 60 ;* Minimum packet length * -SIS900_DSIZE equ 0x00000fff -SIS900_CRC_SIZE equ 4 -SIS900_RFADDR_shift equ 16 -;SIS900 Symbolic offsets to registers. - SIS900_cr equ 0x0 ; Command Register - SIS900_cfg equ 0x4 ; Configuration Register - SIS900_mear equ 0x8 ; EEPROM Access Register - SIS900_ptscr equ 0xc ; PCI Test Control Register - SIS900_isr equ 0x10 ; Interrupt Status Register - SIS900_imr equ 0x14 ; Interrupt Mask Register - SIS900_ier equ 0x18 ; Interrupt Enable Register - SIS900_epar equ 0x18 ; Enhanced PHY Access Register - SIS900_txdp equ 0x20 ; Transmit Descriptor Pointer Register - SIS900_txcfg equ 0x24 ; Transmit Configuration Register - SIS900_rxdp equ 0x30 ; Receive Descriptor Pointer Register - SIS900_rxcfg equ 0x34 ; Receive Configuration Register - SIS900_flctrl equ 0x38 ; Flow Control Register - SIS900_rxlen equ 0x3c ; Receive Packet Length Register - SIS900_rfcr equ 0x48 ; Receive Filter Control Register - SIS900_rfdr equ 0x4C ; Receive Filter Data Register - SIS900_pmctrl equ 0xB0 ; Power Management Control Register - SIS900_pmer equ 0xB4 ; Power Management Wake-up Event Register -;SIS900 Command Register Bits - SIS900_RELOAD equ 0x00000400 - SIS900_ACCESSMODE equ 0x00000200 - SIS900_RESET equ 0x00000100 - SIS900_SWI equ 0x00000080 - SIS900_RxRESET equ 0x00000020 - SIS900_TxRESET equ 0x00000010 - SIS900_RxDIS equ 0x00000008 - SIS900_RxENA equ 0x00000004 - SIS900_TxDIS equ 0x00000002 - SIS900_TxENA equ 0x00000001 -;SIS900 Configuration Register Bits - SIS900_DESCRFMT equ 0x00000100 ; 7016 specific - SIS900_REQALG equ 0x00000080 - SIS900_SB equ 0x00000040 - SIS900_POW equ 0x00000020 - SIS900_EXD equ 0x00000010 - SIS900_PESEL equ 0x00000008 - SIS900_LPM equ 0x00000004 - SIS900_BEM equ 0x00000001 - SIS900_RND_CNT equ 0x00000400 - SIS900_FAIR_BACKOFF equ 0x00000200 - SIS900_EDB_MASTER_EN equ 0x00002000 -;SIS900 Eeprom Access Reigster Bits - SIS900_MDC equ 0x00000040 - SIS900_MDDIR equ 0x00000020 - SIS900_MDIO equ 0x00000010 ; 7016 specific - SIS900_EECS equ 0x00000008 - SIS900_EECLK equ 0x00000004 - SIS900_EEDO equ 0x00000002 - SIS900_EEDI equ 0x00000001 -;SIS900 TX Configuration Register Bits - SIS900_ATP equ 0x10000000 ;Automatic Transmit Padding - SIS900_MLB equ 0x20000000 ;Mac Loopback Enable - SIS900_HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup) - SIS900_CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du -;SIS900 RX Configuration Register Bits - SIS900_AJAB equ 0x08000000 ; - SIS900_ATX equ 0x10000000 ;Accept Transmit Packets - SIS900_ARP equ 0x40000000 ;accept runt packets (<64bytes) - SIS900_AEP equ 0x80000000 ;accept error packets -;SIS900 Interrupt Reigster Bits - SIS900_WKEVT equ 0x10000000 - SIS900_TxPAUSEEND equ 0x08000000 - SIS900_TxPAUSE equ 0x04000000 - SIS900_TxRCMP equ 0x02000000 - SIS900_RxRCMP equ 0x01000000 - SIS900_DPERR equ 0x00800000 - SIS900_SSERR equ 0x00400000 - SIS900_RMABT equ 0x00200000 - SIS900_RTABT equ 0x00100000 - SIS900_RxSOVR equ 0x00010000 - SIS900_HIBERR equ 0x00008000 - SIS900_SWINT equ 0x00001000 - SIS900_MIBINT equ 0x00000800 - SIS900_TxURN equ 0x00000400 - SIS900_TxIDLE equ 0x00000200 - SIS900_TxERR equ 0x00000100 - SIS900_TxDESC equ 0x00000080 - SIS900_TxOK equ 0x00000040 - SIS900_RxORN equ 0x00000020 - SIS900_RxIDLE equ 0x00000010 - SIS900_RxEARLY equ 0x00000008 - SIS900_RxERR equ 0x00000004 - SIS900_RxDESC equ 0x00000002 - SIS900_RxOK equ 0x00000001 -;SIS900 Interrupt Enable Reigster Bits - SIS900_IE equ 0x00000001 -;SIS900 Revision ID - SIS900B_900_REV equ 0x03 - SIS630A_900_REV equ 0x80 - SIS630E_900_REV equ 0x81 - SIS630S_900_REV equ 0x82 - SIS630EA1_900_REV equ 0x83 - SIS630ET_900_REV equ 0x84 - SIS635A_900_REV equ 0x90 - SIS900_960_REV equ 0x91 -;SIS900 Receive Filter Control Register Bits - SIS900_RFEN equ 0x80000000 - SIS900_RFAAB equ 0x40000000 - SIS900_RFAAM equ 0x20000000 - SIS900_RFAAP equ 0x10000000 - SIS900_RFPromiscuous equ 0x70000000 -;SIS900 Reveive Filter Data Mask - SIS900_RFDAT equ 0x0000FFFF -;SIS900 Eeprom Address - SIS900_EEPROMSignature equ 0x00 - SIS900_EEPROMVendorID equ 0x02 - SIS900_EEPROMDeviceID equ 0x03 - SIS900_EEPROMMACAddr equ 0x08 - SIS900_EEPROMChecksum equ 0x0b -;The EEPROM commands include the alway-set leading bit. -;SIS900 Eeprom Command - SIS900_EEread equ 0x0180 - SIS900_EEwrite equ 0x0140 - SIS900_EEerase equ 0x01C0 - SIS900_EEwriteEnable equ 0x0130 - SIS900_EEwriteDisable equ 0x0100 - SIS900_EEeraseAll equ 0x0120 - SIS900_EEwriteAll equ 0x0110 - SIS900_EEaddrMask equ 0x013F - SIS900_EEcmdShift equ 16 -;For SiS962 or SiS963, request the eeprom software access - SIS900_EEREQ equ 0x00000400 - SIS900_EEDONE equ 0x00000200 - SIS900_EEGNT equ 0x00000100 -;General Varibles - SIS900_pci_revision: db 0 - SIS900_Status dd 0x03000000 -sis900_specific_table: -; dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0 -; dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0 - dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0 - dd SIS630EA1_900_REV,Get_Mac_SIS635_900_REV,0 - dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN - dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0 - dd SIS900_960_REV,SIS960_get_mac_addr,0 - dd SIS900B_900_REV,SIS900_get_mac_addr,0 - dd 0,0,0,0 ; end of list -sis900_get_mac_func: dd 0 -sis900_special_func: dd 0 -sis900_table_entries: db 8 - -;*************************************************************************** -; Function -; SIS900_probe -; Description -; Searches for an ethernet card, enables it and clears the rx buffer -; If a card was found, it enables the ethernet -> TCPIP link -;not done - still need to probe mii transcievers -;*************************************************************************** -if defined SIS900_DEBUG -SIS900_Debug_Str_Unsupported db 'Sorry your card is unsupported ',13,10,0 -end if -SIS900_probe: -;******Wake Up Chip******* - mov al, 4 - mov bh, [pci_dev] - mov ecx, 0 - mov ah, [pci_bus] - mov bl, 0x40 - call pci_write_reg -;*******Set some PCI Settings********* - call SIS900_adjust_pci_device -;*****Get Card Revision****** - mov al, 1 ;one byte to read - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, 0x08 ;Revision Register - call pci_read_reg - mov [SIS900_pci_revision], al ;save the revision for later use -;****** Look up through the sis900_specific_table - mov esi,sis900_specific_table -.probe_loop: - cmp dword [esi],0 ; Check if we reached end of the list - je .probe_loop_failed - cmp al,[esi] ; Check if revision is OK - je .probe_loop_ok - add esi,12 ; Advance to next entry - jmp .probe_loop -.probe_loop_failed: - jmp SIS900_Probe_Unsupported -;*********Find Get Mac Function********* -.probe_loop_ok: - mov eax,[esi+4] ; Get pointer to "get MAC" function - mov [sis900_get_mac_func],eax - mov eax,[esi+8] ; Get pointer to special initialization fn - mov [sis900_special_func],eax -;******** Get MAC ******** - call dword [sis900_get_mac_func] -;******** Call special initialization fn if requested ******** - cmp dword [sis900_special_func],0 - je .no_special_init - call dword [sis900_special_func] -.no_special_init: -;******** Set table entries ******** - mov al,[SIS900_pci_revision] - cmp al,SIS635A_900_REV - jae .ent16 - cmp al,SIS900B_900_REV - je .ent16 - jmp .ent8 -.ent16: - mov byte [sis900_table_entries],16 -.ent8: -;*******Probe for mii transceiver******* -;TODO!!********************* -;*******Initialize Device******* - call sis900_init - ret - -SIS900_Probe_Unsupported: -if defined SIS900_DEBUG - mov esi, SIS900_Debug_Str_Unsupported - call sys_msg_board_str -end if - ret -;*************************************************************************** -; Function: sis900_init -; -; Description: resets the ethernet controller chip and various -; data structures required for sending and receiving packets. -; -; Arguments: -; -; returns: none -;not done -;*************************************************************************** -sis900_init: - call SIS900_reset ;Done - call SIS900_init_rxfilter ;Done - call SIS900_init_txd ;Done - call SIS900_init_rxd ;Done - call SIS900_set_rx_mode ;done - call SIS900_set_tx_mode - ;call SIS900_check_mode - ret - -;*************************************************************************** -; Function -; SIS900_reset -; Description -; disables interrupts and soft resets the controller chip -; -;done+ -;*************************************************************************** -if defined SIS900_DEBUG - SIS900_Debug_Reset_Failed db 'Reset Failed ',0 -end if -SIS900_reset: - ;******Disable Interrupts and reset Receive Filter******* - mov ebp, [io_addr] ; base address - xor eax, eax ; 0 to initialize - lea edx,[ebp+SIS900_ier] - out dx, eax ; Write 0 to location - lea edx,[ebp+SIS900_imr] - out dx, eax ; Write 0 to location - lea edx,[ebp+SIS900_rfcr] - out dx, eax ; Write 0 to location - ;*******Reset Card*********************************************** - lea edx,[ebp+SIS900_cr] - in eax, dx ; Get current Command Register - or eax, SIS900_RESET ; set flags - or eax, SIS900_RxRESET ; - or eax, SIS900_TxRESET ; - out dx, eax ; Write new Command Register - ;*******Wait Loop************************************************ - lea edx,[ebp+SIS900_isr] - mov ecx, [SIS900_Status] ; Status we would like to see from card - mov ebx, 2001 ; only loop 1000 times -SIS900_Wait: - dec ebx ; 1 less loop - jz SIS900_DoneWait_e ; 1000 times yet? - in eax, dx ; move interrup status to eax - and eax, ecx - xor ecx, eax - jz SIS900_DoneWait - jmp SIS900_Wait -SIS900_DoneWait_e: -if defined SIS900_DEBUG - mov esi, SIS900_Debug_Reset_Failed - call sys_msg_board_str -end if -SIS900_DoneWait: - ;*******Set Configuration Register depending on Card Revision******** - lea edx,[ebp+SIS900_cfg] - mov eax, SIS900_PESEL ; Configuration Register Bit - mov bl, [SIS900_pci_revision] ; card revision - mov cl, SIS635A_900_REV ; Check card revision - cmp bl, cl - je SIS900_RevMatch - mov cl, SIS900B_900_REV ; Check card revision - cmp bl, cl - je SIS900_RevMatch - out dx, eax ; no revision match - jmp SIS900_Reset_Complete -SIS900_RevMatch: ; Revision match - or eax, SIS900_RND_CNT ; Configuration Register Bit - out dx, eax -SIS900_Reset_Complete: - mov eax, [pci_data] - mov [eth_status], eax - ret - -;*************************************************************************** -; Function: sis_init_rxfilter -; -; Description: sets receive filter address to our MAC address -; -; Arguments: -; -; returns: -;done+ -;*************************************************************************** -SIS900_init_rxfilter: - ;****Get Receive Filter Control Register ******** - mov ebp, [io_addr] ; base address - lea edx,[ebp+SIS900_rfcr] - in eax, dx ; get register - push eax - ;****disable packet filtering before setting filter******* - mov eax, SIS900_RFEN ;move receive filter enable flag - not eax ;1s complement - pop ebx ;and with our saved register - and eax, ebx ;disable receiver - push ebx ;save filter for another use - out dx, eax ;set receive disabled - ;********load MAC addr to filter data register********* - xor ecx, ecx -SIS900_RXINT_Mac_Write: - ;high word of eax tells card which mac byte to write - mov eax, ecx - lea edx,[ebp+SIS900_rfcr] - shl eax, 16 ; - out dx, eax ; - lea edx,[ebp+SIS900_rfdr] - mov ax, word [node_addr+ecx*2] ; Get Mac ID word - out dx, ax ; Send Mac ID - inc cl ; send next word - cmp cl, 3 ; more to send? - jne SIS900_RXINT_Mac_Write - ;********enable packet filitering ***** - pop eax ;old register value - lea edx,[ebp+SIS900_rfcr] - or eax, SIS900_RFEN ;enable filtering - out dx, eax ;set register - ret - -;*************************************************************************** -;* -;* Function: sis_init_txd -;* -;* Description: initializes the Tx descriptor -;* -;* Arguments: -;* -;* returns: -;*done -;*************************************************************************** -SIS900_init_txd: - ;********** initialize TX descriptor ************** - mov [txd], dword 0 ;put link to next descriptor in link field - mov [txd+4],dword 0 ;clear status field - mov [txd+8], dword txb - OS_BASE ;save address to buffer ptr field - ;*************** load Transmit Descriptor Register *************** - mov dx, [io_addr] ; base address - add dx, SIS900_txdp ; TX Descriptor Pointer - mov eax, txd - OS_BASE ; First Descriptor - out dx, eax ; move the pointer - ret - -;*************************************************************************** -;* Function: sis_init_rxd -;* -;* Description: initializes the Rx descriptor ring -;* -;* Arguments: -;* -;* Returns: -;*done -;*************************************************************************** -SIS900_init_rxd: - xor ecx,ecx - mov [cur_rx], cl ;Set cuurent rx discriptor to 0 - ;******** init RX descriptors ******** -SIS900_init_rxd_Loop: - mov eax, ecx ;current descriptor - imul eax, 12 ; - mov ebx, ecx ;determine next link descriptor - inc ebx ; - cmp ebx, NUM_RX_DESC ; - jne SIS900_init_rxd_Loop_0 ; - xor ebx, ebx ; -SIS900_init_rxd_Loop_0: ; - imul ebx, 12 ; - add ebx, rxd - OS_BASE ; - mov [rxd+eax], ebx ;save link to next descriptor - mov [rxd+eax+4],dword RX_BUFF_SZ ;status bits init to buf size - mov ebx, ecx ;find where the buf is located - imul ebx,RX_BUFF_SZ ; - add ebx, rxb - OS_BASE ; - mov [rxd+eax+8], ebx ;save buffer pointer - inc ecx ;next descriptor - cmp ecx, NUM_RX_DESC ; - jne SIS900_init_rxd_Loop ; - ;********* load Receive Descriptor Register with address of first - ; descriptor********* - mov dx, [io_addr] - add dx, SIS900_rxdp - mov eax, rxd - OS_BASE - out dx, eax - ret - -;*************************************************************************** -;* Function: sis900_set_tx_mode -;* -;* Description: -;* sets the transmit mode to allow for full duplex -;* -;* -;* Arguments: -;* -;* Returns: -;* -;* Comments: -;* If you are having problems transmitting packet try changing the -;* Max DMA Burst, Possible settings are as follows: -;* 0x00000000 = 512 bytes -;* 0x00100000 = 4 bytes -;* 0x00200000 = 8 bytes -;* 0x00300000 = 16 bytes -;* 0x00400000 = 32 bytes -;* 0x00500000 = 64 bytes -;* 0x00600000 = 128 bytes -;* 0x00700000 = 256 bytes -;*************************************************************************** -SIS900_set_tx_mode: - mov ebp,[io_addr] - lea edx,[ebp+SIS900_cr] - in eax, dx ; Get current Command Register - or eax, SIS900_TxENA ;Enable Receive - out dx, eax - lea edx,[ebp+SIS900_txcfg]; Transmit config Register offset - mov eax, SIS900_ATP ;allow automatic padding - or eax, SIS900_HBI ;allow heartbeat ignore - or eax, SIS900_CSI ;allow carrier sense ignore - or eax, 0x00600000 ;Max DMA Burst - or eax, 0x00000100 ;TX Fill Threshold - or eax, 0x00000020 ;TX Drain Threshold - out dx, eax - ret - -;*************************************************************************** -;* Function: sis900_set_rx_mode -;* -;* Description: -;* sets the receive mode to accept all broadcast packets and packets -;* with our MAC address, and reject all multicast packets. Also allows -;* full-duplex -;* -;* Arguments: -;* -;* Returns: -;* -;* Comments: -;* If you are having problems receiving packet try changing the -;* Max DMA Burst, Possible settings are as follows: -;* 0x00000000 = 512 bytes -;* 0x00100000 = 4 bytes -;* 0x00200000 = 8 bytes -;* 0x00300000 = 16 bytes -;* 0x00400000 = 32 bytes -;* 0x00500000 = 64 bytes -;* 0x00600000 = 128 bytes -;* 0x00700000 = 256 bytes -;*************************************************************************** -SIS900_mc_filter: times 16 dw 0 -SIS900_set_rx_mode: - mov ebp,[io_addr] - ;**************update Multicast Hash Table in Receive Filter - mov ebx, 0xffff - xor cl, cl -SIS900_set_rx_mode_Loop: - mov eax, ecx - shl eax, 1 - mov [SIS900_mc_filter+eax], bx - lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Reg offset - mov eax, 4 ;determine table entry - add al, cl - shl eax, 16 - out dx, eax ;tell card which entry to modify - lea edx,[ebp+SIS900_rfdr] ; Receive Filter Control Reg offset - mov eax, ebx ;entry value - out dx, ax ;write value to table in card - inc cl ;next entry - cmp cl,[sis900_table_entries] ; - jl SIS900_set_rx_mode_Loop - ;*******Set Receive Filter Control Register************* - lea edx,[ebp+SIS900_rfcr] ; Receive Filter Control Register offset - mov eax, SIS900_RFAAB ;accecpt all broadcast packets - or eax, SIS900_RFAAM ;accept all multicast packets - or eax, SIS900_RFAAP ;Accept all packets - or eax, SIS900_RFEN ;enable receiver filter - out dx, eax - ;******Enable Receiver************ - lea edx,[ebp+SIS900_cr] ; Command Register offset - in eax, dx ; Get current Command Register - or eax, SIS900_RxENA ;Enable Receive - out dx, eax - ;*********Set - lea edx,[ebp+SIS900_rxcfg] ; Receive Config Register offset - mov eax, SIS900_ATX ;Accept Transmit Packets - ; (Req for full-duplex and PMD Loopback) - or eax, 0x00600000 ;Max DMA Burst - or eax, 0x00000002 ;RX Drain Threshold, 8X8 bytes or 64bytes - out dx, eax ; - ret - -;*************************************************************************** -; * SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model -; * @pci_dev: the sis900 pci device -; * @net_dev: the net device to get address for -; * -; * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM -; * is shared by -; * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first -; * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access -; * by LAN, otherwise is not. After MAC address is read from EEPROM, send -; * EEDONE signal to refuse EEPROM access by LAN. -; * The EEPROM map of SiS962 or SiS963 is different to SiS900. -; * The signature field in SiS962 or SiS963 spec is meaningless. -; * MAC address is read into @net_dev->dev_addr. -; *done -;* -;* Return 0 is EAX = failure -;*Done+ -;*************************************************************************** -if defined SIS900_DEBUG -SIS900_Debug_Str_GetMac_Start db 'Attempting to get SIS900 Mac ID: ',13,10,0 -SIS900_Debug_Str_GetMac_Failed db 'Access to EEprom Failed',13,10,0 -SIS900_Debug_Str_GetMac_Address db 'Your Mac ID is: ',0 -SIS900_Debug_Str_GetMac_Address2 db 'Your SIS96x Mac ID is: ',0 -end if -SIS960_get_mac_addr: - mov ebp,[io_addr] - ;**********Send Request for eeprom access********************* - lea edx,[ebp+SIS900_mear] ; Eeprom access register - mov eax, SIS900_EEREQ ; Request access to eeprom - out dx, eax ; Send request - xor ebx,ebx ; - ;******Loop 4000 times and if access not granted error out***** -SIS96X_Get_Mac_Wait: - in eax, dx ;get eeprom status - and eax, SIS900_EEGNT ;see if eeprom access granted flag is set - jnz SIS900_Got_EEP_Access ;if it is, go access the eeprom - inc ebx ;else keep waiting - cmp ebx, 4000 ;have we tried 4000 times yet? - jl SIS96X_Get_Mac_Wait ;if not ask again - xor eax, eax ;return zero in eax indicating failure - ;*******Debug ********************** -if defined SIS900_DEBUG - mov esi,SIS900_Debug_Str_GetMac_Failed - call sys_msg_board_str -end if - jmp SIS960_get_mac_addr_done - ;**********EEprom access granted, read MAC from card************* -SIS900_Got_EEP_Access: - ; zero based so 3-16 bit reads will take place - mov ecx, 2 -SIS96x_mac_read_loop: - mov eax, SIS900_EEPROMMACAddr ;Base Mac Address - add eax, ecx ;Current Mac Byte Offset - push ecx - call sis900_read_eeprom ;try to read 16 bits - pop ecx - mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID varible - dec ecx ;one less word to read - jns SIS96x_mac_read_loop ;if more read more - mov eax, 1 ;return non-zero indicating success - ;*******Debug Print MAC ID to debug window********************** -if defined SIS900_DEBUG - mov esi,SIS900_Debug_Str_GetMac_Address2 - call sys_msg_board_str - mov edx, node_addr - call Create_Mac_String -end if - ;**********Tell EEPROM We are Done Accessing It********************* -SIS960_get_mac_addr_done: - lea edx,[ebp+SIS900_mear] ; Eeprom access register - mov eax, SIS900_EEDONE ;tell eeprom we are done - out dx,eax - ret -;*************************************************************************** -;* sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model -;* @pci_dev: the sis900 pci device -;* @net_dev: the net device to get address for -;* -;* Older SiS900 and friends, use EEPROM to store MAC address. -;* MAC address is read from read_eeprom() into @net_dev->dev_addr. -;* done/untested -;*************************************************************************** -SIS900_get_mac_addr: - ;*******Debug ********************** -if defined SIS900_DEBUG - mov esi,SIS900_Debug_Str_GetMac_Start - call sys_msg_board_str -end if - ;******** check to see if we have sane EEPROM ******* - mov eax, SIS900_EEPROMSignature ;Base Eeprom Signature - call sis900_read_eeprom ;try to read 16 bits - cmp ax, 0xffff - je SIS900_Bad_Eeprom - cmp ax, 0 - je SIS900_Bad_Eeprom - ;**************Read MacID************** - ; zero based so 3-16 bit reads will take place - mov ecx, 2 -SIS900_mac_read_loop: - mov eax, SIS900_EEPROMMACAddr ;Base Mac Address - add eax, ecx ;Current Mac Byte Offset - push ecx - call sis900_read_eeprom ;try to read 16 bits - pop ecx - mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID storage - dec ecx ;one less word to read - jns SIS900_mac_read_loop ;if more read more - mov eax, 1 ;return non-zero indicating success - ;*******Debug Print MAC ID to debug window********************** -if defined SIS900_DEBUG - mov esi,SIS900_Debug_Str_GetMac_Address - call sys_msg_board_str - mov edx, node_addr - call Create_Mac_String -end if - ret - -SIS900_Bad_Eeprom: - xor eax, eax - ;*******Debug ********************** -if defined SIS900_DEBUG - mov esi,SIS900_Debug_Str_GetMac_Failed - call sys_msg_board_str -end if - ret -;*************************************************************************** -;* Get_Mac_SIS635_900_REV: - Get MAC address for model 635 -;* -;* -;*************************************************************************** -Get_Mac_SIS635_900_REV: -if defined SIS900_DEBUG - mov esi,SIS900_Debug_Str_GetMac_Start - call sys_msg_board_str -end if - mov ebp,[io_addr] - lea edx,[ebp+SIS900_rfcr] - in eax,dx - mov edi,eax ; EDI=rfcrSave - lea edx,[ebp+SIS900_cr] - or eax,SIS900_RELOAD - out dx,eax - xor eax,eax - out dx,eax - ; Disable packet filtering before setting filter - lea edx,[ebp+SIS900_rfcr] - mov eax,edi - and edi,not SIS900_RFEN - out dx,eax - ; Load MAC to filter data register - xor ecx,ecx - mov esi,node_addr -.get_mac_loop: - lea edx,[ebp+SIS900_rfcr] - mov eax,ecx - shl eax,SIS900_RFADDR_shift - out dx,eax - lea edx,[ebp+SIS900_rfdr] - in eax,dx - mov [esi],ax - add esi,2 - inc ecx - cmp ecx,3 - jne .get_mac_loop - ; Enable packet filtering - ;lea edx,[ebp+SIS900_rfcr] - ;mov eax,edi - ;or eax,SIS900_RFEN - ;out dx, eax - ;*******Debug Print MAC ID to debug window********************** -if defined SIS900_DEBUG - mov esi,SIS900_Debug_Str_GetMac_Address - call sys_msg_board_str - mov edx, node_addr - call Create_Mac_String -end if - ret -;*************************************************************************** -;* Function: sis900_read_eeprom -;* -;* Description: reads and returns a given location from EEPROM -;* -;* Arguments: eax - location: requested EEPROM location -;* -;* Returns: eax : contents of requested EEPROM location -;* -; Read Serial EEPROM through EEPROM Access Register, Note that location is -; in word (16 bits) unit */ -;done+ -;*************************************************************************** -sis900_read_eeprom: - push esi - push edx - push ecx - push ebx - mov ebp,[io_addr] - mov ebx, eax ;location of Mac byte to read - or ebx, SIS900_EEread ; - lea edx,[ebp+SIS900_mear] ; Eeprom access register - xor eax, eax ; start send - out dx,eax - call SIS900_Eeprom_Delay_1 - mov eax, SIS900_EECLK - out dx, eax - call SIS900_Eeprom_Delay_1 - ;************ Shift the read command (9) bits out. ********* - mov cl, 8 ; -sis900_read_eeprom_Send: - mov eax, 1 - shl eax, cl - and eax, ebx - jz SIS900_Read_Eeprom_8 - mov eax, 9 - jmp SIS900_Read_Eeprom_9 -SIS900_Read_Eeprom_8: - mov eax, 8 -SIS900_Read_Eeprom_9: - out dx, eax - call SIS900_Eeprom_Delay_1 - or eax, SIS900_EECLK - out dx, eax - call SIS900_Eeprom_Delay_1 - cmp cl, 0 - je sis900_read_eeprom_Send_Done - dec cl - jmp sis900_read_eeprom_Send - ;********************* -sis900_read_eeprom_Send_Done: - mov eax, SIS900_EECS ; - out dx, eax - call SIS900_Eeprom_Delay_1 - ;********** Read 16-bits of data in *************** - mov cx, 16 ;16 bits to read -sis900_read_eeprom_Send2: - mov eax, SIS900_EECS - out dx, eax - call SIS900_Eeprom_Delay_1 - or eax, SIS900_EECLK - out dx, eax - call SIS900_Eeprom_Delay_1 - in eax, dx - shl ebx, 1 - and eax, SIS900_EEDO - jz SIS900_Read_Eeprom_0 - or ebx, 1 -SIS900_Read_Eeprom_0: - dec cx - jnz sis900_read_eeprom_Send2 - ;************** Terminate the EEPROM access. ************** - xor eax, eax - out dx, eax - call SIS900_Eeprom_Delay_1 - mov eax, SIS900_EECLK - out dx, eax - mov eax, ebx - and eax, 0x0000ffff ;return only 16 bits - pop ebx - pop ecx - pop edx - pop esi - ret -;*************************************************************************** -; Function -; SIS900_Eeprom_Delay_1 -; Description -; -; -; -; -;*************************************************************************** -SIS900_Eeprom_Delay_1: - push eax - in eax, dx - pop eax - ret - -;*************************************************************************** -; Function -; SIS900_poll -; Description -; polls card to see if there is a packet waiting -; -; Currently only supports one descriptor per packet, if packet is fragmented -; between multiple descriptors you will lose part of the packet -;*************************************************************************** -if defined SIS900_DEBUG -SIS900_Debug_Pull_Packet_good db 'Good Packet Waiting: ',13,10,0 -SIS900_Debug_Pull_Bad_Packet_Status db 'Bad Packet Waiting: Status',13,10,0 -SIS900_Debug_Pull_Bad_Packet_Size db 'Bad Packet Waiting: Size',13,10,0 -end if -SIS900_poll: - ;**************Get Status ************** - xor eax, eax ;get RX_Status - mov [eth_rx_data_len], ax - mov al, [cur_rx] ;find current discriptor - imul eax, 12 ; - mov ecx, [rxd+eax+4] ; get receive status - ;**************Check Status ************** - mov ebx, ecx ;move status - ;Check RX_Status to see if packet is waiting - and ebx, 0x80000000 - jnz SIS900_poll_IS_packet - ret - ;**********There is a packet waiting check it for errors************** -SIS900_poll_IS_packet: - mov ebx, ecx ;move status - and ebx, 0x67C0000 ;see if there are any errors - jnz SIS900_Poll_Error_Status - ;**************Check size of packet************* - and ecx, SIS900_DSIZE ;get packet size minus CRC - cmp cx, SIS900_CRC_SIZE - ;make sure packet contains data - jle SIS900_Poll_Error_Size - ;*******Copy Good Packet to receive buffer****** - sub cx, SIS900_CRC_SIZE ;dont want crc - mov word [eth_rx_data_len], cx ;save size of packet - ;**********Continue copying packet**************** - push ecx - ; first copy dword-wise, divide size by 4 - shr ecx, 2 - mov esi, [rxd+eax+8] ; set source - add esi, OS_BASE ; get linear address - mov edi, Ether_buffer ; set destination - cld ; clear direction - rep movsd ; copy the dwords - pop ecx - and ecx, 3 ; - rep movsb - ;********Debug, tell user we have a good packet************* -if defined SIS900_DEBUG - mov esi, SIS900_Debug_Pull_Packet_good - call sys_msg_board_str -end if - jmp SIS900_Poll_Cnt ; - ;*************Error occured let user know through debug window*********** -SIS900_Poll_Error_Status: -if defined SIS900_DEBUG - mov esi, SIS900_Debug_Pull_Bad_Packet_Status - call sys_msg_board_str -end if - jmp SIS900_Poll_Cnt -SIS900_Poll_Error_Size: -if defined SIS900_DEBUG - mov esi, SIS900_Debug_Pull_Bad_Packet_Size - call sys_msg_board_str -end if - ;*************Increment to next available descriptor************** -SIS900_Poll_Cnt: - ;Reset status, allow ethernet card access to descriptor - mov ecx, RX_BUFF_SZ - mov [rxd+eax+4], ecx ; - inc [cur_rx] ;get next descriptor - and [cur_rx],3 ;only 4 descriptors 0-3 - ;******Enable Receiver************ - mov ebp, [io_addr] ; Base Address - lea edx,[ebp+SIS900_cr] ; Command Register offset - in eax, dx ; Get current Command Register - or eax, SIS900_RxENA ;Enable Receive - out dx, eax - ret -;*************************************************************************** -; Function -; SIS900_transmit -; Description -; Transmits a packet of data via the ethernet card -; Pointer to 48 bit destination address in edi -; Type of packet in bx -; size of packet in ecx -; pointer to packet data in esi -; -; only one transmit descriptor is used -; -;*************************************************************************** -if defined SIS900_DEBUG -SIS900_Debug_Transmit_Packet db 'Transmitting Packet: ',13,10,0 -SIS900_Debug_Transmit_Packet_Err db 'Transmitting Packet Error: ',13,10,0 -end if -str1 db 'Transmitting packet:',13,10,0 -str2 db ' ',0 -SIS900_transmit: - mov ebp, [io_addr] ; Base Address - ;******** Stop the transmitter ******** - lea edx,[ebp+SIS900_cr] ; Command Register offset - in eax, dx ; Get current Command Register - or eax, SIS900_TxDIS ; Disable Transmitter - out dx, eax - ;*******load Transmit Descriptor Register ******* - lea edx,[ebp+SIS900_txdp] - mov eax, txd - OS_BASE - out dx, eax - ;******* copy packet to descriptor******* - push esi - mov esi, edi ;copy destination addess - mov edi, txb - cld - movsd - movsw - mov esi, node_addr ;copy my mac address - movsd - movsw - mov [edi], bx ;copy packet type - add edi, 2 - pop esi ;restore pointer to source of packet - push ecx ;save packet size - shr ecx, 2 ;divide by 4, size in bytes send in dwords - rep movsd ;copy data to decriptor - pop ecx ;restore packet size - push ecx ;save packet size - and ecx, 3 ;last three bytes if not a multiple of 4 - rep movsb - ;**************set length tag************** - pop ecx ;restore packet size - add ecx, SIS900_ETH_HLEN ;add header to length - and ecx, SIS900_DSIZE ; - ;**************pad to minimum packet size **************not needed - ;cmp ecx, SIS900_ETH_ZLEN - ;jge SIS900_transmit_Size_Ok - ;push ecx - ;mov ebx, SIS900_ETH_ZLEN - ;sub ebx, ecx - ;mov ecx, ebx - ;rep movsb - ;pop ecx -SIS900_transmit_Size_Ok: - mov [txd+4], dword 0x80000000 ;card owns descriptor - or [txd+4], ecx ;set size of packet -if defined SIS900_DEBUG - mov esi, SIS900_Debug_Transmit_Packet - call sys_msg_board_str -end if - ;***************restart the transmitter ******** - lea edx,[ebp+SIS900_cr] - in eax, dx ; Get current Command Register - or eax, SIS900_TxENA ; Enable Transmitter - out dx, eax - ;****make sure packet transmitted successfully**** -; mov esi,10 -; call delay_ms - mov eax, [txd+4] - and eax, 0x6200000 - jz SIS900_transmit_OK - ;**************Tell user there was an error through debug window -if defined SIS900_DEBUG - mov esi, SIS900_Debug_Transmit_Packet_Err - call sys_msg_board_str -end if -SIS900_transmit_OK: - ;******** Disable interrupts by clearing the interrupt mask. ******** - lea edx,[ebp+SIS900_imr] ; Interupt Mask Register - xor eax, eax - out dx,eax - ret - -;*************************************************************************** -;* Function: Create_Mac_String -;* -;* Description: Converts the 48 bit value to a string for display -;* -;* String Format: XX:XX:XX:XX:XX:XX -;* -;* Arguments: node_addr is location of 48 bit MAC ID -;* -;* Returns: Prints string to general debug window -;* -;* -;done -;*************************************************************************** -if defined SIS900_DEBUG - -SIS900_Char_String db '0','1','2','3','4','5','6','7','8','9' - db 'A','B','C','D','E','F' -Mac_str_build: times 20 db 0 -Create_Mac_String: - pusha - xor ecx, ecx -Create_Mac_String_loop: - mov al,byte [edx+ecx];[node_addr+ecx] - push eax - shr eax, 4 - and eax, 0x0f - mov bl, byte [SIS900_Char_String+eax] - mov [Mac_str_build+ecx*3], bl - pop eax - and eax, 0x0f - mov bl, byte [SIS900_Char_String+eax] - mov [Mac_str_build+1+ecx*3], bl - cmp ecx, 5 - je Create_Mac_String_done - mov bl, ':' - mov [Mac_str_build+2+ecx*3], bl - inc ecx - jmp Create_Mac_String_loop -Create_Mac_String_done: ;Insert CR and Zero Terminate - mov [Mac_str_build+2+ecx*3],byte 13 - mov [Mac_str_build+3+ecx*3],byte 10 - mov [Mac_str_build+4+ecx*3],byte 0 - mov esi, Mac_str_build - call sys_msg_board_str ;Print String to message board - popa - ret -end if -;*************************************************************************** -;* Set device to be a busmaster in case BIOS neglected to do so. -;* Also adjust PCI latency timer to a reasonable value, 64. -;*************************************************************************** -SIS900_adjust_pci_device: - ;*******Get current setting************************ - mov al, 2 ;read a word - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, 0x04 ;from command Register - call pci_read_reg - ;******see if its already set as bus master******** - mov bx, ax - and bx,5 - cmp bx,5 - je SIS900_adjust_pci_device_Latency - ;******Make card a bus master******* - mov cx, ax ;value to write - mov bh, [pci_dev] - mov al, 2 ;write a word - or cx,5 - mov ah, [pci_bus] - mov bl, 0x04 ;to command register - call pci_write_reg - ;******Check latency setting*********** -SIS900_adjust_pci_device_Latency: - ;*******Get current latency setting************************ - mov al, 1 ;read a byte - mov bh, [pci_dev] - mov ah, [pci_bus] - mov bl, 0x0D ;from Lantency Timer Register - call pci_read_reg - ;******see if its aat least 64 clocks******** - cmp ax,64 - jge SIS900_adjust_pci_device_Done - ;******Set latency to 32 clocks******* - mov cx, 64 ;value to write - mov bh, [pci_dev] - mov al, 1 ;write a byte - mov ah, [pci_bus] - mov bl, 0x0D ;to Lantency Timer Register - call pci_write_reg - ;******Check latency setting*********** -SIS900_adjust_pci_device_Done: - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; SIS900.INC ;; +;; ;; +;; Ethernet driver for Menuet OS ;; +;; ;; +;; Version 0.4 26 April 2004 ;; +;; ;; +;; This driver is based on the SIS900 driver from ;; +;; the etherboot 5.0.6 project. The copyright statement is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2004 Jason Delozier, ;; +;; cordata51@hotmail.com ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; Updates: ;; +;; Revision Look up table and SIS635 Mac Address by Jarek Pelczar ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;******************************************************************** +; Interface +; SIS900_reset +; SIS900_probe +; SIS900_poll +; SIS900_transmit +; +;******************************************************************** +;******************************************************************** +; Comments: +; Known to work with the following SIS900 ethernet cards: +; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x91 +; - Device ID: 0x0900 Vendor ID: 0x1039 Revision: 0x90 +; +; If your card is not listed, try it and let me know if it +; functions properly and it will be aded to the list. If not +; we may be able to add support for it. +; +; How To Use: +; Add the following lines to Ethernet.inc in their appropriate locations +; +; include "Sis900.INC" +; dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, +; SIS900_transmit +; dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, +; SIS900_transmit ;untested +; +; ToDo: +; - Enable MII interface for reading speed +; and duplex settings. +; +; - Update Poll routine to support packet fragmentation. +; +; - Add additional support for other sis900 based cards +; +;******************************************************************** + +; comment the next line out if you don't want debug info printed +; on the debug board. This option adds a lot of bytes to the driver +; so it's worth to comment it out. +; SIS900_DEBUG equ 1 + + +;* buffers and descriptors +cur_rx db 0 +NUM_RX_DESC equ 4 ;* Number of RX descriptors * +NUM_TX_DESC equ 1 ;* Number of TX descriptors * +RX_BUFF_SZ equ 1520 ;* Buffer size for each Rx buffer * +TX_BUFF_SZ equ 1516 ;* Buffer size for each Tx buffer * + +uglobal +align 4 +txd: + times (3 * NUM_TX_DESC) dd 0 +rxd: + times (3 * NUM_RX_DESC) dd 0 +endg + +txb equ eth_data_start +rxb equ txb + (NUM_TX_DESC * TX_BUFF_SZ) +SIS900_ETH_ALEN equ 6 ;* Size of Ethernet address * +SIS900_ETH_HLEN equ 14 ;* Size of ethernet header * +SIS900_ETH_ZLEN equ 60 ;* Minimum packet length * +SIS900_DSIZE equ 0x00000fff +SIS900_CRC_SIZE equ 4 +SIS900_RFADDR_shift equ 16 +;SIS900 Symbolic offsets to registers. + SIS900_cr equ 0x0 ; Command Register + SIS900_cfg equ 0x4 ; Configuration Register + SIS900_mear equ 0x8 ; EEPROM Access Register + SIS900_ptscr equ 0xc ; PCI Test Control Register + SIS900_isr equ 0x10 ; Interrupt Status Register + SIS900_imr equ 0x14 ; Interrupt Mask Register + SIS900_ier equ 0x18 ; Interrupt Enable Register + SIS900_epar equ 0x18 ; Enhanced PHY Access Register + SIS900_txdp equ 0x20 ; Transmit Descriptor Pointer Register + SIS900_txcfg equ 0x24 ; Transmit Configuration Register + SIS900_rxdp equ 0x30 ; Receive Descriptor Pointer Register + SIS900_rxcfg equ 0x34 ; Receive Configuration Register + SIS900_flctrl equ 0x38 ; Flow Control Register + SIS900_rxlen equ 0x3c ; Receive Packet Length Register + SIS900_rfcr equ 0x48 ; Receive Filter Control Register + SIS900_rfdr equ 0x4C ; Receive Filter Data Register + SIS900_pmctrl equ 0xB0 ; Power Management Control Register + SIS900_pmer equ 0xB4 ; Power Management Wake-up Event Register +;SIS900 Command Register Bits + SIS900_RELOAD equ 0x00000400 + SIS900_ACCESSMODE equ 0x00000200 + SIS900_RESET equ 0x00000100 + SIS900_SWI equ 0x00000080 + SIS900_RxRESET equ 0x00000020 + SIS900_TxRESET equ 0x00000010 + SIS900_RxDIS equ 0x00000008 + SIS900_RxENA equ 0x00000004 + SIS900_TxDIS equ 0x00000002 + SIS900_TxENA equ 0x00000001 +;SIS900 Configuration Register Bits + SIS900_DESCRFMT equ 0x00000100 ; 7016 specific + SIS900_REQALG equ 0x00000080 + SIS900_SB equ 0x00000040 + SIS900_POW equ 0x00000020 + SIS900_EXD equ 0x00000010 + SIS900_PESEL equ 0x00000008 + SIS900_LPM equ 0x00000004 + SIS900_BEM equ 0x00000001 + SIS900_RND_CNT equ 0x00000400 + SIS900_FAIR_BACKOFF equ 0x00000200 + SIS900_EDB_MASTER_EN equ 0x00002000 +;SIS900 Eeprom Access Reigster Bits + SIS900_MDC equ 0x00000040 + SIS900_MDDIR equ 0x00000020 + SIS900_MDIO equ 0x00000010 ; 7016 specific + SIS900_EECS equ 0x00000008 + SIS900_EECLK equ 0x00000004 + SIS900_EEDO equ 0x00000002 + SIS900_EEDI equ 0x00000001 +;SIS900 TX Configuration Register Bits + SIS900_ATP equ 0x10000000 ;Automatic Transmit Padding + SIS900_MLB equ 0x20000000 ;Mac Loopback Enable + SIS900_HBI equ 0x40000000 ;HeartBeat Ignore (Req for full-dup) + SIS900_CSI equ 0x80000000 ;CarrierSenseIgnore (Req for full-du +;SIS900 RX Configuration Register Bits + SIS900_AJAB equ 0x08000000 ; + SIS900_ATX equ 0x10000000 ;Accept Transmit Packets + SIS900_ARP equ 0x40000000 ;accept runt packets (<64bytes) + SIS900_AEP equ 0x80000000 ;accept error packets +;SIS900 Interrupt Reigster Bits + SIS900_WKEVT equ 0x10000000 + SIS900_TxPAUSEEND equ 0x08000000 + SIS900_TxPAUSE equ 0x04000000 + SIS900_TxRCMP equ 0x02000000 + SIS900_RxRCMP equ 0x01000000 + SIS900_DPERR equ 0x00800000 + SIS900_SSERR equ 0x00400000 + SIS900_RMABT equ 0x00200000 + SIS900_RTABT equ 0x00100000 + SIS900_RxSOVR equ 0x00010000 + SIS900_HIBERR equ 0x00008000 + SIS900_SWINT equ 0x00001000 + SIS900_MIBINT equ 0x00000800 + SIS900_TxURN equ 0x00000400 + SIS900_TxIDLE equ 0x00000200 + SIS900_TxERR equ 0x00000100 + SIS900_TxDESC equ 0x00000080 + SIS900_TxOK equ 0x00000040 + SIS900_RxORN equ 0x00000020 + SIS900_RxIDLE equ 0x00000010 + SIS900_RxEARLY equ 0x00000008 + SIS900_RxERR equ 0x00000004 + SIS900_RxDESC equ 0x00000002 + SIS900_RxOK equ 0x00000001 +;SIS900 Interrupt Enable Reigster Bits + SIS900_IE equ 0x00000001 +;SIS900 Revision ID + SIS900B_900_REV equ 0x03 + SIS630A_900_REV equ 0x80 + SIS630E_900_REV equ 0x81 + SIS630S_900_REV equ 0x82 + SIS630EA1_900_REV equ 0x83 + SIS630ET_900_REV equ 0x84 + SIS635A_900_REV equ 0x90 + SIS900_960_REV equ 0x91 +;SIS900 Receive Filter Control Register Bits + SIS900_RFEN equ 0x80000000 + SIS900_RFAAB equ 0x40000000 + SIS900_RFAAM equ 0x20000000 + SIS900_RFAAP equ 0x10000000 + SIS900_RFPromiscuous equ 0x70000000 +;SIS900 Reveive Filter Data Mask + SIS900_RFDAT equ 0x0000FFFF +;SIS900 Eeprom Address + SIS900_EEPROMSignature equ 0x00 + SIS900_EEPROMVendorID equ 0x02 + SIS900_EEPROMDeviceID equ 0x03 + SIS900_EEPROMMACAddr equ 0x08 + SIS900_EEPROMChecksum equ 0x0b +;The EEPROM commands include the alway-set leading bit. +;SIS900 Eeprom Command + SIS900_EEread equ 0x0180 + SIS900_EEwrite equ 0x0140 + SIS900_EEerase equ 0x01C0 + SIS900_EEwriteEnable equ 0x0130 + SIS900_EEwriteDisable equ 0x0100 + SIS900_EEeraseAll equ 0x0120 + SIS900_EEwriteAll equ 0x0110 + SIS900_EEaddrMask equ 0x013F + SIS900_EEcmdShift equ 16 +;For SiS962 or SiS963, request the eeprom software access + SIS900_EEREQ equ 0x00000400 + SIS900_EEDONE equ 0x00000200 + SIS900_EEGNT equ 0x00000100 +;General Varibles + SIS900_pci_revision: + db 0 + SIS900_Status dd 0x03000000 +sis900_specific_table: +; dd SIS630A_900_REV,Get_Mac_SIS630A_900_REV,0 +; dd SIS630E_900_REV,Get_Mac_SIS630E_900_REV,0 + dd SIS630S_900_REV,Get_Mac_SIS635_900_REV,0 + dd SIS630EA1_900_REV,Get_Mac_SIS635_900_REV,0 + dd SIS630ET_900_REV,Get_Mac_SIS635_900_REV,0;SIS630ET_900_REV_SpecialFN + dd SIS635A_900_REV,Get_Mac_SIS635_900_REV,0 + dd SIS900_960_REV,SIS960_get_mac_addr,0 + dd SIS900B_900_REV,SIS900_get_mac_addr,0 + dd 0,0,0,0 ; end of list +sis900_get_mac_func: + dd 0 +sis900_special_func: + dd 0 +sis900_table_entries: + db 8 + +;*************************************************************************** +; Function +; SIS900_probe +; Description +; Searches for an ethernet card, enables it and clears the rx buffer +; If a card was found, it enables the ethernet -> TCPIP link +;not done - still need to probe mii transcievers +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Str_Unsupported db 'Sorry your card is unsupported ',13,10,0 +end if +SIS900_probe: +;******Wake Up Chip******* + mov al, 4 + mov bh, [pci_dev] + mov ecx, 0 + mov ah, [pci_bus] + mov bl, 0x40 + call pci_write_reg +;*******Set some PCI Settings********* + call SIS900_adjust_pci_device +;*****Get Card Revision****** + mov al, 1 ;one byte to read + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x08 ;Revision Register + call pci_read_reg + mov [SIS900_pci_revision], al;save the revision for later use +;****** Look up through the sis900_specific_table + mov esi, sis900_specific_table +.probe_loop: + cmp dword [esi], 0 ; Check if we reached end of the list + je .probe_loop_failed + cmp al, [esi] ; Check if revision is OK + je .probe_loop_ok + add esi, 12 ; Advance to next entry + jmp .probe_loop +.probe_loop_failed: + jmp SIS900_Probe_Unsupported +;*********Find Get Mac Function********* +.probe_loop_ok: + mov eax, [esi+4] ; Get pointer to "get MAC" function + mov [sis900_get_mac_func], eax + mov eax, [esi+8] ; Get pointer to special initialization fn + mov [sis900_special_func], eax +;******** Get MAC ******** + call dword [sis900_get_mac_func] +;******** Call special initialization fn if requested ******** + cmp dword [sis900_special_func], 0 + je .no_special_init + call dword [sis900_special_func] +.no_special_init: +;******** Set table entries ******** + mov al, [SIS900_pci_revision] + cmp al, SIS635A_900_REV + jae .ent16 + cmp al, SIS900B_900_REV + je .ent16 + jmp .ent8 +.ent16: + mov byte [sis900_table_entries], 16 +.ent8: +;*******Probe for mii transceiver******* +;TODO!!********************* +;*******Initialize Device******* + call sis900_init + ret + +SIS900_Probe_Unsupported: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_Unsupported + call sys_msg_board_str +end if + ret +;*************************************************************************** +; Function: sis900_init +; +; Description: resets the ethernet controller chip and various +; data structures required for sending and receiving packets. +; +; Arguments: +; +; returns: none +;not done +;*************************************************************************** +sis900_init: + call SIS900_reset ;Done + call SIS900_init_rxfilter;Done + call SIS900_init_txd;Done + call SIS900_init_rxd ;Done + call SIS900_set_rx_mode;done + call SIS900_set_tx_mode + ;call SIS900_check_mode + ret + +;*************************************************************************** +; Function +; SIS900_reset +; Description +; disables interrupts and soft resets the controller chip +; +;done+ +;*************************************************************************** +if defined SIS900_DEBUG + SIS900_Debug_Reset_Failed db 'Reset Failed ',0 +end if +SIS900_reset: + ;******Disable Interrupts and reset Receive Filter******* + mov ebp, [io_addr] ; base address + xor eax, eax ; 0 to initialize + lea edx, [ebp+SIS900_ier] + out dx, eax ; Write 0 to location + lea edx, [ebp+SIS900_imr] + out dx, eax ; Write 0 to location + lea edx, [ebp+SIS900_rfcr] + out dx, eax ; Write 0 to location + ;*******Reset Card*********************************************** + lea edx, [ebp+SIS900_cr] + in eax, dx ; Get current Command Register + or eax, SIS900_RESET ; set flags + or eax, SIS900_RxRESET ; + or eax, SIS900_TxRESET ; + out dx, eax ; Write new Command Register + ;*******Wait Loop************************************************ + lea edx, [ebp+SIS900_isr] + mov ecx, [SIS900_Status]; Status we would like to see from card + mov ebx, 2001 ; only loop 1000 times +SIS900_Wait: + dec ebx ; 1 less loop + jz SIS900_DoneWait_e ; 1000 times yet? + in eax, dx ; move interrup status to eax + and eax, ecx + xor ecx, eax + jz SIS900_DoneWait + jmp SIS900_Wait +SIS900_DoneWait_e: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Reset_Failed + call sys_msg_board_str +end if +SIS900_DoneWait: + ;*******Set Configuration Register depending on Card Revision******** + lea edx, [ebp+SIS900_cfg] + mov eax, SIS900_PESEL ; Configuration Register Bit + mov bl, [SIS900_pci_revision]; card revision + mov cl, SIS635A_900_REV ; Check card revision + cmp bl, cl + je SIS900_RevMatch + mov cl, SIS900B_900_REV ; Check card revision + cmp bl, cl + je SIS900_RevMatch + out dx, eax ; no revision match + jmp SIS900_Reset_Complete +SIS900_RevMatch: ; Revision match + or eax, SIS900_RND_CNT ; Configuration Register Bit + out dx, eax +SIS900_Reset_Complete: + mov eax, [pci_data] + mov [eth_status], eax + ret + +;*************************************************************************** +; Function: sis_init_rxfilter +; +; Description: sets receive filter address to our MAC address +; +; Arguments: +; +; returns: +;done+ +;*************************************************************************** +SIS900_init_rxfilter: + ;****Get Receive Filter Control Register ******** + mov ebp, [io_addr] ; base address + lea edx, [ebp+SIS900_rfcr] + in eax, dx ; get register + push eax + ;****disable packet filtering before setting filter******* + mov eax, SIS900_RFEN;move receive filter enable flag + not eax ;1s complement + pop ebx ;and with our saved register + and eax, ebx ;disable receiver + push ebx ;save filter for another use + out dx, eax ;set receive disabled + ;********load MAC addr to filter data register********* + xor ecx, ecx +SIS900_RXINT_Mac_Write: + ;high word of eax tells card which mac byte to write + mov eax, ecx + lea edx, [ebp+SIS900_rfcr] + shl eax, 16 ; + out dx, eax ; + lea edx, [ebp+SIS900_rfdr] + mov ax, word [node_addr+ecx*2]; Get Mac ID word + out dx, ax ; Send Mac ID + inc cl ; send next word + cmp cl, 3 ; more to send? + jne SIS900_RXINT_Mac_Write + ;********enable packet filitering ***** + pop eax ;old register value + lea edx, [ebp+SIS900_rfcr] + or eax, SIS900_RFEN;enable filtering + out dx, eax ;set register + ret + +;*************************************************************************** +;* +;* Function: sis_init_txd +;* +;* Description: initializes the Tx descriptor +;* +;* Arguments: +;* +;* returns: +;*done +;*************************************************************************** +SIS900_init_txd: + ;********** initialize TX descriptor ************** + mov [txd], dword 0 ;put link to next descriptor in link field + mov [txd+4], dword 0;clear status field + mov [txd+8], dword txb - OS_BASE;save address to buffer ptr field + ;*************** load Transmit Descriptor Register *************** + mov dx, [io_addr] ; base address + add dx, SIS900_txdp ; TX Descriptor Pointer + mov eax, txd - OS_BASE ; First Descriptor + out dx, eax ; move the pointer + ret + +;*************************************************************************** +;* Function: sis_init_rxd +;* +;* Description: initializes the Rx descriptor ring +;* +;* Arguments: +;* +;* Returns: +;*done +;*************************************************************************** +SIS900_init_rxd: + xor ecx, ecx + mov [cur_rx], cl ;Set cuurent rx discriptor to 0 + ;******** init RX descriptors ******** +SIS900_init_rxd_Loop: + mov eax, ecx ;current descriptor + imul eax, 12 ; + mov ebx, ecx ;determine next link descriptor + inc ebx ; + cmp ebx, NUM_RX_DESC ; + jne SIS900_init_rxd_Loop_0 ; + xor ebx, ebx ; +SIS900_init_rxd_Loop_0: ; + imul ebx, 12 ; + add ebx, rxd - OS_BASE ; + mov [rxd+eax], ebx ;save link to next descriptor + mov [rxd+eax+4], dword RX_BUFF_SZ ;status bits init to buf size + mov ebx, ecx ;find where the buf is located + imul ebx, RX_BUFF_SZ ; + add ebx, rxb - OS_BASE ; + mov [rxd+eax+8], ebx ;save buffer pointer + inc ecx ;next descriptor + cmp ecx, NUM_RX_DESC ; + jne SIS900_init_rxd_Loop ; + ;********* load Receive Descriptor Register with address of first + ; descriptor********* + mov dx, [io_addr] + add dx, SIS900_rxdp + mov eax, rxd - OS_BASE + out dx, eax + ret + +;*************************************************************************** +;* Function: sis900_set_tx_mode +;* +;* Description: +;* sets the transmit mode to allow for full duplex +;* +;* +;* Arguments: +;* +;* Returns: +;* +;* Comments: +;* If you are having problems transmitting packet try changing the +;* Max DMA Burst, Possible settings are as follows: +;* 0x00000000 = 512 bytes +;* 0x00100000 = 4 bytes +;* 0x00200000 = 8 bytes +;* 0x00300000 = 16 bytes +;* 0x00400000 = 32 bytes +;* 0x00500000 = 64 bytes +;* 0x00600000 = 128 bytes +;* 0x00700000 = 256 bytes +;*************************************************************************** +SIS900_set_tx_mode: + mov ebp, [io_addr] + lea edx, [ebp+SIS900_cr] + in eax, dx ; Get current Command Register + or eax, SIS900_TxENA;Enable Receive + out dx, eax + lea edx, [ebp+SIS900_txcfg]; Transmit config Register offset + mov eax, SIS900_ATP ;allow automatic padding + or eax, SIS900_HBI ;allow heartbeat ignore + or eax, SIS900_CSI ;allow carrier sense ignore + or eax, 0x00600000 ;Max DMA Burst + or eax, 0x00000100 ;TX Fill Threshold + or eax, 0x00000020 ;TX Drain Threshold + out dx, eax + ret + +;*************************************************************************** +;* Function: sis900_set_rx_mode +;* +;* Description: +;* sets the receive mode to accept all broadcast packets and packets +;* with our MAC address, and reject all multicast packets. Also allows +;* full-duplex +;* +;* Arguments: +;* +;* Returns: +;* +;* Comments: +;* If you are having problems receiving packet try changing the +;* Max DMA Burst, Possible settings are as follows: +;* 0x00000000 = 512 bytes +;* 0x00100000 = 4 bytes +;* 0x00200000 = 8 bytes +;* 0x00300000 = 16 bytes +;* 0x00400000 = 32 bytes +;* 0x00500000 = 64 bytes +;* 0x00600000 = 128 bytes +;* 0x00700000 = 256 bytes +;*************************************************************************** +SIS900_mc_filter: + times 16 dw 0 +SIS900_set_rx_mode: + mov ebp, [io_addr] + ;**************update Multicast Hash Table in Receive Filter + mov ebx, 0xffff + xor cl, cl +SIS900_set_rx_mode_Loop: + mov eax, ecx + shl eax, 1 + mov [SIS900_mc_filter+eax], bx + lea edx, [ebp+SIS900_rfcr] ; Receive Filter Control Reg offset + mov eax, 4 ;determine table entry + add al, cl + shl eax, 16 + out dx, eax ;tell card which entry to modify + lea edx, [ebp+SIS900_rfdr] ; Receive Filter Control Reg offset + mov eax, ebx ;entry value + out dx, ax ;write value to table in card + inc cl ;next entry + cmp cl, [sis900_table_entries]; + jl SIS900_set_rx_mode_Loop + ;*******Set Receive Filter Control Register************* + lea edx, [ebp+SIS900_rfcr] ; Receive Filter Control Register offset + mov eax, SIS900_RFAAB ;accecpt all broadcast packets + or eax, SIS900_RFAAM ;accept all multicast packets + or eax, SIS900_RFAAP ;Accept all packets + or eax, SIS900_RFEN ;enable receiver filter + out dx, eax + ;******Enable Receiver************ + lea edx, [ebp+SIS900_cr]; Command Register offset + in eax, dx ; Get current Command Register + or eax, SIS900_RxENA;Enable Receive + out dx, eax + ;*********Set + lea edx, [ebp+SIS900_rxcfg] ; Receive Config Register offset + mov eax, SIS900_ATX ;Accept Transmit Packets + ; (Req for full-duplex and PMD Loopback) + or eax, 0x00600000 ;Max DMA Burst + or eax, 0x00000002 ;RX Drain Threshold, 8X8 bytes or 64bytes + out dx, eax ; + ret + +;*************************************************************************** +; * SIS960_get_mac_addr: - Get MAC address for SiS962 or SiS963 model +; * @pci_dev: the sis900 pci device +; * @net_dev: the net device to get address for +; * +; * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM +; * is shared by +; * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first +; * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access +; * by LAN, otherwise is not. After MAC address is read from EEPROM, send +; * EEDONE signal to refuse EEPROM access by LAN. +; * The EEPROM map of SiS962 or SiS963 is different to SiS900. +; * The signature field in SiS962 or SiS963 spec is meaningless. +; * MAC address is read into @net_dev->dev_addr. +; *done +;* +;* Return 0 is EAX = failure +;*Done+ +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Str_GetMac_Start db 'Attempting to get SIS900 Mac ID: ',13,10,0 +SIS900_Debug_Str_GetMac_Failed db 'Access to EEprom Failed',13,10,0 +SIS900_Debug_Str_GetMac_Address db 'Your Mac ID is: ',0 +SIS900_Debug_Str_GetMac_Address2 db 'Your SIS96x Mac ID is: ',0 +end if +SIS960_get_mac_addr: + mov ebp, [io_addr] + ;**********Send Request for eeprom access********************* + lea edx, [ebp+SIS900_mear] ; Eeprom access register + mov eax, SIS900_EEREQ ; Request access to eeprom + out dx, eax ; Send request + xor ebx, ebx ; + ;******Loop 4000 times and if access not granted error out***** +SIS96X_Get_Mac_Wait: + in eax, dx ;get eeprom status + and eax, SIS900_EEGNT ;see if eeprom access granted flag is set + jnz SIS900_Got_EEP_Access ;if it is, go access the eeprom + inc ebx ;else keep waiting + cmp ebx, 4000 ;have we tried 4000 times yet? + jl SIS96X_Get_Mac_Wait ;if not ask again + xor eax, eax ;return zero in eax indicating failure + ;*******Debug ********************** +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_GetMac_Failed + call sys_msg_board_str +end if + jmp SIS960_get_mac_addr_done + ;**********EEprom access granted, read MAC from card************* +SIS900_Got_EEP_Access: + ; zero based so 3-16 bit reads will take place + mov ecx, 2 +SIS96x_mac_read_loop: + mov eax, SIS900_EEPROMMACAddr;Base Mac Address + add eax, ecx ;Current Mac Byte Offset + push ecx + call sis900_read_eeprom ;try to read 16 bits + pop ecx + mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID varible + dec ecx ;one less word to read + jns SIS96x_mac_read_loop ;if more read more + mov eax, 1 ;return non-zero indicating success + ;*******Debug Print MAC ID to debug window********************** +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_GetMac_Address2 + call sys_msg_board_str + mov edx, node_addr + call Create_Mac_String +end if + ;**********Tell EEPROM We are Done Accessing It********************* +SIS960_get_mac_addr_done: + lea edx, [ebp+SIS900_mear] ; Eeprom access register + mov eax, SIS900_EEDONE ;tell eeprom we are done + out dx, eax + ret +;*************************************************************************** +;* sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model +;* @pci_dev: the sis900 pci device +;* @net_dev: the net device to get address for +;* +;* Older SiS900 and friends, use EEPROM to store MAC address. +;* MAC address is read from read_eeprom() into @net_dev->dev_addr. +;* done/untested +;*************************************************************************** +SIS900_get_mac_addr: + ;*******Debug ********************** +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_GetMac_Start + call sys_msg_board_str +end if + ;******** check to see if we have sane EEPROM ******* + mov eax, SIS900_EEPROMSignature;Base Eeprom Signature + call sis900_read_eeprom ;try to read 16 bits + cmp ax, 0xffff + je SIS900_Bad_Eeprom + cmp ax, 0 + je SIS900_Bad_Eeprom + ;**************Read MacID************** + ; zero based so 3-16 bit reads will take place + mov ecx, 2 +SIS900_mac_read_loop: + mov eax, SIS900_EEPROMMACAddr;Base Mac Address + add eax, ecx ;Current Mac Byte Offset + push ecx + call sis900_read_eeprom ;try to read 16 bits + pop ecx + mov [node_addr+ecx*2], ax ;save 16 bits to the MAC ID storage + dec ecx ;one less word to read + jns SIS900_mac_read_loop ;if more read more + mov eax, 1 ;return non-zero indicating success + ;*******Debug Print MAC ID to debug window********************** +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_GetMac_Address + call sys_msg_board_str + mov edx, node_addr + call Create_Mac_String +end if + ret + +SIS900_Bad_Eeprom: + xor eax, eax + ;*******Debug ********************** +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_GetMac_Failed + call sys_msg_board_str +end if + ret +;*************************************************************************** +;* Get_Mac_SIS635_900_REV: - Get MAC address for model 635 +;* +;* +;*************************************************************************** +Get_Mac_SIS635_900_REV: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_GetMac_Start + call sys_msg_board_str +end if + mov ebp, [io_addr] + lea edx, [ebp+SIS900_rfcr] + in eax, dx + mov edi, eax; EDI=rfcrSave + lea edx, [ebp+SIS900_cr] + or eax, SIS900_RELOAD + out dx, eax + xor eax, eax + out dx, eax + ; Disable packet filtering before setting filter + lea edx, [ebp+SIS900_rfcr] + mov eax, edi + and edi, not SIS900_RFEN + out dx, eax + ; Load MAC to filter data register + xor ecx, ecx + mov esi, node_addr +.get_mac_loop: + lea edx, [ebp+SIS900_rfcr] + mov eax, ecx + shl eax, SIS900_RFADDR_shift + out dx, eax + lea edx, [ebp+SIS900_rfdr] + in eax, dx + mov [esi], ax + add esi, 2 + inc ecx + cmp ecx, 3 + jne .get_mac_loop + ; Enable packet filtering + ;lea edx,[ebp+SIS900_rfcr] + ;mov eax,edi + ;or eax,SIS900_RFEN + ;out dx, eax + ;*******Debug Print MAC ID to debug window********************** +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Str_GetMac_Address + call sys_msg_board_str + mov edx, node_addr + call Create_Mac_String +end if + ret +;*************************************************************************** +;* Function: sis900_read_eeprom +;* +;* Description: reads and returns a given location from EEPROM +;* +;* Arguments: eax - location: requested EEPROM location +;* +;* Returns: eax : contents of requested EEPROM location +;* +; Read Serial EEPROM through EEPROM Access Register, Note that location is +; in word (16 bits) unit */ +;done+ +;*************************************************************************** +sis900_read_eeprom: + push esi + push edx + push ecx + push ebx + mov ebp, [io_addr] + mov ebx, eax ;location of Mac byte to read + or ebx, SIS900_EEread ; + lea edx, [ebp+SIS900_mear]; Eeprom access register + xor eax, eax ; start send + out dx, eax + call SIS900_Eeprom_Delay_1 + mov eax, SIS900_EECLK + out dx, eax + call SIS900_Eeprom_Delay_1 + ;************ Shift the read command (9) bits out. ********* + mov cl, 8 ; +sis900_read_eeprom_Send: + mov eax, 1 + shl eax, cl + and eax, ebx + jz SIS900_Read_Eeprom_8 + mov eax, 9 + jmp SIS900_Read_Eeprom_9 +SIS900_Read_Eeprom_8: + mov eax, 8 +SIS900_Read_Eeprom_9: + out dx, eax + call SIS900_Eeprom_Delay_1 + or eax, SIS900_EECLK + out dx, eax + call SIS900_Eeprom_Delay_1 + cmp cl, 0 + je sis900_read_eeprom_Send_Done + dec cl + jmp sis900_read_eeprom_Send + ;********************* +sis900_read_eeprom_Send_Done: + mov eax, SIS900_EECS ; + out dx, eax + call SIS900_Eeprom_Delay_1 + ;********** Read 16-bits of data in *************** + mov cx, 16 ;16 bits to read +sis900_read_eeprom_Send2: + mov eax, SIS900_EECS + out dx, eax + call SIS900_Eeprom_Delay_1 + or eax, SIS900_EECLK + out dx, eax + call SIS900_Eeprom_Delay_1 + in eax, dx + shl ebx, 1 + and eax, SIS900_EEDO + jz SIS900_Read_Eeprom_0 + or ebx, 1 +SIS900_Read_Eeprom_0: + dec cx + jnz sis900_read_eeprom_Send2 + ;************** Terminate the EEPROM access. ************** + xor eax, eax + out dx, eax + call SIS900_Eeprom_Delay_1 + mov eax, SIS900_EECLK + out dx, eax + mov eax, ebx + and eax, 0x0000ffff ;return only 16 bits + pop ebx + pop ecx + pop edx + pop esi + ret +;*************************************************************************** +; Function +; SIS900_Eeprom_Delay_1 +; Description +; +; +; +; +;*************************************************************************** +SIS900_Eeprom_Delay_1: + push eax + in eax, dx + pop eax + ret + +;*************************************************************************** +; Function +; SIS900_poll +; Description +; polls card to see if there is a packet waiting +; +; Currently only supports one descriptor per packet, if packet is fragmented +; between multiple descriptors you will lose part of the packet +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Pull_Packet_good db 'Good Packet Waiting: ',13,10,0 +SIS900_Debug_Pull_Bad_Packet_Status db 'Bad Packet Waiting: Status',13,10,0 +SIS900_Debug_Pull_Bad_Packet_Size db 'Bad Packet Waiting: Size',13,10,0 +end if +SIS900_poll: + ;**************Get Status ************** + xor eax, eax ;get RX_Status + mov [eth_rx_data_len], ax + mov al, [cur_rx] ;find current discriptor + imul eax, 12 ; + mov ecx, [rxd+eax+4] ; get receive status + ;**************Check Status ************** + mov ebx, ecx ;move status + ;Check RX_Status to see if packet is waiting + and ebx, 0x80000000 + jnz SIS900_poll_IS_packet + ret + ;**********There is a packet waiting check it for errors************** +SIS900_poll_IS_packet: + mov ebx, ecx ;move status + and ebx, 0x67C0000 ;see if there are any errors + jnz SIS900_Poll_Error_Status + ;**************Check size of packet************* + and ecx, SIS900_DSIZE ;get packet size minus CRC + cmp cx, SIS900_CRC_SIZE + ;make sure packet contains data + jle SIS900_Poll_Error_Size + ;*******Copy Good Packet to receive buffer****** + sub cx, SIS900_CRC_SIZE ;dont want crc + mov word [eth_rx_data_len], cx ;save size of packet + ;**********Continue copying packet**************** + push ecx + ; first copy dword-wise, divide size by 4 + shr ecx, 2 + mov esi, [rxd+eax+8] ; set source + add esi, OS_BASE ; get linear address + mov edi, Ether_buffer ; set destination + cld ; clear direction + rep movsd ; copy the dwords + pop ecx + and ecx, 3 ; + rep movsb + ;********Debug, tell user we have a good packet************* +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Pull_Packet_good + call sys_msg_board_str +end if + jmp SIS900_Poll_Cnt ; + ;*************Error occured let user know through debug window*********** +SIS900_Poll_Error_Status: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Pull_Bad_Packet_Status + call sys_msg_board_str +end if + jmp SIS900_Poll_Cnt +SIS900_Poll_Error_Size: +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Pull_Bad_Packet_Size + call sys_msg_board_str +end if + ;*************Increment to next available descriptor************** +SIS900_Poll_Cnt: + ;Reset status, allow ethernet card access to descriptor + mov ecx, RX_BUFF_SZ + mov [rxd+eax+4], ecx ; + inc [cur_rx] ;get next descriptor + and [cur_rx], 3 ;only 4 descriptors 0-3 + ;******Enable Receiver************ + mov ebp, [io_addr] ; Base Address + lea edx, [ebp+SIS900_cr]; Command Register offset + in eax, dx ; Get current Command Register + or eax, SIS900_RxENA;Enable Receive + out dx, eax + ret +;*************************************************************************** +; Function +; SIS900_transmit +; Description +; Transmits a packet of data via the ethernet card +; Pointer to 48 bit destination address in edi +; Type of packet in bx +; size of packet in ecx +; pointer to packet data in esi +; +; only one transmit descriptor is used +; +;*************************************************************************** +if defined SIS900_DEBUG +SIS900_Debug_Transmit_Packet db 'Transmitting Packet: ',13,10,0 +SIS900_Debug_Transmit_Packet_Err db 'Transmitting Packet Error: ',13,10,0 +end if +str1 db 'Transmitting packet:',13,10,0 +str2 db ' ',0 +SIS900_transmit: + mov ebp, [io_addr] ; Base Address + ;******** Stop the transmitter ******** + lea edx, [ebp+SIS900_cr]; Command Register offset + in eax, dx ; Get current Command Register + or eax, SIS900_TxDIS; Disable Transmitter + out dx, eax + ;*******load Transmit Descriptor Register ******* + lea edx, [ebp+SIS900_txdp] + mov eax, txd - OS_BASE + out dx, eax + ;******* copy packet to descriptor******* + push esi + mov esi, edi ;copy destination addess + mov edi, txb + cld + movsd + movsw + mov esi, node_addr;copy my mac address + movsd + movsw + mov [edi], bx ;copy packet type + add edi, 2 + pop esi ;restore pointer to source of packet + push ecx ;save packet size + shr ecx, 2 ;divide by 4, size in bytes send in dwords + rep movsd ;copy data to decriptor + pop ecx ;restore packet size + push ecx ;save packet size + and ecx, 3 ;last three bytes if not a multiple of 4 + rep movsb + ;**************set length tag************** + pop ecx ;restore packet size + add ecx, SIS900_ETH_HLEN;add header to length + and ecx, SIS900_DSIZE; + ;**************pad to minimum packet size **************not needed + ;cmp ecx, SIS900_ETH_ZLEN + ;jge SIS900_transmit_Size_Ok + ;push ecx + ;mov ebx, SIS900_ETH_ZLEN + ;sub ebx, ecx + ;mov ecx, ebx + ;rep movsb + ;pop ecx +SIS900_transmit_Size_Ok: + mov [txd+4], dword 0x80000000 ;card owns descriptor + or [txd+4], ecx ;set size of packet +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Transmit_Packet + call sys_msg_board_str +end if + ;***************restart the transmitter ******** + lea edx, [ebp+SIS900_cr] + in eax, dx ; Get current Command Register + or eax, SIS900_TxENA; Enable Transmitter + out dx, eax + ;****make sure packet transmitted successfully**** +; mov esi,10 +; call delay_ms + mov eax, [txd+4] + and eax, 0x6200000 + jz SIS900_transmit_OK + ;**************Tell user there was an error through debug window +if defined SIS900_DEBUG + mov esi, SIS900_Debug_Transmit_Packet_Err + call sys_msg_board_str +end if +SIS900_transmit_OK: + ;******** Disable interrupts by clearing the interrupt mask. ******** + lea edx, [ebp+SIS900_imr] ; Interupt Mask Register + xor eax, eax + out dx, eax + ret + +;*************************************************************************** +;* Function: Create_Mac_String +;* +;* Description: Converts the 48 bit value to a string for display +;* +;* String Format: XX:XX:XX:XX:XX:XX +;* +;* Arguments: node_addr is location of 48 bit MAC ID +;* +;* Returns: Prints string to general debug window +;* +;* +;done +;*************************************************************************** +if defined SIS900_DEBUG + +SIS900_Char_String db '0','1','2','3','4','5','6','7','8','9' + db 'A','B','C','D','E','F' +Mac_str_build: + times 20 db 0 +Create_Mac_String: + pusha + xor ecx, ecx +Create_Mac_String_loop: + mov al, byte [edx+ecx];[node_addr+ecx] + push eax + shr eax, 4 + and eax, 0x0f + mov bl, byte [SIS900_Char_String+eax] + mov [Mac_str_build+ecx*3], bl + pop eax + and eax, 0x0f + mov bl, byte [SIS900_Char_String+eax] + mov [Mac_str_build+1+ecx*3], bl + cmp ecx, 5 + je Create_Mac_String_done + mov bl, ':' + mov [Mac_str_build+2+ecx*3], bl + inc ecx + jmp Create_Mac_String_loop +Create_Mac_String_done: ;Insert CR and Zero Terminate + mov [Mac_str_build+2+ecx*3], byte 13 + mov [Mac_str_build+3+ecx*3], byte 10 + mov [Mac_str_build+4+ecx*3], byte 0 + mov esi, Mac_str_build + call sys_msg_board_str ;Print String to message board + popa + ret +end if +;*************************************************************************** +;* Set device to be a busmaster in case BIOS neglected to do so. +;* Also adjust PCI latency timer to a reasonable value, 64. +;*************************************************************************** +SIS900_adjust_pci_device: + ;*******Get current setting************************ + mov al, 2 ;read a word + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x04 ;from command Register + call pci_read_reg + ;******see if its already set as bus master******** + mov bx, ax + and bx, 5 + cmp bx, 5 + je SIS900_adjust_pci_device_Latency + ;******Make card a bus master******* + mov cx, ax ;value to write + mov bh, [pci_dev] + mov al, 2 ;write a word + or cx, 5 + mov ah, [pci_bus] + mov bl, 0x04 ;to command register + call pci_write_reg + ;******Check latency setting*********** +SIS900_adjust_pci_device_Latency: + ;*******Get current latency setting************************ + mov al, 1 ;read a byte + mov bh, [pci_dev] + mov ah, [pci_bus] + mov bl, 0x0D ;from Lantency Timer Register + call pci_read_reg + ;******see if its aat least 64 clocks******** + cmp ax, 64 + jge SIS900_adjust_pci_device_Done + ;******Set latency to 32 clocks******* + mov cx, 64 ;value to write + mov bh, [pci_dev] + mov al, 1 ;write a byte + mov ah, [pci_bus] + mov bl, 0x0D ;to Lantency Timer Register + call pci_write_reg + ;******Check latency setting*********** +SIS900_adjust_pci_device_Done: + ret diff --git a/kernel/trunk/network/eth_drv/ethernet.inc b/kernel/trunk/network/eth_drv/ethernet.inc index 5a8e4772d..5247adcc9 100644 --- a/kernel/trunk/network/eth_drv/ethernet.inc +++ b/kernel/trunk/network/eth_drv/ethernet.inc @@ -1,506 +1,524 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ETHERNET.INC ;; -;; ;; -;; Ethernet network layer for Menuet OS ;; -;; ;; -;; This file contains the following: ;; -;; PCI bus scanning for valid devices ;; -;; Table of supported ethernet drivers ;; -;; Code to identify and activate a supported driver ;; -;; ARP handler ;; -;; Driver interface to the IP layer ;; -;; Gateway support ;; -;; ;; -;; Individual driver files are included here ;; -;; ;; -;; The PCI bus scanning code was ported from the etherboot ;; -;; 5.0.6 project. The copyright statement for that code is ;; -;; ;; -;; GNU GENERAL PUBLIC LICENSE ;; -;; Version 2, June 1991 ;; -;; ;; -;; remaining parts Copyright 2002 Mike Hibbett ;; -;; mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;******************************************************************** -; Interface -; ethernet_driver called by stack_handler in stack.inc -; eth_probe called by app_stack_handler in stack.inc -; -;******************************************************************** - -ETHER_IP equ 0x0008 ; Reversed from 0800 for intel -ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel -ETHER_RARP equ 0x3580 - -struc ETH_FRAME -{ .DstMAC dp ? ;destination MAC-address [6 bytes] - .SrcMAC dp ? ;source MAC-address [6 bytes] - .Type dw ? ;type of the upper-layer protocol [2 bytes] - .Data db ? ;data [46-1500 bytes] - } - -virtual at Ether_buffer - ETH_FRAME ETH_FRAME -end virtual - - -; Some useful information on data structures - -; Ethernet Packet - ARP Request example -; -; 0 1 2 3 -; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -; -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Dest H/W Address | -; | ( 14 byte header ) | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | | Source H/W Address | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Protocol - ARP 08 06 | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | H/W Type 00 01 | Protocol Type 08 00 | -; | ( ARP Request packet ) | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | HLen 0x06 | PLen 0x04 | OpCode 00 01 | -; | ( 0001 for request, 0002 for reply ) | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Source Hardware Address ( MAC Address ) | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | | Source IP Address | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | | Destination Hardware Address | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Destination IP Address | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -; Include individual drivers source files at this point. -; If you create a new driver, include it below. - -include "drivers/rtl8029.inc" -include "drivers/i8255x.inc" -include "drivers/rtl8139.inc" -include "drivers/3c59x.inc" -include "drivers/sis900.inc" -include "drivers/pcnet32.inc" -include "drivers/rtl8169.inc" -include "drivers/forcedeth.inc" -include "drivers/r6040.inc" - -; PCICards -; ======== -; PCI vendor and hardware types for hardware supported by the above drivers -; If you add a driver, ensure you update this datastructure, otherwise the -; card will not be probed. -; Each driver is defined by 4 double words. These are -; PCIVendorDevice probeFunction ResetFunction PollFunction transmitFunction -; The last entry must be kept at all zeros, to indicate the end of the list -; As a PCI driver may support more than one hardware implementation, there may -; be several lines which refer to the same functions. -; The first driver found on the PCI bus will be the one used. - -PCICARDS_ENTRY_SIZE equ 24 ; Size of each PCICARDS entry - -iglobal -PCICards: -dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 -dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 -dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 -dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 -dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 - -dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0 - -;dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable -;dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable - -dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 -dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 -dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 -dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 -dd 0x816710ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 - -dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 -dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 - -dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 -dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 - -dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 -dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 -dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 - -dd 0x006610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; nVidia Corporation nForce2 Ethernet Controller -dd 0x01c310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x008610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x008c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x00e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x00df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x005610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x005710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x003710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x003810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x026810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x026910de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x037210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x037310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x03e510de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x03e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x03ee10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x03ef10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x045010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x045110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x045210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x045310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x054c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x054d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x054e10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x054f10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x07dc10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x07dd10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x07de10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x07df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x076010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; MCP77 Ethernet Controller -dd 0x076110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x076210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x076310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x0ab010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x0ab110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x0ab210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x0ab310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested -dd 0x0d7d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested - -dd 0x604017F3, r6040_probe, r6040_reset, r6040_poll, r6040_transmit, 0 - -rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove -endg - -uglobal -;Net-stack's interface's settings - node_addr: db 0,0,0,0,0,0 - gateway_ip: dd 0 - dns_ip: dd 0 - - eth_rx_data_len: dw 0 - eth_status: dd 0 - io_addr: dd 0 - hdrtype: db 0 - vendor_device: dd 0 - pci_data: dd 0 - pci_dev: dd 0 - pci_bus: dd 0 - - ; These will hold pointers to the selected driver functions - drvr_probe: dd 0 - drvr_reset: dd 0 - drvr_poll: dd 0 - drvr_transmit: dd 0 - drvr_cable: dd 0 - -endg - -iglobal - broadcast_add: db 0xff,0xff,0xff,0xff,0xff,0xff - subnet_mask: dd 0x00ffffff ; 255.255.255.0 -endg - -include "arp.inc" ;arp-protocol functions -include "pci.inc" ;PCI bus access functions - - -;*************************************************************************** -; Function -; eth_tx -; -; Description -; Looks at the NET1OUT_QUEUE for data to send. -; Stores that destination IP in a location used by the tx routine -; Looks up the MAC address in the ARP table; stores that where -; the tx routine can get it -; Get the length of the data. Store that where the tx routine wants it -; Call tx -; Places buffer on empty queue when the tx routine finished -; -;*************************************************************************** -proc eth_tx stdcall uses ebx esi edi -local MACAddress dp ? ;allocate 6 bytes in the stack - - ; Look for a buffer to tx - mov eax, NET1OUT_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .exit ; Exit if no buffer available - - push eax ;save buffer number - - ; convert buffer pointer eax to the absolute address - imul eax, IPBUFFSIZE - add eax, IPbuffs - - ; Extract the destination IP - ; find the destination IP in the ARP table, get MAC - ; store this MAC in 'MACAddress' - mov ebx, eax ; Save buffer address - mov edx, [ebx + 16] ; get destination address - - ; If the destination address is 255.255.255.255, - ; set the MACAddress to all ones ( broadcast ) - cld - mov esi, broadcast_add - lea edi, [MACAddress] - movsd - movsw - cmp edx, 0xffffffff - je .send ; If it is broadcast, just send - - lea eax, [MACAddress] ;cause this is local variable - stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, edx, eax ;opcode,IP,MAC_ptr - Get the MAC address. - - cmp eax, ARP_VALID_MAPPING - je .send - - ; No valid entry. Has the request been sent, but timed out? - cmp eax, ARP_RESPONSE_TIMEOUT - je .freebuf - - .wait_response: ;we wait arp-response - ; Re-queue the packet, and exit - pop ebx - mov eax, NET1OUT_QUEUE - call queue ; Get the buffer back - jmp .exit - - .send: ;if ARP_VALID_MAPPING then send the packet - lea edi, [MACAddress] ; Pointer to 48 bit destination address - movzx ecx, word[ebx+2] ; Size of IP packet to send - xchg ch, cl ; because mirror byte-order - mov esi, ebx ; Pointer to packet data - mov bx, ETHER_IP ; Type of packet - push ebp - call dword [drvr_transmit] ; Call the drivers transmit function - pop ebp - - ; OK, we have sent a packet, so increment the count - inc dword [ip_tx_count] - - ; And finally, return the buffer to the free queue - .freebuf: - pop eax - call freeBuff - - .exit: - ret -endp - -;*************************************************************************** -; Function -; ether_IP_handler -; -; Description -; Called when an IP ethernet packet is received on the ethernet -; Header + Data is in Ether_buffer[] -; We just need to get a buffer from the 'free' queue, and -; store the packet in it, then insert the packet number into the -; IPRX queue. -; If no queue entry is available, the packet is silently discarded -; All registers may be destroyed -; -;*************************************************************************** -;uglobal -; ether_IP_handler_cnt dd ? -;endg -ether_IP_handler: - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je eiph00x - - ; convert buffer pointer eax to the absolute address - push eax - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - - mov edi, eax - - ; get a pointer to the start of the DATA - mov esi, ETH_FRAME.Data - - ; Now store it all away - mov ecx, IPBUFFSIZE / 4 ; Copy all of the available - ; data across - worse case - cld - rep movsd - -; inc [ether_IP_handler_cnt] -; DEBUGF 1, "K : ether_IP_handler (%u)\n", [ether_IP_handler_cnt] - - ; And finally, place the buffer in the IPRX queue - pop ebx - mov eax, IPIN_QUEUE - call queue - -eiph00x: - ret - -;*************************************************************************** -; Function -; eth_probe -; Description -; Searches for an ethernet card. If found, the card is enabled and -; the ethernet -> IP link established -; -; This function scans the PCI bus looking for a supported device. -; ISA bus is currently not supported. -; -; eax is 0 if no hardware found -;*************************************************************************** -eth_probe: - ; Find a card on the PCI bus, and get it's address - call scan_bus ; Find the ethernet cards PIC address - xor eax, eax - cmp [io_addr], eax - je ep_00x ; Return 0 in eax if no cards found - - call dword [drvr_probe] ; Call the drivers probe function - - mov eax, [io_addr] ; return a non zero value - -ep_00x: - ret - -;*************************************************************************** -; Function -; ethernet_driver -; -; Description -; The ethernet RX and TX handler -; This is a kernel function, called by stack_handler -; -;*************************************************************************** -ethernet_driver: - ; Do nothing if the driver is inactive - cmp [ethernet_active], byte 0 - je eth_exit - - call eth_rx - call eth_tx - -eth_exit: - ret - -;*************************************************************************** -; Function -; eth_rx -; -; Description -; Polls the ethernet card for received data. Extracts if present -; Depending on the Protocol within the packet: -; ARP : Pass to ARP_handler. This may result in an ARP reply -; being tx'ed -; IP : Store in an IP buffer -; -;*************************************************************************** -eth_rx: - xor ax, ax - mov [eth_rx_data_len], ax - call dword [drvr_poll] ; Call the drivers poll function - - mov ax, [eth_rx_data_len] - cmp ax, 0 - je .exit - - - ; Check the protocol. Call appropriate handler - - mov ax, [ETH_FRAME.Type] ; The address of the protocol word - - cmp ax, ETHER_IP - je .is_ip ; It's IP - - cmp ax, ETHER_ARP - je .is_arp ; It is ARP - - DEBUGF 1,"K : eth_rx - dumped (%u)\n", ax - inc [dumped_rx_count] - jmp .exit ; If not IP or ARP, ignore - - .is_ip: -; DEBUGF 1,"K : eth_rx - IP packet\n" - inc dword [ip_rx_count] - call ether_IP_handler - jmp .exit - - .is_arp: -; DEBUGF 1,"K : eth_rx - ARP packet\n" - ; At this point, the packet is still in the Ether_buffer - call arp_handler - - .exit: - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ETHERNET.INC ;; +;; ;; +;; Ethernet network layer for Menuet OS ;; +;; ;; +;; This file contains the following: ;; +;; PCI bus scanning for valid devices ;; +;; Table of supported ethernet drivers ;; +;; Code to identify and activate a supported driver ;; +;; ARP handler ;; +;; Driver interface to the IP layer ;; +;; Gateway support ;; +;; ;; +;; Individual driver files are included here ;; +;; ;; +;; The PCI bus scanning code was ported from the etherboot ;; +;; 5.0.6 project. The copyright statement for that code is ;; +;; ;; +;; GNU GENERAL PUBLIC LICENSE ;; +;; Version 2, June 1991 ;; +;; ;; +;; remaining parts Copyright 2002 Mike Hibbett ;; +;; mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;******************************************************************** +; Interface +; ethernet_driver called by stack_handler in stack.inc +; eth_probe called by app_stack_handler in stack.inc +; +;******************************************************************** + +ETHER_IP equ 0x0008 ; Reversed from 0800 for intel +ETHER_ARP equ 0x0608 ; Reversed from 0806 for intel +ETHER_RARP equ 0x3580 + +struc ETH_FRAME +{ .DstMAC dp ? ;destination MAC-address [6 bytes] + .SrcMAC dp ? ;source MAC-address [6 bytes] + .Type dw ? ;type of the upper-layer protocol [2 bytes] + .Data db ? ;data [46-1500 bytes] + } + +virtual at Ether_buffer + ETH_FRAME ETH_FRAME +end virtual + + +; Some useful information on data structures + +; Ethernet Packet - ARP Request example +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Dest H/W Address | +; | ( 14 byte header ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | Source H/W Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Protocol - ARP 08 06 | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | H/W Type 00 01 | Protocol Type 08 00 | +; | ( ARP Request packet ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | HLen 0x06 | PLen 0x04 | OpCode 00 01 | +; | ( 0001 for request, 0002 for reply ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Source Hardware Address ( MAC Address ) | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | Source IP Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | Destination Hardware Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Destination IP Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +; Include individual drivers source files at this point. +; If you create a new driver, include it below. + +include "drivers/rtl8029.inc" +include "drivers/i8255x.inc" +include "drivers/rtl8139.inc" +include "drivers/3c59x.inc" +include "drivers/sis900.inc" +include "drivers/pcnet32.inc" +include "drivers/rtl8169.inc" +include "drivers/forcedeth.inc" +include "drivers/r6040.inc" + +; PCICards +; ======== +; PCI vendor and hardware types for hardware supported by the above drivers +; If you add a driver, ensure you update this datastructure, otherwise the +; card will not be probed. +; Each driver is defined by 4 double words. These are +; PCIVendorDevice probeFunction ResetFunction PollFunction transmitFunction +; The last entry must be kept at all zeros, to indicate the end of the list +; As a PCI driver may support more than one hardware implementation, there may +; be several lines which refer to the same functions. +; The first driver found on the PCI bus will be the one used. + +PCICARDS_ENTRY_SIZE equ 24 ; Size of each PCICARDS entry + +iglobal +PCICards: +dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 +dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 +dd 0x12298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 +dd 0x10308086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 +dd 0x24498086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit, 0 + +dd 0x802910ec, rtl8029_probe, rtl8029_reset, rtl8029_poll, rtl8029_transmit, 0 + +;dd 0x813910ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x813810ec, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x12111113, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x13601500, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x13604033, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x13001186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x13401186, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0xab0613d1, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0xa1171259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0xa11e1259, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0xab0614ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0xab0714ea, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x123411db, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x91301432, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x101202ac, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x0106018a, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x1211126c, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x81391743, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable +;dd 0x8139021b, rtl8139_probe, rtl8139_reset, rtl8139_poll, rtl8139_transmit, rtl8139_cable + +dd 0x816810ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 +dd 0x816910ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 +dd 0x011616ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 +dd 0x43001186, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 +dd 0x816710ec, rtl8169_probe, rtl8169_reset, rtl8169_poll, rtl8169_transmit, 0 + +dd 0x590010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x592010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x597010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x595010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x595110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x595210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x900010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x900110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x900410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x900510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x900610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x900A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x905010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x905110b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x905510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x905810b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x905A10b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x920010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x980010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x980510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x764610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x505510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x605510b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x605610b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x5b5710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x505710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x515710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x525710b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x656010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x656210b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x656410b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 +dd 0x450010b7, e3c59x_probe, e3c59x_reset, e3c59x_poll, e3c59x_transmit, 0 + +dd 0x09001039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 +dd 0x70161039, SIS900_probe, SIS900_reset, SIS900_poll, SIS900_transmit, 0 + +dd 0x20001022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 +dd 0x26251022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 +dd 0x20011022, pcnet32_probe, pcnet32_reset, pcnet32_poll, pcnet32_xmit, 0 + +dd 0x006610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; nVidia Corporation nForce2 Ethernet Controller +dd 0x01c310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x00D610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x008610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x008c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x00e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x00df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x005610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x005710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x003710de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x003810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x026810de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x026910de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x037210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x037310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x03e510de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x03e610de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x03ee10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x03ef10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x045010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x045110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x045210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x045310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x054c10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x054d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x054e10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x054f10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x07dc10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x07dd10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x07de10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x07df10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x076010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; MCP77 Ethernet Controller +dd 0x076110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x076210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x076310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x0ab010de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x0ab110de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x0ab210de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x0ab310de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested +dd 0x0d7d10de, forcedeth_probe, forcedeth_reset, forcedeth_poll, forcedeth_transmit, forcedeth_cable ; not tested + +dd 0x604017F3, r6040_probe, r6040_reset, r6040_poll, r6040_transmit, 0 + +rb PCICARDS_ENTRY_SIZE ; end of list marker, do not remove +endg + +uglobal +;Net-stack's interface's settings + node_addr: + db 0,0,0,0,0,0 + gateway_ip: + dd 0 + dns_ip: + dd 0 + + eth_rx_data_len: + dw 0 + eth_status: + dd 0 + io_addr: + dd 0 + hdrtype: + db 0 + vendor_device: + dd 0 + pci_data: + dd 0 + pci_dev: + dd 0 + pci_bus: + dd 0 + + ; These will hold pointers to the selected driver functions + drvr_probe: + dd 0 + drvr_reset: + dd 0 + drvr_poll: + dd 0 + drvr_transmit: + dd 0 + drvr_cable: + dd 0 + +endg + +iglobal + broadcast_add: + db 0xff,0xff,0xff,0xff,0xff,0xff + subnet_mask: + dd 0x00ffffff ; 255.255.255.0 +endg + +include "arp.inc" ;arp-protocol functions +include "pci.inc" ;PCI bus access functions + + +;*************************************************************************** +; Function +; eth_tx +; +; Description +; Looks at the NET1OUT_QUEUE for data to send. +; Stores that destination IP in a location used by the tx routine +; Looks up the MAC address in the ARP table; stores that where +; the tx routine can get it +; Get the length of the data. Store that where the tx routine wants it +; Call tx +; Places buffer on empty queue when the tx routine finished +; +;*************************************************************************** +proc eth_tx stdcall uses ebx esi edi +local MACAddress dp ? ;allocate 6 bytes in the stack + + ; Look for a buffer to tx + mov eax, NET1OUT_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit ; Exit if no buffer available + + push eax;save buffer number + + ; convert buffer pointer eax to the absolute address + imul eax, IPBUFFSIZE + add eax, IPbuffs + + ; Extract the destination IP + ; find the destination IP in the ARP table, get MAC + ; store this MAC in 'MACAddress' + mov ebx, eax ; Save buffer address + mov edx, [ebx + 16] ; get destination address + + ; If the destination address is 255.255.255.255, + ; set the MACAddress to all ones ( broadcast ) + cld + mov esi, broadcast_add + lea edi, [MACAddress] + movsd + movsw + cmp edx, 0xffffffff + je .send ; If it is broadcast, just send + + lea eax, [MACAddress];cause this is local variable + stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, edx, eax;opcode,IP,MAC_ptr - Get the MAC address. + + cmp eax, ARP_VALID_MAPPING + je .send + + ; No valid entry. Has the request been sent, but timed out? + cmp eax, ARP_RESPONSE_TIMEOUT + je .freebuf + + .wait_response: ;we wait arp-response + ; Re-queue the packet, and exit + pop ebx + mov eax, NET1OUT_QUEUE + call queue ; Get the buffer back + jmp .exit + + .send: ;if ARP_VALID_MAPPING then send the packet + lea edi, [MACAddress] ; Pointer to 48 bit destination address + movzx ecx, word[ebx+2] ; Size of IP packet to send + xchg ch, cl ; because mirror byte-order + mov esi, ebx ; Pointer to packet data + mov bx, ETHER_IP ; Type of packet + push ebp + call dword [drvr_transmit]; Call the drivers transmit function + pop ebp + + ; OK, we have sent a packet, so increment the count + inc dword [ip_tx_count] + + ; And finally, return the buffer to the free queue + .freebuf: + pop eax + call freeBuff + + .exit: + ret +endp + +;*************************************************************************** +; Function +; ether_IP_handler +; +; Description +; Called when an IP ethernet packet is received on the ethernet +; Header + Data is in Ether_buffer[] +; We just need to get a buffer from the 'free' queue, and +; store the packet in it, then insert the packet number into the +; IPRX queue. +; If no queue entry is available, the packet is silently discarded +; All registers may be destroyed +; +;*************************************************************************** +;uglobal +; ether_IP_handler_cnt dd ? +;endg +ether_IP_handler: + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je eiph00x + + ; convert buffer pointer eax to the absolute address + push eax + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edi, eax + + ; get a pointer to the start of the DATA + mov esi, ETH_FRAME.Data + + ; Now store it all away + mov ecx, IPBUFFSIZE / 4 ; Copy all of the available + ; data across - worse case + cld + rep movsd + +; inc [ether_IP_handler_cnt] +; DEBUGF 1, "K : ether_IP_handler (%u)\n", [ether_IP_handler_cnt] + + ; And finally, place the buffer in the IPRX queue + pop ebx + mov eax, IPIN_QUEUE + call queue + +eiph00x: + ret + +;*************************************************************************** +; Function +; eth_probe +; Description +; Searches for an ethernet card. If found, the card is enabled and +; the ethernet -> IP link established +; +; This function scans the PCI bus looking for a supported device. +; ISA bus is currently not supported. +; +; eax is 0 if no hardware found +;*************************************************************************** +eth_probe: + ; Find a card on the PCI bus, and get it's address + call scan_bus ; Find the ethernet cards PIC address + xor eax, eax + cmp [io_addr], eax + je ep_00x ; Return 0 in eax if no cards found + + call dword [drvr_probe] ; Call the drivers probe function + + mov eax, [io_addr] ; return a non zero value + +ep_00x: + ret + +;*************************************************************************** +; Function +; ethernet_driver +; +; Description +; The ethernet RX and TX handler +; This is a kernel function, called by stack_handler +; +;*************************************************************************** +ethernet_driver: + ; Do nothing if the driver is inactive + cmp [ethernet_active], byte 0 + je eth_exit + + call eth_rx + call eth_tx + +eth_exit: + ret + +;*************************************************************************** +; Function +; eth_rx +; +; Description +; Polls the ethernet card for received data. Extracts if present +; Depending on the Protocol within the packet: +; ARP : Pass to ARP_handler. This may result in an ARP reply +; being tx'ed +; IP : Store in an IP buffer +; +;*************************************************************************** +eth_rx: + xor ax, ax + mov [eth_rx_data_len], ax + call dword [drvr_poll] ; Call the drivers poll function + + mov ax, [eth_rx_data_len] + cmp ax, 0 + je .exit + + + ; Check the protocol. Call appropriate handler + + mov ax, [ETH_FRAME.Type]; The address of the protocol word + + cmp ax, ETHER_IP + je .is_ip ; It's IP + + cmp ax, ETHER_ARP + je .is_arp ; It is ARP + + DEBUGF 1,"K : eth_rx - dumped (%u)\n", ax + inc [dumped_rx_count] + jmp .exit ; If not IP or ARP, ignore + + .is_ip: +; DEBUGF 1,"K : eth_rx - IP packet\n" + inc dword [ip_rx_count] + call ether_IP_handler + jmp .exit + + .is_arp: +; DEBUGF 1,"K : eth_rx - ARP packet\n" + ; At this point, the packet is still in the Ether_buffer + call arp_handler + + .exit: + ret diff --git a/kernel/trunk/network/eth_drv/pci.inc b/kernel/trunk/network/eth_drv/pci.inc index 5935480c9..6bd451cfc 100644 --- a/kernel/trunk/network/eth_drv/pci.inc +++ b/kernel/trunk/network/eth_drv/pci.inc @@ -1,351 +1,351 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;*************************************************************************** -; -; PCI CODE FOLLOWS -; -; the following functions provide access to the PCI interface. -; These functions are used by scan_bus, and also some ethernet drivers -; -;*************************************************************************** - -; PCI Bus defines -PCI_HEADER_TYPE equ 0x0e ;8 bit -PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit -PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits -PCI_BASE_ADDRESS_SPACE_IO equ 0x01 -PCI_VENDOR_ID equ 0x00 ;16 bit -PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC - -;*************************************************************************** -; Function -; config_cmd -; -; Description -; creates a command dword for use with the PCI bus -; bus # in ebx -; devfn in ecx -; where in edx -; -; command dword returned in eax -; Only eax destroyed -;*************************************************************************** -config_cmd: - push ecx - mov eax, ebx - shl eax, 16 - or eax, 0x80000000 - shl ecx, 8 - or eax, ecx - pop ecx - or eax, edx - and eax, 0xFFFFFFFC - ret - -;*************************************************************************** -; Function -; pcibios_read_config_byte -; -; Description -; reads a byte from the PCI config space -; bus # in ebx -; devfn in ecx -; where in edx ( ls 16 bits significant ) -; -; byte returned in al ( rest of eax zero ) -; Only eax/edx destroyed -;*************************************************************************** -pcibios_read_config_byte: - call config_cmd - push dx - mov dx, 0xCF8 - out dx, eax - pop dx - - xor eax, eax - and dx, 0x03 - add dx, 0xCFC -; and dx, 0xFFC - in al, dx - ret - -;*************************************************************************** -; Function -; pcibios_read_config_word -; -; Description -; reads a word from the PCI config space -; bus # in ebx -; devfn in ecx -; where in edx ( ls 16 bits significant ) -; -; word returned in ax ( rest of eax zero ) -; Only eax/edx destroyed -;*************************************************************************** -pcibios_read_config_word: - call config_cmd - push dx - mov dx, 0xCF8 - out dx, eax - pop dx - - xor eax, eax - and dx, 0x02 - add dx, 0xCFC -; and dx, 0xFFC - in ax, dx - ret - -;*************************************************************************** -; Function -; pcibios_read_config_dword -; -; Description -; reads a dword from the PCI config space -; bus # in ebx -; devfn in ecx -; where in edx ( ls 16 bits significant ) -; -; dword returned in eax -; Only eax/edx destroyed -;*************************************************************************** -pcibios_read_config_dword: - push edx - call config_cmd - push dx - mov dx, 0xCF8 - out dx, eax - pop dx - xor eax, eax - mov dx, 0xCFC - in eax, dx - pop edx - ret - -;*************************************************************************** -; Function -; pcibios_write_config_byte -; -; Description -; write a byte in al to the PCI config space -; bus # in ebx -; devfn in ecx -; where in edx ( ls 16 bits significant ) -; -; Only eax/edx destroyed -;*************************************************************************** -pcibios_write_config_byte: - push ax - call config_cmd - push dx - mov dx, 0xCF8 - out dx, eax - pop dx - pop ax - - and dx, 0x03 - add dx, 0xCFC - out dx, al - ret - -;*************************************************************************** -; Function -; pcibios_write_config_word -; -; Description -; write a word in ax to the PCI config space -; bus # in ebx -; devfn in ecx -; where in edx ( ls 16 bits significant ) -; -; Only eax/edx destroyed -;*************************************************************************** -pcibios_write_config_word: - push ax - call config_cmd - push dx - mov dx, 0xCF8 - out dx, eax - pop dx - pop ax - - and dx, 0x02 - add dx, 0xCFC - out dx, ax - ret - -;*************************************************************************** -; Function -; delay_us -; -; Description -; delays for 30 to 60 us -; -; I would prefer this routine to be able to delay for -; a selectable number of microseconds, but this works for now. -; -; If you know a better way to do 2us delay, pleae tell me! -;*************************************************************************** -delay_us: - push eax - push ecx - - mov ecx,2 - - in al,0x61 - and al,0x10 - mov ah,al - cld - -dcnt1: - in al,0x61 - and al,0x10 - cmp al,ah - jz dcnt1 - - mov ah,al - loop dcnt1 - - pop ecx - pop eax - - ret - -;*************************************************************************** -; Function -; scan_bus -; -; Description -; Scans the PCI bus for a supported device -; If a supported device is found, the drvr_ variables are initialised -; to that drivers functions ( as defined in the PCICards table) -; -; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid -; pci_data holds the PCI vendor + device code -; pci_dev holds PCI bus dev # -; pci_bus holds PCI bus # -; -; io_addr will be zero if no card found -; -;*************************************************************************** -scan_bus: - xor eax, eax - mov [hdrtype], al - mov [pci_data], eax - - xor ebx, ebx ; ebx = bus# 0 .. 255 - -sb_bus_loop: - xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? ) - -sb_devf_loop: - mov eax, ecx - and eax, 0x07 - - cmp eax, 0 - jne sb_001 - - mov edx, PCI_HEADER_TYPE - call pcibios_read_config_byte - mov [hdrtype], al - jmp sb_002 - -sb_001: - mov al, [hdrtype] - and al, 0x80 - cmp al, 0x80 - jne sb_inc_devf - -sb_002: - mov edx, PCI_VENDOR_ID - call pcibios_read_config_dword - mov [vendor_device], eax - cmp eax, 0xffffffff - je sb_empty - cmp eax, 0 - jne sb_check_vendor - -sb_empty: - mov [hdrtype], byte 0 - jmp sb_inc_devf - -sb_check_vendor: - ; iterate though PCICards until end or match found - mov esi, PCICards - -sb_check: - cmp [esi], dword 0 - je sb_inc_devf ; Quit if at last entry - cmp eax, [esi] - je sb_got_card - add esi, PCICARDS_ENTRY_SIZE - jmp sb_check - -sb_got_card: - ; indicate that we have found the card - mov [pci_data], eax - mov [pci_dev], ecx - mov [pci_bus], ebx - - ; Define the driver functions - push eax - mov eax, [esi+4] - mov [drvr_probe], eax - mov eax, [esi+8] - mov [drvr_reset], eax - mov eax, [esi+12] - mov [drvr_poll], eax - mov eax, [esi+16] - mov [drvr_transmit], eax - mov eax, [esi+20] - mov [drvr_cable], eax - pop eax - - mov edx, PCI_BASE_ADDRESS_0 - -sb_reg_check: - call pcibios_read_config_dword - mov [io_addr], eax - and eax, PCI_BASE_ADDRESS_IO_MASK - cmp eax, 0 - je sb_inc_reg - mov eax, [io_addr] - and eax, PCI_BASE_ADDRESS_SPACE_IO - cmp eax, 0 - je sb_inc_reg - - mov eax, [io_addr] - and eax, PCI_BASE_ADDRESS_IO_MASK - mov [io_addr], eax - -sb_exit1: - ret - -sb_inc_reg: - add edx, 4 - cmp edx, PCI_BASE_ADDRESS_5 - jbe sb_reg_check - -sb_inc_devf: - inc ecx - cmp ecx, 255 - jb sb_devf_loop - inc ebx - cmp ebx, 256 - jb sb_bus_loop - - ; We get here if we didn't find our card - ; set io_addr to 0 as an indication - xor eax, eax - mov [io_addr], eax - -sb_exit2: - ret \ No newline at end of file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;*************************************************************************** +; +; PCI CODE FOLLOWS +; +; the following functions provide access to the PCI interface. +; These functions are used by scan_bus, and also some ethernet drivers +; +;*************************************************************************** + +; PCI Bus defines +PCI_HEADER_TYPE equ 0x0e ;8 bit +PCI_BASE_ADDRESS_0 equ 0x10 ;32 bit +PCI_BASE_ADDRESS_5 equ 0x24 ;32 bits +PCI_BASE_ADDRESS_SPACE_IO equ 0x01 +PCI_VENDOR_ID equ 0x00 ;16 bit +PCI_BASE_ADDRESS_IO_MASK equ 0xFFFFFFFC + +;*************************************************************************** +; Function +; config_cmd +; +; Description +; creates a command dword for use with the PCI bus +; bus # in ebx +; devfn in ecx +; where in edx +; +; command dword returned in eax +; Only eax destroyed +;*************************************************************************** +config_cmd: + push ecx + mov eax, ebx + shl eax, 16 + or eax, 0x80000000 + shl ecx, 8 + or eax, ecx + pop ecx + or eax, edx + and eax, 0xFFFFFFFC + ret + +;*************************************************************************** +; Function +; pcibios_read_config_byte +; +; Description +; reads a byte from the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; byte returned in al ( rest of eax zero ) +; Only eax/edx destroyed +;*************************************************************************** +pcibios_read_config_byte: + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + + xor eax, eax + and dx, 0x03 + add dx, 0xCFC +; and dx, 0xFFC + in al, dx + ret + +;*************************************************************************** +; Function +; pcibios_read_config_word +; +; Description +; reads a word from the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; word returned in ax ( rest of eax zero ) +; Only eax/edx destroyed +;*************************************************************************** +pcibios_read_config_word: + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + + xor eax, eax + and dx, 0x02 + add dx, 0xCFC +; and dx, 0xFFC + in ax, dx + ret + +;*************************************************************************** +; Function +; pcibios_read_config_dword +; +; Description +; reads a dword from the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; dword returned in eax +; Only eax/edx destroyed +;*************************************************************************** +pcibios_read_config_dword: + push edx + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + xor eax, eax + mov dx, 0xCFC + in eax, dx + pop edx + ret + +;*************************************************************************** +; Function +; pcibios_write_config_byte +; +; Description +; write a byte in al to the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; Only eax/edx destroyed +;*************************************************************************** +pcibios_write_config_byte: + push ax + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + pop ax + + and dx, 0x03 + add dx, 0xCFC + out dx, al + ret + +;*************************************************************************** +; Function +; pcibios_write_config_word +; +; Description +; write a word in ax to the PCI config space +; bus # in ebx +; devfn in ecx +; where in edx ( ls 16 bits significant ) +; +; Only eax/edx destroyed +;*************************************************************************** +pcibios_write_config_word: + push ax + call config_cmd + push dx + mov dx, 0xCF8 + out dx, eax + pop dx + pop ax + + and dx, 0x02 + add dx, 0xCFC + out dx, ax + ret + +;*************************************************************************** +; Function +; delay_us +; +; Description +; delays for 30 to 60 us +; +; I would prefer this routine to be able to delay for +; a selectable number of microseconds, but this works for now. +; +; If you know a better way to do 2us delay, pleae tell me! +;*************************************************************************** +delay_us: + push eax + push ecx + + mov ecx, 2 + + in al, 0x61 + and al, 0x10 + mov ah, al + cld + +dcnt1: + in al, 0x61 + and al, 0x10 + cmp al, ah + jz dcnt1 + + mov ah, al + loop dcnt1 + + pop ecx + pop eax + + ret + +;*************************************************************************** +; Function +; scan_bus +; +; Description +; Scans the PCI bus for a supported device +; If a supported device is found, the drvr_ variables are initialised +; to that drivers functions ( as defined in the PCICards table) +; +; io_addr holds card I/O space. 32 bit, but only LS 16 bits valid +; pci_data holds the PCI vendor + device code +; pci_dev holds PCI bus dev # +; pci_bus holds PCI bus # +; +; io_addr will be zero if no card found +; +;*************************************************************************** +scan_bus: + xor eax, eax + mov [hdrtype], al + mov [pci_data], eax + + xor ebx, ebx ; ebx = bus# 0 .. 255 + +sb_bus_loop: + xor ecx, ecx ; ecx = devfn# 0 .. 254 ( not 255? ) + +sb_devf_loop: + mov eax, ecx + and eax, 0x07 + + cmp eax, 0 + jne sb_001 + + mov edx, PCI_HEADER_TYPE + call pcibios_read_config_byte + mov [hdrtype], al + jmp sb_002 + +sb_001: + mov al, [hdrtype] + and al, 0x80 + cmp al, 0x80 + jne sb_inc_devf + +sb_002: + mov edx, PCI_VENDOR_ID + call pcibios_read_config_dword + mov [vendor_device], eax + cmp eax, 0xffffffff + je sb_empty + cmp eax, 0 + jne sb_check_vendor + +sb_empty: + mov [hdrtype], byte 0 + jmp sb_inc_devf + +sb_check_vendor: + ; iterate though PCICards until end or match found + mov esi, PCICards + +sb_check: + cmp [esi], dword 0 + je sb_inc_devf ; Quit if at last entry + cmp eax, [esi] + je sb_got_card + add esi, PCICARDS_ENTRY_SIZE + jmp sb_check + +sb_got_card: + ; indicate that we have found the card + mov [pci_data], eax + mov [pci_dev], ecx + mov [pci_bus], ebx + + ; Define the driver functions + push eax + mov eax, [esi+4] + mov [drvr_probe], eax + mov eax, [esi+8] + mov [drvr_reset], eax + mov eax, [esi+12] + mov [drvr_poll], eax + mov eax, [esi+16] + mov [drvr_transmit], eax + mov eax, [esi+20] + mov [drvr_cable], eax + pop eax + + mov edx, PCI_BASE_ADDRESS_0 + +sb_reg_check: + call pcibios_read_config_dword + mov [io_addr], eax + and eax, PCI_BASE_ADDRESS_IO_MASK + cmp eax, 0 + je sb_inc_reg + mov eax, [io_addr] + and eax, PCI_BASE_ADDRESS_SPACE_IO + cmp eax, 0 + je sb_inc_reg + + mov eax, [io_addr] + and eax, PCI_BASE_ADDRESS_IO_MASK + mov [io_addr], eax + +sb_exit1: + ret + +sb_inc_reg: + add edx, 4 + cmp edx, PCI_BASE_ADDRESS_5 + jbe sb_reg_check + +sb_inc_devf: + inc ecx + cmp ecx, 255 + jb sb_devf_loop + inc ebx + cmp ebx, 256 + jb sb_bus_loop + + ; We get here if we didn't find our card + ; set io_addr to 0 as an indication + xor eax, eax + mov [io_addr], eax + +sb_exit2: + ret diff --git a/kernel/trunk/network/icmp.inc b/kernel/trunk/network/icmp.inc index 5c0fc9f2f..67e7b6b39 100644 --- a/kernel/trunk/network/icmp.inc +++ b/kernel/trunk/network/icmp.inc @@ -1,193 +1,193 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ICMP.INC ;; -;; ;; -;; Internet Control Message Protocol ( RFC 792 ) ;; -;; ;; -;; Last revision: 11.11.2006 ;; -;; ;; -;; This file contains the following: ;; -;; icmp_rx - processes ICMP-packets received by the IP layer ;; -;; ;; -;; Changes history: ;; -;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; -;; 11.11.2006 - [Johnny_B] and [smb] ;; -;; ;; -;; Current status: ;; -;; This implemetation of ICMP proto supports message of ECHO type. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -struc ICMP_PACKET -{ .Type db ? ;+00 - .Code db ? ;+01 - .Checksum dw ? ;+02 - .Identifier dw ? ;+04 - .SequenceNumber dw ? ;+06 - .Data db ? ;+08 -} - -virtual at 0 - ICMP_PACKET ICMP_PACKET -end virtual - - -; Example: -; ECHO message format -; -; -; 0 1 2 3 -; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Type | Code | Checksum | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Identifier | Sequence Number | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Data ... -; +-+-+-+-+- -; - -; -; ICMP types & codes, RFC 792 and FreeBSD's ICMP sources -; - -ICMP_ECHOREPLY equ 0 ; echo reply message - -ICMP_UNREACH equ 3 - ICMP_UNREACH_NET equ 0 ; bad net - ICMP_UNREACH_HOST equ 1 ; bad host - ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol - ICMP_UNREACH_PORT equ 3 ; bad port - ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop - ICMP_UNREACH_SRCFAIL equ 5 ; src route failed - ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net - ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host - ICMP_UNREACH_ISOLATED equ 8 ; src host isolated - ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access - ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto - ICMP_UNREACH_TOSNET equ 11 ; bad tos for net - ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host - ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib - ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio. - ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff - -ICMP_SOURCEQUENCH equ 4 ; packet lost, slow down - -ICMP_REDIRECT equ 5 ; shorter route, codes: - ICMP_REDIRECT_NET equ 0 ; for network - ICMP_REDIRECT_HOST equ 1 ; for host - ICMP_REDIRECT_TOSNET equ 2 ; for tos and net - ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host - -ICMP_ALTHOSTADDR equ 6 ; alternate host address -ICMP_ECHO equ 8 ; echo service -ICMP_ROUTERADVERT equ 9 ; router advertisement - ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement - ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing - -ICMP_ROUTERSOLICIT equ 10 ; router solicitation -ICMP_TIMXCEED equ 11 ; time exceeded, code: - ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit - ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass - -ICMP_PARAMPROB equ 12 ; ip header bad - ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr - ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent - ICMP_PARAMPROB_LENGTH equ 2 ; bad length - -ICMP_TSTAMP equ 13 ; timestamp request -ICMP_TSTAMPREPLY equ 14 ; timestamp reply -ICMP_IREQ equ 15 ; information request -ICMP_IREQREPLY equ 16 ; information reply -ICMP_MASKREQ equ 17 ; address mask request -ICMP_MASKREPLY equ 18 ; address mask reply -ICMP_TRACEROUTE equ 30 ; traceroute -ICMP_DATACONVERR equ 31 ; data conversion error -ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect -ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you - ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here -ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req -ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply -ICMP_SKIP equ 39 ; SKIP - -ICMP_PHOTURIS equ 40 ; Photuris - ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index - ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed - ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed - - -;*************************************************************************** -; Function -; icmp_rx [by Johnny_B] -; -; Description -; ICMP protocol handler -; This is a kernel function, called by ip_rx -; -; IN: -; buffer_number - # of IP-buffer. This buffer must be reused or marked as empty afterwards -; IPPacketBase - IP_PACKET base address -; IPHeaderLength - Header length of IP_PACKET -; -; OUT: -; EAX=not defined -; -; All used registers will be saved -; -;*************************************************************************** -proc icmp_rx stdcall uses ebx esi edi,\ - buffer_number:DWORD,IPPacketBase:DWORD,IPHeaderLength:DWORD - - mov esi,[IPPacketBase] ;esi=IP_PACKET base address - mov edi, esi - add edi,[IPHeaderLength] ;edi=ICMP_PACKET base address - - cmp byte[edi + ICMP_PACKET.Type], ICMP_ECHO ; Is this an echo request? discard if not - jz .icmp_echo - - mov eax, [buffer_number] - call freeBuff - jmp .exit - - .icmp_echo: - - ; swap the source and destination addresses - mov ecx, [esi + IP_PACKET.DestinationAddress] - mov ebx, [esi + IP_PACKET.SourceAddress] - mov [esi + IP_PACKET.DestinationAddress], ebx - mov [esi + IP_PACKET.SourceAddress], ecx - - ; recalculate the IP header checksum - mov eax,[IPHeaderLength] - stdcall checksum_jb,esi,eax ;buf_ptr,buf_size - - mov byte[esi + IP_PACKET.HeaderChecksum], ah - mov byte[esi + IP_PACKET.HeaderChecksum + 1], al ; ?? correct byte order? - - mov byte[edi + ICMP_PACKET.Type], ICMP_ECHOREPLY ; change the request to a response - mov word[edi + ICMP_PACKET.Checksum], 0 ; clear ICMP checksum prior to re-calc - - ; Calculate the length of the ICMP data ( IP payload) - xor eax, eax - mov ah, byte[esi + IP_PACKET.TotalLength] - mov al, byte[esi + IP_PACKET.TotalLength + 1] - sub ax, word[IPHeaderLength] ;ax=ICMP-packet length - - stdcall checksum_jb,edi,eax ;buf_ptr,buf_size - - mov byte[edi + ICMP_PACKET.Checksum], ah - mov byte[edi + ICMP_PACKET.Checksum + 1], al - - ; Queue packet for transmission - mov ebx, [buffer_number] - mov eax, NET1OUT_QUEUE - call queue - - .exit: - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ICMP.INC ;; +;; ;; +;; Internet Control Message Protocol ( RFC 792 ) ;; +;; ;; +;; Last revision: 11.11.2006 ;; +;; ;; +;; This file contains the following: ;; +;; icmp_rx - processes ICMP-packets received by the IP layer ;; +;; ;; +;; Changes history: ;; +;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; +;; 11.11.2006 - [Johnny_B] and [smb] ;; +;; ;; +;; Current status: ;; +;; This implemetation of ICMP proto supports message of ECHO type. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +struc ICMP_PACKET +{ .Type db ? ;+00 + .Code db ? ;+01 + .Checksum dw ? ;+02 + .Identifier dw ? ;+04 + .SequenceNumber dw ? ;+06 + .Data db ? ;+08 +} + +virtual at 0 + ICMP_PACKET ICMP_PACKET +end virtual + + +; Example: +; ECHO message format +; +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Type | Code | Checksum | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Identifier | Sequence Number | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Data ... +; +-+-+-+-+- +; + +; +; ICMP types & codes, RFC 792 and FreeBSD's ICMP sources +; + +ICMP_ECHOREPLY equ 0 ; echo reply message + +ICMP_UNREACH equ 3 + ICMP_UNREACH_NET equ 0 ; bad net + ICMP_UNREACH_HOST equ 1 ; bad host + ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol + ICMP_UNREACH_PORT equ 3 ; bad port + ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop + ICMP_UNREACH_SRCFAIL equ 5 ; src route failed + ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net + ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host + ICMP_UNREACH_ISOLATED equ 8 ; src host isolated + ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access + ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto + ICMP_UNREACH_TOSNET equ 11 ; bad tos for net + ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host + ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib + ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio. + ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff + +ICMP_SOURCEQUENCH equ 4 ; packet lost, slow down + +ICMP_REDIRECT equ 5 ; shorter route, codes: + ICMP_REDIRECT_NET equ 0 ; for network + ICMP_REDIRECT_HOST equ 1 ; for host + ICMP_REDIRECT_TOSNET equ 2 ; for tos and net + ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host + +ICMP_ALTHOSTADDR equ 6 ; alternate host address +ICMP_ECHO equ 8 ; echo service +ICMP_ROUTERADVERT equ 9 ; router advertisement + ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement + ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing + +ICMP_ROUTERSOLICIT equ 10 ; router solicitation +ICMP_TIMXCEED equ 11 ; time exceeded, code: + ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit + ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass + +ICMP_PARAMPROB equ 12 ; ip header bad + ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr + ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent + ICMP_PARAMPROB_LENGTH equ 2 ; bad length + +ICMP_TSTAMP equ 13 ; timestamp request +ICMP_TSTAMPREPLY equ 14 ; timestamp reply +ICMP_IREQ equ 15 ; information request +ICMP_IREQREPLY equ 16 ; information reply +ICMP_MASKREQ equ 17 ; address mask request +ICMP_MASKREPLY equ 18 ; address mask reply +ICMP_TRACEROUTE equ 30 ; traceroute +ICMP_DATACONVERR equ 31 ; data conversion error +ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect +ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you + ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here +ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req +ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply +ICMP_SKIP equ 39 ; SKIP + +ICMP_PHOTURIS equ 40 ; Photuris + ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index + ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed + ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed + + +;*************************************************************************** +; Function +; icmp_rx [by Johnny_B] +; +; Description +; ICMP protocol handler +; This is a kernel function, called by ip_rx +; +; IN: +; buffer_number - # of IP-buffer. This buffer must be reused or marked as empty afterwards +; IPPacketBase - IP_PACKET base address +; IPHeaderLength - Header length of IP_PACKET +; +; OUT: +; EAX=not defined +; +; All used registers will be saved +; +;*************************************************************************** +proc icmp_rx stdcall uses ebx esi edi,\ + buffer_number:DWORD,IPPacketBase:DWORD,IPHeaderLength:DWORD + + mov esi, [IPPacketBase];esi=IP_PACKET base address + mov edi, esi + add edi, [IPHeaderLength];edi=ICMP_PACKET base address + + cmp byte[edi + ICMP_PACKET.Type], ICMP_ECHO; Is this an echo request? discard if not + jz .icmp_echo + + mov eax, [buffer_number] + call freeBuff + jmp .exit + + .icmp_echo: + + ; swap the source and destination addresses + mov ecx, [esi + IP_PACKET.DestinationAddress] + mov ebx, [esi + IP_PACKET.SourceAddress] + mov [esi + IP_PACKET.DestinationAddress], ebx + mov [esi + IP_PACKET.SourceAddress], ecx + + ; recalculate the IP header checksum + mov eax, [IPHeaderLength] + stdcall checksum_jb, esi, eax;buf_ptr,buf_size + + mov byte[esi + IP_PACKET.HeaderChecksum], ah + mov byte[esi + IP_PACKET.HeaderChecksum + 1], al ; ?? correct byte order? + + mov byte[edi + ICMP_PACKET.Type], ICMP_ECHOREPLY; change the request to a response + mov word[edi + ICMP_PACKET.Checksum], 0; clear ICMP checksum prior to re-calc + + ; Calculate the length of the ICMP data ( IP payload) + xor eax, eax + mov ah, byte[esi + IP_PACKET.TotalLength] + mov al, byte[esi + IP_PACKET.TotalLength + 1] + sub ax, word[IPHeaderLength];ax=ICMP-packet length + + stdcall checksum_jb, edi, eax;buf_ptr,buf_size + + mov byte[edi + ICMP_PACKET.Checksum], ah + mov byte[edi + ICMP_PACKET.Checksum + 1], al + + ; Queue packet for transmission + mov ebx, [buffer_number] + mov eax, NET1OUT_QUEUE + call queue + + .exit: + ret +endp diff --git a/kernel/trunk/network/ip.inc b/kernel/trunk/network/ip.inc index 2fda5fd3e..3d421109d 100644 --- a/kernel/trunk/network/ip.inc +++ b/kernel/trunk/network/ip.inc @@ -1,244 +1,244 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; IP.INC ;; -;; ;; -;; IP Processes for Menuet OS TCP/IP stack ;; -;; ;; -;; Version 0.3 29 August 2002 ;; -;; ;; -;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; IP underlying protocols numbers -PROTOCOL_ICMP equ 1 -PROTOCOL_TCP equ 6 -PROTOCOL_UDP equ 17 - -struc IP_PACKET -{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits] - .TypeOfService db ? ;+01 - .TotalLength dw ? ;+02 - .Identification dw ? ;+04 - .FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15] - .TimeToLive db ? ;+08 - .Protocol db ? ;+09 - .HeaderChecksum dw ? ;+10 - .SourceAddress dd ? ;+12 - .DestinationAddress dd ? ;+16 - .DataOrOptional dd ? ;+20 -} - -virtual at 0 - IP_PACKET IP_PACKET -end virtual - - -;******************************************************************* -; Interface -; -; ip_rx processes all packets received by the network layer -; It calls the appropriate protocol handler -; -; -; -;******************************************************************* - - -; -; IP Packet after reception - Normal IP packet format -; -; 0 1 2 3 -; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 -; -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;0 |Version| IHL |Type of Service| Total Length | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;4 | Identification |Flags| Fragment Offset | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;8 | Time to Live | Protocol | Header Checksum | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;12 | Source Address | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;16 | Destination Address | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;20 | Data | -; +-+-+-.......... -+ -; -; -; [smb] attention! according to RFC 791 IP packet may have 'options' sections, -; so we can't simply think, that data have offset 20. We must calculate offset from -; IHL field -; -macro GET_IHL reg, header_addr -{ - movzx reg, byte [header_addr] - - ; we need 4-7 bits, so.... - and reg, 0x0000000F - - ; IHL keeps number of octets, so we need to << 2 'reg' - shl reg, 2 -} - - -include "tcp.inc" -include "udp.inc" -include "icmp.inc" - -;*************************************************************************** -; Function -; ip_rx -; -; Description -; This is a kernel function, called by stack_handler -; Processes all IP-packets received by the network layer -; It calls the appropriate protocol handler -; -;*************************************************************************** -proc ip_rx stdcall -local buffer_number dd ? - - ; Look for a buffer to tx - mov eax, IPIN_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .exit ; Exit if no buffer available - - mov [buffer_number], eax ;save buffer number - - ; convert buffer pointer eax to the absolute address - imul eax, IPBUFFSIZE - add eax, IPbuffs - - mov ebx, eax ; ebx=pointer to IP_PACKET - -; DEBUGF 1, "K : ip_rx - proto: %u\n", [ebx + IP_PACKET.Protocol]:1 - - ; Validate the IP checksum - mov dx, word[ebx + IP_PACKET.HeaderChecksum] - xchg dh,dl ; Get the checksum in intel format - - mov [ebx + IP_PACKET.HeaderChecksum], 0 ; clear checksum field - need to when - ; recalculating checksum - ; this needs two data pointers and two size #. - ; 2nd pointer can be of length 0 - - GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx - stdcall checksum_jb, ebx, ecx ;buf_ptr, buf_size - cmp dx, ax - -; DEBUGF 1, "K : ip_rx - checksums: %x - %x\n", dx, ax - - jnz .dump.1 ;if CHECKSUM isn't valid then dump packet - mov edx, ebx ; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!! - -; DEBUGF 1, "K : ip_rx - dest: %x - %x\n", [ebx + IP_PACKET.DestinationAddress], [stack_ip] - - ; Validate the IP address, if it isn't broadcast - mov eax, [stack_ip] - cmp dword[ebx + IP_PACKET.DestinationAddress], eax - je @f - - ; If the IP address is 255.255.255.255, accept it - ; - it is a broadcast packet, which we need for dhcp - - mov eax, [ebx + IP_PACKET.DestinationAddress] - cmp eax, 0xffffffff - je @f - mov ecx, [stack_ip] - and eax, [subnet_mask] - and ecx, [subnet_mask] - cmp eax, ecx - jne .dump.2 - mov eax, [ebx + IP_PACKET.DestinationAddress] - or eax, [subnet_mask] - cmp eax, 0xffffffff - jne .dump.2 - - @@: - mov al, [ebx + IP_PACKET.VersionAndIHL] - and al, 0x0f ;get IHL(header length) - cmp al, 0x05 ;if IHL!= 5*4(20 bytes) -; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al - jnz .dump.3 ;then dump it - -; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2 - - cmp [ebx + IP_PACKET.TimeToLive], 0 - je .dump.4 ;if TTL==0 then dump it - - mov ax, [ebx + IP_PACKET.FlagsAndFragmentOffset] - and ax, 0xFFBF ;get flags -; DEBUGF 1, "K : ip_rx - flags: %x - 0000\n", ax - cmp ax, 0 ;if some flags was set then we dump this packet - jnz .dump.5 ;the flags should be used for fragmented packets - - ; Check the protocol, and call the appropriate handler - ; Each handler will re-use or free the queue buffer as appropriate - - mov al, [ebx + IP_PACKET.Protocol] - - cmp al , PROTOCOL_TCP - jne .not_tcp -; DEBUGF 1,"K : ip_rx - TCP packet\n" - mov eax, dword[buffer_number] - call tcp_rx - jmp .exit - - .not_tcp: - cmp al, PROTOCOL_UDP - jne .not_udp -; DEBUGF 1,"K : ip_rx - UDP packet\n" - mov eax, dword[buffer_number] - call udp_rx - jmp .exit - - .not_udp: - cmp al, PROTOCOL_ICMP - jne .dump.6 ;protocol ain't supported - -; DEBUGF 1,"K : ip_rx - ICMP packet\n" - ;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx - mov eax, dword[buffer_number] - stdcall icmp_rx,eax,ebx,ecx ;buffer_number,IPPacketBase,IPHeaderLength - jmp .exit - - - .dump.1: - DEBUGF 1, "K : ip_rx - dumped (checksum: 0x%x-0x%x)\n", dx, ax - jmp .dump.x - - .dump.2: - DEBUGF 1, "K : ip_rx - dumped (ip: %u.%u.%u.%u)\n", [ebx + IP_PACKET.DestinationAddress + 0]:1, [ebx + IP_PACKET.DestinationAddress + 1]:1, [ebx + IP_PACKET.DestinationAddress + 2]:1, [ebx + IP_PACKET.DestinationAddress + 3]:1 - jmp .dump.x - - .dump.3: - DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", al - jmp .dump.x - - .dump.4: - DEBUGF 1, "K : ip_rx - dumped (ttl: %u)\n", [ebx + IP_PACKET.TimeToLive] - jmp .dump.x - - .dump.5: - DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax - jmp .dump.x - - .dump.6: - DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1 - - .dump.x: - inc dword[dumped_rx_count] - mov eax, [buffer_number] - call freeBuff - - .exit: - ret -endp - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; IP.INC ;; +;; ;; +;; IP Processes for Menuet OS TCP/IP stack ;; +;; ;; +;; Version 0.3 29 August 2002 ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; IP underlying protocols numbers +PROTOCOL_ICMP equ 1 +PROTOCOL_TCP equ 6 +PROTOCOL_UDP equ 17 + +struc IP_PACKET +{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits] + .TypeOfService db ? ;+01 + .TotalLength dw ? ;+02 + .Identification dw ? ;+04 + .FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15] + .TimeToLive db ? ;+08 + .Protocol db ? ;+09 + .HeaderChecksum dw ? ;+10 + .SourceAddress dd ? ;+12 + .DestinationAddress dd ? ;+16 + .DataOrOptional dd ? ;+20 +} + +virtual at 0 + IP_PACKET IP_PACKET +end virtual + + +;******************************************************************* +; Interface +; +; ip_rx processes all packets received by the network layer +; It calls the appropriate protocol handler +; +; +; +;******************************************************************* + + +; +; IP Packet after reception - Normal IP packet format +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +; +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;0 |Version| IHL |Type of Service| Total Length | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;4 | Identification |Flags| Fragment Offset | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;8 | Time to Live | Protocol | Header Checksum | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;12 | Source Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;16 | Destination Address | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;20 | Data | +; +-+-+-.......... -+ +; +; +; [smb] attention! according to RFC 791 IP packet may have 'options' sections, +; so we can't simply think, that data have offset 20. We must calculate offset from +; IHL field +; +macro GET_IHL reg, header_addr +{ + movzx reg, byte [header_addr] + + ; we need 4-7 bits, so.... + and reg, 0x0000000F + + ; IHL keeps number of octets, so we need to << 2 'reg' + shl reg, 2 +} + + +include "tcp.inc" +include "udp.inc" +include "icmp.inc" + +;*************************************************************************** +; Function +; ip_rx +; +; Description +; This is a kernel function, called by stack_handler +; Processes all IP-packets received by the network layer +; It calls the appropriate protocol handler +; +;*************************************************************************** +proc ip_rx stdcall +local buffer_number dd ? + + ; Look for a buffer to tx + mov eax, IPIN_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit ; Exit if no buffer available + + mov [buffer_number], eax;save buffer number + + ; convert buffer pointer eax to the absolute address + imul eax, IPBUFFSIZE + add eax, IPbuffs + + mov ebx, eax; ebx=pointer to IP_PACKET + +; DEBUGF 1, "K : ip_rx - proto: %u\n", [ebx + IP_PACKET.Protocol]:1 + + ; Validate the IP checksum + mov dx, word[ebx + IP_PACKET.HeaderChecksum] + xchg dh, dl ; Get the checksum in intel format + + mov [ebx + IP_PACKET.HeaderChecksum], 0; clear checksum field - need to when + ; recalculating checksum + ; this needs two data pointers and two size #. + ; 2nd pointer can be of length 0 + + GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx + stdcall checksum_jb, ebx, ecx;buf_ptr, buf_size + cmp dx, ax + +; DEBUGF 1, "K : ip_rx - checksums: %x - %x\n", dx, ax + + jnz .dump.1;if CHECKSUM isn't valid then dump packet + mov edx, ebx; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!! + +; DEBUGF 1, "K : ip_rx - dest: %x - %x\n", [ebx + IP_PACKET.DestinationAddress], [stack_ip] + + ; Validate the IP address, if it isn't broadcast + mov eax, [stack_ip] + cmp dword[ebx + IP_PACKET.DestinationAddress], eax + je @f + + ; If the IP address is 255.255.255.255, accept it + ; - it is a broadcast packet, which we need for dhcp + + mov eax, [ebx + IP_PACKET.DestinationAddress] + cmp eax, 0xffffffff + je @f + mov ecx, [stack_ip] + and eax, [subnet_mask] + and ecx, [subnet_mask] + cmp eax, ecx + jne .dump.2 + mov eax, [ebx + IP_PACKET.DestinationAddress] + or eax, [subnet_mask] + cmp eax, 0xffffffff + jne .dump.2 + + @@: + mov al, [ebx + IP_PACKET.VersionAndIHL] + and al, 0x0f;get IHL(header length) + cmp al, 0x05;if IHL!= 5*4(20 bytes) +; DEBUGF 1, "K : ip_rx - ihl: %x - 05\n", al + jnz .dump.3 ;then dump it + +; DEBUGF 1, "K : ip_rx - ttl: %x - 00\n", [ebx + IP_PACKET.TimeToLive]:2 + + cmp [ebx + IP_PACKET.TimeToLive], 0 + je .dump.4 ;if TTL==0 then dump it + + mov ax, [ebx + IP_PACKET.FlagsAndFragmentOffset] + and ax, 0xFFBF;get flags +; DEBUGF 1, "K : ip_rx - flags: %x - 0000\n", ax + cmp ax, 0 ;if some flags was set then we dump this packet + jnz .dump.5 ;the flags should be used for fragmented packets + + ; Check the protocol, and call the appropriate handler + ; Each handler will re-use or free the queue buffer as appropriate + + mov al, [ebx + IP_PACKET.Protocol] + + cmp al , PROTOCOL_TCP + jne .not_tcp +; DEBUGF 1,"K : ip_rx - TCP packet\n" + mov eax, dword[buffer_number] + call tcp_rx + jmp .exit + + .not_tcp: + cmp al, PROTOCOL_UDP + jne .not_udp +; DEBUGF 1,"K : ip_rx - UDP packet\n" + mov eax, dword[buffer_number] + call udp_rx + jmp .exit + + .not_udp: + cmp al, PROTOCOL_ICMP + jne .dump.6 ;protocol ain't supported + +; DEBUGF 1,"K : ip_rx - ICMP packet\n" + ;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx + mov eax, dword[buffer_number] + stdcall icmp_rx, eax, ebx, ecx;buffer_number,IPPacketBase,IPHeaderLength + jmp .exit + + + .dump.1: + DEBUGF 1, "K : ip_rx - dumped (checksum: 0x%x-0x%x)\n", dx, ax + jmp .dump.x + + .dump.2: + DEBUGF 1, "K : ip_rx - dumped (ip: %u.%u.%u.%u)\n", [ebx + IP_PACKET.DestinationAddress + 0]:1, [ebx + IP_PACKET.DestinationAddress + 1]:1, [ebx + IP_PACKET.DestinationAddress + 2]:1, [ebx + IP_PACKET.DestinationAddress + 3]:1 + jmp .dump.x + + .dump.3: + DEBUGF 1, "K : ip_rx - dumped (ihl: %u)\n", al + jmp .dump.x + + .dump.4: + DEBUGF 1, "K : ip_rx - dumped (ttl: %u)\n", [ebx + IP_PACKET.TimeToLive] + jmp .dump.x + + .dump.5: + DEBUGF 1, "K : ip_rx - dumped (flags: 0x%x)\n", ax + jmp .dump.x + + .dump.6: + DEBUGF 1, "K : ip_rx - dumped (proto: %u)\n", [ebx + IP_PACKET.Protocol]:1 + + .dump.x: + inc dword[dumped_rx_count] + mov eax, [buffer_number] + call freeBuff + + .exit: + ret +endp + diff --git a/kernel/trunk/network/queue.inc b/kernel/trunk/network/queue.inc index fb5d27ce9..ce330911e 100644 --- a/kernel/trunk/network/queue.inc +++ b/kernel/trunk/network/queue.inc @@ -1,229 +1,229 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ;; -;; QUEUE.INC ;; -;; ;; -;; Buffer queue management for Menuet OS TCP/IP Stack ;; -;; ;; -;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;******************************************************************* -; Interface -; -; queueInit Configures the queues to empty -; dequeue Removes a buffer pointer from a queue -; queue Inserts a buffer pointer into a queue -; freeBuff Adds the buffer pointer to the list of free buffers -; queueSize Returns the number of entries in a queue -; -; The various defines for queue names can be found in stack.inc -; -;******************************************************************* - - -;*************************************************************************** -; Function -; freeBuff -; -; Description -; Adds a buffer number to the beginning of the free list. -; buffer number in eax ( ms word zeroed ) -; all other registers preserved -; This always works, so no error returned -;*************************************************************************** -;uglobal -; freeBuff_cnt dd ? -;endg -freeBuff: -; inc [freeBuff_cnt] -; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt] - push ebx - push ecx - mov ebx, queues + EMPTY_QUEUE * 2 - cli ; Ensure that another process does not interfer - mov cx, [ebx] - mov [ebx], ax - mov [queueList + eax * 2], cx - sti - pop ecx - pop ebx - - ret - - -;*************************************************************************** -; Function -; queueSize -; -; Description -; Counts the number of entries in a queue -; queue number in ebx ( ms word zeroed ) -; Queue size returned in eax -; This always works, so no error returned -;*************************************************************************** -queueSize: - xor eax, eax - shl ebx, 1 - add ebx, queues - movzx ecx, word [ebx] - cmp cx, NO_BUFFER - je qs_exit - -qs_001: - inc eax - shl ecx, 1 - add ecx, queueList - movzx ecx, word [ecx] - cmp cx, NO_BUFFER - je qs_exit - jmp qs_001 - -qs_exit: - ret - - -;*************************************************************************** -; Function -; queue -; -; Description -; Adds a buffer number to the *end* of a queue -; This is quite quick because these queues will be short -; queue number in eax ( ms word zeroed ) -; buffer number in ebx ( ms word zeroed ) -; all other registers preserved -; This always works, so no error returned -;*************************************************************************** -;uglobal -; queue_cnt dd ? -;endg -queue: -; inc [queue_cnt] -; DEBUGF 1, "K : queue (%u)\n", [queue_cnt] - push ebx - shl ebx, 1 - add ebx, queueList ; eax now holds address of queue entry - mov [ebx], word NO_BUFFER ; This buffer will be the last - - cli - shl eax, 1 - add eax, queues ; eax now holds address of queue - movzx ebx, word [eax] - - cmp bx, NO_BUFFER - jne qu_001 - - pop ebx - ; The list is empty, so add this to the head - mov [eax], bx - jmp qu_exit - -qu_001: - ; Find the last entry - shl ebx, 1 - add ebx, queueList - mov eax, ebx - movzx ebx, word [ebx] - cmp bx, NO_BUFFER - jne qu_001 - - mov ebx, eax - pop eax - mov [ebx], ax - -qu_exit: - sti - ret - - - -;*************************************************************************** -; Function -; dequeue -; -; Description -; removes a buffer number from the head of a queue -; This is fast, as it unlinks the first entry in the list -; queue number in eax ( ms word zeroed ) -; buffer number returned in eax ( ms word zeroed ) -; all other registers preserved -; -;*************************************************************************** -;uglobal -; dequeue_cnt dd ? -;endg -dequeue: - push ebx - shl eax, 1 - add eax, queues ; eax now holds address of queue - mov ebx, eax - cli - movzx eax, word [eax] - cmp ax, NO_BUFFER - je dq_exit -; inc [dequeue_cnt] -; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt] - push eax - shl eax, 1 - add eax, queueList ; eax now holds address of queue entry - mov ax, [eax] - mov [ebx], ax - pop eax - -dq_exit: - sti - pop ebx - ret - - -;*************************************************************************** -; Function -; queueInit -; -; Description -; Initialises the queues to empty, and creates the free queue -; list. -; -;*************************************************************************** -queueInit: - mov esi, queues - mov ecx, NUMQUEUES - mov ax, NO_BUFFER - -qi001: - mov [esi], ax - inc esi - inc esi - loop qi001 - - mov esi, queues + ( 2 * EMPTY_QUEUE ) - - ; Initialise empty queue list - - xor ax, ax - mov [esi], ax - - mov ecx, NUMQUEUEENTRIES - 1 - mov esi, queueList - -qi002: - inc ax - mov [esi], ax - inc esi - inc esi - loop qi002 - - mov ax, NO_BUFFER - mov [esi], ax - - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; QUEUE.INC ;; +;; ;; +;; Buffer queue management for Menuet OS TCP/IP Stack ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;******************************************************************* +; Interface +; +; queueInit Configures the queues to empty +; dequeue Removes a buffer pointer from a queue +; queue Inserts a buffer pointer into a queue +; freeBuff Adds the buffer pointer to the list of free buffers +; queueSize Returns the number of entries in a queue +; +; The various defines for queue names can be found in stack.inc +; +;******************************************************************* + + +;*************************************************************************** +; Function +; freeBuff +; +; Description +; Adds a buffer number to the beginning of the free list. +; buffer number in eax ( ms word zeroed ) +; all other registers preserved +; This always works, so no error returned +;*************************************************************************** +;uglobal +; freeBuff_cnt dd ? +;endg +freeBuff: +; inc [freeBuff_cnt] +; DEBUGF 1, "K : freeBuff (%u)\n", [freeBuff_cnt] + push ebx + push ecx + mov ebx, queues + EMPTY_QUEUE * 2 + cli ; Ensure that another process does not interfer + mov cx, [ebx] + mov [ebx], ax + mov [queueList + eax * 2], cx + sti + pop ecx + pop ebx + + ret + + +;*************************************************************************** +; Function +; queueSize +; +; Description +; Counts the number of entries in a queue +; queue number in ebx ( ms word zeroed ) +; Queue size returned in eax +; This always works, so no error returned +;*************************************************************************** +queueSize: + xor eax, eax + shl ebx, 1 + add ebx, queues + movzx ecx, word [ebx] + cmp cx, NO_BUFFER + je qs_exit + +qs_001: + inc eax + shl ecx, 1 + add ecx, queueList + movzx ecx, word [ecx] + cmp cx, NO_BUFFER + je qs_exit + jmp qs_001 + +qs_exit: + ret + + +;*************************************************************************** +; Function +; queue +; +; Description +; Adds a buffer number to the *end* of a queue +; This is quite quick because these queues will be short +; queue number in eax ( ms word zeroed ) +; buffer number in ebx ( ms word zeroed ) +; all other registers preserved +; This always works, so no error returned +;*************************************************************************** +;uglobal +; queue_cnt dd ? +;endg +queue: +; inc [queue_cnt] +; DEBUGF 1, "K : queue (%u)\n", [queue_cnt] + push ebx + shl ebx, 1 + add ebx, queueList ; eax now holds address of queue entry + mov [ebx], word NO_BUFFER; This buffer will be the last + + cli + shl eax, 1 + add eax, queues ; eax now holds address of queue + movzx ebx, word [eax] + + cmp bx, NO_BUFFER + jne qu_001 + + pop ebx + ; The list is empty, so add this to the head + mov [eax], bx + jmp qu_exit + +qu_001: + ; Find the last entry + shl ebx, 1 + add ebx, queueList + mov eax, ebx + movzx ebx, word [ebx] + cmp bx, NO_BUFFER + jne qu_001 + + mov ebx, eax + pop eax + mov [ebx], ax + +qu_exit: + sti + ret + + + +;*************************************************************************** +; Function +; dequeue +; +; Description +; removes a buffer number from the head of a queue +; This is fast, as it unlinks the first entry in the list +; queue number in eax ( ms word zeroed ) +; buffer number returned in eax ( ms word zeroed ) +; all other registers preserved +; +;*************************************************************************** +;uglobal +; dequeue_cnt dd ? +;endg +dequeue: + push ebx + shl eax, 1 + add eax, queues ; eax now holds address of queue + mov ebx, eax + cli + movzx eax, word [eax] + cmp ax, NO_BUFFER + je dq_exit +; inc [dequeue_cnt] +; DEBUGF 1, "K : dequeue (%u)\n", [dequeue_cnt] + push eax + shl eax, 1 + add eax, queueList ; eax now holds address of queue entry + mov ax, [eax] + mov [ebx], ax + pop eax + +dq_exit: + sti + pop ebx + ret + + +;*************************************************************************** +; Function +; queueInit +; +; Description +; Initialises the queues to empty, and creates the free queue +; list. +; +;*************************************************************************** +queueInit: + mov esi, queues + mov ecx, NUMQUEUES + mov ax, NO_BUFFER + +qi001: + mov [esi], ax + inc esi + inc esi + loop qi001 + + mov esi, queues + ( 2 * EMPTY_QUEUE ) + + ; Initialise empty queue list + + xor ax, ax + mov [esi], ax + + mov ecx, NUMQUEUEENTRIES - 1 + mov esi, queueList + +qi002: + inc ax + mov [esi], ax + inc esi + inc esi + loop qi002 + + mov ax, NO_BUFFER + mov [esi], ax + + ret diff --git a/kernel/trunk/network/socket.inc b/kernel/trunk/network/socket.inc index 16616c298..ba2de0464 100644 --- a/kernel/trunk/network/socket.inc +++ b/kernel/trunk/network/socket.inc @@ -1,1124 +1,1129 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; SOCKET.INC ;; -;; ;; -;; Sockets constants, structures and functions ;; -;; ;; -;; This file contains the following: ;; -;; is_localport_unused ;; -;; get_free_socket ;; -;; socket_open ;; -;; socket_open_tcp ;; -;; socket_close ;; -;; socket_close_tcp ;; -;; socket_poll ;; -;; socket_status ;; -;; socket_read ;; -;; socket_write ;; -;; socket_write_tcp ;; -;; ;; -;; ;; -;; Changes history: ;; -;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; -;; 11.11.2006 - [Johnny_B] and [smb] ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -; socket data structure -struct SOCKET - .PrevPtr dd ? ; pointer to previous socket in list - .NextPtr dd ? ; pointer to next socket in list - .Number dd ? ; socket number (unique within single process) - .PID dd ? ; application process id - .LocalIP dd ? ; local IP address - .LocalPort dw ? ; local port - .RemoteIP dd ? ; remote IP address - .RemotePort dw ? ; remote port - .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) - .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) - .rxDataCount dd ? ; rx data count - .TCBState dd ? ; TCB state - .TCBTimer dd ? ; TCB timer (seconds) - .ISS dd ? ; initial send sequence - .IRS dd ? ; initial receive sequence - .SND_UNA dd ? ; sequence number of unack'ed sent packets - .SND_NXT dd ? ; bext send sequence number to use - .SND_WND dd ? ; send window - .RCV_NXT dd ? ; next receive sequence number to use - .RCV_WND dd ? ; receive window - .SEG_LEN dd ? ; segment length - .SEG_WND dd ? ; segment window - .wndsizeTimer dd ? ; window size timer - .lock MUTEX ; lock mutex - .rxData dd ? ; receive data buffer here -ends - -; TCP opening modes -SOCKET_PASSIVE = 0 -SOCKET_ACTIVE = 1 - -; socket types -SOCK_STREAM = 1 -SOCK_DGRAM = 2 - -; pointer to bitmap of free ports (1=free, 0=used) -uglobal -align 4 -network_free_ports dd ? -endg - -iglobal -align 4 -network_free_hint dd 1024/8 -endg - -;; Allocate memory for socket data and put new socket into the list -; Newly created socket is initialized with calling PID and number and -; put into beginning of list (which is a fastest way). -; -; @return socket structure address in EAX -;; -proc net_socket_alloc stdcall uses ebx ecx edx edi - stdcall kernel_alloc, SOCKETBUFFSIZE - DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax - ; check if we can allocate needed amount of memory - or eax, eax - jz .exit - - ; zero-initialize allocated memory - push eax - mov edi, eax - mov ecx, SOCKETBUFFSIZE / 4 - cld - xor eax, eax - rep stosd - pop eax - - mov ebx, eax - lea ecx, [eax+SOCKET.lock] - call mutex_init - mov eax, ebx - - ; add socket to the list by changing pointers - mov ebx, net_sockets - push [ebx + SOCKET.NextPtr] - mov [ebx + SOCKET.NextPtr], eax - mov [eax + SOCKET.PrevPtr], ebx - pop ebx - mov [eax + SOCKET.NextPtr], ebx - or ebx, ebx - jz @f - mov [ebx + SOCKET.PrevPtr], eax - - @@: ; set socket owner PID to the one of calling process - mov ebx, [TASK_BASE] - mov ebx, [ebx + TASKDATA.pid] - mov [eax + SOCKET.PID], ebx - - ; find first free socket number and use it - ;mov edx, ebx - mov ebx, net_sockets - xor ecx, ecx - .next_socket_number: - inc ecx - .next_socket: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .last_socket_number - cmp [ebx + SOCKET.Number], ecx - jne .next_socket - ;cmp [ebx + SOCKET.PID], edx - ;jne .next_socket - mov ebx, net_sockets - jmp .next_socket_number - - .last_socket_number: - mov [eax + SOCKET.Number], ecx - - .exit: - ret -endp - -;; Free socket data memory and pop socket off the list -; -; @param sockAddr is a socket structure address -;; -proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD - mov eax, [sockAddr] - DEBUGF 1, "K : net_socket_free (0x%x)\n", eax - ; check if we got something similar to socket structure address - or eax, eax - jz .error - - ; make sure sockAddr is one of the socket addresses in the list - mov ebx, net_sockets - ;mov ecx, [TASK_BASE] - ;mov ecx, [ecx + TASKDATA.pid] - .next_socket: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .error - cmp ebx, eax - jne .next_socket - ;cmp [ebx + SOCKET.PID], ecx - ;jne .next_socket - - ; okay, we found the correct one - ; mark local port as unused - movzx ebx, [eax + SOCKET.LocalPort] - push eax - mov eax, [network_free_ports] - xchg bl, bh -lock bts [eax], ebx - pop eax - ; remove it from the list first, changing pointers - mov ebx, [eax + SOCKET.NextPtr] - mov eax, [eax + SOCKET.PrevPtr] - mov [eax + SOCKET.NextPtr], ebx - or ebx, ebx - jz @f - mov [ebx + SOCKET.PrevPtr], eax - - @@: ; and finally free the memory structure used - stdcall kernel_free, [sockAddr] - ret - - .error: - DEBUGF 1, "K : failed\n" - ret -endp - -;; Get socket structure address by its number -; Scan through sockets list to find the socket with specified number. -; This proc uses SOCKET.PID indirectly to check if socket is owned by -; calling process. -; -; @param sockNum is a socket number -; @return socket structure address or 0 (not found) in EAX -;; -proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD - mov eax, [sockNum] - ; check if we got something similar to socket number - or eax, eax - jz .error - - ; scan through sockets list - mov ebx, net_sockets - ;mov ecx, [TASK_BASE] - ;mov ecx, [ecx + TASKDATA.pid] - .next_socket: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .error - cmp [ebx + SOCKET.Number], eax - jne .next_socket - ;cmp [ebx + SOCKET.PID], ecx - ;jne .next_socket - - ; okay, we found the correct one - mov eax, ebx - ret - - .error: - xor eax, eax - ret -endp - -;; Get socket number by its structure address -; Scan through sockets list to find the socket with specified address. -; This proc uses SOCKET.PID indirectly to check if socket is owned by -; calling process. -; -; @param sockAddr is a socket structure address -; @return socket number (SOCKET.Number) or 0 (not found) in EAX -;; -proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD - mov eax, [sockAddr] - ; check if we got something similar to socket structure address - or eax, eax - jz .error - - ; scan through sockets list - mov ebx, net_sockets - ;mov ecx, [TASK_BASE] - ;mov ecx, [ecx + TASKDATA.pid] - .next_socket: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .error - cmp ebx, eax - jne .next_socket - ;cmp [ebx + SOCKET.PID], ecx - ;jne .next_socket - - ; okay, we found the correct one - mov eax, [ebx + SOCKET.Number] - ret - - .error: - xor eax, eax - ret -endp - -;; [53.9] Check if local port is used by any socket in the system. -; Scan through sockets list, checking SOCKET.LocalPort. -; Useful when you want a to generate a unique local port number. -; This proc doesn't guarantee that after calling it and trying to use -; the port reported being free in calls to socket_open/socket_open_tcp it'll -; still be free or otherwise it'll still be used if reported being in use. -; -; @param BX is a port number -; @return 1 (port is free) or 0 (port is in use) in EAX -;; -proc is_localport_unused stdcall - movzx ebx, bx - mov eax, [network_free_ports] - bt [eax], ebx - setc al - movzx eax, al - ret -endp - -;====================================== -set_local_port: -;-------------------------------------- -;? Set local port in socket structure. -;-------------------------------------- -;> eax -> struct SOCKET -;> bx = local port, or 0 if the kernel must select it itself -;-------------------------------------- -;< CF set on error / cleared on success -;< [eax+SOCKET.LocalPort] filled on success -;====================================== -; 0. Prepare: save registers, make eax point to ports table, expand port to ebx. - push eax ecx - mov eax, [network_free_ports] - movzx ebx, bx -; 1. Test, whether the kernel should choose port itself. If no, proceed to 5. - test ebx, ebx - jnz .given -; 2. Yes, it should. Set ecx = limit of table, eax = start value - lea ecx, [eax+0x10000/8] - add eax, [network_free_hint] -; 3. First scan loop: from free hint to end of table. -.scan1: -; 3a. For each dword, find bit set to 1 - bsf ebx, [eax] - jz .next1 -; 3b. If such bit has been found, atomically test again and clear it. -lock btr [eax], ebx -; 3c. If the bit was still set (usual case), we have found and reserved one port. -; Proceed to 6. - jc .found -; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search. - jmp .scan1 -.next1: -; 3e. All bits are cleared, so advance to next dword. - add eax, 4 -; 3f. Check limit and continue loop. - cmp eax, ecx - jb .scan1 -; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint. - mov eax, [network_free_ports] - mov ecx, eax - add ecx, [network_free_hint] - add eax, 1024/8 -; 4a. Test whether there is something to scan. - cmp eax, ecx - jae .fail -; 4b. Enter the loop, the process is same as for 3. -.scan2: - bsf ebx, [eax] - jz .next2 -lock btr [eax], ebx - jc .found - jmp .scan2 -.next2: - add eax, 4 - cmp eax, ecx - jb .scan2 -; 4c. None found. Fail. -.fail: - pop ecx eax - stc - ret -; 5. No, the kernel should reserve selected port. -.given: -; 5a. Atomically test old value and clear bit. -lock btr [eax], ebx -; 5b. If the bit was set, reservation is successful. Proceed to 8. - jc .set -; 5c. Otherwise, fail. - jmp .fail -.found: -; 6. We have found the bit set to 1, convert the position to port number. - sub eax, [network_free_ports] - lea ebx, [ebx+eax*8] -; 7. Update free hint. - add eax, 4 - cmp eax, 65536/8 - jb @f - mov eax, 1024/8 -@@: - mov [network_free_hint], eax -.set: -; 8. Restore eax, set SOCKET.LocalPort and return. - pop ecx eax - xchg bl, bh ; Intel -> network byte order - mov [eax + SOCKET.LocalPort], bx - clc - ret - -;; [53.0] Open DGRAM socket (connectionless, unreliable) -; -; @param BX is local port number -; @param CX is remote port number -; @param EDX is remote IP address -; @return socket number or -1 (error) in EAX -;; -proc socket_open stdcall - call net_socket_alloc - or eax, eax - jz .error - - DEBUGF 1, "K : socket_open (0x%x)\n", eax - - push eax - - call set_local_port - jc .error.free - xchg ch, cl - mov [eax + SOCKET.RemotePort], cx - mov ebx, [stack_ip] - mov [eax + SOCKET.LocalIP], ebx - mov [eax + SOCKET.RemoteIP], edx - - ;pop eax ; Get the socket number back, so we can return it - stdcall net_socket_addr_to_num - ret - - .error.free: - stdcall net_socket_free;, eax - - .error: - DEBUGF 1, "K : socket_open (fail)\n" - or eax, -1 - ret -endp - -;; [53.5] Open STREAM socket (connection-based, sequenced, reliable, two-way) -; -; @param BX is local port number -; @param CX is remote port number -; @param EDX is remote IP address -; @param ESI is open mode (SOCKET_ACTIVE, SOCKET_PASSIVE) -; @return socket number or -1 (error) in EAX -;; -proc socket_open_tcp stdcall -local sockAddr dd ? - - cmp esi, SOCKET_PASSIVE - jne .skip_port_check - - push ebx - mov eax, ebx - xchg al, ah - mov ebx, net_sockets - - .next_socket: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .last_socket - cmp [ebx + SOCKET.TCBState], TCB_LISTEN - jne .next_socket - cmp [ebx + SOCKET.LocalPort], ax - jne .next_socket - - xchg al, ah - DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx - pop ebx - jmp .error - - .last_socket: - pop ebx - - .skip_port_check: - call net_socket_alloc - or eax, eax - jz .error - - DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax - - mov [sockAddr], eax - - ; TODO - check this works! - ;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. - - call set_local_port - jc .error.free - xchg ch, cl - mov [eax + SOCKET.RemotePort], cx - mov [eax + SOCKET.OrigRemotePort], cx - mov ebx, [stack_ip] - mov [eax + SOCKET.LocalIP], ebx - mov [eax + SOCKET.RemoteIP], edx - mov [eax + SOCKET.OrigRemoteIP], edx - - mov ebx, TCB_LISTEN - cmp esi, SOCKET_PASSIVE - je @f - mov ebx, TCB_SYN_SENT - @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB - - cmp ebx, TCB_LISTEN - je .exit - - ; Now, if we are in active mode, then we have to send a SYN to the specified remote port - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .exit - - push eax - - mov bl, TH_SYN - xor ecx, ecx - stdcall build_tcp_packet, [sockAddr] - - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - pop ebx - call queue - - mov esi, [sockAddr] - - ; increment SND.NXT in socket - add esi, SOCKET.SND_NXT - call inc_inet_esi - - .exit: - ; Get the socket number back, so we can return it - stdcall net_socket_addr_to_num, [sockAddr] - ret - - .error.free: - stdcall net_socket_free, eax - - .error: - DEBUGF 1, "K : socket_open_tcp (fail)\n" - or eax, -1 - ret -endp - -;; [53.1] Close DGRAM socket -; -; @param EBX is socket number -; @return 0 (closed successfully) or -1 (error) in EAX -;; -proc socket_close stdcall - DEBUGF 1, "K : socket_close (0x%x)\n", ebx - stdcall net_socket_num_to_addr, ebx - or eax, eax - jz .error - - stdcall net_socket_free, eax - - xor eax, eax - ret - - .error: - DEBUGF 1, "K : socket_close (fail)\n" - or eax, -1 - ret -endp - -;; [53.8] Close STREAM socket -; Closing TCP sockets takes time, so when you get successful return code -; from this function doesn't always mean that socket is actually closed. -; -; @param EBX is socket number -; @return 0 (closed successfully) or -1 (error) in EAX -;; -proc socket_close_tcp stdcall -local sockAddr dd ? - - DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx - ; first, remove any resend entries - pusha - - mov esi, resendQ - mov ecx, 0 - - .next_resendq: - cmp ecx, NUMRESENDENTRIES - je .last_resendq ; None left - cmp [esi + 4], ebx - je @f ; found one - inc ecx - add esi, 8 - jmp .next_resendq - - @@: mov dword[esi + 4], 0 - inc ecx - add esi, 8 - jmp .next_resendq - - .last_resendq: - popa - - stdcall net_socket_num_to_addr, ebx - or eax, eax - jz .error - - mov ebx, eax - mov [sockAddr], eax - - cmp [ebx + SOCKET.TCBState], TCB_LISTEN - je .destroy_tcb - cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT - je .destroy_tcb - cmp [ebx + SOCKET.TCBState], TCB_CLOSED - je .destroy_tcb - - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .error - - push eax - - mov bl, TH_FIN+TH_ACK - xor ecx, ecx - xor esi, esi - stdcall build_tcp_packet, [sockAddr] - - mov ebx, [sockAddr] - ; increament SND.NXT in socket - lea esi, [ebx + SOCKET.SND_NXT] - call inc_inet_esi - - ; Get the socket state - mov eax, [ebx + SOCKET.TCBState] - cmp eax, TCB_SYN_RECEIVED - je .fin_wait_1 - cmp eax, TCB_ESTABLISHED - je .fin_wait_1 - - ; assume CLOSE WAIT - ; Send a fin, then enter last-ack state - mov [ebx + SOCKET.TCBState], TCB_LAST_ACK - jmp .send - - .fin_wait_1: - ; Send a fin, then enter finwait2 state - mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 - - .send: - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - pop ebx - call queue - jmp .exit - - .destroy_tcb: - - ; Clear the socket variables - stdcall net_socket_free, ebx - - .exit: - xor eax, eax - ret - - .error: - DEBUGF 1, "K : socket_close_tcp (fail)\n" - or eax, -1 - ret -endp - -;; [53.2] Poll socket -; -; @param EBX is socket number -; @return count or bytes in rx buffer or 0 (error) in EAX -;; -proc socket_poll stdcall -; DEBUGF 1, "socket_poll(0x%x)\n", ebx - stdcall net_socket_num_to_addr, ebx - or eax, eax - jz .error - - mov eax, [eax + SOCKET.rxDataCount] - ret - - .error: - xor eax, eax - ret -endp - -;; [53.6] Get socket TCB state -; -; @param EBX is socket number -; @return socket TCB state or 0 (error) in EAX -;; -proc socket_status stdcall -;; DEBUGF 1, "socket_status(0x%x)\n", ebx - stdcall net_socket_num_to_addr, ebx - or eax, eax - jz .error - - mov eax, [eax + SOCKET.TCBState] - ret - - .error: - xor eax, eax - ret -endp - -;; [53.3] Get one byte from rx buffer -; This function can return 0 in two cases: if there's one byte read and -; non left, and if an error occured. Behavior should be changed and function -; shouldn't be used for now. Consider using [53.11] instead. -; -; @param EBX is socket number -; @return number of bytes left in rx buffer or 0 (error) in EAX -; @return byte read in BL -;; -proc socket_read stdcall -; DEBUGF 1, "socket_read(0x%x)\n", ebx - stdcall net_socket_num_to_addr, ebx - or eax, eax - jz .error - - mov ebx, eax - lea ecx, [eax + SOCKET.lock] - call mutex_lock - - mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes - test eax, eax - jz .error_release - - dec eax - mov esi, ebx ; esi is address of socket - mov [ebx + SOCKET.rxDataCount], eax ; store new count - movzx eax, byte[ebx + SOCKET.rxData] ; get the byte - - mov ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1 - lea edi, [esi + SOCKET.rxData] - lea esi, [edi + 1] - cld - push ecx - shr ecx, 2 - rep movsd - pop ecx - and ecx, 3 - rep movsb - - lea ecx, [ebx + SOCKET.lock] - mov ebx, eax - call mutex_unlock - mov eax, ebx - ret - - .error_release: - lea ecx, [ebx + SOCKET.lock] - call mutex_unlock - .error: - xor ebx, ebx - xor eax, eax - ret -endp - -;; [53.11] Get specified number of bytes from rx buffer -; Number of bytes in rx buffer can be less than requested size. In this case, -; only available number of bytes is read. -; This function can return 0 in two cases: if there's no data to read, and if -; an error occured. Behavior should be changed. -; -; @param EBX is socket number -; @param ECX is pointer to application buffer -; @param EDX is application buffer size (number of bytes to read) -; @return number of bytes read or 0 (error) in EAX -;; -proc socket_read_packet stdcall -; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx - stdcall net_socket_num_to_addr, ebx ; get real socket address - or eax, eax - jz .error - - mov ebx, eax - - push ecx edx - lea ecx, [eax + SOCKET.lock] - call mutex_lock - pop edx ecx - - mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes - test eax, eax ; if count of bytes is zero.. - jz .exit ; exit function (eax will be zero) - - test edx, edx ; if buffer size is zero, copy all data - jz .copy_all_bytes - cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data - jge .copy_all_bytes - - sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) - mov [ebx + SOCKET.rxDataCount], eax ; - push eax - mov eax, edx ; number of bytes we want to copy must be in eax - call .start_copy ; copy to the application - - mov esi, ebx ; now we're going to copy the remaining bytes to the beginning - add esi, SOCKET.rxData ; we dont need to copy the header - mov edi, esi ; edi is where we're going to copy to - add esi, edx ; esi is from where we copy - pop ecx ; count of bytes we have left - push ecx ; push it again so we can re-use it later - shr ecx, 2 ; divide eax by 4 - cld - rep movsd ; copy all full dwords - pop ecx - and ecx, 3 - rep movsb ; copy remaining bytes - - .exit: - lea ecx, [ebx + SOCKET.lock] - mov ebx,eax - call mutex_unlock - mov eax,ebx - ret ; at last, exit - - .error: - xor eax, eax - ret - - .copy_all_bytes: - xor esi, esi - mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) - call .start_copy - lea ecx, [ebx + SOCKET.lock] - mov ebx,eax - call mutex_unlock - mov eax,ebx - ret - - .start_copy: - mov edi, ecx - mov esi, ebx - add esi, SOCKET.rxData ; we dont need to copy the header - mov ecx, eax ; eax is count of bytes - push ecx - shr ecx, 2 ; divide eax by 4 - cld ; copy all full dwords - rep movsd - pop ecx - and ecx, 3 - rep movsb ; copy the rest bytes - retn ; exit, or go back to shift remaining bytes if any -endp - -;; [53.4] Send data through DGRAM socket -; -; @param EBX is socket number -; @param ECX is application data size (number of bytes to send) -; @param EDX is pointer to application data buffer -; @return 0 (sent successfully) or -1 (error) in EAX -;; -proc socket_write stdcall -; DEBUGF 1, "socket_write(0x%x)\n", ebx - stdcall net_socket_num_to_addr, ebx ; get real socket address - or eax, eax - jz .error - - mov ebx, eax - - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .error - - ; Save the queue entry number - push eax - - ; save the pointers to the data buffer & size - push edx - push ecx - - ; convert buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - - mov edx, eax - - ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr - - ; Fill in the IP header (some data is in the socket descriptor) - mov eax, [ebx + SOCKET.LocalIP] - mov [edx + IP_PACKET.SourceAddress], eax - mov eax, [ebx + SOCKET.RemoteIP] - mov [edx + IP_PACKET.DestinationAddress], eax - - mov [edx + IP_PACKET.VersionAndIHL], 0x45 - mov [edx + IP_PACKET.TypeOfService], 0 - - pop eax ; Get the UDP data length - push eax - - add eax, 20 + 8 ; add IP header and UDP header lengths - xchg al, ah - mov [edx + IP_PACKET.TotalLength], ax - xor eax, eax - mov [edx + IP_PACKET.Identification], ax - mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 - mov [edx + IP_PACKET.TimeToLive], 0x20 - mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP - - ; Checksum left unfilled - mov [edx + IP_PACKET.HeaderChecksum], ax - - ; Fill in the UDP header (some data is in the socket descriptor) - mov ax, [ebx + SOCKET.LocalPort] - mov [edx + 20 + UDP_PACKET.SourcePort], ax - - mov ax, [ebx + SOCKET.RemotePort] - mov [edx + 20 + UDP_PACKET.DestinationPort], ax - - pop eax - push eax - - add eax, 8 - xchg al, ah - mov [edx + 20 + UDP_PACKET.Length], ax - - ; Checksum left unfilled - xor eax, eax - mov [edx + 20 + UDP_PACKET.Checksum], ax - - pop ecx ; count of bytes to send - mov ebx, ecx ; need the length later - pop eax ; get callers ptr to data to send - - ; Get the address of the callers data - mov edi, [TASK_BASE] - add edi, TASKDATA.mem_start - add eax, [edi] - mov esi, eax - - mov edi, edx - add edi, 28 - cld - rep movsb ; copy the data across - - ; we have edx as IPbuffer ptr. - ; Fill in the UDP checksum - ; First, fill in pseudoheader - mov eax, [edx + IP_PACKET.SourceAddress] - mov [pseudoHeader], eax - mov eax, [edx + IP_PACKET.DestinationAddress] - mov [pseudoHeader + 4], eax - mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol - add ebx, 8 - mov eax, ebx - xchg al, ah - mov [pseudoHeader + 10], ax - - mov eax, pseudoHeader - mov [checkAdd1], eax - mov [checkSize1], word 12 - mov eax, edx - add eax, 20 - mov [checkAdd2], eax - mov eax, ebx - mov [checkSize2], ax ; was eax!! mjh 8/7/02 - - call checksum - - ; store it in the UDP checksum ( in the correct order! ) - mov ax, [checkResult] - - ; If the UDP checksum computes to 0, we must make it 0xffff - ; (0 is reserved for 'not used') - test ax, ax - jnz @f - mov ax, 0xffff - - @@: xchg al, ah - mov [edx + 20 + UDP_PACKET.Checksum], ax - - ; Fill in the IP header checksum - GET_IHL ecx,edx ; get IP-Header length - stdcall checksum_jb,edx,ecx ; buf_ptr, buf_size - xchg al, ah - mov [edx + IP_PACKET.HeaderChecksum], ax - - ; Check destination IP address. - ; If it is the local host IP, route it back to IP_RX - - pop ebx - - mov eax, NET1OUT_QUEUE - mov ecx, [edx + SOCKET.RemoteIP] - mov edx, [stack_ip] - cmp edx, ecx - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - call queue - - xor eax, eax - ret - - .error: - or eax, -1 - ret -endp - -;; [53.7] Send data through STREAM socket -; -; @param EBX is socket number -; @param ECX is application data size (number of bytes to send) -; @param EDX is pointer to application data buffer -; @return 0 (sent successfully) or -1 (error) in EAX -;; -proc socket_write_tcp stdcall -local sockAddr dd ? - -; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx - stdcall net_socket_num_to_addr, ebx - or eax, eax - jz .error - - mov ebx, eax - mov [sockAddr], ebx - - ; If the sockets window timer is nonzero, do not queue packet - cmp [ebx + SOCKET.wndsizeTimer], 0 - jne .error - - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .error - - push eax - - ; Get the address of the callers data - mov edi, [TASK_BASE] - add edi, TASKDATA.mem_start - add edx, [edi] - mov esi, edx - - pop eax - push eax - - push ecx - mov bl, TH_ACK - stdcall build_tcp_packet, [sockAddr] - pop ecx - - ; Check destination IP address. - ; If it is the local host IP, route it back to IP_RX - - pop ebx - push ecx - - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - pop ecx - push ebx ; save ipbuffer number - - call queue - - mov esi, [sockAddr] - - ; increament SND.NXT in socket - ; Amount to increment by is in ecx - add esi, SOCKET.SND_NXT - call add_inet_esi - - pop ebx - - ; Copy the IP buffer to a resend queue - ; If there isn't one, dont worry about it for now - mov esi, resendQ - mov ecx, 0 - - .next_resendq: - cmp ecx, NUMRESENDENTRIES - je .exit ; None found - cmp dword[esi + 4], 0 - je @f ; found one - inc ecx - add esi, 8 - jmp .next_resendq - - @@: push ebx - - ; OK, we have a buffer descriptor ptr in esi. - ; resend entry # in ecx - ; Populate it - ; socket # - ; retries count - ; retry time - ; fill IP buffer associated with this descriptor - - stdcall net_socket_addr_to_num, [sockAddr] - mov [esi + 4], eax - mov byte[esi + 1], TCP_RETRIES - mov word[esi + 2], TCP_TIMEOUT - - inc ecx - ; Now get buffer location, and copy buffer across. argh! more copying,, - mov edi, resendBuffer - IPBUFFSIZE - - @@: add edi, IPBUFFSIZE - loop @b - - ; we have dest buffer location in edi - pop eax - ; convert source buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - mov esi, eax - - ; do copy - mov ecx, IPBUFFSIZE - cld - rep movsb - - .exit: - xor eax, eax - ret - - .error: - or eax, -1 - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; SOCKET.INC ;; +;; ;; +;; Sockets constants, structures and functions ;; +;; ;; +;; This file contains the following: ;; +;; is_localport_unused ;; +;; get_free_socket ;; +;; socket_open ;; +;; socket_open_tcp ;; +;; socket_close ;; +;; socket_close_tcp ;; +;; socket_poll ;; +;; socket_status ;; +;; socket_read ;; +;; socket_write ;; +;; socket_write_tcp ;; +;; ;; +;; ;; +;; Changes history: ;; +;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; +;; 11.11.2006 - [Johnny_B] and [smb] ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +; socket data structure +struct SOCKET + .PrevPtr dd ? ; pointer to previous socket in list + .NextPtr dd ? ; pointer to next socket in list + .Number dd ? ; socket number (unique within single process) + .PID dd ? ; application process id + .LocalIP dd ? ; local IP address + .LocalPort dw ? ; local port + .RemoteIP dd ? ; remote IP address + .RemotePort dw ? ; remote port + .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) + .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) + .rxDataCount dd ? ; rx data count + .TCBState dd ? ; TCB state + .TCBTimer dd ? ; TCB timer (seconds) + .ISS dd ? ; initial send sequence + .IRS dd ? ; initial receive sequence + .SND_UNA dd ? ; sequence number of unack'ed sent packets + .SND_NXT dd ? ; bext send sequence number to use + .SND_WND dd ? ; send window + .RCV_NXT dd ? ; next receive sequence number to use + .RCV_WND dd ? ; receive window + .SEG_LEN dd ? ; segment length + .SEG_WND dd ? ; segment window + .wndsizeTimer dd ? ; window size timer + .lock MUTEX ; lock mutex + .rxData dd ? ; receive data buffer here +ends + +; TCP opening modes +SOCKET_PASSIVE = 0 +SOCKET_ACTIVE = 1 + +; socket types +SOCK_STREAM = 1 +SOCK_DGRAM = 2 + +; pointer to bitmap of free ports (1=free, 0=used) +uglobal +align 4 +network_free_ports dd ? +endg + +iglobal +align 4 +network_free_hint dd 1024/8 +endg + +;; Allocate memory for socket data and put new socket into the list +; Newly created socket is initialized with calling PID and number and +; put into beginning of list (which is a fastest way). +; +; @return socket structure address in EAX +;; +proc net_socket_alloc stdcall uses ebx ecx edx edi + stdcall kernel_alloc, SOCKETBUFFSIZE + DEBUGF 1, "K : net_socket_alloc (0x%x)\n", eax + ; check if we can allocate needed amount of memory + or eax, eax + jz .exit + + ; zero-initialize allocated memory + push eax + mov edi, eax + mov ecx, SOCKETBUFFSIZE / 4 + cld + xor eax, eax + rep stosd + pop eax + + mov ebx, eax + lea ecx, [eax+SOCKET.lock] + call mutex_init + mov eax, ebx + + ; add socket to the list by changing pointers + mov ebx, net_sockets + push [ebx + SOCKET.NextPtr] + mov [ebx + SOCKET.NextPtr], eax + mov [eax + SOCKET.PrevPtr], ebx + pop ebx + mov [eax + SOCKET.NextPtr], ebx + or ebx, ebx + jz @f + mov [ebx + SOCKET.PrevPtr], eax + + @@: ; set socket owner PID to the one of calling process + mov ebx, [TASK_BASE] + mov ebx, [ebx + TASKDATA.pid] + mov [eax + SOCKET.PID], ebx + + ; find first free socket number and use it + ;mov edx, ebx + mov ebx, net_sockets + xor ecx, ecx + .next_socket_number: + inc ecx + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .last_socket_number + cmp [ebx + SOCKET.Number], ecx + jne .next_socket + ;cmp [ebx + SOCKET.PID], edx + ;jne .next_socket + mov ebx, net_sockets + jmp .next_socket_number + + .last_socket_number: + mov [eax + SOCKET.Number], ecx + + .exit: + ret +endp + +;; Free socket data memory and pop socket off the list +; +; @param sockAddr is a socket structure address +;; +proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD + mov eax, [sockAddr] + DEBUGF 1, "K : net_socket_free (0x%x)\n", eax + ; check if we got something similar to socket structure address + or eax, eax + jz .error + + ; make sure sockAddr is one of the socket addresses in the list + mov ebx, net_sockets + ;mov ecx, [TASK_BASE] + ;mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + + ; okay, we found the correct one + ; mark local port as unused + movzx ebx, [eax + SOCKET.LocalPort] + push eax + mov eax, [network_free_ports] + xchg bl, bh + lock bts [eax], ebx + pop eax + ; remove it from the list first, changing pointers + mov ebx, [eax + SOCKET.NextPtr] + mov eax, [eax + SOCKET.PrevPtr] + mov [eax + SOCKET.NextPtr], ebx + or ebx, ebx + jz @f + mov [ebx + SOCKET.PrevPtr], eax + + @@: ; and finally free the memory structure used + stdcall kernel_free, [sockAddr] + ret + + .error: + DEBUGF 1, "K : failed\n" + ret +endp + +;; Get socket structure address by its number +; Scan through sockets list to find the socket with specified number. +; This proc uses SOCKET.PID indirectly to check if socket is owned by +; calling process. +; +; @param sockNum is a socket number +; @return socket structure address or 0 (not found) in EAX +;; +proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD + mov eax, [sockNum] + ; check if we got something similar to socket number + or eax, eax + jz .error + + ; scan through sockets list + mov ebx, net_sockets + ;mov ecx, [TASK_BASE] + ;mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp [ebx + SOCKET.Number], eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + + ; okay, we found the correct one + mov eax, ebx + ret + + .error: + xor eax, eax + ret +endp + +;; Get socket number by its structure address +; Scan through sockets list to find the socket with specified address. +; This proc uses SOCKET.PID indirectly to check if socket is owned by +; calling process. +; +; @param sockAddr is a socket structure address +; @return socket number (SOCKET.Number) or 0 (not found) in EAX +;; +proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD + mov eax, [sockAddr] + ; check if we got something similar to socket structure address + or eax, eax + jz .error + + ; scan through sockets list + mov ebx, net_sockets + ;mov ecx, [TASK_BASE] + ;mov ecx, [ecx + TASKDATA.pid] + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .error + cmp ebx, eax + jne .next_socket + ;cmp [ebx + SOCKET.PID], ecx + ;jne .next_socket + + ; okay, we found the correct one + mov eax, [ebx + SOCKET.Number] + ret + + .error: + xor eax, eax + ret +endp + +;; [53.9] Check if local port is used by any socket in the system. +; Scan through sockets list, checking SOCKET.LocalPort. +; Useful when you want a to generate a unique local port number. +; This proc doesn't guarantee that after calling it and trying to use +; the port reported being free in calls to socket_open/socket_open_tcp it'll +; still be free or otherwise it'll still be used if reported being in use. +; +; @param BX is a port number +; @return 1 (port is free) or 0 (port is in use) in EAX +;; +proc is_localport_unused stdcall + movzx ebx, bx + mov eax, [network_free_ports] + bt [eax], ebx + setc al + movzx eax, al + ret +endp + +;====================================== +set_local_port: +;-------------------------------------- +;? Set local port in socket structure. +;-------------------------------------- +;> eax -> struct SOCKET +;> bx = local port, or 0 if the kernel must select it itself +;-------------------------------------- +;< CF set on error / cleared on success +;< [eax+SOCKET.LocalPort] filled on success +;====================================== +; 0. Prepare: save registers, make eax point to ports table, expand port to ebx. + push eax ecx + mov eax, [network_free_ports] + movzx ebx, bx +; 1. Test, whether the kernel should choose port itself. If no, proceed to 5. + test ebx, ebx + jnz .given +; 2. Yes, it should. Set ecx = limit of table, eax = start value + lea ecx, [eax+0x10000/8] + add eax, [network_free_hint] +; 3. First scan loop: from free hint to end of table. +.scan1: +; 3a. For each dword, find bit set to 1 + bsf ebx, [eax] + jz .next1 +; 3b. If such bit has been found, atomically test again and clear it. + lock btr [eax], ebx +; 3c. If the bit was still set (usual case), we have found and reserved one port. +; Proceed to 6. + jc .found +; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search. + jmp .scan1 +.next1: +; 3e. All bits are cleared, so advance to next dword. + add eax, 4 +; 3f. Check limit and continue loop. + cmp eax, ecx + jb .scan1 +; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint. + mov eax, [network_free_ports] + mov ecx, eax + add ecx, [network_free_hint] + add eax, 1024/8 +; 4a. Test whether there is something to scan. + cmp eax, ecx + jae .fail +; 4b. Enter the loop, the process is same as for 3. +.scan2: + bsf ebx, [eax] + jz .next2 + lock btr [eax], ebx + jc .found + jmp .scan2 +.next2: + add eax, 4 + cmp eax, ecx + jb .scan2 +; 4c. None found. Fail. +.fail: + pop ecx eax + stc + ret +; 5. No, the kernel should reserve selected port. +.given: +; 5a. Atomically test old value and clear bit. + lock btr [eax], ebx +; 5b. If the bit was set, reservation is successful. Proceed to 8. + jc .set +; 5c. Otherwise, fail. + jmp .fail +.found: +; 6. We have found the bit set to 1, convert the position to port number. + sub eax, [network_free_ports] + lea ebx, [ebx+eax*8] +; 7. Update free hint. + add eax, 4 + cmp eax, 65536/8 + jb @f + mov eax, 1024/8 +@@: + mov [network_free_hint], eax +.set: +; 8. Restore eax, set SOCKET.LocalPort and return. + pop ecx eax + xchg bl, bh ; Intel -> network byte order + mov [eax + SOCKET.LocalPort], bx + clc + ret + +;; [53.0] Open DGRAM socket (connectionless, unreliable) +; +; @param BX is local port number +; @param CX is remote port number +; @param EDX is remote IP address +; @return socket number or -1 (error) in EAX +;; +proc socket_open stdcall + call net_socket_alloc + or eax, eax + jz .error + + DEBUGF 1, "K : socket_open (0x%x)\n", eax + + push eax + + call set_local_port + jc .error.free + xchg ch, cl + mov [eax + SOCKET.RemotePort], cx + mov ebx, [stack_ip] + mov [eax + SOCKET.LocalIP], ebx + mov [eax + SOCKET.RemoteIP], edx + + ;pop eax ; Get the socket number back, so we can return it + stdcall net_socket_addr_to_num + ret + + .error.free: + stdcall net_socket_free;, eax + + .error: + DEBUGF 1, "K : socket_open (fail)\n" + or eax, -1 + ret +endp + +;; [53.5] Open STREAM socket (connection-based, sequenced, reliable, two-way) +; +; @param BX is local port number +; @param CX is remote port number +; @param EDX is remote IP address +; @param ESI is open mode (SOCKET_ACTIVE, SOCKET_PASSIVE) +; @return socket number or -1 (error) in EAX +;; +proc socket_open_tcp stdcall +local sockAddr dd ? + + cmp esi, SOCKET_PASSIVE + jne .skip_port_check + + push ebx + mov eax, ebx + xchg al, ah + mov ebx, net_sockets + + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .last_socket + cmp [ebx + SOCKET.TCBState], TCB_LISTEN + jne .next_socket + cmp [ebx + SOCKET.LocalPort], ax + jne .next_socket + + xchg al, ah + DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx + pop ebx + jmp .error + + .last_socket: + pop ebx + + .skip_port_check: + call net_socket_alloc + or eax, eax + jz .error + + DEBUGF 1, "K : socket_open_tcp (0x%x)\n", eax + + mov [sockAddr], eax + + ; TODO - check this works! + ;mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. + + call set_local_port + jc .error.free + xchg ch, cl + mov [eax + SOCKET.RemotePort], cx + mov [eax + SOCKET.OrigRemotePort], cx + mov ebx, [stack_ip] + mov [eax + SOCKET.LocalIP], ebx + mov [eax + SOCKET.RemoteIP], edx + mov [eax + SOCKET.OrigRemoteIP], edx + + mov ebx, TCB_LISTEN + cmp esi, SOCKET_PASSIVE + je @f + mov ebx, TCB_SYN_SENT + @@: + mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB + + cmp ebx, TCB_LISTEN + je .exit + + ; Now, if we are in active mode, then we have to send a SYN to the specified remote port + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit + + push eax + + mov bl, TH_SYN + xor ecx, ecx + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + mov esi, [sockAddr] + + ; increment SND.NXT in socket + add esi, SOCKET.SND_NXT + call inc_inet_esi + + .exit: + ; Get the socket number back, so we can return it + stdcall net_socket_addr_to_num, [sockAddr] + ret + + .error.free: + stdcall net_socket_free, eax + + .error: + DEBUGF 1, "K : socket_open_tcp (fail)\n" + or eax, -1 + ret +endp + +;; [53.1] Close DGRAM socket +; +; @param EBX is socket number +; @return 0 (closed successfully) or -1 (error) in EAX +;; +proc socket_close stdcall + DEBUGF 1, "K : socket_close (0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + stdcall net_socket_free, eax + + xor eax, eax + ret + + .error: + DEBUGF 1, "K : socket_close (fail)\n" + or eax, -1 + ret +endp + +;; [53.8] Close STREAM socket +; Closing TCP sockets takes time, so when you get successful return code +; from this function doesn't always mean that socket is actually closed. +; +; @param EBX is socket number +; @return 0 (closed successfully) or -1 (error) in EAX +;; +proc socket_close_tcp stdcall +local sockAddr dd ? + + DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx + ; first, remove any resend entries + pusha + + mov esi, resendQ + mov ecx, 0 + + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .last_resendq ; None left + cmp [esi + 4], ebx + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + @@: + mov dword[esi + 4], 0 + inc ecx + add esi, 8 + jmp .next_resendq + + .last_resendq: + popa + + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + mov ebx, eax + mov [sockAddr], eax + + cmp [ebx + SOCKET.TCBState], TCB_LISTEN + je .destroy_tcb + cmp [ebx + SOCKET.TCBState], TCB_SYN_SENT + je .destroy_tcb + cmp [ebx + SOCKET.TCBState], TCB_CLOSED + je .destroy_tcb + + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .error + + push eax + + mov bl, TH_FIN+TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov ebx, [sockAddr] + ; increament SND.NXT in socket + lea esi, [ebx + SOCKET.SND_NXT] + call inc_inet_esi + + ; Get the socket state + mov eax, [ebx + SOCKET.TCBState] + cmp eax, TCB_SYN_RECEIVED + je .fin_wait_1 + cmp eax, TCB_ESTABLISHED + je .fin_wait_1 + + ; assume CLOSE WAIT + ; Send a fin, then enter last-ack state + mov [ebx + SOCKET.TCBState], TCB_LAST_ACK + jmp .send + + .fin_wait_1: + ; Send a fin, then enter finwait2 state + mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 + + .send: + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + jmp .exit + + .destroy_tcb: + + ; Clear the socket variables + stdcall net_socket_free, ebx + + .exit: + xor eax, eax + ret + + .error: + DEBUGF 1, "K : socket_close_tcp (fail)\n" + or eax, -1 + ret +endp + +;; [53.2] Poll socket +; +; @param EBX is socket number +; @return count or bytes in rx buffer or 0 (error) in EAX +;; +proc socket_poll stdcall +; DEBUGF 1, "socket_poll(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + mov eax, [eax + SOCKET.rxDataCount] + ret + + .error: + xor eax, eax + ret +endp + +;; [53.6] Get socket TCB state +; +; @param EBX is socket number +; @return socket TCB state or 0 (error) in EAX +;; +proc socket_status stdcall +;; DEBUGF 1, "socket_status(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + mov eax, [eax + SOCKET.TCBState] + ret + + .error: + xor eax, eax + ret +endp + +;; [53.3] Get one byte from rx buffer +; This function can return 0 in two cases: if there's one byte read and +; non left, and if an error occured. Behavior should be changed and function +; shouldn't be used for now. Consider using [53.11] instead. +; +; @param EBX is socket number +; @return number of bytes left in rx buffer or 0 (error) in EAX +; @return byte read in BL +;; +proc socket_read stdcall +; DEBUGF 1, "socket_read(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + mov ebx, eax + lea ecx, [eax + SOCKET.lock] + call mutex_lock + + mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes + test eax, eax + jz .error_release + + dec eax + mov esi, ebx ; esi is address of socket + mov [ebx + SOCKET.rxDataCount], eax ; store new count + movzx eax, byte[ebx + SOCKET.rxData] ; get the byte + + mov ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1 + lea edi, [esi + SOCKET.rxData] + lea esi, [edi + 1] + cld + push ecx + shr ecx, 2 + rep movsd + pop ecx + and ecx, 3 + rep movsb + + lea ecx, [ebx + SOCKET.lock] + mov ebx, eax + call mutex_unlock + mov eax, ebx + ret + + .error_release: + lea ecx, [ebx + SOCKET.lock] + call mutex_unlock + .error: + xor ebx, ebx + xor eax, eax + ret +endp + +;; [53.11] Get specified number of bytes from rx buffer +; Number of bytes in rx buffer can be less than requested size. In this case, +; only available number of bytes is read. +; This function can return 0 in two cases: if there's no data to read, and if +; an error occured. Behavior should be changed. +; +; @param EBX is socket number +; @param ECX is pointer to application buffer +; @param EDX is application buffer size (number of bytes to read) +; @return number of bytes read or 0 (error) in EAX +;; +proc socket_read_packet stdcall +; DEBUGF 1, "socket_read_packet(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx ; get real socket address + or eax, eax + jz .error + + mov ebx, eax + + push ecx edx + lea ecx, [eax + SOCKET.lock] + call mutex_lock + pop edx ecx + + mov eax, [ebx + SOCKET.rxDataCount] ; get count of bytes + test eax, eax ; if count of bytes is zero.. + jz .exit ; exit function (eax will be zero) + + test edx, edx ; if buffer size is zero, copy all data + jz .copy_all_bytes + cmp edx, eax ; if buffer size is larger then the bytes of data, copy all data + jge .copy_all_bytes + + sub eax, edx ; store new count (data bytes in buffer - bytes we're about to copy) + mov [ebx + SOCKET.rxDataCount], eax ; + push eax + mov eax, edx ; number of bytes we want to copy must be in eax + call .start_copy ; copy to the application + + mov esi, ebx ; now we're going to copy the remaining bytes to the beginning + add esi, SOCKET.rxData ; we dont need to copy the header + mov edi, esi ; edi is where we're going to copy to + add esi, edx ; esi is from where we copy + pop ecx ; count of bytes we have left + push ecx ; push it again so we can re-use it later + shr ecx, 2 ; divide eax by 4 + cld + rep movsd ; copy all full dwords + pop ecx + and ecx, 3 + rep movsb ; copy remaining bytes + + .exit: + lea ecx, [ebx + SOCKET.lock] + mov ebx, eax + call mutex_unlock + mov eax, ebx + ret ; at last, exit + + .error: + xor eax, eax + ret + + .copy_all_bytes: + xor esi, esi + mov [ebx + SOCKET.rxDataCount], esi ; store new count (zero) + call .start_copy + lea ecx, [ebx + SOCKET.lock] + mov ebx, eax + call mutex_unlock + mov eax, ebx + ret + + .start_copy: + mov edi, ecx + mov esi, ebx + add esi, SOCKET.rxData ; we dont need to copy the header + mov ecx, eax ; eax is count of bytes + push ecx + shr ecx, 2 ; divide eax by 4 + cld ; copy all full dwords + rep movsd + pop ecx + and ecx, 3 + rep movsb ; copy the rest bytes + retn ; exit, or go back to shift remaining bytes if any +endp + +;; [53.4] Send data through DGRAM socket +; +; @param EBX is socket number +; @param ECX is application data size (number of bytes to send) +; @param EDX is pointer to application data buffer +; @return 0 (sent successfully) or -1 (error) in EAX +;; +proc socket_write stdcall +; DEBUGF 1, "socket_write(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx ; get real socket address + or eax, eax + jz .error + + mov ebx, eax + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .error + + ; Save the queue entry number + push eax + + ; save the pointers to the data buffer & size + push edx + push ecx + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edx, eax + + ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr + + ; Fill in the IP header (some data is in the socket descriptor) + mov eax, [ebx + SOCKET.LocalIP] + mov [edx + IP_PACKET.SourceAddress], eax + mov eax, [ebx + SOCKET.RemoteIP] + mov [edx + IP_PACKET.DestinationAddress], eax + + mov [edx + IP_PACKET.VersionAndIHL], 0x45 + mov [edx + IP_PACKET.TypeOfService], 0 + + pop eax ; Get the UDP data length + push eax + + add eax, 20 + 8 ; add IP header and UDP header lengths + xchg al, ah + mov [edx + IP_PACKET.TotalLength], ax + xor eax, eax + mov [edx + IP_PACKET.Identification], ax + mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 + mov [edx + IP_PACKET.TimeToLive], 0x20 + mov [edx + IP_PACKET.Protocol], PROTOCOL_UDP + + ; Checksum left unfilled + mov [edx + IP_PACKET.HeaderChecksum], ax + + ; Fill in the UDP header (some data is in the socket descriptor) + mov ax, [ebx + SOCKET.LocalPort] + mov [edx + 20 + UDP_PACKET.SourcePort], ax + + mov ax, [ebx + SOCKET.RemotePort] + mov [edx + 20 + UDP_PACKET.DestinationPort], ax + + pop eax + push eax + + add eax, 8 + xchg al, ah + mov [edx + 20 + UDP_PACKET.Length], ax + + ; Checksum left unfilled + xor eax, eax + mov [edx + 20 + UDP_PACKET.Checksum], ax + + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later + pop eax ; get callers ptr to data to send + + ; Get the address of the callers data + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add eax, [edi] + mov esi, eax + + mov edi, edx + add edi, 28 + cld + rep movsb ; copy the data across + + ; we have edx as IPbuffer ptr. + ; Fill in the UDP checksum + ; First, fill in pseudoheader + mov eax, [edx + IP_PACKET.SourceAddress] + mov [pseudoHeader], eax + mov eax, [edx + IP_PACKET.DestinationAddress] + mov [pseudoHeader + 4], eax + mov word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0 ; 0 + protocol + add ebx, 8 + mov eax, ebx + xchg al, ah + mov [pseudoHeader + 10], ax + + mov eax, pseudoHeader + mov [checkAdd1], eax + mov [checkSize1], word 12 + mov eax, edx + add eax, 20 + mov [checkAdd2], eax + mov eax, ebx + mov [checkSize2], ax ; was eax!! mjh 8/7/02 + + call checksum + + ; store it in the UDP checksum ( in the correct order! ) + mov ax, [checkResult] + + ; If the UDP checksum computes to 0, we must make it 0xffff + ; (0 is reserved for 'not used') + test ax, ax + jnz @f + mov ax, 0xffff + + @@: + xchg al, ah + mov [edx + 20 + UDP_PACKET.Checksum], ax + + ; Fill in the IP header checksum + GET_IHL ecx,edx ; get IP-Header length + stdcall checksum_jb, edx, ecx; buf_ptr, buf_size + xchg al, ah + mov [edx + IP_PACKET.HeaderChecksum], ax + + ; Check destination IP address. + ; If it is the local host IP, route it back to IP_RX + + pop ebx + + mov eax, NET1OUT_QUEUE + mov ecx, [edx + SOCKET.RemoteIP] + mov edx, [stack_ip] + cmp edx, ecx + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + call queue + + xor eax, eax + ret + + .error: + or eax, -1 + ret +endp + +;; [53.7] Send data through STREAM socket +; +; @param EBX is socket number +; @param ECX is application data size (number of bytes to send) +; @param EDX is pointer to application data buffer +; @return 0 (sent successfully) or -1 (error) in EAX +;; +proc socket_write_tcp stdcall +local sockAddr dd ? + +; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx + stdcall net_socket_num_to_addr, ebx + or eax, eax + jz .error + + mov ebx, eax + mov [sockAddr], ebx + + ; If the sockets window timer is nonzero, do not queue packet + cmp [ebx + SOCKET.wndsizeTimer], 0 + jne .error + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .error + + push eax + + ; Get the address of the callers data + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add edx, [edi] + mov esi, edx + + pop eax + push eax + + push ecx + mov bl, TH_ACK + stdcall build_tcp_packet, [sockAddr] + pop ecx + + ; Check destination IP address. + ; If it is the local host IP, route it back to IP_RX + + pop ebx + push ecx + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + pop ecx + push ebx ; save ipbuffer number + + call queue + + mov esi, [sockAddr] + + ; increament SND.NXT in socket + ; Amount to increment by is in ecx + add esi, SOCKET.SND_NXT + call add_inet_esi + + pop ebx + + ; Copy the IP buffer to a resend queue + ; If there isn't one, dont worry about it for now + mov esi, resendQ + mov ecx, 0 + + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .exit ; None found + cmp dword[esi + 4], 0 + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + @@: + push ebx + + ; OK, we have a buffer descriptor ptr in esi. + ; resend entry # in ecx + ; Populate it + ; socket # + ; retries count + ; retry time + ; fill IP buffer associated with this descriptor + + stdcall net_socket_addr_to_num, [sockAddr] + mov [esi + 4], eax + mov byte[esi + 1], TCP_RETRIES + mov word[esi + 2], TCP_TIMEOUT + + inc ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + mov edi, resendBuffer - IPBUFFSIZE + + @@: + add edi, IPBUFFSIZE + loop @b + + ; we have dest buffer location in edi + pop eax + ; convert source buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + mov esi, eax + + ; do copy + mov ecx, IPBUFFSIZE + cld + rep movsb + + .exit: + xor eax, eax + ret + + .error: + or eax, -1 + ret +endp diff --git a/kernel/trunk/network/stack.inc b/kernel/trunk/network/stack.inc index 00f752bab..844a074eb 100644 --- a/kernel/trunk/network/stack.inc +++ b/kernel/trunk/network/stack.inc @@ -1,908 +1,912 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; STACK.INC ;; -;; ;; -;; TCP/IP stack for Menuet OS ;; -;; ;; -;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;; Version 0.7 ;; -;; Added a timer per socket to allow delays when rx window ;; -;; gets below 1KB ;; -;; ;; -;;10.01.2007 Bugfix for checksum function from Paolo Franchetti ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;******************************************************************* -; Interface -; The interfaces defined in ETHERNET.INC plus: -; stack_init -; stack_handler -; app_stack_handler -; app_socket_handler -; checksum -; -;******************************************************************* - -uglobal -StackCounters: - dumped_rx_count dd 0 - arp_tx_count: dd 0 - arp_rx_count: dd 0 - ip_rx_count: dd 0 - ip_tx_count: dd 0 -endg - -; socket buffers -SOCKETBUFFSIZE equ 4096 ; state + config + buffer. -SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data - -;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 - -; IPBUFF status values -BUFF_EMPTY equ 0 -BUFF_RX_FULL equ 1 -BUFF_ALLOCATED equ 2 -BUFF_TX_FULL equ 3 - -NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX - -NUMQUEUES equ 4 - -EMPTY_QUEUE equ 0 -IPIN_QUEUE equ 1 -IPOUT_QUEUE equ 2 -NET1OUT_QUEUE equ 3 - -NO_BUFFER equ 0xFFFF -IPBUFFSIZE equ 1500 ; MTU of an ethernet packet -NUMQUEUEENTRIES equ NUM_IPBUFFERS -NUMRESENDENTRIES equ 18 ; Buffers for TCP resend packets - -; These are the 0x40 function codes for application access to the stack -STACK_DRIVER_STATUS equ 52 -SOCKET_INTERFACE equ 53 - - -; 128KB allocated for the stack and network driver buffers and other -; data requirements -;stack_data_start equ 0x700000 -;eth_data_start equ 0x700000 -;stack_data equ 0x704000 -;stack_data_end equ 0x71ffff - -; 32 bit word -stack_config equ stack_data - -; 32 bit word - IP Address in network format -stack_ip equ stack_data + 4 - -; 1 byte. 0 == inactive, 1 = active -ethernet_active equ stack_data + 9 - - -; TODO :: empty memory area - -; Address of selected socket -;sktAddr equ stack_data + 32 -; Parameter to checksum routine - data ptr -checkAdd1 equ stack_data + 36 -; Parameter to checksum routine - 2nd data ptr -checkAdd2 equ stack_data + 40 -; Parameter to checksum routine - data size -checkSize1 equ stack_data + 44 -; Parameter to checksum routine - 2nd data size -checkSize2 equ stack_data + 46 -; result of checksum routine -checkResult equ stack_data + 48 - -; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len| -pseudoHeader equ stack_data + 50 - -; receive and transmit IP buffer allocation -;sockets equ stack_data + 62 -Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) -; 1560 byte buffer for rx / tx ethernet packets -Ether_buffer equ Next_free2 -Next_free3 equ Ether_buffer + 1518 -last_1sTick equ Next_free3 -IPbuffs equ Next_free3 + 1 -queues equ IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE ) -queueList equ queues + (2 * NUMQUEUES) -last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES ) - -;resendQ equ queueList + ( 2 * NUMQUEUEENTRIES ) -;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP -; equ resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES ) - - - -;resendQ equ 0x770000 -;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size -resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP - - -uglobal -net_sockets rd 2 -endg - -; simple macro for memory set operation -macro _memset_dw adr,value,amount -{ - mov edi, adr - mov ecx, amount - if value = 0 - xor eax, eax - else - mov eax, value - end if - cld - rep stosd -} - - -; Below, the main network layer source code is included -; -include "queue.inc" -include "eth_drv/ethernet.inc" -include "ip.inc" -include "socket.inc" - -;*************************************************************************** -; Function -; stack_init -; -; Description -; Clear all allocated memory to zero. This ensures that -; on startup, the stack is inactive, and consumes no resources -; This is a kernel function, called prior to the OS main loop -; in set_variables -; -;*************************************************************************** - -stack_init: - ; Init two address spaces with default values - _memset_dw stack_data_start, 0, 0x20000/4 - _memset_dw resendQ, 0, NUMRESENDENTRIES * 2 - - mov [net_sockets], 0 - mov [net_sockets + 4], 0 - - ; Queries initialization - call queueInit - - ; The following block sets up the 1s timer - mov al, 0x0 - out 0x70, al - in al, 0x71 - mov [last_1sTick], al -ret - - - -;*************************************************************************** -; Function -; stack_handler -; -; Description -; The kernel loop routine for the stack -; This is a kernel function, called in the main loop -; -;*************************************************************************** -align 4 -stack_handler: - - call ethernet_driver - call ip_rx - - - ; Test for 10ms tick, call tcp timer - mov eax, [timer_ticks] ;[0xfdf0] - cmp eax, [last_1hsTick] - je sh_001 - - mov [last_1hsTick], eax - call tcp_tx_handler - -sh_001: - - ; Test for 1 second event, call 1s timer functions - mov al, 0x0 ;second - out 0x70, al - in al, 0x71 - cmp al, [last_1sTick] - je sh_exit - - mov [last_1sTick], al - - stdcall arp_table_manager, ARP_TABLE_TIMER, 0, 0 - call tcp_tcb_handler - -sh_exit: - ret - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Checksum [by Johnny_B] -;; IN: -;; buf_ptr=POINTER to buffer -;; buf_size=SIZE of buffer -;; OUT: -;; AX=16-bit checksum -;; Saves all used registers -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -proc checksum_jb stdcall uses ebx esi ecx,\ - buf_ptr:DWORD, buf_size:DWORD - - xor eax, eax - xor ebx, ebx ;accumulator - mov esi, dword[buf_ptr] - mov ecx, dword[buf_size] - shr ecx, 1 ; ecx=ecx/2 - jnc @f ; if CF==0 then size is even number - mov bh, byte[esi + ecx*2] - @@: - cld - - .loop: - lodsw ;eax=word[esi],esi=esi+2 - xchg ah,al ;cause must be a net byte-order - add ebx, eax - loop .loop - - mov eax, ebx - shr eax, 16 - add ax, bx - not ax - - ret -endp - -;*************************************************************************** -; Function -; checksum -; -; Description -; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult -; Dont break anything; Most registers are used by the caller -; This code is derived from the 'C' source, cksum.c, in the book -; Internetworking with TCP/IP Volume II by D.E. Comer -; -;*************************************************************************** - - -checksum: - pusha - mov eax, [checkAdd1] - xor edx, edx ; edx is the accumulative checksum - xor ebx, ebx - mov cx, [checkSize1] - shr cx, 1 - jz cs1_1 - -cs1: - mov bh, [eax] - mov bl, [eax + 1] - - add eax, 2 - add edx, ebx - - loopw cs1 - -cs1_1: - and word [checkSize1], 0x01 - jz cs_test2 - - mov bh, [eax] - xor bl, bl - - add edx, ebx - -cs_test2: - mov cx, [checkSize2] - cmp cx, 0 - jz cs_exit ; Finished if no 2nd buffer - - mov eax, [checkAdd2] - - shr cx, 1 - jz cs2_1 - -cs2: - mov bh, [eax] - mov bl, [eax + 1] - - add eax, 2 - add edx, ebx - - loopw cs2 - -cs2_1: - and word [checkSize2], 0x01 - jz cs_exit - - mov bh, [eax] - xor bl, bl - - add edx, ebx - -cs_exit: - mov ebx, edx - - shr ebx, 16 - and edx, 0xffff - add edx, ebx - mov eax, edx - shr eax, 16 - add edx, eax - not dx - - mov [checkResult], dx - popa - ret - - - - -;*************************************************************************** -; Function -; app_stack_handler -; -; Description -; This is an application service, called by int 0x40, function 52 -; It provides application access to the network interface layer -; -;*************************************************************************** -iglobal -align 4 -f52call: - dd app_stack_handler.00 - dd app_stack_handler.01 - dd app_stack_handler.02 - dd app_stack_handler.03 - dd app_stack_handler.fail ;04 - dd app_stack_handler.fail ;05 - dd stack_insert_packet ;app_stack_handler.06 - dd app_stack_handler.fail ;07 - dd stack_get_packet ;app_stack_handler.08 - dd app_stack_handler.09 - dd app_stack_handler.10 - dd app_stack_handler.11 - dd app_stack_handler.12 - dd app_stack_handler.13 - dd app_stack_handler.14 - dd app_stack_handler.15 -endg -app_stack_handler: -;in ebx,ecx -;out eax - cmp ebx,15 - ja .fail ;if more than 15 then exit - - jmp dword [f52call+ebx*4] - - -.00: -; Read the configuration word - mov eax, [stack_config] - ret - -.01: -; read the IP address - mov eax, [stack_ip] - ret - -.02: -; write the configuration word - mov [stack_config], ecx - -; -; If ethernet now enabled, probe for the card, reset it and empty -; the packet buffer -; If all successfull, enable the card. -; If ethernet now disabled, set it as disabled. Should really -; empty the tcpip data area too. - -; ethernet interface is '3' in ls 7 bits - and cl, 0x7f - cmp cl, 3 - je ash_eth_enable -; Ethernet isn't enabled, so make sure that the card is disabled - mov [ethernet_active], byte 0 - ret - -.03: -; write the IP Address - mov [stack_ip], ecx - ret -;old functions was deleted -;.06: -; Insert an IP packet into the stacks received packet queue -; call stack_insert_packet -; ret - -; Test for any packets queued for transmission over the network - -;.08: -; call stack_get_packet -; Extract a packet queued for transmission by the network -; ret - -.09: -; read the gateway IP address - mov eax, [gateway_ip] - ret - -.10: -; read the subnet mask - mov eax, [subnet_mask] - ret -.11: -; write the gateway IP Address - mov [gateway_ip], ecx - ret - -.12: -; write the subnet mask - mov [subnet_mask], ecx - ret - -.13: -; read the dns - mov eax, [dns_ip] - ret - -.14: -; write the dns IP Address - mov [dns_ip], ecx - ret - -.15: -; -; in ecx we need 4 to read the last 2 bytes -; or we need 0 to read the first 4 bytes - cmp ecx,4 - ja .param_error - -; read MAC, returned (in mirrored byte order) in eax - mov eax, [node_addr + ecx] - ret - -.param_error: - or eax, -1 ; params not accepted - ret - -.16: -; 0 -> arp_probe -; 1 -> arp_announce -; 2 -> arp_responce (not supported yet) - test ecx,ecx - je a_probe - - dec ebx - jz a_ann ; arp announce -.fail: - or eax, -1 - ret - -; cmp ebx,2 -; jne a_resp ; arp response - -; arp probe, sender IP must be set to 0.0.0.0, target IP is set to address being probed -; ecx: pointer to target MAC, MAC should set to 0 by application -; edx: target IP -a_probe: - push dword [stack_ip] - - mov edx, [stack_ip] - and [stack_ip], dword 0 - mov esi, ecx ; pointer to target MAC address - call arp_request - - pop dword [stack_ip] - ret - -; arp announce, sender IP must be set to target IP -; ecx: pointer to target MAC -a_ann: - mov edx, [stack_ip] - mov esi, ecx ; pointer to target MAC address - call arp_request - ret - -.17: -; -; modified by [smb] - -; -; ARPTable manager interface - ;see "proc arp_table_manager" for more details - stdcall arp_table_manager,ecx,edx,esi ;Opcode,Index,Extra - ret -; - -;;;;;;;;;;;;;;;;;;;;;;;;;;;; -ash_eth_enable: -; Probe for the card. This will reset it and enable the interface -; if found - call eth_probe - test eax,eax - jz ash_eth_done ; Abort if no hardware found - - mov [ethernet_active], byte 1 -ash_eth_done: - ret -;*************************************************************************** -; Function -; app_socket_handler -; -; Description -; This is an application service, called by int 0x40, function 53 -; It provides application access to stack socket services -; such as opening sockets -; -;*************************************************************************** -iglobal -align 4 -f53call: - dd socket_open ;00 - dd socket_close ;01 - dd socket_poll ;02 - dd socket_read ;03 - dd socket_write ;04 - dd socket_open_tcp ;05 - dd socket_status ;06 - dd socket_write_tcp ;07 - dd socket_close_tcp ;08 - dd is_localport_unused ;09 - dd app_socket_handler.10 - dd socket_read_packet ;11 -endg - -app_socket_handler: -;in ebx,ecx,edx,wsi -;out eax - cmp eax,255 - je stack_internal_status - - cmp eax,11 - ja .fail ;if more than 15 then exit - - jmp dword [f53call+eax*4] - -.10: - mov eax,dword[drvr_cable] - test eax,eax - jnz @f ; if function is not implented, return -1 - or al,-1 - ret -@@: - jmp dword[drvr_cable] - -.fail: - or eax,-1 - ret -uglobal - ARPTmp: - times 14 db 0 -endg - -;*************************************************************************** -; Function -; stack_internal_status -; -; Description -; Returns information about the internal status of the stack -; This is only useful for debugging -; It works with the ethernet driver -; sub function in ebx -; return requested data in eax -; -;*************************************************************************** -; This sub function allows access to debugging information on the stack -; ecx holds the request: -; 100 : return length of empty queue -; 101 : return length of IPOUT QUEUE -; 102 : return length of IPIN QUEUE -; 103 : return length of NET1OUT QUEUE -; 200 : return # of ARP entries -; 201 : return size of ARP table ( max # entries ) -; 202 : select ARP table entry # -; 203 : return IP of selected table entry -; 204 : return High 4 bytes of MAC address of selected table entry -; 205 : return low 2 bytes of MAC address of selected table entry -; 206 : return status word of selected table entry -; 207 : return Time to live of selected table entry - - -; 2 : return number of IP packets received -; 3 : return number of packets transmitted -; 4 : return number of received packets dumped -; 5 : return number of arp packets received -; 6 : return status of packet driver -; ( 0 == not active, FFFFFFFF = successful ) - - -stack_internal_status: - cmp ebx, 100 - jnz notsis100 - - ; 100 : return length of EMPTY QUEUE - mov ebx, EMPTY_QUEUE - call queueSize - ret - -notsis100: - cmp ebx, 101 - jnz notsis101 - - ; 101 : return length of IPOUT QUEUE - mov ebx, IPOUT_QUEUE - call queueSize - ret - -notsis101: - cmp ebx, 102 - jnz notsis102 - - ; 102 : return length of IPIN QUEUE - mov ebx, IPIN_QUEUE - call queueSize - ret - -notsis102: - cmp ebx, 103 - jnz notsis103 - - ; 103 : return length of NET1OUT QUEUE - mov ebx, NET1OUT_QUEUE - call queueSize - ret - -notsis103: - cmp ebx, 200 - jnz notsis200 - - ; 200 : return num entries in arp table - movzx eax, byte [NumARP] - ret - -notsis200: - cmp ebx, 201 - jnz notsis201 - - ; 201 : return arp table size - mov eax, 20 ; ARP_TABLE_SIZE - ret - -notsis201: - cmp ebx, 202 - jnz notsis202 - - ; 202 - read the requested table entry - ; into a temporary buffer - ; ecx holds the entry number - - mov eax, ecx - mov ecx, 14 ; ARP_ENTRY_SIZE - mul ecx - - mov ecx, [eax + ARPTable] - mov [ARPTmp], ecx - mov ecx, [eax + ARPTable+4] - mov [ARPTmp+4], ecx - mov ecx, [eax + ARPTable+8] - mov [ARPTmp+8], ecx - mov cx, [eax + ARPTable+12] - mov [ARPTmp+12], cx - ret - -notsis202: - cmp ebx, 203 - jnz notsis203 - - ; 203 - return IP address - mov eax, [ARPTmp] - ret - -notsis203: - cmp ebx, 204 - jnz notsis204 - - ; 204 - return MAC high dword - mov eax, [ARPTmp+4] - ret - -notsis204: - cmp ebx, 205 - jnz notsis205 - - ; 205 - return MAC ls word - movzx eax, word [ARPTmp+8] - ret - -notsis205: - cmp ebx, 206 - jnz notsis206 - - ; 206 - return status word - movzx eax, word [ARPTmp+10] - ret - -notsis206: - cmp ebx, 207 - jnz notsis207 - - ; 207 - return ttl word - movzx eax, word [ARPTmp+12] - ret - -notsis207: - cmp ebx, 2 - jnz notsis2 - - ; 2 : return number of IP packets received - mov eax, [ip_rx_count] - ret - -notsis2: - cmp ebx, 3 - jnz notsis3 - - ; 3 : return number of packets transmitted - mov eax, [ip_tx_count] - ret - -notsis3: - cmp ebx, 4 - jnz notsis4 - - ; 4 : return number of received packets dumped - mov eax, [dumped_rx_count] - ret - -notsis4: - cmp ebx, 5 - jnz notsis5 - - ; 5 : return number of arp packets received - mov eax, [arp_rx_count] - ret - -notsis5: - cmp ebx, 6 - jnz notsis6 - - ; 6 : return status of packet driver - ; ( 0 == not active, FFFFFFFF = successful ) - mov eax, [eth_status] - ret - -notsis6: - xor eax, eax - ret - - - -;*************************************************************************** -; Function -; stack_get_packet -; -; Description -; extracts an IP packet from the NET1 output queue -; and sends the data to the calling process -; pointer to data in edx -; returns number of bytes read in eax -; -;*************************************************************************** -stack_get_packet: - ; Look for a buffer to tx - mov eax, NET1OUT_QUEUE - call dequeue - cmp ax, NO_BUFFER - je sgp_non_exit ; Exit if no buffer available - - push eax ; Save buffer number for freeing at end - - push edx - ; convert buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - pop edx - - push eax ; save address of IP data - ; Get the address of the callers data - mov edi,[TASK_BASE] - add edi,TASKDATA.mem_start - add edx,[edi] - mov edi, edx - pop eax - - mov ecx, 1500 ; should get the actual number of bytes to write - mov esi, eax - cld - rep movsb ; copy the data across - - ; And finally, return the buffer to the free queue - pop eax - call freeBuff - - mov eax, 1500 - ret - -sgp_non_exit: - xor eax, eax - ret - - - -;*************************************************************************** -; Function -; stack_insert_packet -; -; Description -; writes an IP packet into the stacks receive queue -; # of bytes to write in ecx -; pointer to data in edx -; returns 0 in eax ok, -1 == failed -; -;*************************************************************************** -stack_insert_packet: - - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je sip_err_exit - - push eax - - ; save the pointers to the data buffer & size - push edx - push ecx - - ; convert buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - - mov edx, eax - - ; So, edx holds the IPbuffer ptr - - pop ecx ; count of bytes to send - mov ebx, ecx ; need the length later - pop eax ; get callers ptr to data to send - - ; Get the address of the callers data - mov edi,[TASK_BASE] - add edi,TASKDATA.mem_start - add eax,[edi] - mov esi, eax - - mov edi, edx - cld - rep movsb ; copy the data across - - pop ebx - - mov eax, IPIN_QUEUE - call queue - - inc dword [ip_rx_count] - - mov eax, 0 - ret - -sip_err_exit: - mov eax, 0xFFFFFFFF - ret - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; STACK.INC ;; +;; ;; +;; TCP/IP stack for Menuet OS ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;; Version 0.7 ;; +;; Added a timer per socket to allow delays when rx window ;; +;; gets below 1KB ;; +;; ;; +;;10.01.2007 Bugfix for checksum function from Paolo Franchetti ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;******************************************************************* +; Interface +; The interfaces defined in ETHERNET.INC plus: +; stack_init +; stack_handler +; app_stack_handler +; app_socket_handler +; checksum +; +;******************************************************************* + +uglobal +StackCounters: + dumped_rx_count dd 0 + arp_tx_count: + dd 0 + arp_rx_count: + dd 0 + ip_rx_count: + dd 0 + ip_tx_count: + dd 0 +endg + +; socket buffers +SOCKETBUFFSIZE equ 4096 ; state + config + buffer. +SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data + +;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20 + +; IPBUFF status values +BUFF_EMPTY equ 0 +BUFF_RX_FULL equ 1 +BUFF_ALLOCATED equ 2 +BUFF_TX_FULL equ 3 + +NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX + +NUMQUEUES equ 4 + +EMPTY_QUEUE equ 0 +IPIN_QUEUE equ 1 +IPOUT_QUEUE equ 2 +NET1OUT_QUEUE equ 3 + +NO_BUFFER equ 0xFFFF +IPBUFFSIZE equ 1500 ; MTU of an ethernet packet +NUMQUEUEENTRIES equ NUM_IPBUFFERS +NUMRESENDENTRIES equ 18 ; Buffers for TCP resend packets + +; These are the 0x40 function codes for application access to the stack +STACK_DRIVER_STATUS equ 52 +SOCKET_INTERFACE equ 53 + + +; 128KB allocated for the stack and network driver buffers and other +; data requirements +;stack_data_start equ 0x700000 +;eth_data_start equ 0x700000 +;stack_data equ 0x704000 +;stack_data_end equ 0x71ffff + +; 32 bit word +stack_config equ stack_data + +; 32 bit word - IP Address in network format +stack_ip equ stack_data + 4 + +; 1 byte. 0 == inactive, 1 = active +ethernet_active equ stack_data + 9 + + +; TODO :: empty memory area + +; Address of selected socket +;sktAddr equ stack_data + 32 +; Parameter to checksum routine - data ptr +checkAdd1 equ stack_data + 36 +; Parameter to checksum routine - 2nd data ptr +checkAdd2 equ stack_data + 40 +; Parameter to checksum routine - data size +checkSize1 equ stack_data + 44 +; Parameter to checksum routine - 2nd data size +checkSize2 equ stack_data + 46 +; result of checksum routine +checkResult equ stack_data + 48 + +; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len| +pseudoHeader equ stack_data + 50 + +; receive and transmit IP buffer allocation +;sockets equ stack_data + 62 +Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS) +; 1560 byte buffer for rx / tx ethernet packets +Ether_buffer equ Next_free2 +Next_free3 equ Ether_buffer + 1518 +last_1sTick equ Next_free3 +IPbuffs equ Next_free3 + 1 +queues equ IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE ) +queueList equ queues + (2 * NUMQUEUES) +last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES ) + +;resendQ equ queueList + ( 2 * NUMQUEUEENTRIES ) +;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP +; equ resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES ) + + + +;resendQ equ 0x770000 +;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size +resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP + + +uglobal +net_sockets rd 2 +endg + +; simple macro for memory set operation +macro _memset_dw adr,value,amount +{ + mov edi, adr + mov ecx, amount + if value = 0 + xor eax, eax + else + mov eax, value + end if + cld + rep stosd +} + + +; Below, the main network layer source code is included +; +include "queue.inc" +include "eth_drv/ethernet.inc" +include "ip.inc" +include "socket.inc" + +;*************************************************************************** +; Function +; stack_init +; +; Description +; Clear all allocated memory to zero. This ensures that +; on startup, the stack is inactive, and consumes no resources +; This is a kernel function, called prior to the OS main loop +; in set_variables +; +;*************************************************************************** + +stack_init: + ; Init two address spaces with default values + _memset_dw stack_data_start, 0, 0x20000/4 + _memset_dw resendQ, 0, NUMRESENDENTRIES * 2 + + mov [net_sockets], 0 + mov [net_sockets + 4], 0 + + ; Queries initialization + call queueInit + + ; The following block sets up the 1s timer + mov al, 0x0 + out 0x70, al + in al, 0x71 + mov [last_1sTick], al + ret + + + +;*************************************************************************** +; Function +; stack_handler +; +; Description +; The kernel loop routine for the stack +; This is a kernel function, called in the main loop +; +;*************************************************************************** +align 4 +stack_handler: + + call ethernet_driver + call ip_rx + + + ; Test for 10ms tick, call tcp timer + mov eax, [timer_ticks];[0xfdf0] + cmp eax, [last_1hsTick] + je sh_001 + + mov [last_1hsTick], eax + call tcp_tx_handler + +sh_001: + + ; Test for 1 second event, call 1s timer functions + mov al, 0x0;second + out 0x70, al + in al, 0x71 + cmp al, [last_1sTick] + je sh_exit + + mov [last_1sTick], al + + stdcall arp_table_manager, ARP_TABLE_TIMER, 0, 0 + call tcp_tcb_handler + +sh_exit: + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Checksum [by Johnny_B] +;; IN: +;; buf_ptr=POINTER to buffer +;; buf_size=SIZE of buffer +;; OUT: +;; AX=16-bit checksum +;; Saves all used registers +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +proc checksum_jb stdcall uses ebx esi ecx,\ + buf_ptr:DWORD, buf_size:DWORD + + xor eax, eax + xor ebx, ebx;accumulator + mov esi, dword[buf_ptr] + mov ecx, dword[buf_size] + shr ecx, 1; ecx=ecx/2 + jnc @f ; if CF==0 then size is even number + mov bh, byte[esi + ecx*2] + @@: + cld + + .loop: + lodsw ;eax=word[esi],esi=esi+2 + xchg ah, al;cause must be a net byte-order + add ebx, eax + loop .loop + + mov eax, ebx + shr eax, 16 + add ax, bx + not ax + + ret +endp + +;*************************************************************************** +; Function +; checksum +; +; Description +; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult +; Dont break anything; Most registers are used by the caller +; This code is derived from the 'C' source, cksum.c, in the book +; Internetworking with TCP/IP Volume II by D.E. Comer +; +;*************************************************************************** + + +checksum: + pusha + mov eax, [checkAdd1] + xor edx, edx ; edx is the accumulative checksum + xor ebx, ebx + mov cx, [checkSize1] + shr cx, 1 + jz cs1_1 + +cs1: + mov bh, [eax] + mov bl, [eax + 1] + + add eax, 2 + add edx, ebx + + loopw cs1 + +cs1_1: + and word [checkSize1], 0x01 + jz cs_test2 + + mov bh, [eax] + xor bl, bl + + add edx, ebx + +cs_test2: + mov cx, [checkSize2] + cmp cx, 0 + jz cs_exit ; Finished if no 2nd buffer + + mov eax, [checkAdd2] + + shr cx, 1 + jz cs2_1 + +cs2: + mov bh, [eax] + mov bl, [eax + 1] + + add eax, 2 + add edx, ebx + + loopw cs2 + +cs2_1: + and word [checkSize2], 0x01 + jz cs_exit + + mov bh, [eax] + xor bl, bl + + add edx, ebx + +cs_exit: + mov ebx, edx + + shr ebx, 16 + and edx, 0xffff + add edx, ebx + mov eax, edx + shr eax, 16 + add edx, eax + not dx + + mov [checkResult], dx + popa + ret + + + + +;*************************************************************************** +; Function +; app_stack_handler +; +; Description +; This is an application service, called by int 0x40, function 52 +; It provides application access to the network interface layer +; +;*************************************************************************** +iglobal +align 4 +f52call: + dd app_stack_handler.00 + dd app_stack_handler.01 + dd app_stack_handler.02 + dd app_stack_handler.03 + dd app_stack_handler.fail ;04 + dd app_stack_handler.fail ;05 + dd stack_insert_packet ;app_stack_handler.06 + dd app_stack_handler.fail ;07 + dd stack_get_packet ;app_stack_handler.08 + dd app_stack_handler.09 + dd app_stack_handler.10 + dd app_stack_handler.11 + dd app_stack_handler.12 + dd app_stack_handler.13 + dd app_stack_handler.14 + dd app_stack_handler.15 +endg +app_stack_handler: +;in ebx,ecx +;out eax + cmp ebx, 15 + ja .fail ;if more than 15 then exit + + jmp dword [f52call+ebx*4] + + +.00: +; Read the configuration word + mov eax, [stack_config] + ret + +.01: +; read the IP address + mov eax, [stack_ip] + ret + +.02: +; write the configuration word + mov [stack_config], ecx + +; +; If ethernet now enabled, probe for the card, reset it and empty +; the packet buffer +; If all successfull, enable the card. +; If ethernet now disabled, set it as disabled. Should really +; empty the tcpip data area too. + +; ethernet interface is '3' in ls 7 bits + and cl, 0x7f + cmp cl, 3 + je ash_eth_enable +; Ethernet isn't enabled, so make sure that the card is disabled + mov [ethernet_active], byte 0 + ret + +.03: +; write the IP Address + mov [stack_ip], ecx + ret +;old functions was deleted +;.06: +; Insert an IP packet into the stacks received packet queue +; call stack_insert_packet +; ret + +; Test for any packets queued for transmission over the network + +;.08: +; call stack_get_packet +; Extract a packet queued for transmission by the network +; ret + +.09: +; read the gateway IP address + mov eax, [gateway_ip] + ret + +.10: +; read the subnet mask + mov eax, [subnet_mask] + ret +.11: +; write the gateway IP Address + mov [gateway_ip], ecx + ret + +.12: +; write the subnet mask + mov [subnet_mask], ecx + ret + +.13: +; read the dns + mov eax, [dns_ip] + ret + +.14: +; write the dns IP Address + mov [dns_ip], ecx + ret + +.15: +; +; in ecx we need 4 to read the last 2 bytes +; or we need 0 to read the first 4 bytes + cmp ecx, 4 + ja .param_error + +; read MAC, returned (in mirrored byte order) in eax + mov eax, [node_addr + ecx] + ret + +.param_error: + or eax, -1 ; params not accepted + ret + +.16: +; 0 -> arp_probe +; 1 -> arp_announce +; 2 -> arp_responce (not supported yet) + test ecx, ecx + je a_probe + + dec ebx + jz a_ann ; arp announce +.fail: + or eax, -1 + ret + +; cmp ebx,2 +; jne a_resp ; arp response + +; arp probe, sender IP must be set to 0.0.0.0, target IP is set to address being probed +; ecx: pointer to target MAC, MAC should set to 0 by application +; edx: target IP +a_probe: + push dword [stack_ip] + + mov edx, [stack_ip] + and [stack_ip], dword 0 + mov esi, ecx ; pointer to target MAC address + call arp_request + + pop dword [stack_ip] + ret + +; arp announce, sender IP must be set to target IP +; ecx: pointer to target MAC +a_ann: + mov edx, [stack_ip] + mov esi, ecx ; pointer to target MAC address + call arp_request + ret + +.17: +; +; modified by [smb] + +; +; ARPTable manager interface + ;see "proc arp_table_manager" for more details + stdcall arp_table_manager, ecx, edx, esi;Opcode,Index,Extra + ret +; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +ash_eth_enable: +; Probe for the card. This will reset it and enable the interface +; if found + call eth_probe + test eax, eax + jz ash_eth_done ; Abort if no hardware found + + mov [ethernet_active], byte 1 +ash_eth_done: + ret +;*************************************************************************** +; Function +; app_socket_handler +; +; Description +; This is an application service, called by int 0x40, function 53 +; It provides application access to stack socket services +; such as opening sockets +; +;*************************************************************************** +iglobal +align 4 +f53call: + dd socket_open ;00 + dd socket_close ;01 + dd socket_poll ;02 + dd socket_read ;03 + dd socket_write ;04 + dd socket_open_tcp ;05 + dd socket_status ;06 + dd socket_write_tcp ;07 + dd socket_close_tcp ;08 + dd is_localport_unused ;09 + dd app_socket_handler.10 + dd socket_read_packet ;11 +endg + +app_socket_handler: +;in ebx,ecx,edx,wsi +;out eax + cmp eax, 255 + je stack_internal_status + + cmp eax, 11 + ja .fail ;if more than 15 then exit + + jmp dword [f53call+eax*4] + +.10: + mov eax, dword[drvr_cable] + test eax, eax + jnz @f ; if function is not implented, return -1 + or al, -1 + ret +@@: + jmp dword[drvr_cable] + +.fail: + or eax, -1 + ret +uglobal + ARPTmp: + times 14 db 0 +endg + +;*************************************************************************** +; Function +; stack_internal_status +; +; Description +; Returns information about the internal status of the stack +; This is only useful for debugging +; It works with the ethernet driver +; sub function in ebx +; return requested data in eax +; +;*************************************************************************** +; This sub function allows access to debugging information on the stack +; ecx holds the request: +; 100 : return length of empty queue +; 101 : return length of IPOUT QUEUE +; 102 : return length of IPIN QUEUE +; 103 : return length of NET1OUT QUEUE +; 200 : return # of ARP entries +; 201 : return size of ARP table ( max # entries ) +; 202 : select ARP table entry # +; 203 : return IP of selected table entry +; 204 : return High 4 bytes of MAC address of selected table entry +; 205 : return low 2 bytes of MAC address of selected table entry +; 206 : return status word of selected table entry +; 207 : return Time to live of selected table entry + + +; 2 : return number of IP packets received +; 3 : return number of packets transmitted +; 4 : return number of received packets dumped +; 5 : return number of arp packets received +; 6 : return status of packet driver +; ( 0 == not active, FFFFFFFF = successful ) + + +stack_internal_status: + cmp ebx, 100 + jnz notsis100 + + ; 100 : return length of EMPTY QUEUE + mov ebx, EMPTY_QUEUE + call queueSize + ret + +notsis100: + cmp ebx, 101 + jnz notsis101 + + ; 101 : return length of IPOUT QUEUE + mov ebx, IPOUT_QUEUE + call queueSize + ret + +notsis101: + cmp ebx, 102 + jnz notsis102 + + ; 102 : return length of IPIN QUEUE + mov ebx, IPIN_QUEUE + call queueSize + ret + +notsis102: + cmp ebx, 103 + jnz notsis103 + + ; 103 : return length of NET1OUT QUEUE + mov ebx, NET1OUT_QUEUE + call queueSize + ret + +notsis103: + cmp ebx, 200 + jnz notsis200 + + ; 200 : return num entries in arp table + movzx eax, byte [NumARP] + ret + +notsis200: + cmp ebx, 201 + jnz notsis201 + + ; 201 : return arp table size + mov eax, 20; ARP_TABLE_SIZE + ret + +notsis201: + cmp ebx, 202 + jnz notsis202 + + ; 202 - read the requested table entry + ; into a temporary buffer + ; ecx holds the entry number + + mov eax, ecx + mov ecx, 14; ARP_ENTRY_SIZE + mul ecx + + mov ecx, [eax + ARPTable] + mov [ARPTmp], ecx + mov ecx, [eax + ARPTable+4] + mov [ARPTmp+4], ecx + mov ecx, [eax + ARPTable+8] + mov [ARPTmp+8], ecx + mov cx, [eax + ARPTable+12] + mov [ARPTmp+12], cx + ret + +notsis202: + cmp ebx, 203 + jnz notsis203 + + ; 203 - return IP address + mov eax, [ARPTmp] + ret + +notsis203: + cmp ebx, 204 + jnz notsis204 + + ; 204 - return MAC high dword + mov eax, [ARPTmp+4] + ret + +notsis204: + cmp ebx, 205 + jnz notsis205 + + ; 205 - return MAC ls word + movzx eax, word [ARPTmp+8] + ret + +notsis205: + cmp ebx, 206 + jnz notsis206 + + ; 206 - return status word + movzx eax, word [ARPTmp+10] + ret + +notsis206: + cmp ebx, 207 + jnz notsis207 + + ; 207 - return ttl word + movzx eax, word [ARPTmp+12] + ret + +notsis207: + cmp ebx, 2 + jnz notsis2 + + ; 2 : return number of IP packets received + mov eax, [ip_rx_count] + ret + +notsis2: + cmp ebx, 3 + jnz notsis3 + + ; 3 : return number of packets transmitted + mov eax, [ip_tx_count] + ret + +notsis3: + cmp ebx, 4 + jnz notsis4 + + ; 4 : return number of received packets dumped + mov eax, [dumped_rx_count] + ret + +notsis4: + cmp ebx, 5 + jnz notsis5 + + ; 5 : return number of arp packets received + mov eax, [arp_rx_count] + ret + +notsis5: + cmp ebx, 6 + jnz notsis6 + + ; 6 : return status of packet driver + ; ( 0 == not active, FFFFFFFF = successful ) + mov eax, [eth_status] + ret + +notsis6: + xor eax, eax + ret + + + +;*************************************************************************** +; Function +; stack_get_packet +; +; Description +; extracts an IP packet from the NET1 output queue +; and sends the data to the calling process +; pointer to data in edx +; returns number of bytes read in eax +; +;*************************************************************************** +stack_get_packet: + ; Look for a buffer to tx + mov eax, NET1OUT_QUEUE + call dequeue + cmp ax, NO_BUFFER + je sgp_non_exit ; Exit if no buffer available + + push eax ; Save buffer number for freeing at end + + push edx + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + pop edx + + push eax ; save address of IP data + ; Get the address of the callers data + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add edx, [edi] + mov edi, edx + pop eax + + mov ecx, 1500 ; should get the actual number of bytes to write + mov esi, eax + cld + rep movsb ; copy the data across + + ; And finally, return the buffer to the free queue + pop eax + call freeBuff + + mov eax, 1500 + ret + +sgp_non_exit: + xor eax, eax + ret + + + +;*************************************************************************** +; Function +; stack_insert_packet +; +; Description +; writes an IP packet into the stacks receive queue +; # of bytes to write in ecx +; pointer to data in edx +; returns 0 in eax ok, -1 == failed +; +;*************************************************************************** +stack_insert_packet: + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je sip_err_exit + + push eax + + ; save the pointers to the data buffer & size + push edx + push ecx + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edx, eax + + ; So, edx holds the IPbuffer ptr + + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later + pop eax ; get callers ptr to data to send + + ; Get the address of the callers data + mov edi, [TASK_BASE] + add edi, TASKDATA.mem_start + add eax, [edi] + mov esi, eax + + mov edi, edx + cld + rep movsb ; copy the data across + + pop ebx + + mov eax, IPIN_QUEUE + call queue + + inc dword [ip_rx_count] + + mov eax, 0 + ret + +sip_err_exit: + mov eax, 0xFFFFFFFF + ret + diff --git a/kernel/trunk/network/tcp.inc b/kernel/trunk/network/tcp.inc index 50204492a..b571d282d 100644 --- a/kernel/trunk/network/tcp.inc +++ b/kernel/trunk/network/tcp.inc @@ -1,1172 +1,1176 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; TCP.INC ;; -;; ;; -;; TCP Processes for Menuet OS TCP/IP stack ;; -;; ;; -;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; v0.6 : Added reset handling in the established state ;; -;; Added a timer per socket to allow delays when ;; -;; rx window gets below 1KB ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; TCP TCB states -TCB_LISTEN equ 1 -TCB_SYN_SENT equ 2 -TCB_SYN_RECEIVED equ 3 -TCB_ESTABLISHED equ 4 -TCB_FIN_WAIT_1 equ 5 -TCB_FIN_WAIT_2 equ 6 -TCB_CLOSE_WAIT equ 7 -TCB_CLOSING equ 8 -TCB_LAST_ACK equ 9 -TCB_TIMED_WAIT equ 10 -TCB_CLOSED equ 11 - -TH_FIN = 0x01 -TH_SYN = 0x02 -TH_RST = 0x04 -TH_PUSH = 0x08 -TH_ACK = 0x10 -TH_URG = 0x20 - -TWOMSL equ 10 ; # of secs to wait before closing socket - -TCP_RETRIES equ 5 ; Number of times to resend a packet -TCP_TIMEOUT equ 20 ; resend if not replied to in x hs - -;******************************************************************* -; Interface -; -; tcp_tx_handler Handles the TCP transmit queue -; tcp_rx The protocol handler for received data -; buildTCPPacket fills in the packet headers and data -; tcpStateMachine Main state machine for received TCP packets -; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state -; -;******************************************************************* - - -; TCP Payload ( Data field in IP datagram ) -; -; 0 1 2 3 -; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;20 | Source Port | Destination Port | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;24 | Sequence Number | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;28 | Acknowledgment Number | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;32 | Data | |U|A|P|R|S|F| | -; | Offset| Reserved |R|C|S|S|Y|I| Window | -; | | |G|K|H|T|N|N| | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;36 | Checksum | Urgent Pointer | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -;40 | Options | Padding | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | data - - -struc TCP_PACKET -{ .SourcePort dw ? ;+00 - .DestinationPort dw ? ;+02 - .SequenceNumber dd ? ;+04 - .AckNumber dd ? ;+08 - .DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] - .Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN - .Window dw ? ;+14 - .Checksum dw ? ;+16 - .UrgentPointer dw ? ;+18 - .Options rb 3 ;+20 - .Padding db ? ;+23 - .Data db ? ;+24 -} - -virtual at 0 - TCP_PACKET TCP_PACKET -end virtual - - - -;*************************************************************************** -; Function -; tcp_tcb_handler -; -; Description -; Handles sockets in the timewait state, closing them -; when the TCB timer expires -; -;*************************************************************************** - -proc tcp_tcb_handler stdcall uses ebx - ; scan through all the sockets, decrementing active timers - - mov ebx, net_sockets - - cmp [ebx + SOCKET.NextPtr], 0 - je .exit - ;DEBUGF 1, "K : sockets:\n" - - .next_socket: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .exit - - ;DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] - - cmp [ebx + SOCKET.TCBTimer], 0 - jne .decrement_tcb - cmp [ebx + SOCKET.wndsizeTimer], 0 - jne .decrement_wnd - jmp .next_socket - - .decrement_tcb: - ; decrement it, delete socket if TCB timer = 0 & socket in timewait state - dec [ebx + SOCKET.TCBTimer] - jnz .next_socket - - cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT - jne .next_socket - - push [ebx + SOCKET.PrevPtr] - stdcall net_socket_free, ebx - pop ebx - jmp .next_socket - - .decrement_wnd: - ; TODO - prove it works! - dec [ebx + SOCKET.wndsizeTimer] - jmp .next_socket - - .exit: - ret -endp - - -;*************************************************************************** -; Function -; tcp_tx_handler -; -; Description -; Handles queued TCP data -; This is a kernel function, called by stack_handler -; -;*************************************************************************** - -proc tcp_tx_handler stdcall - ; decrement all resend buffers timers. If they - ; expire, queue them for sending, and restart the timer. - ; If the retries counter reach 0, delete the entry - - mov esi, resendQ - mov ecx, 0 - - .next_resendq: - cmp ecx, NUMRESENDENTRIES - je .exit ; None left - cmp dword[esi + 4], 0 - jne @f ; found one - inc ecx - add esi, 8 - jmp .next_resendq - - @@: ; we have one. decrement it's timer by 1 - dec word[esi + 2] - jz @f - inc ecx - add esi, 8 - jmp .next_resendq ; Timer not zero, so move on - - @@: - xor ebx, ebx - ; restart timer, and decrement retries - ; After the first resend, back of on next, by a factor of 5 - mov [esi + 2], word TCP_TIMEOUT * 5 - dec byte[esi + 1] - jnz @f - - ; retries now 0, so delete from queue - xchg [esi + 4], ebx - - @@: ; resend packet - pushad - - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - jne .tth004z - - ; TODO - try again in 10ms. - test ebx, ebx - jnz @f - mov [esi + 4], ebx - - @@: ; Mark it to expire in 10ms - 1 tick - mov byte[esi + 1], 1 - mov word[esi + 2], 1 - jmp .tth005 - - .tth004z: - ; we have a buffer # in ax - push eax ecx - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - - ; we have the buffer address in eax - mov edi, eax - pop ecx - ; Now get buffer location, and copy buffer across. argh! more copying,, - imul esi, ecx, IPBUFFSIZE - add esi, resendBuffer - - ; we have resend buffer location in esi - mov ecx, IPBUFFSIZE - - ; copy data across - push edi - cld - rep movsb - pop edi - - ; queue packet - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - cmp edx, [edi + IP_PACKET.DestinationAddress] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - pop ebx - call queue - - .tth005: - popad - - inc ecx - add esi, 8 - jmp .next_resendq - - .exit: - ret -endp - - -;*************************************************************************** -; Function -; tcp_rx -; -; Description -; TCP protocol handler -; This is a kernel function, called by ip_rx -; IP buffer address given in edx -; IP buffer number in eax -; Free up (or re-use) IP buffer when finished -; -;*************************************************************************** - -proc tcp_rx stdcall uses ebx - ; The process is as follows. - ; Look for a socket with matching remote IP, remote port, local port - ; if not found, then - ; look for remote IP + local port match ( where sockets remote port = 0) - ; if not found, then - ; look for a socket where local socket port == IP packets remote port - ; where sockets remote port, remote IP = 0 - ; discard if not found - ; Call sockets tcbStateMachine, with pointer to packet. - ; the state machine will not delete the packet, so do that here. - - push eax - - ; Look for a socket where - ; IP Packet TCP Destination Port = local Port - ; IP Packet SA = Remote IP - ; IP Packet TCP Source Port = remote Port - - mov ebx, net_sockets - - .next_socket.1: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .next_socket.1.exit - -; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 - - mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr - cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr - jne .next_socket.1 ; different - try next socket - -; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] - - mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr - cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP - jne .next_socket.1 ; different - try next socket - -; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 - - mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr - cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port - jne .next_socket.1 ; different - try next socket - - ; We have a complete match - use this socket - jmp .change_state - - .next_socket.1.exit: - - ; If we got here, there was no match - ; Look for a socket where - ; IP Packet TCP Destination Port = local Port - ; IP Packet SA = Remote IP - ; socket remote Port = 0 - - mov ebx, net_sockets - - .next_socket.2: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .next_socket.2.exit - -; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 - - mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr - cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port - jne .next_socket.2 ; different - try next socket - -; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] - - mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr - cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP - jne .next_socket.2 ; different - try next socket - -; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 - - cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 - jne .next_socket.2 ; different - try next socket - - ; We have a complete match - use this socket - jmp .change_state - - .next_socket.2.exit: - - ; If we got here, there was no match - ; Look for a socket where - ; IP Packet TCP Destination Port = local Port - ; socket Remote IP = 0 - ; socket remote Port = 0 - - mov ebx, net_sockets - - .next_socket.3: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .next_socket.3.exit - -; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 - - mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr - cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port - jne .next_socket.3 ; different - try next socket - -; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] - - cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 - jne .next_socket.3 ; different - try next socket - -; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 - - cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 - jne .next_socket.3 ; different - try next socket - - ; We have a complete match - use this socket - jmp .change_state - - .next_socket.3.exit: - - ; If we got here, we need to reject the packet - - DEBUGF 1, "K : tcp_rx - dumped\n" - DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2 - - inc [dumped_rx_count] - jmp .exit - - .change_state: - - ; We have a valid socket/TCB, so call the TCB State Machine for that skt. - ; socket is pointed to by ebx - ; IP packet is pointed to by edx - ; IP buffer number is on stack ( it will be popped at the end) - - stdcall tcpStateMachine, ebx - - .exit: - pop eax - call freeBuff - ret -endp - - -;*************************************************************************** -; Function -; buildTCPPacket -; -; Description -; builds an IP Packet with TCP data fully populated for transmission -; You may destroy any and all registers -; TCP control flags specified in bl -; This TCB is in [sktAddr] -; User data pointed to by esi -; Data length in ecx -; Transmit buffer number in eax -; -;*************************************************************************** - -proc build_tcp_packet stdcall, sockAddr:DWORD - push ecx ; Save data length - - ; convert buffer pointer eax to the absolute address - mov ecx, IPBUFFSIZE - mul ecx - add eax, IPbuffs - - mov edx, eax - - mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags - - mov ebx, [sockAddr] - - ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr - - ; Fill in the IP header ( some data is in the socket descriptor) - mov eax, [ebx + SOCKET.LocalIP] - mov [edx + IP_PACKET.SourceAddress], eax - mov eax, [ebx + SOCKET.RemoteIP] - mov [edx + IP_PACKET.DestinationAddress], eax - - mov [edx + IP_PACKET.VersionAndIHL], 0x45 - mov [edx + IP_PACKET.TypeOfService], 0 - - pop eax ; Get the TCP data length - push eax - - add eax, 20 + 20 ; add IP header and TCP header lengths - rol ax, 8 - mov [edx + IP_PACKET.TotalLength], ax - mov [edx + IP_PACKET.Identification], 0 - mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 - mov [edx + IP_PACKET.TimeToLive], 0x20 - mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP - - ; Checksum left unfilled - mov [edx + IP_PACKET.HeaderChecksum], 0 - - ; Fill in the TCP header (some data is in the socket descriptor) - mov ax, [ebx + SOCKET.LocalPort] - mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port - - mov ax, [ebx + SOCKET.RemotePort] - mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port - - ; Checksum left unfilled - mov [edx + 20 + TCP_PACKET.Checksum], 0 - - ; sequence number - mov eax, [ebx + SOCKET.SND_NXT] - mov [edx + 20 + TCP_PACKET.SequenceNumber], eax - - ; ack number - mov eax, [ebx + SOCKET.RCV_NXT] - mov [edx + 20 + TCP_PACKET.AckNumber], eax - - ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) - ; 768 bytes seems better - mov [edx + 20 + TCP_PACKET.Window], 0x0003 - - ; Urgent pointer (0) - mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 - - ; data offset ( 0x50 ) - mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 - - pop ecx ; count of bytes to send - mov ebx, ecx ; need the length later - - cmp ebx, 0 - jz @f - - mov edi, edx - add edi, 40 - cld - rep movsb ; copy the data across - - @@: ; we have edx as IPbuffer ptr. - ; Fill in the TCP checksum - ; First, fill in pseudoheader - mov eax, [edx + IP_PACKET.SourceAddress] - mov [pseudoHeader], eax - mov eax, [edx + IP_PACKET.DestinationAddress] - mov [pseudoHeader + 4], eax - mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 - add ebx, 20 - mov [pseudoHeader + 10], bh - mov [pseudoHeader + 11], bl - - mov eax, pseudoHeader - mov [checkAdd1], eax - mov word[checkSize1], 12 - mov eax, edx - add eax, 20 - mov [checkAdd2], eax - mov eax, ebx - mov [checkSize2], ax - - call checksum - - ; store it in the TCP checksum ( in the correct order! ) - mov ax, [checkResult] - rol ax, 8 - mov [edx + 20 + TCP_PACKET.Checksum], ax - - ; Fill in the IP header checksum - GET_IHL eax, edx ; get IP-Header length - stdcall checksum_jb, edx, eax ; buf_ptr, buf_size - rol ax, 8 - mov [edx + IP_PACKET.HeaderChecksum], ax - - ret -endp - - -; Increments the 32 bit value pointed to by esi in internet order -proc inc_inet_esi stdcall - push eax - mov eax, [esi] - bswap eax - inc eax - bswap eax - mov [esi], eax - pop eax - ret -endp - - -; Increments the 32 bit value pointed to by esi in internet order -; by the value in ecx -proc add_inet_esi stdcall - push eax - mov eax, [esi] - bswap eax - add eax, ecx - bswap eax - mov [esi], eax - pop eax - ret -endp - - -iglobal - TCBStateHandler dd \ - stateTCB_LISTEN, \ - stateTCB_SYN_SENT, \ - stateTCB_SYN_RECEIVED, \ - stateTCB_ESTABLISHED, \ - stateTCB_FIN_WAIT_1, \ - stateTCB_FIN_WAIT_2, \ - stateTCB_CLOSE_WAIT, \ - stateTCB_CLOSING, \ - stateTCB_LAST_ACK, \ - stateTCB_TIME_WAIT, \ - stateTCB_CLOSED -endg - - -;*************************************************************************** -; Function -; tcpStateMachine -; -; Description -; TCP state machine -; This is a kernel function, called by tcp_rx -; -; IP buffer address given in edx -; Socket/TCB address in ebx -; -; The IP buffer will be released by the caller -;*************************************************************************** - -proc tcpStateMachine stdcall, sockAddr:DWORD - ; as a packet has been received, update the TCB timer - mov [ebx + SOCKET.TCBTimer], TWOMSL - - ; If the received packet has an ACK bit set, - ; remove any packets in the resend queue that this - ; received packet acknowledges - pushad - test [edx + 20 + TCP_PACKET.Flags], TH_ACK - jz .call_handler ; No ACK, so no data yet - - ; get skt number in eax - stdcall net_socket_addr_to_num, ebx - - ; The ack number is in [edx + 28], inet format - ; skt in eax - - mov esi, resendQ - xor ecx, ecx - - .next_resendq: - cmp ecx, NUMRESENDENTRIES - je .call_handler ; None left - cmp [esi + 4], eax - je @f ; found one - inc ecx - add esi, 8 - jmp .next_resendq - - @@: ; Can we delete this buffer? - - ; If yes, goto @@. No, goto .next_resendq - ; Get packet data address - - push ecx - ; Now get buffer location, and copy buffer across. argh! more copying,, - imul edi, ecx, IPBUFFSIZE - add edi, resendBuffer - - ; we have dest buffer location in edi. incoming packet in edx. - ; Get this packets sequence number - ; preserve al, ecx, esi, edx - mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] - bswap ecx - movzx ebx, word[edi + 2] - xchg bl, bh - sub ebx, 40 - add ecx, ebx ; ecx is now seq# of last byte +1, intel format - - ; get recievd ack #, in intel format - mov ebx, [edx + 20 + TCP_PACKET.AckNumber] - bswap ebx - - cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que - ; DANGER! need to handle case that we have just - ; passed the 2**32, and wrapped round! - pop ecx - jae @f ; if rx > old, delete old - - inc ecx - add esi, 8 - jmp .next_resendq - - @@: mov dword[esi + 4], 0 - inc ecx - add esi, 8 - jmp .next_resendq - - .call_handler: - popad - - ; Call handler for given TCB state - - mov eax, [ebx + SOCKET.TCBState] - cmp eax, TCB_LISTEN - jb .exit - cmp eax, TCB_CLOSED - ja .exit - - stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] - - .exit: - ret -endp - -;*************************************************************************** -; Function -; signal_network_event -; -; Description -; Signals about network event to socket owner -; This is a kernel function, called from TCP handler -; -; Socket/TCB address in ebx -;*************************************************************************** -proc signal_network_event - push ecx esi eax - mov eax, [ebx + SOCKET.PID] - mov ecx, 1 - mov esi, TASK_DATA + TASKDATA.pid - - .next_pid: - cmp [esi], eax - je .found_pid - inc ecx - add esi, 0x20 - cmp ecx, [TASK_COUNT] - jbe .next_pid - - .found_pid: - shl ecx, 8 - or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event - pop eax esi ecx - ret -endp - -proc stateTCB_LISTEN stdcall, sockAddr:DWORD - ; In this case, we are expecting a SYN packet - ; For now, if the packet is a SYN, process it, and send a response - ; If not, ignore it - - ; Look at control flags - test [edx + 20 + TCP_PACKET.Flags], TH_SYN - jz .exit - - ; We have a SYN. update the socket with this IP packets details, - ; And send a response - - mov eax, [edx + IP_PACKET.SourceAddress] - mov [ebx + SOCKET.RemoteIP], eax - mov ax, [edx + 20 + TCP_PACKET.SourcePort] - mov [ebx + SOCKET.RemotePort], ax - mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] - mov [ebx + SOCKET.IRS], eax - mov [ebx + SOCKET.RCV_NXT], eax - lea esi, [ebx + SOCKET.RCV_NXT] - call inc_inet_esi ; RCV.NXT - mov eax, [ebx + SOCKET.ISS] - mov [ebx + SOCKET.SND_NXT], eax - - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .exit - - push ebx - push eax - mov bl, TH_SYN + TH_ACK - xor ecx, ecx - xor esi, esi - stdcall build_tcp_packet, [sockAddr] - - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - pop ebx - call queue - - pop ebx - mov esi, [sockAddr] - mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED - call signal_network_event - - ; increment SND.NXT in socket - add esi, SOCKET.SND_NXT - call inc_inet_esi - - .exit: - ret -endp - - -proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD - ; We are awaiting an ACK to our SYN, with a SYM - ; Look at control flags - expecting an ACK - - mov al, [edx + 20 + TCP_PACKET.Flags] - and al, TH_SYN + TH_ACK - cmp al, TH_SYN + TH_ACK - je .syn_ack - - test al, TH_SYN - jz .exit - - mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED - push TH_SYN + TH_ACK - jmp .send - - .syn_ack: - mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED - push TH_ACK - - .send: - call signal_network_event - ; Store the recv.nxt field - mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] - - ; Update our recv.nxt field - mov [ebx + SOCKET.RCV_NXT], eax - lea esi, [ebx + SOCKET.RCV_NXT] - call inc_inet_esi - - ; Send an ACK - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - pop ebx - je .exit - - push eax - - xor ecx, ecx - xor esi, esi - stdcall build_tcp_packet, [sockAddr] - - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - pop ebx - call queue - - .exit: - ret -endp - - -proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD - ; In this case, we are expecting an ACK packet - ; For now, if the packet is an ACK, process it, - ; If not, ignore it - - test [edx + 20 + TCP_PACKET.Flags], TH_RST - jz .check_ack - - push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] - pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] - - mov [ebx + SOCKET.TCBState], TCB_LISTEN - jmp .signal - - .check_ack: - ; Look at control flags - expecting an ACK - test [edx + 20 + TCP_PACKET.Flags], TH_ACK - jz .exit - - mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED - .signal: - call signal_network_event - - .exit: - ret -endp - - -proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD - ; Here we are expecting data, or a request to close - ; OR both... - - ; Ignore all packets with sequnce number other than next expected - - ; recv.nxt is in dword [edx+24], in inet format - ; recv seq is in [sktAddr]+56, in inet format - ; just do a comparision - mov eax, [ebx + SOCKET.RCV_NXT] - cmp eax, [edx + 20 + TCP_PACKET.SequenceNumber] - jne .exit - - ; Did we receive a FIN or RST? - test [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST - jz .check_ack - - ; It was a fin or reset. - - ; Remove resend entries from the queue - I dont want to send any more data - pushad - - ; get skt # - stdcall net_socket_addr_to_num, ebx - - mov esi, resendQ - mov ecx, 0 - - .next_resendq: - cmp ecx, NUMRESENDENTRIES - je .last_resendq ; None left - cmp [esi + 4], eax - je @f ; found one - inc ecx - add esi, 8 - jmp .next_resendq - - @@: mov dword[esi + 4], 0 - inc ecx - add esi, 8 - jmp .next_resendq - - .last_resendq: - popad - - @@: ; Send an ACK to that fin, and enter closewait state - - mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT - test [edx + 20 + TCP_PACKET.Flags], TH_RST - je @f - mov [ebx + SOCKET.TCBState], TCB_CLOSED - @@: - call signal_network_event - lea esi, [ebx + SOCKET.RCV_NXT] - mov eax, [esi] ; save original - call inc_inet_esi - ;; jmp ste_ack - NO, there may be data - - .check_ack: - ; Check that we received an ACK - test [edx + 20 + TCP_PACKET.Flags], TH_ACK - jz .exit - - ; TODO - done, I think! - ; First, look at the incoming window. If this is less than or equal to 1024, - ; Set the socket window timer to 1. This will stop an additional packets being queued. - ; ** I may need to tweak this value, since I do not know how many packets are already queued - mov cx, [edx + 20 + TCP_PACKET.Window] - xchg cl, ch - cmp cx, 1024 - ja @f - - mov [ebx + SOCKET.wndsizeTimer], 1 - - @@: ; OK, here is the deal - - - ; Read the data bytes, store in socket buffer - movzx ecx, [edx + IP_PACKET.TotalLength] - xchg cl, ch - sub ecx, 40 ; Discard 40 bytes of header - ja .data ; Read data, if any - - ; If we had received a fin, we need to ACK it. - cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT - je .ack - jmp .exit - - .data: - push ecx - push ecx edx - lea ecx, [ebx+SOCKET.lock] - call mutex_lock - pop edx ecx - - push ebx - mov eax, [ebx + SOCKET.rxDataCount] - add eax, ecx - cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE - ja .overflow - - mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer - - ; point to the location to store the data - lea edi, [ebx + eax + SOCKETHEADERSIZE] - sub edi, ecx - - add edx, 40 ; edx now points to the data - mov esi, edx - - cld - rep movsb ; copy the data across - - lea ecx,[ebx + SOCKET.lock] - call mutex_unlock - - ; flag an event to the application - pop ebx - call signal_network_event - - pop ecx - - ; Update our recv.nxt field - lea esi, [ebx + SOCKET.RCV_NXT] - call add_inet_esi - - .ack: - ; Send an ACK - ; Now construct the response, and queue for sending by IP - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .exit - - push eax - - mov bl, TH_ACK - xor ecx, ecx - xor esi, esi - stdcall build_tcp_packet, [sockAddr] - - mov eax, NET1OUT_QUEUE - - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - pop ebx - call queue - - .exit: - ret - .overflow: - ; no place in buffer - ; so simply restore stack and exit - lea ecx, [ebx + SOCKET.lock] - call mutex_unlock - pop eax ecx - ret -endp - - -proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD - ; We can either receive an ACK of a fin, or a fin - mov al, [edx + 20 + TCP_PACKET.Flags] - and al, TH_FIN + TH_ACK - - cmp al, TH_ACK - jne @f - - ; It was an ACK - mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 - jmp .exit - - @@: mov [ebx + SOCKET.TCBState], TCB_CLOSING - cmp al, TH_FIN - je @f - mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT - - @@: lea esi, [ebx + SOCKET.RCV_NXT] - call inc_inet_esi - - ; Send an ACK - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .exit - - push eax - - mov bl, TH_ACK - xor ecx, ecx - xor esi, esi - stdcall build_tcp_packet, [sockAddr] - - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - pop ebx - call queue - - .exit: - ret -endp - - -proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD - test [edx + 20 + TCP_PACKET.Flags], TH_FIN - jz .exit - - ; Change state, as we have a fin - mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT - - lea esi, [ebx + SOCKET.RCV_NXT] - call inc_inet_esi - - ; Send an ACK - mov eax, EMPTY_QUEUE - call dequeue - cmp ax, NO_BUFFER - je .exit - - push eax - - mov bl, TH_ACK - xor ecx, ecx - xor esi, esi - stdcall build_tcp_packet, [sockAddr] - - mov eax, NET1OUT_QUEUE - mov edx, [stack_ip] - mov ecx, [sockAddr] - cmp edx, [ecx + SOCKET.RemoteIP] - jne .not_local - mov eax, IPIN_QUEUE - - .not_local: - ; Send it. - pop ebx - call queue - - .exit: - ret -endp - - -proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD - ; Intentionally left empty - ; socket_close_tcp handles this - ret -endp - - -proc stateTCB_CLOSING stdcall, sockAddr:DWORD - ; We can either receive an ACK of a fin, or a fin - test [edx + 20 + TCP_PACKET.Flags], TH_ACK - jz .exit - - mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT - - .exit: - ret -endp - - -proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD - ; Look at control flags - expecting an ACK - test [edx + 20 + TCP_PACKET.Flags], TH_ACK - jz .exit - - ; delete the socket - stdcall net_socket_free, ebx - - .exit: - ret -endp - - -proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD - ret -endp - - -proc stateTCB_CLOSED stdcall, sockAddr:DWORD - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; TCP.INC ;; +;; ;; +;; TCP Processes for Menuet OS TCP/IP stack ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; v0.6 : Added reset handling in the established state ;; +;; Added a timer per socket to allow delays when ;; +;; rx window gets below 1KB ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; TCP TCB states +TCB_LISTEN equ 1 +TCB_SYN_SENT equ 2 +TCB_SYN_RECEIVED equ 3 +TCB_ESTABLISHED equ 4 +TCB_FIN_WAIT_1 equ 5 +TCB_FIN_WAIT_2 equ 6 +TCB_CLOSE_WAIT equ 7 +TCB_CLOSING equ 8 +TCB_LAST_ACK equ 9 +TCB_TIMED_WAIT equ 10 +TCB_CLOSED equ 11 + +TH_FIN = 0x01 +TH_SYN = 0x02 +TH_RST = 0x04 +TH_PUSH = 0x08 +TH_ACK = 0x10 +TH_URG = 0x20 + +TWOMSL equ 10 ; # of secs to wait before closing socket + +TCP_RETRIES equ 5 ; Number of times to resend a packet +TCP_TIMEOUT equ 20 ; resend if not replied to in x hs + +;******************************************************************* +; Interface +; +; tcp_tx_handler Handles the TCP transmit queue +; tcp_rx The protocol handler for received data +; buildTCPPacket fills in the packet headers and data +; tcpStateMachine Main state machine for received TCP packets +; tcp_tcb_handler 1s timer, to erase tcb's in TIME_WAIT state +; +;******************************************************************* + + +; TCP Payload ( Data field in IP datagram ) +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;20 | Source Port | Destination Port | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;24 | Sequence Number | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;28 | Acknowledgment Number | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;32 | Data | |U|A|P|R|S|F| | +; | Offset| Reserved |R|C|S|S|Y|I| Window | +; | | |G|K|H|T|N|N| | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;36 | Checksum | Urgent Pointer | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +;40 | Options | Padding | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | data + + +struc TCP_PACKET +{ .SourcePort dw ? ;+00 + .DestinationPort dw ? ;+02 + .SequenceNumber dd ? ;+04 + .AckNumber dd ? ;+08 + .DataOffset db ? ;+12 - DataOffset[0-3 bits] and Reserved[4-7] + .Flags db ? ;+13 - Reserved[0-1 bits]|URG|ACK|PSH|RST|SYN|FIN + .Window dw ? ;+14 + .Checksum dw ? ;+16 + .UrgentPointer dw ? ;+18 + .Options rb 3 ;+20 + .Padding db ? ;+23 + .Data db ? ;+24 +} + +virtual at 0 + TCP_PACKET TCP_PACKET +end virtual + + + +;*************************************************************************** +; Function +; tcp_tcb_handler +; +; Description +; Handles sockets in the timewait state, closing them +; when the TCB timer expires +; +;*************************************************************************** + +proc tcp_tcb_handler stdcall uses ebx + ; scan through all the sockets, decrementing active timers + + mov ebx, net_sockets + + cmp [ebx + SOCKET.NextPtr], 0 + je .exit + ;DEBUGF 1, "K : sockets:\n" + + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .exit + + ;DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] + + cmp [ebx + SOCKET.TCBTimer], 0 + jne .decrement_tcb + cmp [ebx + SOCKET.wndsizeTimer], 0 + jne .decrement_wnd + jmp .next_socket + + .decrement_tcb: + ; decrement it, delete socket if TCB timer = 0 & socket in timewait state + dec [ebx + SOCKET.TCBTimer] + jnz .next_socket + + cmp [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + jne .next_socket + + push [ebx + SOCKET.PrevPtr] + stdcall net_socket_free, ebx + pop ebx + jmp .next_socket + + .decrement_wnd: + ; TODO - prove it works! + dec [ebx + SOCKET.wndsizeTimer] + jmp .next_socket + + .exit: + ret +endp + + +;*************************************************************************** +; Function +; tcp_tx_handler +; +; Description +; Handles queued TCP data +; This is a kernel function, called by stack_handler +; +;*************************************************************************** + +proc tcp_tx_handler stdcall + ; decrement all resend buffers timers. If they + ; expire, queue them for sending, and restart the timer. + ; If the retries counter reach 0, delete the entry + + mov esi, resendQ + mov ecx, 0 + + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .exit ; None left + cmp dword[esi + 4], 0 + jne @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + @@: ; we have one. decrement it's timer by 1 + dec word[esi + 2] + jz @f + inc ecx + add esi, 8 + jmp .next_resendq ; Timer not zero, so move on + + @@: + xor ebx, ebx + ; restart timer, and decrement retries + ; After the first resend, back of on next, by a factor of 5 + mov [esi + 2], word TCP_TIMEOUT * 5 + dec byte[esi + 1] + jnz @f + + ; retries now 0, so delete from queue + xchg [esi + 4], ebx + + @@: ; resend packet + pushad + + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + jne .tth004z + + ; TODO - try again in 10ms. + test ebx, ebx + jnz @f + mov [esi + 4], ebx + + @@: ; Mark it to expire in 10ms - 1 tick + mov byte[esi + 1], 1 + mov word[esi + 2], 1 + jmp .tth005 + + .tth004z: + ; we have a buffer # in ax + push eax ecx + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + ; we have the buffer address in eax + mov edi, eax + pop ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + imul esi, ecx, IPBUFFSIZE + add esi, resendBuffer + + ; we have resend buffer location in esi + mov ecx, IPBUFFSIZE + + ; copy data across + push edi + cld + rep movsb + pop edi + + ; queue packet + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + cmp edx, [edi + IP_PACKET.DestinationAddress] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + pop ebx + call queue + + .tth005: + popad + + inc ecx + add esi, 8 + jmp .next_resendq + + .exit: + ret +endp + + +;*************************************************************************** +; Function +; tcp_rx +; +; Description +; TCP protocol handler +; This is a kernel function, called by ip_rx +; IP buffer address given in edx +; IP buffer number in eax +; Free up (or re-use) IP buffer when finished +; +;*************************************************************************** + +proc tcp_rx stdcall uses ebx + ; The process is as follows. + ; Look for a socket with matching remote IP, remote port, local port + ; if not found, then + ; look for remote IP + local port match ( where sockets remote port = 0) + ; if not found, then + ; look for a socket where local socket port == IP packets remote port + ; where sockets remote port, remote IP = 0 + ; discard if not found + ; Call sockets tcbStateMachine, with pointer to packet. + ; the state machine will not delete the packet, so do that here. + + push eax + + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; IP Packet SA = Remote IP + ; IP Packet TCP Source Port = remote Port + + mov ebx, net_sockets + + .next_socket.1: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.1.exit + +; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 + + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr + jne .next_socket.1 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] + + mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr + cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP + jne .next_socket.1 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_PACKET.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 + + mov ax, [edx + 20 + TCP_PACKET.SourcePort] ; get the source port from the TCP hdr + cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port + jne .next_socket.1 ; different - try next socket + + ; We have a complete match - use this socket + jmp .change_state + + .next_socket.1.exit: + + ; If we got here, there was no match + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; IP Packet SA = Remote IP + ; socket remote Port = 0 + + mov ebx, net_sockets + + .next_socket.2: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.2.exit + +; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 + + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get the dest. port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port + jne .next_socket.2 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_PACKET.SourceAddress], [ebx + SOCKET.RemoteIP] + + mov eax, [edx + IP_PACKET.SourceAddress] ; get the source IP Addr from the IP hdr + cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP + jne .next_socket.2 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 + + cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 + jne .next_socket.2 ; different - try next socket + + ; We have a complete match - use this socket + jmp .change_state + + .next_socket.2.exit: + + ; If we got here, there was no match + ; Look for a socket where + ; IP Packet TCP Destination Port = local Port + ; socket Remote IP = 0 + ; socket remote Port = 0 + + mov ebx, net_sockets + + .next_socket.3: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .next_socket.3.exit + +; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 + + mov ax, [edx + 20 + TCP_PACKET.DestinationPort] ; get destination port from the TCP hdr + cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port + jne .next_socket.3 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 3.addr: 00000000 - %x\n", [ebx + SOCKET.RemoteIP] + + cmp [ebx + SOCKET.RemoteIP], 0 ; only match a socket remote IP of 0 + jne .next_socket.3 ; different - try next socket + +; DEBUGF 1, "K : tcp_rx - 3.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 + + cmp [ebx + SOCKET.RemotePort], 0 ; only match a remote socket of 0 + jne .next_socket.3 ; different - try next socket + + ; We have a complete match - use this socket + jmp .change_state + + .next_socket.3.exit: + + ; If we got here, we need to reject the packet + + DEBUGF 1, "K : tcp_rx - dumped\n" + DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_PACKET.DestinationPort]:4, [edx + IP_PACKET.SourceAddress], [edx + 20 + TCP_PACKET.SourcePort]:4, [edx + 20 + TCP_PACKET.Flags]:2 + + inc [dumped_rx_count] + jmp .exit + + .change_state: + + ; We have a valid socket/TCB, so call the TCB State Machine for that skt. + ; socket is pointed to by ebx + ; IP packet is pointed to by edx + ; IP buffer number is on stack ( it will be popped at the end) + + stdcall tcpStateMachine, ebx + + .exit: + pop eax + call freeBuff + ret +endp + + +;*************************************************************************** +; Function +; buildTCPPacket +; +; Description +; builds an IP Packet with TCP data fully populated for transmission +; You may destroy any and all registers +; TCP control flags specified in bl +; This TCB is in [sktAddr] +; User data pointed to by esi +; Data length in ecx +; Transmit buffer number in eax +; +;*************************************************************************** + +proc build_tcp_packet stdcall, sockAddr:DWORD + push ecx ; Save data length + + ; convert buffer pointer eax to the absolute address + mov ecx, IPBUFFSIZE + mul ecx + add eax, IPbuffs + + mov edx, eax + + mov [edx + 20 + TCP_PACKET.Flags], bl ; TCP flags + + mov ebx, [sockAddr] + + ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr + + ; Fill in the IP header ( some data is in the socket descriptor) + mov eax, [ebx + SOCKET.LocalIP] + mov [edx + IP_PACKET.SourceAddress], eax + mov eax, [ebx + SOCKET.RemoteIP] + mov [edx + IP_PACKET.DestinationAddress], eax + + mov [edx + IP_PACKET.VersionAndIHL], 0x45 + mov [edx + IP_PACKET.TypeOfService], 0 + + pop eax ; Get the TCP data length + push eax + + add eax, 20 + 20 ; add IP header and TCP header lengths + rol ax, 8 + mov [edx + IP_PACKET.TotalLength], ax + mov [edx + IP_PACKET.Identification], 0 + mov [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040 + mov [edx + IP_PACKET.TimeToLive], 0x20 + mov [edx + IP_PACKET.Protocol], PROTOCOL_TCP + + ; Checksum left unfilled + mov [edx + IP_PACKET.HeaderChecksum], 0 + + ; Fill in the TCP header (some data is in the socket descriptor) + mov ax, [ebx + SOCKET.LocalPort] + mov [edx + 20 + TCP_PACKET.SourcePort], ax ; Local Port + + mov ax, [ebx + SOCKET.RemotePort] + mov [edx + 20 + TCP_PACKET.DestinationPort], ax ; desitination Port + + ; Checksum left unfilled + mov [edx + 20 + TCP_PACKET.Checksum], 0 + + ; sequence number + mov eax, [ebx + SOCKET.SND_NXT] + mov [edx + 20 + TCP_PACKET.SequenceNumber], eax + + ; ack number + mov eax, [ebx + SOCKET.RCV_NXT] + mov [edx + 20 + TCP_PACKET.AckNumber], eax + + ; window ( 0x2000 is default ).I could accept 4KB, fa0, ( skt buffer size) + ; 768 bytes seems better + mov [edx + 20 + TCP_PACKET.Window], 0x0003 + + ; Urgent pointer (0) + mov [edx + 20 + TCP_PACKET.UrgentPointer], 0 + + ; data offset ( 0x50 ) + mov [edx + 20 + TCP_PACKET.DataOffset], 0x50 + + pop ecx ; count of bytes to send + mov ebx, ecx ; need the length later + + cmp ebx, 0 + jz @f + + mov edi, edx + add edi, 40 + cld + rep movsb ; copy the data across + + @@: ; we have edx as IPbuffer ptr. + ; Fill in the TCP checksum + ; First, fill in pseudoheader + mov eax, [edx + IP_PACKET.SourceAddress] + mov [pseudoHeader], eax + mov eax, [edx + IP_PACKET.DestinationAddress] + mov [pseudoHeader + 4], eax + mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 + add ebx, 20 + mov [pseudoHeader + 10], bh + mov [pseudoHeader + 11], bl + + mov eax, pseudoHeader + mov [checkAdd1], eax + mov word[checkSize1], 12 + mov eax, edx + add eax, 20 + mov [checkAdd2], eax + mov eax, ebx + mov [checkSize2], ax + + call checksum + + ; store it in the TCP checksum ( in the correct order! ) + mov ax, [checkResult] + rol ax, 8 + mov [edx + 20 + TCP_PACKET.Checksum], ax + + ; Fill in the IP header checksum + GET_IHL eax, edx ; get IP-Header length + stdcall checksum_jb, edx, eax ; buf_ptr, buf_size + rol ax, 8 + mov [edx + IP_PACKET.HeaderChecksum], ax + + ret +endp + + +; Increments the 32 bit value pointed to by esi in internet order +proc inc_inet_esi stdcall + push eax + mov eax, [esi] + bswap eax + inc eax + bswap eax + mov [esi], eax + pop eax + ret +endp + + +; Increments the 32 bit value pointed to by esi in internet order +; by the value in ecx +proc add_inet_esi stdcall + push eax + mov eax, [esi] + bswap eax + add eax, ecx + bswap eax + mov [esi], eax + pop eax + ret +endp + + +iglobal + TCBStateHandler dd \ + stateTCB_LISTEN, \ + stateTCB_SYN_SENT, \ + stateTCB_SYN_RECEIVED, \ + stateTCB_ESTABLISHED, \ + stateTCB_FIN_WAIT_1, \ + stateTCB_FIN_WAIT_2, \ + stateTCB_CLOSE_WAIT, \ + stateTCB_CLOSING, \ + stateTCB_LAST_ACK, \ + stateTCB_TIME_WAIT, \ + stateTCB_CLOSED +endg + + +;*************************************************************************** +; Function +; tcpStateMachine +; +; Description +; TCP state machine +; This is a kernel function, called by tcp_rx +; +; IP buffer address given in edx +; Socket/TCB address in ebx +; +; The IP buffer will be released by the caller +;*************************************************************************** + +proc tcpStateMachine stdcall, sockAddr:DWORD + ; as a packet has been received, update the TCB timer + mov [ebx + SOCKET.TCBTimer], TWOMSL + + ; If the received packet has an ACK bit set, + ; remove any packets in the resend queue that this + ; received packet acknowledges + pushad + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .call_handler ; No ACK, so no data yet + + ; get skt number in eax + stdcall net_socket_addr_to_num, ebx + + ; The ack number is in [edx + 28], inet format + ; skt in eax + + mov esi, resendQ + xor ecx, ecx + + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .call_handler ; None left + cmp [esi + 4], eax + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + @@: ; Can we delete this buffer? + + ; If yes, goto @@. No, goto .next_resendq + ; Get packet data address + + push ecx + ; Now get buffer location, and copy buffer across. argh! more copying,, + imul edi, ecx, IPBUFFSIZE + add edi, resendBuffer + + ; we have dest buffer location in edi. incoming packet in edx. + ; Get this packets sequence number + ; preserve al, ecx, esi, edx + mov ecx, [edi + 20 + TCP_PACKET.SequenceNumber] + bswap ecx + movzx ebx, word[edi + 2] + xchg bl, bh + sub ebx, 40 + add ecx, ebx ; ecx is now seq# of last byte +1, intel format + + ; get recievd ack #, in intel format + mov ebx, [edx + 20 + TCP_PACKET.AckNumber] + bswap ebx + + cmp ebx, ecx ; Finally. ecx = rx'ed ack. ebx = last byte in que + ; DANGER! need to handle case that we have just + ; passed the 2**32, and wrapped round! + pop ecx + jae @f ; if rx > old, delete old + + inc ecx + add esi, 8 + jmp .next_resendq + + @@: + mov dword[esi + 4], 0 + inc ecx + add esi, 8 + jmp .next_resendq + + .call_handler: + popad + + ; Call handler for given TCB state + + mov eax, [ebx + SOCKET.TCBState] + cmp eax, TCB_LISTEN + jb .exit + cmp eax, TCB_CLOSED + ja .exit + + stdcall [TCBStateHandler + (eax - 1) * 4], [sockAddr] + + .exit: + ret +endp + +;*************************************************************************** +; Function +; signal_network_event +; +; Description +; Signals about network event to socket owner +; This is a kernel function, called from TCP handler +; +; Socket/TCB address in ebx +;*************************************************************************** +proc signal_network_event + push ecx esi eax + mov eax, [ebx + SOCKET.PID] + mov ecx, 1 + mov esi, TASK_DATA + TASKDATA.pid + + .next_pid: + cmp [esi], eax + je .found_pid + inc ecx + add esi, 0x20 + cmp ecx, [TASK_COUNT] + jbe .next_pid + + .found_pid: + shl ecx, 8 + or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event + pop eax esi ecx + ret +endp + +proc stateTCB_LISTEN stdcall, sockAddr:DWORD + ; In this case, we are expecting a SYN packet + ; For now, if the packet is a SYN, process it, and send a response + ; If not, ignore it + + ; Look at control flags + test [edx + 20 + TCP_PACKET.Flags], TH_SYN + jz .exit + + ; We have a SYN. update the socket with this IP packets details, + ; And send a response + + mov eax, [edx + IP_PACKET.SourceAddress] + mov [ebx + SOCKET.RemoteIP], eax + mov ax, [edx + 20 + TCP_PACKET.SourcePort] + mov [ebx + SOCKET.RemotePort], ax + mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] + mov [ebx + SOCKET.IRS], eax + mov [ebx + SOCKET.RCV_NXT], eax + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi ; RCV.NXT + mov eax, [ebx + SOCKET.ISS] + mov [ebx + SOCKET.SND_NXT], eax + + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit + + push ebx + push eax + mov bl, TH_SYN + TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + pop ebx + mov esi, [sockAddr] + mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED + call signal_network_event + + ; increment SND.NXT in socket + add esi, SOCKET.SND_NXT + call inc_inet_esi + + .exit: + ret +endp + + +proc stateTCB_SYN_SENT stdcall, sockAddr:DWORD + ; We are awaiting an ACK to our SYN, with a SYM + ; Look at control flags - expecting an ACK + + mov al, [edx + 20 + TCP_PACKET.Flags] + and al, TH_SYN + TH_ACK + cmp al, TH_SYN + TH_ACK + je .syn_ack + + test al, TH_SYN + jz .exit + + mov [ebx + SOCKET.TCBState], TCB_SYN_RECEIVED + push TH_SYN + TH_ACK + jmp .send + + .syn_ack: + mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED + push TH_ACK + + .send: + call signal_network_event + ; Store the recv.nxt field + mov eax, [edx + 20 + TCP_PACKET.SequenceNumber] + + ; Update our recv.nxt field + mov [ebx + SOCKET.RCV_NXT], eax + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi + + ; Send an ACK + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + pop ebx + je .exit + + push eax + + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + .exit: + ret +endp + + +proc stateTCB_SYN_RECEIVED stdcall, sockAddr:DWORD + ; In this case, we are expecting an ACK packet + ; For now, if the packet is an ACK, process it, + ; If not, ignore it + + test [edx + 20 + TCP_PACKET.Flags], TH_RST + jz .check_ack + + push [ebx + SOCKET.OrigRemotePort] [ebx + SOCKET.OrigRemoteIP] + pop [ebx + SOCKET.RemoteIP] [ebx + SOCKET.RemotePort] + + mov [ebx + SOCKET.TCBState], TCB_LISTEN + jmp .signal + + .check_ack: + ; Look at control flags - expecting an ACK + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit + + mov [ebx + SOCKET.TCBState], TCB_ESTABLISHED + .signal: + call signal_network_event + + .exit: + ret +endp + + +proc stateTCB_ESTABLISHED stdcall, sockAddr:DWORD + ; Here we are expecting data, or a request to close + ; OR both... + + ; Ignore all packets with sequnce number other than next expected + + ; recv.nxt is in dword [edx+24], in inet format + ; recv seq is in [sktAddr]+56, in inet format + ; just do a comparision + mov eax, [ebx + SOCKET.RCV_NXT] + cmp eax, [edx + 20 + TCP_PACKET.SequenceNumber] + jne .exit + + ; Did we receive a FIN or RST? + test [edx + 20 + TCP_PACKET.Flags], TH_FIN+TH_RST + jz .check_ack + + ; It was a fin or reset. + + ; Remove resend entries from the queue - I dont want to send any more data + pushad + + ; get skt # + stdcall net_socket_addr_to_num, ebx + + mov esi, resendQ + mov ecx, 0 + + .next_resendq: + cmp ecx, NUMRESENDENTRIES + je .last_resendq ; None left + cmp [esi + 4], eax + je @f ; found one + inc ecx + add esi, 8 + jmp .next_resendq + + @@: + mov dword[esi + 4], 0 + inc ecx + add esi, 8 + jmp .next_resendq + + .last_resendq: + popad + + @@: ; Send an ACK to that fin, and enter closewait state + + mov [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + test [edx + 20 + TCP_PACKET.Flags], TH_RST + je @f + mov [ebx + SOCKET.TCBState], TCB_CLOSED + @@: + call signal_network_event + lea esi, [ebx + SOCKET.RCV_NXT] + mov eax, [esi] ; save original + call inc_inet_esi + ;; jmp ste_ack - NO, there may be data + + .check_ack: + ; Check that we received an ACK + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit + + ; TODO - done, I think! + ; First, look at the incoming window. If this is less than or equal to 1024, + ; Set the socket window timer to 1. This will stop an additional packets being queued. + ; ** I may need to tweak this value, since I do not know how many packets are already queued + mov cx, [edx + 20 + TCP_PACKET.Window] + xchg cl, ch + cmp cx, 1024 + ja @f + + mov [ebx + SOCKET.wndsizeTimer], 1 + + @@: ; OK, here is the deal + + + ; Read the data bytes, store in socket buffer + movzx ecx, [edx + IP_PACKET.TotalLength] + xchg cl, ch + sub ecx, 40 ; Discard 40 bytes of header + ja .data ; Read data, if any + + ; If we had received a fin, we need to ACK it. + cmp [ebx + SOCKET.TCBState], TCB_CLOSE_WAIT + je .ack + jmp .exit + + .data: + push ecx + push ecx edx + lea ecx, [ebx+SOCKET.lock] + call mutex_lock + pop edx ecx + + push ebx + mov eax, [ebx + SOCKET.rxDataCount] + add eax, ecx + cmp eax, SOCKETBUFFSIZE - SOCKETHEADERSIZE + ja .overflow + + mov [ebx + SOCKET.rxDataCount], eax ; increment the count of bytes in buffer + + ; point to the location to store the data + lea edi, [ebx + eax + SOCKETHEADERSIZE] + sub edi, ecx + + add edx, 40 ; edx now points to the data + mov esi, edx + + cld + rep movsb ; copy the data across + + lea ecx, [ebx + SOCKET.lock] + call mutex_unlock + + ; flag an event to the application + pop ebx + call signal_network_event + + pop ecx + + ; Update our recv.nxt field + lea esi, [ebx + SOCKET.RCV_NXT] + call add_inet_esi + + .ack: + ; Send an ACK + ; Now construct the response, and queue for sending by IP + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit + + push eax + + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + .exit: + ret + .overflow: + ; no place in buffer + ; so simply restore stack and exit + lea ecx, [ebx + SOCKET.lock] + call mutex_unlock + pop eax ecx + ret +endp + + +proc stateTCB_FIN_WAIT_1 stdcall, sockAddr:DWORD + ; We can either receive an ACK of a fin, or a fin + mov al, [edx + 20 + TCP_PACKET.Flags] + and al, TH_FIN + TH_ACK + + cmp al, TH_ACK + jne @f + + ; It was an ACK + mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_2 + jmp .exit + + @@: + mov [ebx + SOCKET.TCBState], TCB_CLOSING + cmp al, TH_FIN + je @f + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + + @@: + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi + + ; Send an ACK + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit + + push eax + + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + .exit: + ret +endp + + +proc stateTCB_FIN_WAIT_2 stdcall, sockAddr:DWORD + test [edx + 20 + TCP_PACKET.Flags], TH_FIN + jz .exit + + ; Change state, as we have a fin + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + + lea esi, [ebx + SOCKET.RCV_NXT] + call inc_inet_esi + + ; Send an ACK + mov eax, EMPTY_QUEUE + call dequeue + cmp ax, NO_BUFFER + je .exit + + push eax + + mov bl, TH_ACK + xor ecx, ecx + xor esi, esi + stdcall build_tcp_packet, [sockAddr] + + mov eax, NET1OUT_QUEUE + mov edx, [stack_ip] + mov ecx, [sockAddr] + cmp edx, [ecx + SOCKET.RemoteIP] + jne .not_local + mov eax, IPIN_QUEUE + + .not_local: + ; Send it. + pop ebx + call queue + + .exit: + ret +endp + + +proc stateTCB_CLOSE_WAIT stdcall, sockAddr:DWORD + ; Intentionally left empty + ; socket_close_tcp handles this + ret +endp + + +proc stateTCB_CLOSING stdcall, sockAddr:DWORD + ; We can either receive an ACK of a fin, or a fin + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit + + mov [ebx + SOCKET.TCBState], TCB_TIMED_WAIT + + .exit: + ret +endp + + +proc stateTCB_LAST_ACK stdcall, sockAddr:DWORD + ; Look at control flags - expecting an ACK + test [edx + 20 + TCP_PACKET.Flags], TH_ACK + jz .exit + + ; delete the socket + stdcall net_socket_free, ebx + + .exit: + ret +endp + + +proc stateTCB_TIME_WAIT stdcall, sockAddr:DWORD + ret +endp + + +proc stateTCB_CLOSED stdcall, sockAddr:DWORD + ret +endp diff --git a/kernel/trunk/network/udp.inc b/kernel/trunk/network/udp.inc index 9b99e7225..24279e3a8 100644 --- a/kernel/trunk/network/udp.inc +++ b/kernel/trunk/network/udp.inc @@ -1,155 +1,155 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; ;; -;; UDP.INC ;; -;; ;; -;; UDP Processes for Menuet OS TCP/IP stack ;; -;; ;; -;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -;******************************************************************* -; Interface -; -; udp_rx Handles received IP packets with the UDP protocol -; -;******************************************************************* - - -; -; UDP Payload ( Data field in IP datagram ) -; -; 0 1 2 3 -; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 -; -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Source Port | Destination Port | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | Length ( UDP Header + Data ) | Checksum | -; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -; | UDP Data | -; +-+-+-.......... -+ -; - -struc UDP_PACKET -{ .SourcePort dw ? ;+00 - .DestinationPort dw ? ;+02 - .Length dw ? ;+04 - Length of (UDP Header + Data) - .Checksum dw ? ;+06 - .Data db ? ;+08 -} - -virtual at 0 - UDP_PACKET UDP_PACKET -end virtual - - -;*************************************************************************** -; Function -; udp_rx [by Johnny_B] -; -; Description -; UDP protocol handler -; This is a kernel function, called by ip_rx -; IP buffer address given in edx -; IP buffer number in eax -; Free up (or re-use) IP buffer when finished -; -;*************************************************************************** - -proc udp_rx stdcall - push eax - - ; First validate the header & checksum. Discard buffer if error - - ; Look for a socket where - ; IP Packet UDP Destination Port = local Port - ; IP Packet SA = Remote IP - - mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from - ; the IP packet's UDP header - - mov ebx, net_sockets - - .next_socket: - mov ebx, [ebx + SOCKET.NextPtr] - or ebx, ebx - jz .exit ; No match, so exit - cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value, - ; but the comparision is correct - jne .next_socket ; Return back if no match - - ; For dhcp, we must allow any remote server to respond. - ; I will accept the first incoming response to be the one - ; I bind to, if the socket is opened with a destination IP address of - ; 255.255.255.255 - cmp [ebx + SOCKET.RemoteIP], 0xffffffff - je @f - - mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet - cmp [ebx + SOCKET.RemoteIP], eax - jne .exit ; Quit if the source IP is not valid - - @@: ; OK - we have a valid UDP packet for this socket. - ; First, update the sockets remote port number with the incoming msg - ; - it will have changed - ; from the original ( 69 normally ) to allow further connects - mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port - ; ( was 69, now new ) - mov [ebx + SOCKET.RemotePort], ax - - ; Now, copy data to socket. We have socket address as [eax + sockets]. - ; We have IP packet in edx - - ; get # of bytes in ecx - movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract - xchg cl, ch ; 20 + 8 gives data length - sub ecx, 28 - - mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer - add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer - - ; ecx has count, edx points to data - - add edx, 28 ; edx now points to the data - lea edi, [ebx + eax + SOCKETHEADERSIZE] - mov esi, edx - - cld - rep movsb ; copy the data across - - ; flag an event to the application - mov eax, [ebx + SOCKET.PID] ; get socket owner PID - mov ecx, 1 - mov esi, TASK_DATA + TASKDATA.pid - - .next_pid: - cmp [esi], eax - je .found_pid - inc ecx - add esi, 0x20 - cmp ecx, [TASK_COUNT] - jbe .next_pid - - jmp .exit - - .found_pid: - shl ecx, 8 - or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event - - mov [check_idle_semaphore], 200 - - .exit: - pop eax - call freeBuff ; Discard the packet - ret -endp +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; ;; +;; UDP.INC ;; +;; ;; +;; UDP Processes for Menuet OS TCP/IP stack ;; +;; ;; +;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +;******************************************************************* +; Interface +; +; udp_rx Handles received IP packets with the UDP protocol +; +;******************************************************************* + + +; +; UDP Payload ( Data field in IP datagram ) +; +; 0 1 2 3 +; 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +; +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Source Port | Destination Port | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | Length ( UDP Header + Data ) | Checksum | +; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +; | UDP Data | +; +-+-+-.......... -+ +; + +struc UDP_PACKET +{ .SourcePort dw ? ;+00 + .DestinationPort dw ? ;+02 + .Length dw ? ;+04 - Length of (UDP Header + Data) + .Checksum dw ? ;+06 + .Data db ? ;+08 +} + +virtual at 0 + UDP_PACKET UDP_PACKET +end virtual + + +;*************************************************************************** +; Function +; udp_rx [by Johnny_B] +; +; Description +; UDP protocol handler +; This is a kernel function, called by ip_rx +; IP buffer address given in edx +; IP buffer number in eax +; Free up (or re-use) IP buffer when finished +; +;*************************************************************************** + +proc udp_rx stdcall + push eax + + ; First validate the header & checksum. Discard buffer if error + + ; Look for a socket where + ; IP Packet UDP Destination Port = local Port + ; IP Packet SA = Remote IP + + mov ax, [edx + 20 + UDP_PACKET.DestinationPort] ; get the local port from + ; the IP packet's UDP header + + mov ebx, net_sockets + + .next_socket: + mov ebx, [ebx + SOCKET.NextPtr] + or ebx, ebx + jz .exit ; No match, so exit + cmp [ebx + SOCKET.LocalPort], ax ; ax will hold the 'wrong' value, + ; but the comparision is correct + jne .next_socket ; Return back if no match + + ; For dhcp, we must allow any remote server to respond. + ; I will accept the first incoming response to be the one + ; I bind to, if the socket is opened with a destination IP address of + ; 255.255.255.255 + cmp [ebx + SOCKET.RemoteIP], 0xffffffff + je @f + + mov eax, [edx + IP_PACKET.SourceAddress] ; get the Source address from the IP packet + cmp [ebx + SOCKET.RemoteIP], eax + jne .exit ; Quit if the source IP is not valid + + @@: ; OK - we have a valid UDP packet for this socket. + ; First, update the sockets remote port number with the incoming msg + ; - it will have changed + ; from the original ( 69 normally ) to allow further connects + mov ax, [edx + 20 + UDP_PACKET.SourcePort] ; get the UDP source port + ; ( was 69, now new ) + mov [ebx + SOCKET.RemotePort], ax + + ; Now, copy data to socket. We have socket address as [eax + sockets]. + ; We have IP packet in edx + + ; get # of bytes in ecx + movzx ecx, [edx + IP_PACKET.TotalLength] ; total length of IP packet. Subtract + xchg cl, ch ; 20 + 8 gives data length + sub ecx, 28 + + mov eax, [ebx + SOCKET.rxDataCount] ; get # of bytes already in buffer + add [ebx + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer + + ; ecx has count, edx points to data + + add edx, 28 ; edx now points to the data + lea edi, [ebx + eax + SOCKETHEADERSIZE] + mov esi, edx + + cld + rep movsb ; copy the data across + + ; flag an event to the application + mov eax, [ebx + SOCKET.PID] ; get socket owner PID + mov ecx, 1 + mov esi, TASK_DATA + TASKDATA.pid + + .next_pid: + cmp [esi], eax + je .found_pid + inc ecx + add esi, 0x20 + cmp ecx, [TASK_COUNT] + jbe .next_pid + + jmp .exit + + .found_pid: + shl ecx, 8 + or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event + + mov [check_idle_semaphore], 200 + + .exit: + pop eax + call freeBuff ; Discard the packet + ret +endp diff --git a/kernel/trunk/proc32.inc b/kernel/trunk/proc32.inc index 3f474c02f..890aa2243 100644 --- a/kernel/trunk/proc32.inc +++ b/kernel/trunk/proc32.inc @@ -1,271 +1,271 @@ - -$Revision$ - - -; Macroinstructions for defining and calling procedures - -macro stdcall proc,[arg] ; directly call STDCALL procedure - { common - if ~ arg eq - reverse - pushd arg - common - end if - call proc } - -macro invoke proc,[arg] ; indirectly call STDCALL procedure - { common - if ~ arg eq - reverse - pushd arg - common - end if - call [proc] } - -macro ccall proc,[arg] ; directly call CDECL procedure - { common - size@ccall = 0 - if ~ arg eq - reverse - pushd arg - size@ccall = size@ccall+4 - common - end if - call proc - if size@ccall - add esp,size@ccall - end if } - -macro cinvoke proc,[arg] ; indirectly call CDECL procedure - { common - size@ccall = 0 - if ~ arg eq - reverse - pushd arg - size@ccall = size@ccall+4 - common - end if - call [proc] - if size@ccall - add esp,size@ccall - end if } - -macro proc [args] ; define procedure - { common - match name params, args> - \{ define@proc name, \{ prologue name,flag,parmbytes,localbytes,reglist \} - macro locals - \{ virtual at ebp-localbytes+current - macro label . \\{ deflocal@proc .,:, \\} - struc db [val] \\{ \common deflocal@proc .,db,val \\} - struc dw [val] \\{ \common deflocal@proc .,dw,val \\} - struc dp [val] \\{ \common deflocal@proc .,dp,val \\} - struc dd [val] \\{ \common deflocal@proc .,dd,val \\} - struc dt [val] \\{ \common deflocal@proc .,dt,val \\} - struc dq [val] \\{ \common deflocal@proc .,dq,val \\} - struc rb cnt \\{ deflocal@proc .,rb cnt, \\} - struc rw cnt \\{ deflocal@proc .,rw cnt, \\} - struc rp cnt \\{ deflocal@proc .,rp cnt, \\} - struc rd cnt \\{ deflocal@proc .,rd cnt, \\} - struc rt cnt \\{ deflocal@proc .,rt cnt, \\} - struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} - macro endl - \{ purge label - restruc db,dw,dp,dd,dt,dq - restruc rb,rw,rp,rd,rt,rq - restruc byte,word,dword,pword,tword,qword - current = $-(ebp-localbytes) - end virtual \} - macro ret operand - \{ match any, operand \\{ retn operand \\} - match , operand \\{ match epilogue:reglist, epilogue@proc: - \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} - macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 - end if \} } - -macro defargs@proc [arg] - { common - if ~ arg eq - forward - local ..arg,current@arg - match argname:type, arg - \{ current@arg equ argname - label ..arg type - argname equ ..arg - if dqword eq type - dd ?,?,?,? - else if tbyte eq type - dd ?,?,? - else if qword eq type | pword eq type - dd ?,? - else - dd ? - end if \} - match =current@arg,current@arg - \{ current@arg equ arg - arg equ ..arg - ..arg dd ? \} - common - args@proc equ current@arg - forward - restore current@arg - common - end if } - -macro deflocal@proc name,def,[val] - { common - match vars, all@vars \{ all@vars equ all@vars, \} - all@vars equ all@vars name - forward - local ..var,..tmp - ..var def val - match =?, val \{ ..tmp equ \} - match any =dup (=?), val \{ ..tmp equ \} - match tmp : value, ..tmp : val - \{ tmp: end virtual - initlocal@proc ..var,def value - virtual at tmp\} - common - match first rest, ..var, \{ name equ first \} } - -macro initlocal@proc name,def - { virtual at name - def - size@initlocal = $ - name - end virtual - position@initlocal = 0 - while size@initlocal > position@initlocal - virtual at name - def - if size@initlocal - position@initlocal < 2 - current@initlocal = 1 - load byte@initlocal byte from name+position@initlocal - else if size@initlocal - position@initlocal < 4 - current@initlocal = 2 - load word@initlocal word from name+position@initlocal - else - current@initlocal = 4 - load dword@initlocal dword from name+position@initlocal - end if - end virtual - if current@initlocal = 1 - mov byte [name+position@initlocal],byte@initlocal - else if current@initlocal = 2 - mov word [name+position@initlocal],word@initlocal - else - mov dword [name+position@initlocal],dword@initlocal - end if - position@initlocal = position@initlocal + current@initlocal - end while } - -macro endp - { purge ret,locals,endl - finish@proc - purge finish@proc - restore regs@proc - match all,args@proc \{ restore all \} - restore args@proc - match all,all@vars \{ restore all \} } - -macro local [var] - { common - locals - forward done@local equ - match varname[count]:vartype, var - \{ match =BYTE, vartype \\{ varname rb count - restore done@local \\} - match =WORD, vartype \\{ varname rw count - restore done@local \\} - match =DWORD, vartype \\{ varname rd count - restore done@local \\} - match =PWORD, vartype \\{ varname rp count - restore done@local \\} - match =QWORD, vartype \\{ varname rq count - restore done@local \\} - match =TBYTE, vartype \\{ varname rt count - restore done@local \\} - match =DQWORD, vartype \\{ label varname dqword - rq count+count - restore done@local \\} - match , done@local \\{ virtual - varname vartype - end virtual - rb count*sizeof.\#vartype - restore done@local \\} \} - match :varname:vartype, done@local:var - \{ match =BYTE, vartype \\{ varname db ? - restore done@local \\} - match =WORD, vartype \\{ varname dw ? - restore done@local \\} - match =DWORD, vartype \\{ varname dd ? - restore done@local \\} - match =PWORD, vartype \\{ varname dp ? - restore done@local \\} - match =QWORD, vartype \\{ varname dq ? - restore done@local \\} - match =TBYTE, vartype \\{ varname dt ? - restore done@local \\} - match =DQWORD, vartype \\{ label varname dqword - dq ?,? - restore done@local \\} - match , done@local \\{ varname vartype - restore done@local \\} \} - match ,done@local - \{ var - restore done@local \} - common - endl } + +$Revision$ + + +; Macroinstructions for defining and calling procedures + +macro stdcall proc,[arg] ; directly call STDCALL procedure + { common + if ~ arg eq + reverse + pushd arg + common + end if + call proc } + +macro invoke proc,[arg] ; indirectly call STDCALL procedure + { common + if ~ arg eq + reverse + pushd arg + common + end if + call [proc] } + +macro ccall proc,[arg] ; directly call CDECL procedure + { common + size@ccall = 0 + if ~ arg eq + reverse + pushd arg + size@ccall = size@ccall+4 + common + end if + call proc + if size@ccall + add esp, size@ccall + end if } + +macro cinvoke proc,[arg] ; indirectly call CDECL procedure + { common + size@ccall = 0 + if ~ arg eq + reverse + pushd arg + size@ccall = size@ccall+4 + common + end if + call [proc] + if size@ccall + add esp, size@ccall + end if } + +macro proc [args] ; define procedure + { common + match name params, args> + \{ define@proc name, \{ prologue name,flag,parmbytes,localbytes,reglist \} + macro locals + \{ virtual at ebp-localbytes+current + macro label . \\{ deflocal@proc .,:, \\} + struc db [val] \\{ \common deflocal@proc .,db,val \\} + struc dw [val] \\{ \common deflocal@proc .,dw,val \\} + struc dp [val] \\{ \common deflocal@proc .,dp,val \\} + struc dd [val] \\{ \common deflocal@proc .,dd,val \\} + struc dt [val] \\{ \common deflocal@proc .,dt,val \\} + struc dq [val] \\{ \common deflocal@proc .,dq,val \\} + struc rb cnt \\{ deflocal@proc .,rb cnt, \\} + struc rw cnt \\{ deflocal@proc .,rw cnt, \\} + struc rp cnt \\{ deflocal@proc .,rp cnt, \\} + struc rd cnt \\{ deflocal@proc .,rd cnt, \\} + struc rt cnt \\{ deflocal@proc .,rt cnt, \\} + struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \} + macro endl + \{ purge label + restruc db,dw,dp,dd,dt,dq + restruc rb,rw,rp,rd,rt,rq + restruc byte,word,dword,pword,tword,qword + current = $-(ebp-localbytes) + end virtual \} + macro ret operand + \{ match any, operand \\{ retn operand \\} + match , operand \\{ match epilogue:reglist, epilogue@proc: + \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \} + macro finish@proc \{ localbytes = (((current-1) shr 2)+1) shl 2 + end if \} } + +macro defargs@proc [arg] + { common + if ~ arg eq + forward + local ..arg,current@arg + match argname:type, arg + \{ current@arg equ argname + label ..arg type + argname equ ..arg + if dqword eq type + dd ?,?,?,? + else if tbyte eq type + dd ?,?,? + else if qword eq type | pword eq type + dd ?,? + else + dd ? + end if \} + match =current@arg,current@arg + \{ current@arg equ arg + arg equ ..arg + ..arg dd ? \} + common + args@proc equ current@arg + forward + restore current@arg + common + end if } + +macro deflocal@proc name,def,[val] + { common + match vars, all@vars \{ all@vars equ all@vars, \} + all@vars equ all@vars name + forward + local ..var,..tmp + ..var def val + match =?, val \{ ..tmp equ \} + match any =dup (=?), val \{ ..tmp equ \} + match tmp : value, ..tmp : val + \{ tmp: end virtual + initlocal@proc ..var,def value + virtual at tmp\} + common + match first rest, ..var, \{ name equ first \} } + +macro initlocal@proc name,def + { virtual at name + def + size@initlocal = $ - name + end virtual + position@initlocal = 0 + while size@initlocal > position@initlocal + virtual at name + def + if size@initlocal - position@initlocal < 2 + current@initlocal = 1 + load byte@initlocal byte from name+position@initlocal + else if size@initlocal - position@initlocal < 4 + current@initlocal = 2 + load word@initlocal word from name+position@initlocal + else + current@initlocal = 4 + load dword@initlocal dword from name+position@initlocal + end if + end virtual + if current@initlocal = 1 + mov byte [name+position@initlocal], byte@initlocal + else if current@initlocal = 2 + mov word [name+position@initlocal], word@initlocal + else + mov dword [name+position@initlocal], dword@initlocal + end if + position@initlocal = position@initlocal + current@initlocal + end while } + +macro endp + { purge ret,locals,endl + finish@proc + purge finish@proc + restore regs@proc + match all,args@proc \{ restore all \} + restore args@proc + match all,all@vars \{ restore all \} } + +macro local [var] + { common + locals + forward done@local equ + match varname[count]:vartype, var + \{ match =BYTE, vartype \\{ varname rb count + restore done@local \\} + match =WORD, vartype \\{ varname rw count + restore done@local \\} + match =DWORD, vartype \\{ varname rd count + restore done@local \\} + match =PWORD, vartype \\{ varname rp count + restore done@local \\} + match =QWORD, vartype \\{ varname rq count + restore done@local \\} + match =TBYTE, vartype \\{ varname rt count + restore done@local \\} + match =DQWORD, vartype \\{ label varname dqword + rq count+count + restore done@local \\} + match , done@local \\{ virtual + varname vartype + end virtual + rb count*sizeof.\#vartype + restore done@local \\} \} + match :varname:vartype, done@local:var + \{ match =BYTE, vartype \\{ varname db ? + restore done@local \\} + match =WORD, vartype \\{ varname dw ? + restore done@local \\} + match =DWORD, vartype \\{ varname dd ? + restore done@local \\} + match =PWORD, vartype \\{ varname dp ? + restore done@local \\} + match =QWORD, vartype \\{ varname dq ? + restore done@local \\} + match =TBYTE, vartype \\{ varname dt ? + restore done@local \\} + match =DQWORD, vartype \\{ label varname dqword + dq ?,? + restore done@local \\} + match , done@local \\{ varname vartype + restore done@local \\} \} + match ,done@local + \{ var + restore done@local \} + common + endl } diff --git a/kernel/trunk/sec_loader/trunk/boot/after_win/fat.inc b/kernel/trunk/sec_loader/trunk/boot/after_win/fat.inc index 66130eabd..3f4ccda09 100644 --- a/kernel/trunk/sec_loader/trunk/boot/after_win/fat.inc +++ b/kernel/trunk/sec_loader/trunk/boot/after_win/fat.inc @@ -1,509 +1,509 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -; in: ss:bp = 0:dat -; in: es:bx = address to load file -; in: ds:si -> ASCIIZ name -; in: cx = limit in sectors -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) -load_file_fat: - mov eax, [bp + root_clus - dat] - mov [bp + cur_obj - dat], root_string - push es - push bx - push cx -.parse_dir_loop: -; convert name to FAT name - push [bp + cur_obj - dat] - push ax - mov [bp + cur_obj - dat], si - push ss - pop es -; convert ASCIIZ filename to FAT name - mov di, fat_filename - push di - mov cx, 8+3 - mov al, ' ' - rep stosb - pop di - mov cl, 8 ; 8 symbols per name - mov bl, 1 -.nameloop: - lodsb - test al, al - jz .namedone - cmp al, '/' - jz .namedone - cmp al, '.' - jz .namedot - dec cx - js .badname - cmp al, 'a' - jb @f - cmp al, 'z' - ja @f - sub al, 'a'-'A' -@@: - stosb - jmp .nameloop -.namedot: - inc bx - jp .badname - add di, cx - mov cl, 3 - jmp .nameloop -.badname: - mov si, badname_msg - jmp find_error_si -.namedone: -; scan directory - pop ax ; eax = cluster of directory - ; high word of eax is preserved by operations above - push ds - push si -; read a folder sector-by-sector and scan -; first, try to use the cache - push ss - pop ds - mov bx, -2 - mov cx, [bp + rootcache_size - dat] - cmp [bp + root_clus - dat], eax - jz .lookcache_root - mov di, foldcache_mark - xor bx, bx - mov cx, [bp + cachelimit - dat] -@@: - lea si, [di+bx] - mov edx, dword [foldcache_clus+si-foldcache_mark+bx] - cmp edx, eax - jz .cacheok - test edx, edx - jz .cacheadd ; the cache has place for new entry - inc bx - inc bx - dec cx - js @b -; the folder is not present in the cache, so add it -; the cache is full; find the oldest entry and replace it with the new one - mov bx, -2 - mov dx, [bp + cachelimit - dat] -@@: - inc bx - inc bx - cmp word [di+bx], dx ; marks have values 0 through [cachelimit] - jnz @b -.cacheadd: - or word [di+bx], 0xFFFF ; very big value, it will be changed soon - and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet - lea si, [di+bx] - mov dword [foldcache_clus+si-foldcache_mark+bx], eax -.cacheok: -; update cache marks - mov dx, [di+bx] - mov cx, [foldcache_size+di-foldcache_mark+bx] - mov di, [bp + cachelimit - dat] - add di, di -.cacheupdate: - cmp [foldcache_mark+di], dx - adc [foldcache_mark+di], 0 - dec di - dec di - jns .cacheupdate - and [foldcache_mark+bx], 0 -; done, bx contains (position in cache)*2 -.lookcache_root: -; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder - ;mov dx, bx - ;shl dx, 8 - ;add dx, 0x9200 - lea dx, [bx + 0x92] - xchg dl, dh - mov ds, dx - mov si, fat_filename ; ss:si -> filename in FAT style - call fat_scan_for_filename - jz .lookup_done -; cache miss, read folder data from disk -; we are reading parent directory, it can result in disk read errors; restore [cur_obj] - mov di, sp - mov bx, [bp + cur_obj - dat] - xchg bx, [ss:di+4] - mov [bp + cur_obj - dat], bx - mov bx, cx - add bx, 0xF - shr bx, 4 - shl cx, 5 - mov di, cx ; es:di -> free space in cache entry -; external loop: scan clusters -.folder_next_cluster: -; internal loop: scan sectors in cluster - movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus - push eax -; FAT12/16 root - special handling - test eax, eax - jnz .folder_notroot - mov cx, [ss:0x3211] ; BPB_RootEntCnt - mov dx, cx - add cx, 0xF - rcr cx, 1 - shr cx, 3 - mov eax, [bp + root_start - dat] - jmp .folder_next_sector -.folder_notroot: - mul ecx - add eax, [bp + data_start - dat] -.folder_next_sector: - sub dx, 0x10 -; skip first bx sectors - dec bx - jns .folder_skip_sector - push cx - push es di - push 0x8000 - pop es - xor bx, bx - mov cx, 1 - push es - call read - jc ..found_disk_error -; copy data to the cache... - pop ds - pop di es - cmp di, 0x2000 ; ...if there is free space, of course - jae @f - pusha - mov cx, 0x100 - xor si, si - rep movsw - mov di, es - shr di, 8 - cmp di, 0x90 - jz .update_rootcache_size - add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache - jmp .updated_cachesize -.update_rootcache_size: - mov cl, 0x10 - cmp cx, dx - jb @f - mov cx, dx -@@: - add [bp + rootcache_size - dat], cx -.updated_cachesize: - popa -@@: - push es - mov cl, 0x10 ; ch=0 at this point - cmp cx, dx - jb @f - mov cx, dx -@@: - call fat_scan_for_filename - pop es - pop cx - jz .lookup_done_pop -.folder_skip_sector: - inc eax - loop .folder_next_sector - pop eax ; eax = current cluster - test eax, eax - jz @f - call [bp + get_next_cluster_ptr - dat] - jc .folder_next_cluster -@@: - stc - push eax -.lookup_done_pop: - pop eax -.lookup_done: - pop si -; CF=1 <=> failed - jnc .found - pop ds - pop [bp + cur_obj - dat] - mov si, error_not_found - jmp find_error_si -.found: - mov eax, [di+20-2] - mov edx, [di+28] - mov ax, [di+26] ; get cluster - test byte [di+11], 10h ; directory? - pop ds - pop [bp + cur_obj - dat] ; forget old [cur_obj] - jz .regular_file - cmp byte [si-1], 0 - jnz .parse_dir_loop -..directory_error: - mov si, directory_string - jmp find_error_si -.regular_file: - cmp byte [si-1], 0 - jz @f -..notdir_error: - mov si, notdir_string - jmp find_error_si -@@: -; ok, we have found a regular file and the caller requested it -; parse FAT chunk - push ss - pop es - push ss - pop ds - mov di, 0x4005 - mov byte [di-5], 1 ; non-resident attribute - mov dword [di-4], 1 - stosd - pop cx - push cx -.parsefat: - call [bp + get_next_cluster_ptr - dat] - jnc .done - mov esi, [di-8] - add esi, [di-4] - cmp eax, esi - jz .contc - mov dword [di], 1 - scasd - stosd - jmp @f -.contc: - inc dword [di-8] -@@: - sub cl, [0x320D] - sbb ch, 0 - ja .parsefat -.done: - xor eax, eax - stosd - mov si, 0x4000 -load_file_common_end: - xor ecx, ecx - pop cx - pop bx - pop es - mov [bp + filesize - dat], edx - mov [bp + sectors_read - dat], ecx - add edx, 0x1FF - shr edx, 9 - mov [bp + filesize_sectors - dat], edx - cmp edx, ecx - seta al - mov ah, 0 - push ax - call read_file_chunk -continue_load_common_end: - mov [bp + cur_chunk_ptr - dat], si - pop bx - mov ax, word [bp + filesize - dat] - mov dx, word [bp + filesize+2 - dat] - jnc @f - mov bl, 3 ; read error -@@: - ret - -continue_load_file: -; es:bx -> buffer for output, ecx = cx = number of sectors - mov si, [bp + cur_chunk_ptr - dat] - push ecx - add ecx, [bp + sectors_read - dat] - mov [bp + sectors_read - dat], ecx - cmp [bp + filesize_sectors - dat], ecx - pop ecx - seta al - mov ah, 0 - push ax - push continue_load_common_end - push ss - pop ds - cmp [bp + cur_chunk_resident - dat], ah - jnz .nonresident -.resident: - mov ax, word [bp + num_sectors - dat] - jmp read_file_chunk.resident.continue -.nonresident: - mov eax, [bp + cur_cluster - dat] - mov edx, [bp + num_sectors - dat] - add eax, [bp + cur_delta - dat] - jmp read_file_chunk.nonresident.continue - -fat_scan_for_filename: -; in: ss:si -> 11-bytes FAT name -; in: ds:0 -> part of directory data -; in: cx = number of entries -; out: if found: CF=0, ZF=1, es:di -> directory entry -; out: if not found, but continue required: CF=1 and ZF=0 -; out: if not found and zero item reached: CF=1 and ZF=1 - push ds - pop es - xor di, di - push cx - jcxz .noent -.loop: - cmp byte [di], 0 - jz .notfound - test byte [di+11], 8 ; volume label? - jnz .cont ; ignore volume labels - pusha - mov cx, 11 - repz cmps byte [ss:si], byte [es:di] - popa - jz .done -.cont: - add di, 0x20 - loop .loop -.noent: - inc cx ; clear ZF flag -.notfound: - stc -.done: - pop cx - ret - -fat12_get_next_cluster: -; in: ax = cluster (high word of eax is zero) -; out: if there is next cluster: CF=1, ax = next cluster -; out: if there is no next cluster: CF=0 - push si - push ds - push 0x6000 - pop ds - mov si, ax - shr si, 1 - add si, ax - test al, 1 - lodsw - jz @f - shr ax, 4 -@@: - and ax, 0xFFF - cmp ax, 0xFF7 - pop ds si - ret - -fat16_get_next_cluster: -; in: ax = cluster (high word of eax is zero) -; out: if there is next cluster: CF=1, ax = next cluster -; out: if there is no next cluster: CF=0 -; each sector contains 200h bytes = 100h FAT entries -; so ah = # of sector, al = offset in sector - push si - mov si, ax - shr si, 8 -; calculate segment for this sector of FAT table -; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) -; segment = 6000 + 20*si, offset = 0 - push es - push si - shl si, 5 - add si, 0x6000 - mov es, si - pop si - cmp byte [ss:0x3400+si], 0 ; sector already loaded? - jnz .noread -; load corresponding sector, try all FATs if disk read error detected - pusha - movzx di, byte [ss:0x3210] ; BPB_NumFATs - xor bx, bx - mov ax, [ss:0x320E] ; BPB_RsvdSecCnt - xor dx, dx - add ax, si - adc dx, bx -@@: - push es - push dx ax - pop eax - mov cx, 1 ; read 1 sector - call read - pop es - jnc @f - add ax, [ss:0x3216] ; BPB_FATSz16 - adc dx, bx - dec di - jnz @b -..found_disk_error: - mov si, disk_error_msg - jmp find_error_si -@@: - popa -.noread: - mov si, ax - and si, 0xFF - add si, si - mov ax, [es:si] - pop es - cmp ax, 0xFFF7 - pop si - ret - -fat32_get_next_cluster: -; in: eax = cluster -; out: if there is next cluster: CF=1, eax = next cluster -; out: if there is no next cluster: CF=0 - push di - push ax - shr eax, 7 -; eax = FAT sector number; look in cache - push si - mov si, cache1head - call cache_lookup - pop si - jnc .noread -; read FAT, try all FATs if disk read error detected - push es - pushad - movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt - add eax, edx - movzx si, byte [ss:0x3210] ; BPB_NumFATs -@@: - lea cx, [di - 0x3400 + (0x6000 shr (9-3))] - shl cx, 9-3 - mov es, cx - xor bx, bx - mov cx, 1 - call read - jnc @f - add eax, [ss:0x3224] ; BPB_FATSz32 - dec si - jnz @b - jmp ..found_disk_error -@@: - popad - pop es -.noread: -; get requested item - lea ax, [di - 0x3400 + (0x6000 shr (9-3))] - pop di - and di, 0x7F - shl di, 2 - shl ax, 9-3 - push ds - mov ds, ax - and byte [di+3], 0x0F - mov eax, [di] - pop ds - pop di - ;and eax, 0x0FFFFFFF - cmp eax, 0x0FFFFFF7 - ret +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +; in: ss:bp = 0:dat +; in: es:bx = address to load file +; in: ds:si -> ASCIIZ name +; in: cx = limit in sectors +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file has been loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) +load_file_fat: + mov eax, [bp + root_clus - dat] + mov [bp + cur_obj - dat], root_string + push es + push bx + push cx +.parse_dir_loop: +; convert name to FAT name + push [bp + cur_obj - dat] + push ax + mov [bp + cur_obj - dat], si + push ss + pop es +; convert ASCIIZ filename to FAT name + mov di, fat_filename + push di + mov cx, 8+3 + mov al, ' ' + rep stosb + pop di + mov cl, 8 ; 8 symbols per name + mov bl, 1 +.nameloop: + lodsb + test al, al + jz .namedone + cmp al, '/' + jz .namedone + cmp al, '.' + jz .namedot + dec cx + js .badname + cmp al, 'a' + jb @f + cmp al, 'z' + ja @f + sub al, 'a'-'A' +@@: + stosb + jmp .nameloop +.namedot: + inc bx + jp .badname + add di, cx + mov cl, 3 + jmp .nameloop +.badname: + mov si, badname_msg + jmp find_error_si +.namedone: +; scan directory + pop ax ; eax = cluster of directory + ; high word of eax is preserved by operations above + push ds + push si +; read a folder sector-by-sector and scan +; first, try to use the cache + push ss + pop ds + mov bx, -2 + mov cx, [bp + rootcache_size - dat] + cmp [bp + root_clus - dat], eax + jz .lookcache_root + mov di, foldcache_mark + xor bx, bx + mov cx, [bp + cachelimit - dat] +@@: + lea si, [di+bx] + mov edx, dword [foldcache_clus+si-foldcache_mark+bx] + cmp edx, eax + jz .cacheok + test edx, edx + jz .cacheadd ; the cache has place for new entry + inc bx + inc bx + dec cx + js @b +; the folder is not present in the cache, so add it +; the cache is full; find the oldest entry and replace it with the new one + mov bx, -2 + mov dx, [bp + cachelimit - dat] +@@: + inc bx + inc bx + cmp word [di+bx], dx ; marks have values 0 through [cachelimit] + jnz @b +.cacheadd: + or word [di+bx], 0xFFFF ; very big value, it will be changed soon + and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet + lea si, [di+bx] + mov dword [foldcache_clus+si-foldcache_mark+bx], eax +.cacheok: +; update cache marks + mov dx, [di+bx] + mov cx, [foldcache_size+di-foldcache_mark+bx] + mov di, [bp + cachelimit - dat] + add di, di +.cacheupdate: + cmp [foldcache_mark+di], dx + adc [foldcache_mark+di], 0 + dec di + dec di + jns .cacheupdate + and [foldcache_mark+bx], 0 +; done, bx contains (position in cache)*2 +.lookcache_root: +; bx = (position in cache)*2 for non-root folders; bx = -2 for root folder + ;mov dx, bx + ;shl dx, 8 + ;add dx, 0x9200 + lea dx, [bx + 0x92] + xchg dl, dh + mov ds, dx + mov si, fat_filename ; ss:si -> filename in FAT style + call fat_scan_for_filename + jz .lookup_done +; cache miss, read folder data from disk +; we are reading parent directory, it can result in disk read errors; restore [cur_obj] + mov di, sp + mov bx, [bp + cur_obj - dat] + xchg bx, [ss:di+4] + mov [bp + cur_obj - dat], bx + mov bx, cx + add bx, 0xF + shr bx, 4 + shl cx, 5 + mov di, cx ; es:di -> free space in cache entry +; external loop: scan clusters +.folder_next_cluster: +; internal loop: scan sectors in cluster + movzx ecx, byte [ss:0x320D] ; BPB_SecPerClus + push eax +; FAT12/16 root - special handling + test eax, eax + jnz .folder_notroot + mov cx, [ss:0x3211] ; BPB_RootEntCnt + mov dx, cx + add cx, 0xF + rcr cx, 1 + shr cx, 3 + mov eax, [bp + root_start - dat] + jmp .folder_next_sector +.folder_notroot: + mul ecx + add eax, [bp + data_start - dat] +.folder_next_sector: + sub dx, 0x10 +; skip first bx sectors + dec bx + jns .folder_skip_sector + push cx + push es di + push 0x8000 + pop es + xor bx, bx + mov cx, 1 + push es + call read + jc ..found_disk_error +; copy data to the cache... + pop ds + pop di es + cmp di, 0x2000 ; ...if there is free space, of course + jae @f + pusha + mov cx, 0x100 + xor si, si + rep movsw + mov di, es + shr di, 8 + cmp di, 0x90 + jz .update_rootcache_size + add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache + jmp .updated_cachesize +.update_rootcache_size: + mov cl, 0x10 + cmp cx, dx + jb @f + mov cx, dx +@@: + add [bp + rootcache_size - dat], cx +.updated_cachesize: + popa +@@: + push es + mov cl, 0x10 ; ch=0 at this point + cmp cx, dx + jb @f + mov cx, dx +@@: + call fat_scan_for_filename + pop es + pop cx + jz .lookup_done_pop +.folder_skip_sector: + inc eax + loop .folder_next_sector + pop eax ; eax = current cluster + test eax, eax + jz @f + call [bp + get_next_cluster_ptr - dat] + jc .folder_next_cluster +@@: + stc + push eax +.lookup_done_pop: + pop eax +.lookup_done: + pop si +; CF=1 <=> failed + jnc .found + pop ds + pop [bp + cur_obj - dat] + mov si, error_not_found + jmp find_error_si +.found: + mov eax, [di+20-2] + mov edx, [di+28] + mov ax, [di+26] ; get cluster + test byte [di+11], 10h ; directory? + pop ds + pop [bp + cur_obj - dat] ; forget old [cur_obj] + jz .regular_file + cmp byte [si-1], 0 + jnz .parse_dir_loop +..directory_error: + mov si, directory_string + jmp find_error_si +.regular_file: + cmp byte [si-1], 0 + jz @f +..notdir_error: + mov si, notdir_string + jmp find_error_si +@@: +; ok, we have found a regular file and the caller requested it +; parse FAT chunk + push ss + pop es + push ss + pop ds + mov di, 0x4005 + mov byte [di-5], 1 ; non-resident attribute + mov dword [di-4], 1 + stosd + pop cx + push cx +.parsefat: + call [bp + get_next_cluster_ptr - dat] + jnc .done + mov esi, [di-8] + add esi, [di-4] + cmp eax, esi + jz .contc + mov dword [di], 1 + scasd + stosd + jmp @f +.contc: + inc dword [di-8] +@@: + sub cl, [0x320D] + sbb ch, 0 + ja .parsefat +.done: + xor eax, eax + stosd + mov si, 0x4000 +load_file_common_end: + xor ecx, ecx + pop cx + pop bx + pop es + mov [bp + filesize - dat], edx + mov [bp + sectors_read - dat], ecx + add edx, 0x1FF + shr edx, 9 + mov [bp + filesize_sectors - dat], edx + cmp edx, ecx + seta al + mov ah, 0 + push ax + call read_file_chunk +continue_load_common_end: + mov [bp + cur_chunk_ptr - dat], si + pop bx + mov ax, word [bp + filesize - dat] + mov dx, word [bp + filesize+2 - dat] + jnc @f + mov bl, 3 ; read error +@@: + ret + +continue_load_file: +; es:bx -> buffer for output, ecx = cx = number of sectors + mov si, [bp + cur_chunk_ptr - dat] + push ecx + add ecx, [bp + sectors_read - dat] + mov [bp + sectors_read - dat], ecx + cmp [bp + filesize_sectors - dat], ecx + pop ecx + seta al + mov ah, 0 + push ax + push continue_load_common_end + push ss + pop ds + cmp [bp + cur_chunk_resident - dat], ah + jnz .nonresident +.resident: + mov ax, word [bp + num_sectors - dat] + jmp read_file_chunk.resident.continue +.nonresident: + mov eax, [bp + cur_cluster - dat] + mov edx, [bp + num_sectors - dat] + add eax, [bp + cur_delta - dat] + jmp read_file_chunk.nonresident.continue + +fat_scan_for_filename: +; in: ss:si -> 11-bytes FAT name +; in: ds:0 -> part of directory data +; in: cx = number of entries +; out: if found: CF=0, ZF=1, es:di -> directory entry +; out: if not found, but continue required: CF=1 and ZF=0 +; out: if not found and zero item reached: CF=1 and ZF=1 + push ds + pop es + xor di, di + push cx + jcxz .noent +.loop: + cmp byte [di], 0 + jz .notfound + test byte [di+11], 8 ; volume label? + jnz .cont ; ignore volume labels + pusha + mov cx, 11 + repz cmps byte [ss:si], byte [es:di] + popa + jz .done +.cont: + add di, 0x20 + loop .loop +.noent: + inc cx ; clear ZF flag +.notfound: + stc +.done: + pop cx + ret + +fat12_get_next_cluster: +; in: ax = cluster (high word of eax is zero) +; out: if there is next cluster: CF=1, ax = next cluster +; out: if there is no next cluster: CF=0 + push si + push ds + push 0x6000 + pop ds + mov si, ax + shr si, 1 + add si, ax + test al, 1 + lodsw + jz @f + shr ax, 4 +@@: + and ax, 0xFFF + cmp ax, 0xFF7 + pop ds si + ret + +fat16_get_next_cluster: +; in: ax = cluster (high word of eax is zero) +; out: if there is next cluster: CF=1, ax = next cluster +; out: if there is no next cluster: CF=0 +; each sector contains 200h bytes = 100h FAT entries +; so ah = # of sector, al = offset in sector + push si + mov si, ax + shr si, 8 +; calculate segment for this sector of FAT table +; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) +; segment = 6000 + 20*si, offset = 0 + push es + push si + shl si, 5 + add si, 0x6000 + mov es, si + pop si + cmp byte [ss:0x3400+si], 0 ; sector already loaded? + jnz .noread +; load corresponding sector, try all FATs if disk read error detected + pusha + movzx di, byte [ss:0x3210] ; BPB_NumFATs + xor bx, bx + mov ax, [ss:0x320E] ; BPB_RsvdSecCnt + xor dx, dx + add ax, si + adc dx, bx +@@: + push es + push dx ax + pop eax + mov cx, 1 ; read 1 sector + call read + pop es + jnc @f + add ax, [ss:0x3216] ; BPB_FATSz16 + adc dx, bx + dec di + jnz @b +..found_disk_error: + mov si, disk_error_msg + jmp find_error_si +@@: + popa +.noread: + mov si, ax + and si, 0xFF + add si, si + mov ax, [es:si] + pop es + cmp ax, 0xFFF7 + pop si + ret + +fat32_get_next_cluster: +; in: eax = cluster +; out: if there is next cluster: CF=1, eax = next cluster +; out: if there is no next cluster: CF=0 + push di + push ax + shr eax, 7 +; eax = FAT sector number; look in cache + push si + mov si, cache1head + call cache_lookup + pop si + jnc .noread +; read FAT, try all FATs if disk read error detected + push es + pushad + movzx edx, word [ss:0x320E] ; BPB_RsvdSecCnt + add eax, edx + movzx si, byte [ss:0x3210] ; BPB_NumFATs +@@: + lea cx, [di - 0x3400 + (0x6000 shr (9-3))] + shl cx, 9-3 + mov es, cx + xor bx, bx + mov cx, 1 + call read + jnc @f + add eax, [ss:0x3224] ; BPB_FATSz32 + dec si + jnz @b + jmp ..found_disk_error +@@: + popad + pop es +.noread: +; get requested item + lea ax, [di - 0x3400 + (0x6000 shr (9-3))] + pop di + and di, 0x7F + shl di, 2 + shl ax, 9-3 + push ds + mov ds, ax + and byte [di+3], 0x0F + mov eax, [di] + pop ds + pop di + ;and eax, 0x0FFFFFFF + cmp eax, 0x0FFFFFF7 + ret diff --git a/kernel/trunk/sec_loader/trunk/boot/after_win/kordldr.win.asm b/kernel/trunk/sec_loader/trunk/boot/after_win/kordldr.win.asm index 5080bf080..7a50b991f 100644 --- a/kernel/trunk/sec_loader/trunk/boot/after_win/kordldr.win.asm +++ b/kernel/trunk/sec_loader/trunk/boot/after_win/kordldr.win.asm @@ -1,921 +1,924 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond -; It is used when main bootloader is Windows loader. - -; this code is loaded: -; NT/2k/XP: by ntldr to 0D00:0000 -; 9x: by io.sys from config.sys to xxxx:0100 -; Vista: by bootmgr to 0000:7C00 - format binary - use16 - -; in any case, we relocate this code to 0000:0600 - org 0x600 -; entry point for 9x and Vista booting - call @f - db 'NTFS' -@@: - pop si - sub si, 3 - cmp si, 100h - jnz boot_vista - mov si, load_question + 100h - 600h - call out_string -; mov si, answer + 100h - 0600h ; already is -xxy: mov ah, 0 - int 16h - or al, 20h - mov [si], al - cmp al, 'y' - jz xxz - cmp al, 'n' - jnz xxy -; continue load Windows -; call out_string -; ret -out_string: - push bx -@@: - lodsb - test al, al - jz @f - mov ah, 0Eh - mov bx, 7 - int 10h - jmp @b -@@: - pop bx - ret -xxz: -; boot KordOS - call out_string -; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, -; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached - xor di, di - mov ds, di - mov word [di+4], new01handler + 100h - 600h - mov [di+6], cs - pushf - pop ax - or ah, 1 - push ax - popf -; we cannot issue INT 19h directly, because INT command clears TF -; int 19h ; don't issue it directly, because INT command clears TF -; so instead we use direct call -; pushf ; there will be no IRET - call far [di + 19h*4] -xxt: - xor di, di - mov ds, di - cmp word [di + 8*4+2], 0F000h - jz @f - les bx, [di + 8*4] - mov eax, [es:bx+1] - mov [di + 8*4], eax -@@: - mov si, 100h -boot_vista: -; relocate cs:si -> 0000:0600 - push cs - pop ds - xor ax, ax - mov es, ax - mov di, 0x600 - mov cx, 2000h/2 - rep movsw - jmp 0:real_entry - -load_question db 'Load KordOS? [y/n]: ',0 -answer db ? - db 13,10,0 - -new01handler: -; [sp]=ip, [sp+2]=cs, [sp+4]=flags - push bp - mov bp, sp - push ds - lds bp, [bp+2] - cmp word [ds:bp], 19cdh - jz xxt - pop ds - pop bp - iret - -; read from hard disk -; in: eax = absolute sector -; cx = number of sectors -; es:bx -> buffer -; out: CF=1 if error -read: - pushad - add eax, [bp + partition_start - dat] - cmp [bp + use_lba - dat], 0 - jz .chs -; LBA read - push ds -.lbado: - push ax - push cx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - push 0 - push 0 - push eax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [bp + boot_drive - dat] - mov ah, 42h - int 13h - jc .disk_error_lba - add sp, 10h ; restore stack -; increase current sector & buffer; decrease number of sectors - movzx esi, cx - mov ax, es - shl cx, 5 - add ax, cx - mov es, ax - pop cx - pop ax - add eax, esi - sub cx, si - jnz .lbado - pop ds - popad - ret -.disk_error_lba: - add sp, 14h - pop ds - popad - stc - ret - -.chs: - pusha - pop edi ; loword(edi) = di, hiword(edi) = si - push bx - -; eax / (SectorsPerTrack) -> eax, remainder bx - movzx esi, [bp + sectors - dat] - xor edx, edx - div esi - mov bx, dx ; bx = sector-1 - -; eax -> dx:ax - push eax - pop ax - pop dx -; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx - div [bp + heads - dat] - -; number of sectors: read no more than to end of track - sub si, bx - cmp cx, si - jbe @f - mov cx, si -@@: - - inc bx -; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector -; convert to int13 format - movzx edi, cx - mov dh, dl - mov dl, [bp + boot_drive - dat] - shl ah, 6 - mov ch, al - mov al, cl - mov cl, bl - or cl, ah - pop bx - mov si, 3 - mov ah, 2 -@@: - push ax - int 13h - jnc @f - xor ax, ax - int 13h ; reset drive - pop ax - dec si - jnz @b - add sp, 12 - popad - stc - ret -@@: - pop ax - mov ax, es - mov cx, di - shl cx, 5 - add ax, cx - mov es, ax - push edi - popa - add eax, edi - sub cx, di - jnz .chs - popad - ret - -disk_error2 db 'Fatal: cannot read partitions info: ' -disk_error_msg db 'disk read error',0 -disk_params_msg db 'Fatal: cannot get drive parameters',0 -start_msg db 2,' KordOS bootloader',13,10,0 -part_msg db 'looking at partition ' -part_char db '0' ; will be incremented before writing message - db ' ... ',0 -errfs_msg db 'unknown filesystem',13,10,0 -fatxx_msg db 'FATxx' -newline db 13,10,0 -ntfs_msg db 'NTFS',13,10,0 -error_msg db 'Error' -colon db ': ',0 -root_string db '\',0 -nomem_msg db 'No memory',0 -filesys_string db '(filesystem)',0 -directory_string db 'is a directory',0 -notdir_string db 'not a directory',0 - -; entry point for NT/2k/XP booting -; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 - repeat 600h + 256h - $ - db 1 ; any data can be here; 1 in ASCII is a nice face :) - end repeat -; cs=es=0D00, ds=07C0, ss=0 -; esi=edi=ebp=0, esp=7C00 - xor si, si - jmp boot_vista - -real_entry: -; ax = 0 - mov ds, ax - mov es, ax -; our stack is 4 Kb: memory range 2000-3000 - mov ss, ax - mov sp, 3000h - mov bp, dat - sti ; just for case -; say hi to user - mov si, start_msg - call out_string -; we are booting from hard disk identified by [boot_drive] - mov dl, [bp + boot_drive - dat] -; is LBA supported? - mov [bp + use_lba - dat], 0 - mov ah, 41h - mov bx, 55AAh - int 13h - jc .no_lba - cmp bx, 0AA55h - jnz .no_lba - test cl, 1 - jz .no_lba - inc [bp + use_lba - dat] - jmp disk_params_ok -.no_lba: -; get drive geometry - mov ah, 8 - mov dl, [bp + boot_drive - dat] - int 13h - jnc @f - mov si, disk_params_msg - call out_string - jmp $ -@@: - movzx ax, dh - inc ax - mov [bp + heads - dat], ax - and cx, 3Fh - mov [bp + sectors - dat], cx -disk_params_ok: -; determine size of cache for folders - int 12h ; ax = size of available base memory in Kb - sub ax, 94000h / 1024 - jc nomem - shr ax, 3 - mov [bp + cachelimit - dat], ax ; size of cache - 1 -; scan all partitions -new_partition_ex: - xor eax, eax ; read first sector of current disk area - mov [bp + extended_part_cur - dat], eax ; no extended partition yet - mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition - push es - mov cx, 1 - mov bx, 3000h - call read - pop es - jnc new_partition - mov si, disk_error2 - call out_string - jmp $ -new_partition: - mov bx, [bp + cur_partition_ofs - dat] - mov al, [bx+4] ; partition type - test al, al - jz next_partition - cmp al, 5 - jz @f - cmp al, 0xF - jnz not_extended -@@: -; extended partition - mov eax, [bx+8] ; partition start - add eax, [bp + extended_part_start - dat] - mov [bp + extended_part_cur - dat], eax -next_partition: - add [bp + cur_partition_ofs - dat], 10h - cmp [bp + cur_partition_ofs - dat], 31FEh - jb new_partition - mov eax, [bp + extended_part_cur - dat] - test eax, eax - jz partitions_done - cmp [bp + extended_part_start - dat], 0 - jnz @f - mov [bp + extended_part_start - dat], eax -@@: - mov [bp + extended_parent - dat], eax - mov [bp + partition_start - dat], eax - jmp new_partition_ex -partitions_done: - mov si, total_kaput - call out_string - jmp $ -not_extended: - mov eax, [bx+8] - add eax, [bp + extended_parent - dat] - mov [bp + partition_start - dat], eax -; try to load from current partition -; inform user - mov si, part_msg - inc [si + part_char - part_msg] - call out_string -; read bootsector - xor eax, eax - mov [bp + cur_obj - dat], filesys_string - push es - mov cx, 1 - mov bx, 3200h - call read - pop es - mov si, disk_error_msg - jc find_error_si - movzx si, byte [bx+13] - mov word [bp + sect_per_clust - dat], si - test si, si - jz unknown_fs - lea ax, [si-1] - test si, ax - jnz unknown_fs -; determine file system -; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) - cmp word [bx+11], 0x200 - jnz unknown_fs -; is it NTFS? - cmp dword [bx+3], 'NTFS' - jnz not_ntfs - cmp byte [bx+16], bl - jz ntfs -not_ntfs: -; is it FAT? FAT12/FAT16/FAT32? -; get count of sectors to dword in cx:si - mov si, [bx+19] - xor cx, cx - test si, si - jnz @f - mov si, [bx+32] - mov cx, [bx+34] -@@: - xor eax, eax -; subtract size of system area - sub si, [bx+14] ; BPB_ResvdSecCnt - sbb cx, ax - mov ax, [bx+17] ; BPB_RootEntCnt - add ax, 0xF - rcr ax, 1 - shr ax, 3 - sub si, ax - sbb cx, 0 - push cx - push si - mov ax, word [bx+22] - test ax, ax - jnz @f - mov eax, [bx+36] -@@: - movzx ecx, byte [bx+16] - imul ecx, eax - pop eax - sub eax, ecx -; now eax = count of sectors in the data region - xor edx, edx - div [bp + sect_per_clust - dat] -; now eax = count of clusters in the data region - mov si, fatxx_msg - cmp eax, 0xFFF5 - jae test_fat32 -; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 - cmp byte [bx+38], 0x29 - jnz not_fat - cmp ax, 0xFF5 - jae fat16 -fat12: - mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster - mov di, cx ; BPB_NumFATs - mov ax, '12' - push ax ; save for secondary loader - mov word [si+3], ax - call out_string - movzx ecx, word [bx+22] ; BPB_FATSz16 -; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) -.fatloop: -; if first copy is not readable, try to switch to other copies - push 0x6000 - pop es - xor bx, bx - movzx eax, word [0x320E] ; BPB_RsvdSecCnt - push cx - cmp cx, 12 - jb @f - mov cx, 12 -@@: - call read - pop cx - jnc fat1x_common - add eax, ecx ; switch to next copy of FAT - dec di - jnz .fatloop - mov si, disk_error_msg - jmp find_error_si -fat16: - mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster - mov ax, '16' - push ax ; save for secondary loader - mov word [si+3], ax - call out_string -; FAT16: init FAT cache - no sectors loaded - mov di, 0x3400 - xor ax, ax - mov cx, 0x100/2 - rep stosw -fat1x_common: - mov bx, 0x3200 - movzx eax, word [bx+22] ; BPB_FATSz16 - xor esi, esi ; no root cluster - jmp fat_common -test_fat32: -; FAT32 bootsector has it at the offset +66 - cmp byte [bx+66], 0x29 - jnz not_fat - mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster - mov ax, '32' - push ax ; save for secondary loader - mov word [si+3], ax - call out_string -; FAT32 - init cache for FAT table: no sectors loaded - lea si, [bp + cache1head - dat] - mov [si], si ; no sectors in cache: - mov [si+2], si ; 'prev' & 'next' links point to self - mov [bp + cache1end - dat], 3400h ; first free item = 3400h - mov [bp + cache1limit - dat], 3C00h - mov eax, [bx+36] ; BPB_FATSz32 - mov esi, [bx+44] ; BPB_RootClus - jmp fat_common -not_fat: -unknown_fs: - mov si, errfs_msg - call out_string - jmp next_partition -fat_common: - push ss - pop es - movzx edx, byte [bx+16] ; BPB_NumFATs - mul edx - mov [bp + root_start - dat], eax ; this is for FAT1x -; eax = total size of all FAT tables, in sectors - movzx ecx, word [bx+17] ; BPB_RootEntCnt - add ecx, 0xF - shr ecx, 4 - add eax, ecx - mov cx, word [bx+14] ; BPB_RsvdSecCnt - add [bp + root_start - dat], ecx ; this is for FAT1x - add eax, ecx -; cluster 2 begins from sector eax - movzx ebx, byte [bx+13] ; BPB_SecPerClus - sub eax, ebx - sub eax, ebx - mov [bp + data_start - dat], eax -; no clusters in folders cache - mov di, foldcache_clus - 2 - xor ax, ax - mov cx, 7*8/2 + 1 - rep stosw - mov [bp + root_clus - dat], esi -; load secondary loader - mov [bp + load_file_ptr - dat], load_file_fat -load_secondary: - push 0x1000 - pop es - xor bx, bx - mov si, kernel_name - mov cx, 0x30000 / 0x200 - call [bp + load_file_ptr - dat] -; say error if needed - mov si, error_too_big - dec bx - js @f - jz find_error_si - mov si, disk_error_msg - jmp find_error_si -@@: -; fill loader information and jump to secondary loader - mov al, 'h' ; boot device: hard drive - mov ah, [bp + boot_drive - dat] - sub ah, 80h ; boot device: identifier - pop bx ; restore file system ID ('12'/'16'/'32'/'nt') - mov si, callback - jmp 1000h:0000h - -nomem: - mov si, nomem_msg - call out_string - jmp $ - -ntfs: - push 'nt' ; save for secondary loader - mov si, ntfs_msg - call out_string - xor eax, eax - mov [bp + data_start - dat], eax - mov ecx, [bx+40h] ; frs_size - cmp cl, al - jg .1 - neg cl - inc ax - shl eax, cl - jmp .2 -.1: - mov eax, ecx - shl eax, 9 -.2: - mov [bp + frs_size - dat], ax -; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different -; (at least with standard tools) -; we allow extra size, but no more than 0x1000 bytes = 4 Kb - mov si, invalid_volume_msg - cmp eax, 0x1000 - ja find_error_si -; must be multiple of sector size - test ax, 0x1FF - jnz find_error_si - shr ax, 9 - xchg cx, ax -; initialize cache - no data loaded - lea si, [bp + cache1head - dat] - mov [si], si - mov [si+2], si - mov word [si+4], 3400h ; first free item = 3400h - mov word [si+6], 3400h + 8*8 ; 8 items in this cache -; read first MFT record - description of MFT itself - mov [bp + cur_obj - dat], mft_string - mov eax, [bx+30h] ; mft_cluster - mul [bp + sect_per_clust - dat] - push 0x8000 - pop es - xor bx, bx - push es - call read - pop ds - call restore_usa -; scan for unnamed $DATA attribute - mov [bp + freeattr - dat], 4000h - mov ax, 80h - call load_attr - push ss - pop ds - mov si, nodata_string - jc find_error_si -; load secondary loader - mov [bp + load_file_ptr - dat], load_file_ntfs - jmp load_secondary - -find_error_si: - push si -find_error_sp: - cmp [bp + in_callback - dat], 0 - jnz error_in_callback - push ss - pop ds - push ss - pop es - mov si, error_msg - call out_string - mov si, [bp + cur_obj - dat] -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jz @f - mov ah, 0Eh - mov bx, 7 - int 10h - jmp @b -@@: - mov si, colon - call out_string - pop si - call out_string - mov si, newline - call out_string - mov sp, 0x3000 - jmp next_partition -error_in_callback: -; return status: file not found, except for read errors - mov bx, 2 - cmp si, disk_error_msg - jnz @f - inc bx -@@: - mov ax, 0xFFFF - mov dx, ax - mov sp, 3000h - 6 - ret - -callback: -; in: ax = function number; only functions 1 and 2 are defined for now -; save caller's stack - mov dx, ss - mov cx, sp -; set our stack (required because we need ss=0) - xor si, si - mov ss, si - mov sp, 3000h - mov bp, dat - mov [bp + in_callback - dat], 1 - push dx - push cx -; set ds:si -> ASCIIZ name - lea si, [di+6] -; set cx = limit in sectors; 4Kb = 8 sectors - movzx ecx, word [di+4] - shl cx, 3 -; set es:bx = pointer to buffer - les bx, [di] -; call our function - stc ; unsupported function - dec ax - jz callback_readfile - dec ax - jnz callback_ret - call continue_load_file - jmp callback_ret_succ -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call [bp + load_file_ptr - dat] -callback_ret_succ: - clc -callback_ret: -; restore caller's stack - pop cx - pop ss - mov sp, cx -; return to caller - retf - -read_file_chunk.resident: -; auxiliary label for read_file_chunk procedure - mov di, bx - lodsw -read_file_chunk.resident.continue: - mov dx, ax - add dx, 0x1FF - shr dx, 9 - cmp dx, cx - jbe @f - mov ax, cx - shl ax, 9 -@@: - xchg ax, cx - rep movsb - xchg ax, cx - clc ; no disk error if no disk requests - mov word [bp + num_sectors - dat], ax - ret - -read_file_chunk: -; in: ds:si -> file chunk -; in: es:bx -> buffer for output -; in: ecx = maximum number of sectors to read (high word must be 0) -; out: CF=1 <=> disk read error - lodsb - mov [bp + cur_chunk_resident - dat], al - test al, al - jz .resident -; normal case: load (non-resident) attribute from disk -.read_block: - lodsd - xchg eax, edx - test edx, edx - jz .ret - lodsd -; eax = start cluster, edx = number of clusters, cx = limit in sectors - imul eax, [bp + sect_per_clust - dat] - add eax, [bp + data_start - dat] - mov [bp + cur_cluster - dat], eax - imul edx, [bp + sect_per_clust - dat] - mov [bp + num_sectors - dat], edx - and [bp + cur_delta - dat], 0 -.nonresident.continue: - cmp edx, ecx - jb @f - mov edx, ecx -@@: - test dx, dx - jz .read_block - add [bp + cur_delta - dat], edx - sub [bp + num_sectors - dat], edx - sub ecx, edx - push cx - mov cx, dx - call read - pop cx - jc .ret - test cx, cx - jnz .read_block -.ret: - ret - -cache_lookup: -; in: eax = value to look, si = pointer to cache structure -; out: di->cache entry; CF=1 <=> the value was not found - push ds bx - push ss - pop ds - mov di, [si+2] -.look: - cmp di, si - jz .not_in_cache - cmp eax, [di+4] - jz .in_cache - mov di, [di+2] - jmp .look -.not_in_cache: -; cache miss -; cache is full? - mov di, [si+4] - cmp di, [si+6] - jnz .cache_not_full -; yes, delete the oldest entry - mov di, [si] - mov bx, [di] - mov [si], bx - push word [di+2] - pop word [bx+2] - jmp .cache_append -.cache_not_full: -; no, allocate new item - add word [si+4], 8 -.cache_append: - mov [di+4], eax - stc - jmp @f -.in_cache: -; delete this sector from the list - push si - mov si, [di] - mov bx, [di+2] - mov [si+2], bx - mov [bx], si - pop si -@@: -; add new sector to the end of list - mov bx, di - xchg bx, [si+2] - push word [bx] - pop word [di] - mov [bx], di - mov [di+2], bx - pop bx ds - ret - -include 'fat.inc' -include 'ntfs.inc' - -total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 -error_too_big db 'file is too big',0 -nodata_string db '$DATA ' -error_not_found db 'not found',0 -noindex_string db '$INDEX_ROOT not found',0 -badname_msg db 'bad name for FAT',0 -invalid_volume_msg db 'invalid volume',0 -mft_string db '$MFT',0 -fragmented_string db 'too fragmented file',0 -invalid_read_request_string db 'cannot read attribute',0 - -kernel_name db 'kord/loader',0 - -align 4 -dat: - -extended_part_start dd 0 ; start sector for main extended partition -extended_part_cur dd ? ; start sector for current extended child -extended_parent dd 0 ; start sector for current extended parent -partition_start dd 0 ; start sector for current logical disk -cur_partition_ofs dw ? ; offset in MBR data for current partition -sect_per_clust dd 0 -; change this variable if you want to boot from other physical drive -boot_drive db 80h -in_callback db 0 - -; uninitialized data -use_lba db ? -cur_chunk_resident db ? -align 2 -heads dw ? -sectors dw ? -cache1head rw 2 -cache1end dw ? -cache1limit dw ? -data_start dd ? -cachelimit dw ? -load_file_ptr dw ? -cur_obj dw ? -missing_slash dw ? -root_clus dd ? -root_start dd ? -get_next_cluster_ptr dw ? -frs_size dw ? -freeattr dw ? -index_root dw ? -index_alloc dw ? -cur_index_seg dw ? -cur_index_cache dw ? -filesize dd ? -filesize_sectors dd ? -cur_cluster dd ? -cur_delta dd ? -num_sectors dd ? -sectors_read dd ? -cur_chunk_ptr dw ? - -rootcache_size dw ? ; must be immediately before foldcache_clus -if $-dat >= 0x80 -warning: unoptimal data displacement! -end if -foldcache_clus rd 7 -foldcache_mark rw 7 -foldcache_size rw 7 -fat_filename rb 11 - -if $ > 2000h -error: file is too big -end if - -; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long -repeat 0x2600 - $ - db 2 ; any data can be here; 2 is another nice face in ASCII :) -end repeat +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +; KordOS bootloader, based on mtldr, KolibriOS bootloader, by diamond +; It is used when main bootloader is Windows loader. + +; this code is loaded: +; NT/2k/XP: by ntldr to 0D00:0000 +; 9x: by io.sys from config.sys to xxxx:0100 +; Vista: by bootmgr to 0000:7C00 + format binary + use16 + +; in any case, we relocate this code to 0000:0600 + org 0x600 +; entry point for 9x and Vista booting + call @f + db 'NTFS' +@@: + pop si + sub si, 3 + cmp si, 100h + jnz boot_vista + mov si, load_question + 100h - 600h + call out_string +; mov si, answer + 100h - 0600h ; already is +xxy: + mov ah, 0 + int 16h + or al, 20h + mov [si], al + cmp al, 'y' + jz xxz + cmp al, 'n' + jnz xxy +; continue load Windows +; call out_string +; ret +out_string: + push bx +@@: + lodsb + test al, al + jz @f + mov ah, 0Eh + mov bx, 7 + int 10h + jmp @b +@@: + pop bx + ret +xxz: +; boot KordOS + call out_string +; 9x bootloader has already hooked some interrupts; to correctly remove all DOS handlers, +; issue int 19h (reboot interrupt) and trace its DOS handler until original BIOS handler is reached + xor di, di + mov ds, di + mov word [di+4], new01handler + 100h - 600h + mov [di+6], cs + pushf + pop ax + or ah, 1 + push ax + popf +; we cannot issue INT 19h directly, because INT command clears TF +; int 19h ; don't issue it directly, because INT command clears TF +; so instead we use direct call +; pushf ; there will be no IRET + call far [di + 19h*4] +xxt: + xor di, di + mov ds, di + cmp word [di + 8*4+2], 0F000h + jz @f + les bx, [di + 8*4] + mov eax, [es:bx+1] + mov [di + 8*4], eax +@@: + mov si, 100h +boot_vista: +; relocate cs:si -> 0000:0600 + push cs + pop ds + xor ax, ax + mov es, ax + mov di, 0x600 + mov cx, 2000h/2 + rep movsw + jmp 0:real_entry + +load_question db 'Load KordOS? [y/n]: ',0 +answer db ? + db 13,10,0 + +new01handler: +; [sp]=ip, [sp+2]=cs, [sp+4]=flags + push bp + mov bp, sp + push ds + lds bp, [bp+2] + cmp word [ds:bp], 19cdh + jz xxt + pop ds + pop bp + iret + +; read from hard disk +; in: eax = absolute sector +; cx = number of sectors +; es:bx -> buffer +; out: CF=1 if error +read: + pushad + add eax, [bp + partition_start - dat] + cmp [bp + use_lba - dat], 0 + jz .chs +; LBA read + push ds +.lbado: + push ax + push cx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + push 0 + push 0 + push eax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [bp + boot_drive - dat] + mov ah, 42h + int 13h + jc .disk_error_lba + add sp, 10h ; restore stack +; increase current sector & buffer; decrease number of sectors + movzx esi, cx + mov ax, es + shl cx, 5 + add ax, cx + mov es, ax + pop cx + pop ax + add eax, esi + sub cx, si + jnz .lbado + pop ds + popad + ret +.disk_error_lba: + add sp, 14h + pop ds + popad + stc + ret + +.chs: + pusha + pop edi ; loword(edi) = di, hiword(edi) = si + push bx + +; eax / (SectorsPerTrack) -> eax, remainder bx + movzx esi, [bp + sectors - dat] + xor edx, edx + div esi + mov bx, dx ; bx = sector-1 + +; eax -> dx:ax + push eax + pop ax + pop dx +; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx + div [bp + heads - dat] + +; number of sectors: read no more than to end of track + sub si, bx + cmp cx, si + jbe @f + mov cx, si +@@: + + inc bx +; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector +; convert to int13 format + movzx edi, cx + mov dh, dl + mov dl, [bp + boot_drive - dat] + shl ah, 6 + mov ch, al + mov al, cl + mov cl, bl + or cl, ah + pop bx + mov si, 3 + mov ah, 2 +@@: + push ax + int 13h + jnc @f + xor ax, ax + int 13h ; reset drive + pop ax + dec si + jnz @b + add sp, 12 + popad + stc + ret +@@: + pop ax + mov ax, es + mov cx, di + shl cx, 5 + add ax, cx + mov es, ax + push edi + popa + add eax, edi + sub cx, di + jnz .chs + popad + ret + +disk_error2 db 'Fatal: cannot read partitions info: ' +disk_error_msg db 'disk read error',0 +disk_params_msg db 'Fatal: cannot get drive parameters',0 +start_msg db 2,' KordOS bootloader',13,10,0 +part_msg db 'looking at partition ' +part_char db '0' ; will be incremented before writing message + db ' ... ',0 +errfs_msg db 'unknown filesystem',13,10,0 +fatxx_msg db 'FATxx' +newline db 13,10,0 +ntfs_msg db 'NTFS',13,10,0 +error_msg db 'Error' +colon db ': ',0 +root_string db '\',0 +nomem_msg db 'No memory',0 +filesys_string db '(filesystem)',0 +directory_string db 'is a directory',0 +notdir_string db 'not a directory',0 + +; entry point for NT/2k/XP booting +; ntldr loads our code to 0D00:0000 and jumps to 0D00:0256 + repeat 600h + 256h - $ + db 1 ; any data can be here; 1 in ASCII is a nice face :) + end repeat +; cs=es=0D00, ds=07C0, ss=0 +; esi=edi=ebp=0, esp=7C00 + xor si, si + jmp boot_vista + +real_entry: +; ax = 0 + mov ds, ax + mov es, ax +; our stack is 4 Kb: memory range 2000-3000 + mov ss, ax + mov sp, 3000h + mov bp, dat + sti ; just for case +; say hi to user + mov si, start_msg + call out_string +; we are booting from hard disk identified by [boot_drive] + mov dl, [bp + boot_drive - dat] +; is LBA supported? + mov [bp + use_lba - dat], 0 + mov ah, 41h + mov bx, 55AAh + int 13h + jc .no_lba + cmp bx, 0AA55h + jnz .no_lba + test cl, 1 + jz .no_lba + inc [bp + use_lba - dat] + jmp disk_params_ok +.no_lba: +; get drive geometry + mov ah, 8 + mov dl, [bp + boot_drive - dat] + int 13h + jnc @f + mov si, disk_params_msg + call out_string + jmp $ +@@: + movzx ax, dh + inc ax + mov [bp + heads - dat], ax + and cx, 3Fh + mov [bp + sectors - dat], cx +disk_params_ok: +; determine size of cache for folders + int 12h ; ax = size of available base memory in Kb + sub ax, 94000h / 1024 + jc nomem + shr ax, 3 + mov [bp + cachelimit - dat], ax ; size of cache - 1 +; scan all partitions +new_partition_ex: + xor eax, eax ; read first sector of current disk area + mov [bp + extended_part_cur - dat], eax ; no extended partition yet + mov [bp + cur_partition_ofs - dat], 31BEh ; start from first partition + push es + mov cx, 1 + mov bx, 3000h + call read + pop es + jnc new_partition + mov si, disk_error2 + call out_string + jmp $ +new_partition: + mov bx, [bp + cur_partition_ofs - dat] + mov al, [bx+4] ; partition type + test al, al + jz next_partition + cmp al, 5 + jz @f + cmp al, 0xF + jnz not_extended +@@: +; extended partition + mov eax, [bx+8] ; partition start + add eax, [bp + extended_part_start - dat] + mov [bp + extended_part_cur - dat], eax +next_partition: + add [bp + cur_partition_ofs - dat], 10h + cmp [bp + cur_partition_ofs - dat], 31FEh + jb new_partition + mov eax, [bp + extended_part_cur - dat] + test eax, eax + jz partitions_done + cmp [bp + extended_part_start - dat], 0 + jnz @f + mov [bp + extended_part_start - dat], eax +@@: + mov [bp + extended_parent - dat], eax + mov [bp + partition_start - dat], eax + jmp new_partition_ex +partitions_done: + mov si, total_kaput + call out_string + jmp $ +not_extended: + mov eax, [bx+8] + add eax, [bp + extended_parent - dat] + mov [bp + partition_start - dat], eax +; try to load from current partition +; inform user + mov si, part_msg + inc [si + part_char - part_msg] + call out_string +; read bootsector + xor eax, eax + mov [bp + cur_obj - dat], filesys_string + push es + mov cx, 1 + mov bx, 3200h + call read + pop es + mov si, disk_error_msg + jc find_error_si + movzx si, byte [bx+13] + mov word [bp + sect_per_clust - dat], si + test si, si + jz unknown_fs + lea ax, [si-1] + test si, ax + jnz unknown_fs +; determine file system +; Number of bytes per sector == 0x200 (this loader assumes that physical sector size is 200h) + cmp word [bx+11], 0x200 + jnz unknown_fs +; is it NTFS? + cmp dword [bx+3], 'NTFS' + jnz not_ntfs + cmp byte [bx+16], bl + jz ntfs +not_ntfs: +; is it FAT? FAT12/FAT16/FAT32? +; get count of sectors to dword in cx:si + mov si, [bx+19] + xor cx, cx + test si, si + jnz @f + mov si, [bx+32] + mov cx, [bx+34] +@@: + xor eax, eax +; subtract size of system area + sub si, [bx+14] ; BPB_ResvdSecCnt + sbb cx, ax + mov ax, [bx+17] ; BPB_RootEntCnt + add ax, 0xF + rcr ax, 1 + shr ax, 3 + sub si, ax + sbb cx, 0 + push cx + push si + mov ax, word [bx+22] + test ax, ax + jnz @f + mov eax, [bx+36] +@@: + movzx ecx, byte [bx+16] + imul ecx, eax + pop eax + sub eax, ecx +; now eax = count of sectors in the data region + xor edx, edx + div [bp + sect_per_clust - dat] +; now eax = count of clusters in the data region + mov si, fatxx_msg + cmp eax, 0xFFF5 + jae test_fat32 +; test magic value in FAT bootsector - FAT12/16 bootsector has it at the offset +38 + cmp byte [bx+38], 0x29 + jnz not_fat + cmp ax, 0xFF5 + jae fat16 +fat12: + mov [bp + get_next_cluster_ptr - dat], fat12_get_next_cluster + mov di, cx ; BPB_NumFATs + mov ax, '12' + push ax ; save for secondary loader + mov word [si+3], ax + call out_string + movzx ecx, word [bx+22] ; BPB_FATSz16 +; FAT12: read entire FAT table (it is no more than 0x1000*3/2 = 0x1800 bytes) +.fatloop: +; if first copy is not readable, try to switch to other copies + push 0x6000 + pop es + xor bx, bx + movzx eax, word [0x320E] ; BPB_RsvdSecCnt + push cx + cmp cx, 12 + jb @f + mov cx, 12 +@@: + call read + pop cx + jnc fat1x_common + add eax, ecx ; switch to next copy of FAT + dec di + jnz .fatloop + mov si, disk_error_msg + jmp find_error_si +fat16: + mov [bp + get_next_cluster_ptr - dat], fat16_get_next_cluster + mov ax, '16' + push ax ; save for secondary loader + mov word [si+3], ax + call out_string +; FAT16: init FAT cache - no sectors loaded + mov di, 0x3400 + xor ax, ax + mov cx, 0x100/2 + rep stosw +fat1x_common: + mov bx, 0x3200 + movzx eax, word [bx+22] ; BPB_FATSz16 + xor esi, esi ; no root cluster + jmp fat_common +test_fat32: +; FAT32 bootsector has it at the offset +66 + cmp byte [bx+66], 0x29 + jnz not_fat + mov [bp + get_next_cluster_ptr - dat], fat32_get_next_cluster + mov ax, '32' + push ax ; save for secondary loader + mov word [si+3], ax + call out_string +; FAT32 - init cache for FAT table: no sectors loaded + lea si, [bp + cache1head - dat] + mov [si], si ; no sectors in cache: + mov [si+2], si ; 'prev' & 'next' links point to self + mov [bp + cache1end - dat], 3400h ; first free item = 3400h + mov [bp + cache1limit - dat], 3C00h + mov eax, [bx+36] ; BPB_FATSz32 + mov esi, [bx+44] ; BPB_RootClus + jmp fat_common +not_fat: +unknown_fs: + mov si, errfs_msg + call out_string + jmp next_partition +fat_common: + push ss + pop es + movzx edx, byte [bx+16] ; BPB_NumFATs + mul edx + mov [bp + root_start - dat], eax ; this is for FAT1x +; eax = total size of all FAT tables, in sectors + movzx ecx, word [bx+17] ; BPB_RootEntCnt + add ecx, 0xF + shr ecx, 4 + add eax, ecx + mov cx, word [bx+14] ; BPB_RsvdSecCnt + add [bp + root_start - dat], ecx ; this is for FAT1x + add eax, ecx +; cluster 2 begins from sector eax + movzx ebx, byte [bx+13] ; BPB_SecPerClus + sub eax, ebx + sub eax, ebx + mov [bp + data_start - dat], eax +; no clusters in folders cache + mov di, foldcache_clus - 2 + xor ax, ax + mov cx, 7*8/2 + 1 + rep stosw + mov [bp + root_clus - dat], esi +; load secondary loader + mov [bp + load_file_ptr - dat], load_file_fat +load_secondary: + push 0x1000 + pop es + xor bx, bx + mov si, kernel_name + mov cx, 0x30000 / 0x200 + call [bp + load_file_ptr - dat] +; say error if needed + mov si, error_too_big + dec bx + js @f + jz find_error_si + mov si, disk_error_msg + jmp find_error_si +@@: +; fill loader information and jump to secondary loader + mov al, 'h' ; boot device: hard drive + mov ah, [bp + boot_drive - dat] + sub ah, 80h ; boot device: identifier + pop bx ; restore file system ID ('12'/'16'/'32'/'nt') + mov si, callback + jmp 1000h:0000h + +nomem: + mov si, nomem_msg + call out_string + jmp $ + +ntfs: + push 'nt' ; save for secondary loader + mov si, ntfs_msg + call out_string + xor eax, eax + mov [bp + data_start - dat], eax + mov ecx, [bx+40h] ; frs_size + cmp cl, al + jg .1 + neg cl + inc ax + shl eax, cl + jmp .2 +.1: + mov eax, ecx + shl eax, 9 +.2: + mov [bp + frs_size - dat], ax +; standard value for frs_size is 0x400 bytes = 1 Kb, and it cannot be set different +; (at least with standard tools) +; we allow extra size, but no more than 0x1000 bytes = 4 Kb + mov si, invalid_volume_msg + cmp eax, 0x1000 + ja find_error_si +; must be multiple of sector size + test ax, 0x1FF + jnz find_error_si + shr ax, 9 + xchg cx, ax +; initialize cache - no data loaded + lea si, [bp + cache1head - dat] + mov [si], si + mov [si+2], si + mov word [si+4], 3400h ; first free item = 3400h + mov word [si+6], 3400h + 8*8 ; 8 items in this cache +; read first MFT record - description of MFT itself + mov [bp + cur_obj - dat], mft_string + mov eax, [bx+30h] ; mft_cluster + mul [bp + sect_per_clust - dat] + push 0x8000 + pop es + xor bx, bx + push es + call read + pop ds + call restore_usa +; scan for unnamed $DATA attribute + mov [bp + freeattr - dat], 4000h + mov ax, 80h + call load_attr + push ss + pop ds + mov si, nodata_string + jc find_error_si +; load secondary loader + mov [bp + load_file_ptr - dat], load_file_ntfs + jmp load_secondary + +find_error_si: + push si +find_error_sp: + cmp [bp + in_callback - dat], 0 + jnz error_in_callback + push ss + pop ds + push ss + pop es + mov si, error_msg + call out_string + mov si, [bp + cur_obj - dat] +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jz @f + mov ah, 0Eh + mov bx, 7 + int 10h + jmp @b +@@: + mov si, colon + call out_string + pop si + call out_string + mov si, newline + call out_string + mov sp, 0x3000 + jmp next_partition +error_in_callback: +; return status: file not found, except for read errors + mov bx, 2 + cmp si, disk_error_msg + jnz @f + inc bx +@@: + mov ax, 0xFFFF + mov dx, ax + mov sp, 3000h - 6 + ret + +callback: +; in: ax = function number; only functions 1 and 2 are defined for now +; save caller's stack + mov dx, ss + mov cx, sp +; set our stack (required because we need ss=0) + xor si, si + mov ss, si + mov sp, 3000h + mov bp, dat + mov [bp + in_callback - dat], 1 + push dx + push cx +; set ds:si -> ASCIIZ name + lea si, [di+6] +; set cx = limit in sectors; 4Kb = 8 sectors + movzx ecx, word [di+4] + shl cx, 3 +; set es:bx = pointer to buffer + les bx, [di] +; call our function + stc ; unsupported function + dec ax + jz callback_readfile + dec ax + jnz callback_ret + call continue_load_file + jmp callback_ret_succ +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call [bp + load_file_ptr - dat] +callback_ret_succ: + clc +callback_ret: +; restore caller's stack + pop cx + pop ss + mov sp, cx +; return to caller + retf + +read_file_chunk.resident: +; auxiliary label for read_file_chunk procedure + mov di, bx + lodsw +read_file_chunk.resident.continue: + mov dx, ax + add dx, 0x1FF + shr dx, 9 + cmp dx, cx + jbe @f + mov ax, cx + shl ax, 9 +@@: + xchg ax, cx + rep movsb + xchg ax, cx + clc ; no disk error if no disk requests + mov word [bp + num_sectors - dat], ax + ret + +read_file_chunk: +; in: ds:si -> file chunk +; in: es:bx -> buffer for output +; in: ecx = maximum number of sectors to read (high word must be 0) +; out: CF=1 <=> disk read error + lodsb + mov [bp + cur_chunk_resident - dat], al + test al, al + jz .resident +; normal case: load (non-resident) attribute from disk +.read_block: + lodsd + xchg eax, edx + test edx, edx + jz .ret + lodsd +; eax = start cluster, edx = number of clusters, cx = limit in sectors + imul eax, [bp + sect_per_clust - dat] + add eax, [bp + data_start - dat] + mov [bp + cur_cluster - dat], eax + imul edx, [bp + sect_per_clust - dat] + mov [bp + num_sectors - dat], edx + and [bp + cur_delta - dat], 0 +.nonresident.continue: + cmp edx, ecx + jb @f + mov edx, ecx +@@: + test dx, dx + jz .read_block + add [bp + cur_delta - dat], edx + sub [bp + num_sectors - dat], edx + sub ecx, edx + push cx + mov cx, dx + call read + pop cx + jc .ret + test cx, cx + jnz .read_block +.ret: + ret + +cache_lookup: +; in: eax = value to look, si = pointer to cache structure +; out: di->cache entry; CF=1 <=> the value was not found + push ds bx + push ss + pop ds + mov di, [si+2] +.look: + cmp di, si + jz .not_in_cache + cmp eax, [di+4] + jz .in_cache + mov di, [di+2] + jmp .look +.not_in_cache: +; cache miss +; cache is full? + mov di, [si+4] + cmp di, [si+6] + jnz .cache_not_full +; yes, delete the oldest entry + mov di, [si] + mov bx, [di] + mov [si], bx + push word [di+2] + pop word [bx+2] + jmp .cache_append +.cache_not_full: +; no, allocate new item + add word [si+4], 8 +.cache_append: + mov [di+4], eax + stc + jmp @f +.in_cache: +; delete this sector from the list + push si + mov si, [di] + mov bx, [di+2] + mov [si+2], bx + mov [bx], si + pop si +@@: +; add new sector to the end of list + mov bx, di + xchg bx, [si+2] + push word [bx] + pop word [di] + mov [bx], di + mov [di+2], bx + pop bx ds + ret + +include 'fat.inc' +include 'ntfs.inc' + +total_kaput db 13,10,'Fatal error: cannot load the secondary loader',0 +error_too_big db 'file is too big',0 +nodata_string db '$DATA ' +error_not_found db 'not found',0 +noindex_string db '$INDEX_ROOT not found',0 +badname_msg db 'bad name for FAT',0 +invalid_volume_msg db 'invalid volume',0 +mft_string db '$MFT',0 +fragmented_string db 'too fragmented file',0 +invalid_read_request_string db 'cannot read attribute',0 + +kernel_name db 'kord/loader',0 + +align 4 +dat: + +extended_part_start dd 0 ; start sector for main extended partition +extended_part_cur dd ? ; start sector for current extended child +extended_parent dd 0 ; start sector for current extended parent +partition_start dd 0 ; start sector for current logical disk +cur_partition_ofs dw ? ; offset in MBR data for current partition +sect_per_clust dd 0 +; change this variable if you want to boot from other physical drive +boot_drive db 80h +in_callback db 0 + +; uninitialized data +use_lba db ? +cur_chunk_resident db ? +align 2 +heads dw ? +sectors dw ? +cache1head rw 2 +cache1end dw ? +cache1limit dw ? +data_start dd ? +cachelimit dw ? +load_file_ptr dw ? +cur_obj dw ? +missing_slash dw ? +root_clus dd ? +root_start dd ? +get_next_cluster_ptr dw ? +frs_size dw ? +freeattr dw ? +index_root dw ? +index_alloc dw ? +cur_index_seg dw ? +cur_index_cache dw ? +filesize dd ? +filesize_sectors dd ? +cur_cluster dd ? +cur_delta dd ? +num_sectors dd ? +sectors_read dd ? +cur_chunk_ptr dw ? + +rootcache_size dw ? ; must be immediately before foldcache_clus +if $-dat >= 0x80 +warning: + unoptimal data displacement! +end if +foldcache_clus rd 7 +foldcache_mark rw 7 +foldcache_size rw 7 +fat_filename rb 11 + +if $ > 2000h +error: + file is too big +end if + +; for NT/2k/XP, file must be 16 sectors = 0x2000 bytes long +repeat 0x2600 - $ + db 2 ; any data can be here; 2 is another nice face in ASCII :) +end repeat diff --git a/kernel/trunk/sec_loader/trunk/boot/after_win/ntfs.inc b/kernel/trunk/sec_loader/trunk/boot/after_win/ntfs.inc index f92f13caa..413fe9907 100644 --- a/kernel/trunk/sec_loader/trunk/boot/after_win/ntfs.inc +++ b/kernel/trunk/sec_loader/trunk/boot/after_win/ntfs.inc @@ -1,587 +1,587 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -restore_usa: -; Update Sequence Array restore -; in: ds:bx -> USA-protected structure - push bx - lea di, [bx+1feh] - mov cx, [bx+6] - add bx, [bx+4] - dec cx -@@: - mov ax, [bx+2] - mov [di], ax - inc bx - inc bx - add di, 200h - loop @b - pop bx - ret - -find_attr: -; in: ds:di->file record, ax=attribute -; out: ds:di->attribute or di=0 if not found - add di, [di+14h] -.1: -; attributes' codes are formally dwords, but all of them fit in word - cmp word [di], -1 - jz .notfound - cmp word [di], ax - jnz .continue -; for $DATA attribute, scan only unnamed - cmp ax, 80h - jnz .found - cmp byte [di+9], 0 - jz .found -.continue: - add di, [di+4] - jmp .1 -.notfound: - xor di, di -.found: - ret - -process_mcb_nonres: -; in: ds:si->attribute, es:di->buffer -; out: es:di->buffer end - pushad - pop di - add si, [si+20h] - xor ebx, ebx -.loop: - lodsb - test al, al - jz .done - push invalid_read_request_string - movzx cx, al - shr cx, 4 - jz find_error_sp - xchg ax, dx - and dx, 0Fh - jz find_error_sp - add si, cx - add si, dx - pop ax - push si - dec si - movsx eax, byte [si] - dec cx - jz .l1e -.l1: - dec si - shl eax, 8 - mov al, [si] - loop .l1 -.l1e: - xchg ebp, eax - dec si - movsx eax, byte [si] - mov cx, dx - dec cx - jz .l2e -.l2: - dec si - shl eax, 8 - mov al, byte [si] - loop .l2 -.l2e: - pop si - add ebx, ebp -; eax=length, ebx=disk block - stosd - mov eax, ebx - stosd - cmp di, 0x8000 - 12 - jbe .loop -..attr_overflow: - mov si, fragmented_string - jmp find_error_si -.done: - xor ax, ax - stosw - stosw - push di - popad - ret - -load_attr: -; in: ax=attribute, ds:bx->base record -; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, -; edx=size of attribute in bytes -; out: if not found: CF=1 - mov di, [bp + freeattr - dat] - push ss - pop es - mov byte [es:di], 1 - inc di - cmp di, 0x8000 - 12 - ja ..attr_overflow - or edx, -1 ; file size is not known yet -; scan for attribute - push di - mov di, bx - add di, [di+14h] -@@: - call find_attr.1 - test di, di - jz .notfound1 - cmp byte [di+8], 0 - jnz .nonresident - mov si, di - pop di - push ds - jmp .resident -.aux_resident: - mov ax, ds - mov si, di - pop di ds bx ds edx - push ss - pop es - push ds - mov ds, ax -; resident attribute -.resident: - dec di - mov al, 0 - stosb - mov ax, [si+10h] - stosw - push di - add di, ax - cmp di, 0x8000 - 12 - pop di - ja ..attr_overflow - movzx edx, ax ; length of attribute - xchg ax, cx - add si, [si+14h] - rep movsb - mov [bp + freeattr - dat], di - pop ds - ret -.nonresident: -; nonresident attribute - cmp dword [di+10h], 0 - jnz @b -; read start of data - mov si, di - mov edx, [di+30h] ; size of attribute - pop di - call process_mcb_nonres - sub di, 4 - push di -.notfound1: - pop di - push edx -; $ATTRIBUTE_LIST is always in base file record - cmp ax, 20h - jz .nofragmented -; try to load $ATTRIBUTE_LIST = 20h - push ax - mov ax, 20h - push [bp + freeattr - dat] - mov [bp + freeattr - dat], di - push di - call load_attr - pop di - pop [bp + freeattr - dat] - pop ax - jc .nofragmented - push ds bx - pusha - mov si, di - push ss - pop ds - push 0x8100 - pop es - xor ecx, ecx - mov cl, 0x78 - xor bx, bx - push es - call read_file_chunk - pop ds - jc ..found_disk_error - test cx, cx - jz ..attr_overflow - popa - push ss - pop es - xor bx, bx -.1: - cmp [bx], ax - jnz .continue1 -; only unnamed $DATA attributes! - cmp ax, 80h - jnz @f - cmp byte [bx+6], 0 - jnz .continue1 -@@: - cmp dword [bx+10h], 0 - jz .continue1 - cmp dword [bx+8], 0 - jnz @f - dec di - cmp di, [bp + freeattr - dat] - lea di, [di+1] - jnz .continue1 -@@: - push ds di - push ax - mov eax, [bx+10h] - mov ecx, [bx+8] - call read_file_record - pop ax - mov di, [14h] -.2: - call find_attr.1 - cmp byte [di+8], 0 - jz .aux_resident - cmp dword [di+10h], ecx - jnz .2 - mov si, di - mov di, sp - cmp dword [ss:di+8], -1 - jnz @f - push dword [si+30h] ; size of attribute - pop dword [ss:di+8] -@@: - pop di - call process_mcb_nonres - sub di, 4 - pop ds -.continue1: - add bx, [bx+4] - cmp bx, dx - jb .1 - pop bx ds -.nofragmented: - pop edx - dec di - cmp di, [bp + freeattr - dat] - jnz @f - stc - ret -@@: - inc di - xor ax, ax - stosw - stosw - mov [bp + freeattr - dat], di - ret - -read_file_record: -; in: eax = index of record -; out: ds:0 -> record -; find place in cache - push di - push si - mov si, cache1head - call cache_lookup - pop si - pushf - sub di, 3400h - shl di, 10-3 - add di, 0x6000 - mov ds, di - popf - pop di - jnc .noread -; read file record to ds:0 - pushad - push ds - push es - movzx ecx, [bp + frs_size - dat] - shr cx, 9 - mul ecx - push ds - pop es - push ss - pop ds - mov si, 0x4000 - xor bx, bx - push [bp + cur_obj - dat] - mov [bp + cur_obj - dat], mft_string - push es - call read_attr -; initialize cache for $INDEX_ALLOCATION for this record - pop si - push si - sub si, 0x6000 - mov ax, si - shr si, 10-3 - shr ax, 2 - add si, 3480h - add ax, 3500h - mov [si], si - mov [si+2], si - mov [si+4], ax - pop ds - call restore_usa - pop [bp + cur_obj - dat] - pop es - pop ds - popad -.noread: - ret - -read_attr: -; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute - push invalid_read_request_string - cmp byte [si], 0 - jnz .nonresident - cmp eax, 10000h shr 9 - jae find_error_sp - shl ax, 9 - shl cx, 9 - cmp ax, [si+2] - jae find_error_sp - cmp cx, [si+2] - ja find_error_sp - add si, 3 - add si, ax - mov di, bx - rep movsb - pop ax - ret -.nonresident: - inc si -.loop: - mov edx, dword [si] - add si, 8 - test edx, edx - jz find_error_sp - imul edx, [bp + sect_per_clust - dat] - sub eax, edx - jnc .loop - add eax, edx - sub edx, eax - push cx - cmp ecx, edx - jb @f - mov cx, dx -@@: - push bx - mov ebx, [si-4] - imul ebx, [bp + sect_per_clust - dat] - add eax, ebx - pop bx - call read - jc ..found_disk_error - mov dx, cx - pop cx - xor eax, eax - sub cx, dx - jnz .loop - pop ax - ret - -load_file_ntfs: -; in: ss:bp = 0:dat -; in: es:bx = address to load file -; in: ds:si -> ASCIIZ name -; in: cx = limit in sectors -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) - push es bx cx - mov eax, 5 ; root cluster - mov [bp + cur_obj - dat], root_string -.parse_dir_loop: - push ds si - call read_file_record -; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP - mov ax, [bp + freeattr - dat] - mov [bp + index_root - dat], ax - mov ax, 90h ; $INDEX_ROOT - xor bx, bx - call load_attr - mov si, noindex_string - jc find_error_si - mov ax, [bp + freeattr - dat] - mov [bp + index_alloc - dat], ax - mov ax, 0A0h ; $INDEX_ALLOCATION - call load_attr - jnc @f - mov [bp + index_alloc - dat], bx -@@: - push ds -; search for entry - mov si, [bp + index_root - dat] - push ss - pop ds - push 0x8100 - pop es - xor ecx, ecx - mov cl, 0x78 - xor bx, bx - push es - call read_file_chunk - pop ds - jc ..found_disk_error - test cx, cx - jz ..attr_overflow - mov si, invalid_read_request_string - cmp word [bx+10], 0 - jnz find_error_si -; calculate number of items in cache - mov di, [bx+8] ; subnode_size - mov ax, 0x4000 - sub ax, word [bp + frs_size - dat] - cwd - div di - test ax, ax - jz find_error_si - mov si, invalid_volume_msg - test di, 0x1FF - jnz find_error_si - pop cx - mov [bp + cur_index_seg - dat], cx - shl ax, 3 - sub cx, 6000h - mov si, cx - shr cx, 2 - shr si, 10-3 - add cx, ax - add si, 3480h - mov [bp + cur_index_cache - dat], si - add cx, 3500h - mov [ss:si+6], cx - mov dx, di - add bx, 10h -.scan_record: - add bx, [bx] -.scan: - test byte [bx+0Ch], 2 - jnz .look_child - movzx cx, byte [bx+50h] ; namelen - lea di, [bx+52h] ; name - push ds - pop es - pop si ds - push ds si - xor ax, ax -.1: - lodsb - cmp al, '/' - jnz @f - mov al, 0 -@@: - cmp al, 'A' - jb .nocapital - cmp al, 'Z' - ja .nocapital - or al, 20h -.nocapital: - cmp al, 'a' - jb .notletter - cmp al, 'z' - ja .notletter - or byte [es:di], 20h -.notletter: - scasw - loopz .1 - jb .look_child - ja @f - cmp byte [si], 0 - jz .file_found - cmp byte [si], '/' - jz .file_found -@@: - push es - pop ds - add bx, [bx+8] - jmp .scan -.look_child: - push es - pop ds - test byte [bx+0Ch], 1 - jz .not_found - mov si, [bp + index_alloc - dat] - test si, si - jz .not_found - add bx, [bx+8] - mov eax, [bx-8] - mov es, [bp + cur_index_seg - dat] - push si - mov si, [bp + cur_index_cache - dat] - call cache_lookup - pop si - pushf - mov bx, di - mov bh, 0 - shr bx, 3 - imul bx, dx - add bx, [bp + frs_size - dat] - popf - jnc .noread - push es - push dx - push ss - pop ds - movzx ecx, dx - shr cx, 9 - mul [bp + sect_per_clust - dat] - call read_attr - pop dx - pop es - push es - pop ds - call restore_usa -.noread: - push es - pop ds - add bx, 18h - jmp .scan_record -.not_found: - pop [bp + cur_obj - dat] - mov si, error_not_found - jmp find_error_si -.file_found: - pop [bp + cur_obj - dat] - pop cx - mov ax, [bp + index_root - dat] - mov [bp + freeattr - dat], ax - mov eax, [es:bx] - test byte [es:bx+48h+3], 10h - jz .regular_file - cmp byte [si], 0 - jz ..directory_error - inc si - jmp .parse_dir_loop -.regular_file: - cmp byte [si], 0 - jnz ..notdir_error -; read entry - call read_file_record - xor bx, bx - mov ax, 80h - call load_attr - mov si, nodata_string - jc find_error_si - mov si, [bp + index_root - dat] - mov [bp + freeattr - dat], si - push ss - pop ds - jmp load_file_common_end +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +restore_usa: +; Update Sequence Array restore +; in: ds:bx -> USA-protected structure + push bx + lea di, [bx+1feh] + mov cx, [bx+6] + add bx, [bx+4] + dec cx +@@: + mov ax, [bx+2] + mov [di], ax + inc bx + inc bx + add di, 200h + loop @b + pop bx + ret + +find_attr: +; in: ds:di->file record, ax=attribute +; out: ds:di->attribute or di=0 if not found + add di, [di+14h] +.1: +; attributes' codes are formally dwords, but all of them fit in word + cmp word [di], -1 + jz .notfound + cmp word [di], ax + jnz .continue +; for $DATA attribute, scan only unnamed + cmp ax, 80h + jnz .found + cmp byte [di+9], 0 + jz .found +.continue: + add di, [di+4] + jmp .1 +.notfound: + xor di, di +.found: + ret + +process_mcb_nonres: +; in: ds:si->attribute, es:di->buffer +; out: es:di->buffer end + pushad + pop di + add si, [si+20h] + xor ebx, ebx +.loop: + lodsb + test al, al + jz .done + push invalid_read_request_string + movzx cx, al + shr cx, 4 + jz find_error_sp + xchg ax, dx + and dx, 0Fh + jz find_error_sp + add si, cx + add si, dx + pop ax + push si + dec si + movsx eax, byte [si] + dec cx + jz .l1e +.l1: + dec si + shl eax, 8 + mov al, [si] + loop .l1 +.l1e: + xchg ebp, eax + dec si + movsx eax, byte [si] + mov cx, dx + dec cx + jz .l2e +.l2: + dec si + shl eax, 8 + mov al, byte [si] + loop .l2 +.l2e: + pop si + add ebx, ebp +; eax=length, ebx=disk block + stosd + mov eax, ebx + stosd + cmp di, 0x8000 - 12 + jbe .loop +..attr_overflow: + mov si, fragmented_string + jmp find_error_si +.done: + xor ax, ax + stosw + stosw + push di + popad + ret + +load_attr: +; in: ax=attribute, ds:bx->base record +; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, +; edx=size of attribute in bytes +; out: if not found: CF=1 + mov di, [bp + freeattr - dat] + push ss + pop es + mov byte [es:di], 1 + inc di + cmp di, 0x8000 - 12 + ja ..attr_overflow + or edx, -1 ; file size is not known yet +; scan for attribute + push di + mov di, bx + add di, [di+14h] +@@: + call find_attr.1 + test di, di + jz .notfound1 + cmp byte [di+8], 0 + jnz .nonresident + mov si, di + pop di + push ds + jmp .resident +.aux_resident: + mov ax, ds + mov si, di + pop di ds bx ds edx + push ss + pop es + push ds + mov ds, ax +; resident attribute +.resident: + dec di + mov al, 0 + stosb + mov ax, [si+10h] + stosw + push di + add di, ax + cmp di, 0x8000 - 12 + pop di + ja ..attr_overflow + movzx edx, ax ; length of attribute + xchg ax, cx + add si, [si+14h] + rep movsb + mov [bp + freeattr - dat], di + pop ds + ret +.nonresident: +; nonresident attribute + cmp dword [di+10h], 0 + jnz @b +; read start of data + mov si, di + mov edx, [di+30h] ; size of attribute + pop di + call process_mcb_nonres + sub di, 4 + push di +.notfound1: + pop di + push edx +; $ATTRIBUTE_LIST is always in base file record + cmp ax, 20h + jz .nofragmented +; try to load $ATTRIBUTE_LIST = 20h + push ax + mov ax, 20h + push [bp + freeattr - dat] + mov [bp + freeattr - dat], di + push di + call load_attr + pop di + pop [bp + freeattr - dat] + pop ax + jc .nofragmented + push ds bx + pusha + mov si, di + push ss + pop ds + push 0x8100 + pop es + xor ecx, ecx + mov cl, 0x78 + xor bx, bx + push es + call read_file_chunk + pop ds + jc ..found_disk_error + test cx, cx + jz ..attr_overflow + popa + push ss + pop es + xor bx, bx +.1: + cmp [bx], ax + jnz .continue1 +; only unnamed $DATA attributes! + cmp ax, 80h + jnz @f + cmp byte [bx+6], 0 + jnz .continue1 +@@: + cmp dword [bx+10h], 0 + jz .continue1 + cmp dword [bx+8], 0 + jnz @f + dec di + cmp di, [bp + freeattr - dat] + lea di, [di+1] + jnz .continue1 +@@: + push ds di + push ax + mov eax, [bx+10h] + mov ecx, [bx+8] + call read_file_record + pop ax + mov di, [14h] +.2: + call find_attr.1 + cmp byte [di+8], 0 + jz .aux_resident + cmp dword [di+10h], ecx + jnz .2 + mov si, di + mov di, sp + cmp dword [ss:di+8], -1 + jnz @f + push dword [si+30h] ; size of attribute + pop dword [ss:di+8] +@@: + pop di + call process_mcb_nonres + sub di, 4 + pop ds +.continue1: + add bx, [bx+4] + cmp bx, dx + jb .1 + pop bx ds +.nofragmented: + pop edx + dec di + cmp di, [bp + freeattr - dat] + jnz @f + stc + ret +@@: + inc di + xor ax, ax + stosw + stosw + mov [bp + freeattr - dat], di + ret + +read_file_record: +; in: eax = index of record +; out: ds:0 -> record +; find place in cache + push di + push si + mov si, cache1head + call cache_lookup + pop si + pushf + sub di, 3400h + shl di, 10-3 + add di, 0x6000 + mov ds, di + popf + pop di + jnc .noread +; read file record to ds:0 + pushad + push ds + push es + movzx ecx, [bp + frs_size - dat] + shr cx, 9 + mul ecx + push ds + pop es + push ss + pop ds + mov si, 0x4000 + xor bx, bx + push [bp + cur_obj - dat] + mov [bp + cur_obj - dat], mft_string + push es + call read_attr +; initialize cache for $INDEX_ALLOCATION for this record + pop si + push si + sub si, 0x6000 + mov ax, si + shr si, 10-3 + shr ax, 2 + add si, 3480h + add ax, 3500h + mov [si], si + mov [si+2], si + mov [si+4], ax + pop ds + call restore_usa + pop [bp + cur_obj - dat] + pop es + pop ds + popad +.noread: + ret + +read_attr: +; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute + push invalid_read_request_string + cmp byte [si], 0 + jnz .nonresident + cmp eax, 10000h shr 9 + jae find_error_sp + shl ax, 9 + shl cx, 9 + cmp ax, [si+2] + jae find_error_sp + cmp cx, [si+2] + ja find_error_sp + add si, 3 + add si, ax + mov di, bx + rep movsb + pop ax + ret +.nonresident: + inc si +.loop: + mov edx, dword [si] + add si, 8 + test edx, edx + jz find_error_sp + imul edx, [bp + sect_per_clust - dat] + sub eax, edx + jnc .loop + add eax, edx + sub edx, eax + push cx + cmp ecx, edx + jb @f + mov cx, dx +@@: + push bx + mov ebx, [si-4] + imul ebx, [bp + sect_per_clust - dat] + add eax, ebx + pop bx + call read + jc ..found_disk_error + mov dx, cx + pop cx + xor eax, eax + sub cx, dx + jnz .loop + pop ax + ret + +load_file_ntfs: +; in: ss:bp = 0:dat +; in: es:bx = address to load file +; in: ds:si -> ASCIIZ name +; in: cx = limit in sectors +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) + push es bx cx + mov eax, 5 ; root cluster + mov [bp + cur_obj - dat], root_string +.parse_dir_loop: + push ds si + call read_file_record +; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP + mov ax, [bp + freeattr - dat] + mov [bp + index_root - dat], ax + mov ax, 90h ; $INDEX_ROOT + xor bx, bx + call load_attr + mov si, noindex_string + jc find_error_si + mov ax, [bp + freeattr - dat] + mov [bp + index_alloc - dat], ax + mov ax, 0A0h ; $INDEX_ALLOCATION + call load_attr + jnc @f + mov [bp + index_alloc - dat], bx +@@: + push ds +; search for entry + mov si, [bp + index_root - dat] + push ss + pop ds + push 0x8100 + pop es + xor ecx, ecx + mov cl, 0x78 + xor bx, bx + push es + call read_file_chunk + pop ds + jc ..found_disk_error + test cx, cx + jz ..attr_overflow + mov si, invalid_read_request_string + cmp word [bx+10], 0 + jnz find_error_si +; calculate number of items in cache + mov di, [bx+8] ; subnode_size + mov ax, 0x4000 + sub ax, word [bp + frs_size - dat] + cwd + div di + test ax, ax + jz find_error_si + mov si, invalid_volume_msg + test di, 0x1FF + jnz find_error_si + pop cx + mov [bp + cur_index_seg - dat], cx + shl ax, 3 + sub cx, 6000h + mov si, cx + shr cx, 2 + shr si, 10-3 + add cx, ax + add si, 3480h + mov [bp + cur_index_cache - dat], si + add cx, 3500h + mov [ss:si+6], cx + mov dx, di + add bx, 10h +.scan_record: + add bx, [bx] +.scan: + test byte [bx+0Ch], 2 + jnz .look_child + movzx cx, byte [bx+50h] ; namelen + lea di, [bx+52h] ; name + push ds + pop es + pop si ds + push ds si + xor ax, ax +.1: + lodsb + cmp al, '/' + jnz @f + mov al, 0 +@@: + cmp al, 'A' + jb .nocapital + cmp al, 'Z' + ja .nocapital + or al, 20h +.nocapital: + cmp al, 'a' + jb .notletter + cmp al, 'z' + ja .notletter + or byte [es:di], 20h +.notletter: + scasw + loopz .1 + jb .look_child + ja @f + cmp byte [si], 0 + jz .file_found + cmp byte [si], '/' + jz .file_found +@@: + push es + pop ds + add bx, [bx+8] + jmp .scan +.look_child: + push es + pop ds + test byte [bx+0Ch], 1 + jz .not_found + mov si, [bp + index_alloc - dat] + test si, si + jz .not_found + add bx, [bx+8] + mov eax, [bx-8] + mov es, [bp + cur_index_seg - dat] + push si + mov si, [bp + cur_index_cache - dat] + call cache_lookup + pop si + pushf + mov bx, di + mov bh, 0 + shr bx, 3 + imul bx, dx + add bx, [bp + frs_size - dat] + popf + jnc .noread + push es + push dx + push ss + pop ds + movzx ecx, dx + shr cx, 9 + mul [bp + sect_per_clust - dat] + call read_attr + pop dx + pop es + push es + pop ds + call restore_usa +.noread: + push es + pop ds + add bx, 18h + jmp .scan_record +.not_found: + pop [bp + cur_obj - dat] + mov si, error_not_found + jmp find_error_si +.file_found: + pop [bp + cur_obj - dat] + pop cx + mov ax, [bp + index_root - dat] + mov [bp + freeattr - dat], ax + mov eax, [es:bx] + test byte [es:bx+48h+3], 10h + jz .regular_file + cmp byte [si], 0 + jz ..directory_error + inc si + jmp .parse_dir_loop +.regular_file: + cmp byte [si], 0 + jnz ..notdir_error +; read entry + call read_file_record + xor bx, bx + mov ax, 80h + call load_attr + mov si, nodata_string + jc find_error_si + mov si, [bp + index_root - dat] + mov [bp + freeattr - dat], si + push ss + pop ds + jmp load_file_common_end diff --git a/kernel/trunk/sec_loader/trunk/boot/cdfs/bootsect.asm b/kernel/trunk/sec_loader/trunk/boot/cdfs/bootsect.asm index 4d03989b3..f19bb55ab 100644 --- a/kernel/trunk/sec_loader/trunk/boot/cdfs/bootsect.asm +++ b/kernel/trunk/sec_loader/trunk/boot/cdfs/bootsect.asm @@ -1,1024 +1,1024 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - - jmp far 0:real_start -; special text -org $+0x7C00 -real_start: -; initialize - xor ax, ax - mov ss, ax - mov sp, 0x7C00 - mov ds, ax - mov es, ax - cld - sti - mov [bootdrive], dl -; check LBA support - mov ah, 41h - mov bx, 55AAh - int 13h - mov si, aNoLBA - jc err_ - cmp bx, 0AA55h - jnz err_ - test cl, 1 - jz err_ -; get file system information -; scan for Primary Volume Descriptor - db 66h - push 10h-1 - pop eax -pvd_scan_loop: - mov cx, 1 - inc eax - mov bx, 0x1000 - call read_sectors - jnc @f -fatal_read_err: - mov si, aReadError -err_: - call out_string - mov si, aPressAnyKey - call out_string - xor ax, ax - int 16h - int 18h - jmp $ -@@: - push ds - pop es - cmp word [bx+1], 'CD' - jnz pvd_scan_loop - cmp word [bx+3], '00' - jnz pvd_scan_loop - cmp byte [bx+5], '1' - jnz pvd_scan_loop -; we have found ISO9660 descriptor, look for type - cmp byte [bx], 1 ; Primary Volume Descriptor? - jz pvd_found - cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? - jnz pvd_scan_loop -; Volume Descriptor Set Terminator reached, no PVD found - fatal error - mov si, no_pvd - jmp err_ -pvd_found: - add bx, 80h - mov ax, [bx] - mov [lb_size], ax -; calculate number of logical blocks in one sector - mov ax, 800h - cwd - div word [bx] - mov [lb_per_sec], ax -; get location of root directory - mov di, root_location - movzx eax, byte [bx+1Dh] - add eax, [bx+1Eh] - stosd -; get memory size - int 12h - mov si, nomem_str - cmp ax, 71000h / 400h - jb err_ - shr ax, 1 - sub ax, 60000h / 800h - mov [size_rest], ax - mov [free_ptr], 60000h / 800h -; load path table -; if size > 62K => it's very strange, avoid using it -; if size > (size of cache)/2 => avoid using it too - mov ecx, [bx+4] - cmp ecx, 0x10000 - 0x800 - ja nopathtable - shr ax, 1 - cmp ax, 0x20 - jae @f - shl ax, 11 - cmp cx, ax - ja nopathtable -@@: -; size is ok, try to load it - mov [pathtable_size], cx - mov eax, [bx+12] - xor edx, edx - div dword [lb_per_sec] - imul dx, [bx] - mov [pathtable_start], dx - add cx, dx - call cx_to_sectors - xor bx, bx - push 6000h - pop es - call read_sectors - jc nopathtable -; path table has been loaded - inc [use_path_table] - sub [size_rest], cx - add [free_ptr], cx -nopathtable: -; init cache - mov ax, [size_rest] - mov [cache_size], ax - mov ax, [free_ptr] - mov [cache_start], ax -; load secondary loader - mov di, secondary_loader_info - call load_file - test bx, bx - jnz noloader -; set registers for secondary loader - mov ah, [bootdrive] - mov al, 'c' - mov bx, 'is' - mov si, callback - jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 - -noloader: - mov si, aKernelNotFound - jmp err_ - -read_sectors: -; es:bx = pointer to data -; eax = first sector -; cx = number of sectors - pushad - push ds -do_read_sectors: - push ax - push cx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - db 66h - push 0 - push eax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [cs:bootdrive] - mov ah, 42h - int 13h - jc diskreaderr -; restore stack - add sp, 10h -; increase current sector & buffer; decrease number of sectors - movzx esi, cx - mov ax, es - shl cx, 7 - add ax, cx - mov es, ax - pop cx - pop ax - add eax, esi - sub cx, si - jnz do_read_sectors - pop ds - popad - ret -diskreaderr: - add sp, 10h + 2*2 - pop ds - popad - stc -out_string.ret: - ret - -out_string: -; in: ds:si -> ASCIIZ string - lodsb - test al, al - jz .ret - mov ah, 0Eh - mov bx, 7 - int 10h - jmp out_string - -aNoLBA db 'The drive does not support LBA!',0 -aReadError db 'Read error',0 -no_pvd db 'Primary Volume Descriptor not found!',0 -nomem_str db 'No memory',0 -aPressAnyKey db 13,10,'Press any key...',13,10,0 - -load_file: -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) -; parse path to the file - lea si, [di+6] - mov eax, [cs:root_location] - cmp [cs:use_path_table], 0 - jz parse_dir -; scan for path in path table - push di - push 6000h - pop es - mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table - mov dx, 1 ; dx = number of current entry in path table, start from 1 - mov cx, [cs:pathtable_size] -pathtable_newparent: - mov bx, dx ; bx = number of current parent in path table: root = 1 -scan_path_table_e: - call is_last_component - jnc path_table_scanned -scan_path_table_i: - cmp word [es:di+6], bx - jb .next - ja path_table_notfound - call test_filename1 - jc .next -@@: - lodsb - cmp al, '/' - jnz @b - jmp pathtable_newparent -.next: -; go to next entry - inc dx - movzx ax, byte [es:di] - add ax, 8+1 - and al, not 1 - add di, ax - sub cx, ax - ja scan_path_table_i -path_table_notfound: - pop di - mov ax, -1 - mov dx, ax - mov bx, 2 ; file not found - ret -path_table_scanned: - movzx eax, byte [es:di+1] - add eax, [es:di+2] - pop di -parse_dir: -; eax = logical block, ds:di -> information structure, ds:si -> file name -; was the folder already read? - push di ds - push cs - pop ds - mov [cur_desc_end], 2000h - mov bx, cachelist -.scan1: - mov bx, [bx+2] - cmp bx, cachelist - jz .notfound - cmp [bx+4], eax - jnz .scan1 -.found: -; yes; delete this item from the list (the following code will append this item to the tail) - mov di, [bx] - push word [bx+2] - pop word [di+2] - mov di, [bx+2] - push word [bx] - pop word [di] - mov di, bx - jmp .scan -.notfound: -; no; load first sector of the folder to get its size - push eax - push si - mov si, 1 - call load_phys_sector_for_lb_force - mov bx, si - pop si - pop eax - jnc @f -; read error - return -.readerr: - pop ds -.readerr2: - pop di - mov ax, -1 - mov dx, ax - mov bx, 3 - ret -@@: -; first item of the folder describes the folder itself -; do not cache too big folders: size < 64K and size <= (total cache size)/2 - cmp word [bx+12], 0 - jnz .nocache - mov cx, [cache_size] ; cx = cache size in sectors - shr cx, 1 ; cx = (cache size)/2 - cmp cx, 0x20 - jae @f - shl cx, 11 - cmp [bx+10], cx - ja .nocache -@@: -; we want to cache this folder; get space for it - mov cx, [bx+10] - call cx_to_sectors - jnz .yescache -.nocache: - push dword [bx+10] - pop dword [cur_nocache_len] - call lb_to_sector - push ds - pop es - pop ds -.nocache_loop: - push eax - mov dx, 1800h - call scan_for_filename_in_sector - mov cx, dx - pop eax - jnc .j_scandone - sub cx, bx - sub word [es:cur_nocache_len], cx - sbb word [es:cur_nocache_len+2], 0 - jb .j_scandone - ja @f - cmp word [es:cur_nocache_len], 0 - jz .j_scandone -@@: - mov cx, 1 - inc eax - push es - mov bx, 1000h - call read_sectors - pop es - jc .readerr2 - jmp .nocache_loop -.j_scandone: - jmp .scandone -.yescache: - push bx - mov bx, [cachelist.head] -.freeloop: - cmp cx, [size_rest] - jbe .sizeok -@@: -; if we are here: there is not enough free space, so we must delete old folders' data -; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). -; one loop iteration: delete data of one folder - pusha - mov dx, [bx+10] - mov es, dx ; es = segment of folder data to be deleted - xor di, di - mov ax, [bx+8] - add ax, 0x7FF - rcr ax, 1 - shr ax, 10 - push ax - shl ax, 11-4 ; get number of paragraphs in folder data to be deleted - mov cx, [cache_size] - add cx, [cache_start] - push ds - push ax - add ax, dx - mov ds, ax - pop ax - shl cx, 11-4 - sub cx, dx ; cx = number of paragraphs to be moved - push si - xor si, si -; move cx paragraphs from ds:si to es:di to get free space in the end of cache -@@: - sub cx, 1000h - jbe @f - push cx - mov cx, 8000h - rep movsw - mov cx, ds - add cx, 1000h - mov ds, cx - mov cx, es - add cx, 1000h - mov es, cx - pop cx - jmp @b -@@: - add cx, 1000h - shl cx, 3 - rep movsw - pop si - pop ds -; correct positions in cache for existing items - mov cx, 80h - mov di, 8400h -.correct: - cmp [di+10], dx - jbe @f - sub [di+10], ax -@@: - add di, 12 - loop .correct -; some additional space is free now - pop ax - add [size_rest], ax - sub [free_ptr], ax -; add cache item to the list of free items - mov dx, [bx] - mov ax, [free_cache_item] - mov [bx], ax - mov [free_cache_item], bx - mov bx, dx -; current iteration done - popa - jmp .freeloop -.sizeok: - mov [cachelist.head], bx - mov word [bx+2], cachelist -; allocate new item in cache - mov di, [free_cache_item] - test di, di - jz .nofree - push word [di] - pop [free_cache_item] - jmp @f -.nofree: - mov di, [last_cache_item] - add [last_cache_item], 12 -@@: - pop bx - push si di -; mov [di+4], eax ; start of folder - scasd - stosd - push ax - mov ax, [free_ptr] - shl ax, 11-4 - mov [di+10-8], ax - mov es, ax - pop ax - add [free_ptr], cx - sub [size_rest], cx -; read folder data -; first sector is already in memory, 0000:bx - pusha - mov cx, [bx+10] - mov [di+8-8], cx ; folder size in bytes - mov si, bx - xor di, di - mov cx, 0x1800 - sub cx, si - rep movsb - pop ax - push di - popa -; read rest of folder - mov esi, dword [lb_per_sec] - add eax, esi - dec si - not si - and ax, si - mov si, word [bx+10] - mov bx, di - pop di - sub si, bx - jbe @f - mov [cur_limit], esi - call read_many_bytes - pop si - jnc .scan - jmp .readerr -@@: - pop si -.scan: -; now we have required cache item; append it to the end of list - mov bx, [cachelist.tail] - mov [cachelist.tail], di - mov [di+2], bx - mov word [di], cachelist - mov [bx], di -; scan for given filename - mov es, [di+10] - mov dx, [di+8] - pop ds - xor bx, bx - call scan_for_filename_in_sector -.scandone: - push cs - pop es - mov bx, 2000h - cmp bx, [es:cur_desc_end] - jnz filefound -j_notfound: - jmp path_table_notfound -filefound: -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jnz @b -@@: - mov cl, [es:bx+8] - test al, al - jz @f -; parse next component of file name - test cl, 2 ; directory? - jz j_notfound - mov eax, [es:bx] - pop di - jmp parse_dir -@@: - test cl, 2 ; directory? - jnz j_notfound ; do not allow read directories as regular files -; ok, now load the file - pop di - les bx, [di] - call normalize - movzx esi, word [di+4] ; esi = limit in 4K blocks - shl esi, 12 ; esi = limit in bytes - push cs - pop ds - mov [cur_limit], esi - mov di, 2000h -loadloop: - and [cur_start], 0 -.loadnew: - mov esi, [cur_limit] - mov eax, [cur_start] - add esi, eax - mov [overflow], 1 - sub esi, [di+4] - jb @f - xor esi, esi - dec [overflow] -@@: - add esi, [di+4] ; esi = number of bytes to read - mov [cur_start], esi - sub esi, eax - jz .loadcontinue - xor edx, edx - div dword [lb_size] ; eax = number of logical blocks to skip, - mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block - cmp byte [di+10], 0 - jnz .interleaved - add eax, [di] -; read esi bytes from logical block eax to buffer es:bx - call read_many_bytes.with_first - jc .readerr3 -.loadcontinue: - mov [cur_chunk], di - add di, 11 - cmp di, [cur_desc_end] - jae @f - cmp [cur_limit], 0 - jnz loadloop -@@: - mov bx, [overflow] -.calclen: -; calculate length of file - xor ax, ax - xor dx, dx - mov di, 2000h -@@: - add ax, [di+4] - adc dx, [di+6] - add di, 11 - cmp di, [cur_desc_end] - jb @b - ret -.interleaved: - mov [cur_unit_limit], esi - push esi -; skip first blocks - movzx ecx, byte [di+9] ; Unit Size - movzx esi, byte [di+10] ; Interleave Gap - add si, cx - mov edx, [di] -@@: - sub eax, ecx - jb @f - add edx, esi - jmp @b -@@: - add ecx, eax ; ecx = number of logical blocks to skip - lea eax, [ecx+edx] ; eax = first logical block - pop esi -.interleaved_loop: -; get number of bytes in current file unit - push eax - movzx eax, byte [di+9] - sub ax, cx - imul eax, dword [lb_size] - cmp eax, esi - ja .i2 -.i1: - xchg esi, eax -.i2: - pop eax - sub [cur_unit_limit], esi - push eax -; read esi bytes from logical block eax to buffer es:bx - call read_many_bytes.with_first - pop eax - jnc @f -.readerr3: - mov bx, 3 - jmp .calclen -@@: - mov esi, [cur_unit_limit] - test esi, esi - jz .loadcontinue - movzx ecx, byte [di+9] ; add Unit Size - add cl, byte [di+10] ; add Interleave Gap - adc ch, 0 - add eax, ecx - xor cx, cx - mov [first_byte], cx - jmp .interleaved_loop - -cx_to_sectors: - add cx, 7FFh - rcr cx, 1 - shr cx, 10 - ret - -is_last_component: -; in: ds:si -> name -; out: CF set <=> current component is not last (=> folder) - push si -@@: - lodsb - test al, al - jz @f - cmp al, '/' - jnz @b - stc -@@: - pop si - ret - -test_filename1: -; in: ds:si -> filename, es:di -> path table item -; out: CF set <=> no match - pusha - mov cl, [es:di] - add di, 8 - jmp test_filename2.start -test_filename2: -; in: ds:si -> filename, es:bx -> directory item -; out: CF set <=> no match - pusha - mov cl, [es:bx+32] - lea di, [bx+33] -.start: - mov ch, 0 -@@: - lodsb - test al, al - jz .test1 - cmp al, '/' - jz .test1 - call toupper - mov ah, al - mov al, [es:di] - call toupper - inc di - cmp al, ah - loopz @b - jnz .next1 -; if we have reached this point: current name is done - lodsb - test al, al - jz .ret - cmp al, '/' - jz .ret -; if we have reached this point: current name is done, but input name continues -; so they do not match - jmp .next1 -.test1: -; if we have reached this point: input name is done, but current name continues -; "filename.ext;version" in ISO-9660 represents file "filename.ext" -; "filename." and "filename.;version" are also possible for "filename" - cmp byte [es:di], '.' - jnz @f - inc di - dec cx - jz .ret -@@: - cmp byte [es:di], ';' - jnz .next1 - jmp .ret -.next1: - stc -.ret: - popa - ret - -toupper: -; in: al=symbol -; out: al=symbol in uppercase - cmp al, 'a' - jb .ret - cmp al, 'z' - ja .ret - sub al, 'a'-'A' -.ret: - ret - -scan_for_filename_in_sector: -; in: ds:si->filename, es:bx->folder data, dx=limit -; out: CF=0 if found - push bx -.loope: - push bx -.loop: - cmp bx, dx - jae .notfound - cmp byte [es:bx], 0 - jz .loopd - test byte [es:bx+25], 4 ; ignore files with Associated bit - jnz .next - call test_filename2 - jc .next - push ds es di - push es - pop ds - push cs - pop es - mov di, [es:cur_desc_end] - movzx eax, byte [bx+1] - add eax, [bx+2] - stosd ; first logical block - mov eax, [bx+10] - stosd ; length - mov al, [bx+25] - stosb ; flags - mov ax, [bx+26] - stosw ; File Unit size, Interleave Gap size - mov [es:cur_desc_end], di - cmp di, 3000h - pop di es ds - jae .done - test byte [es:bx+25], 80h - jz .done -.next: - add bl, [es:bx] - adc bh, 0 - jmp .loop -.loopd: - mov ax, bx - pop bx -@@: - add bx, [cs:lb_size] - jz .done2 - cmp bx, ax - jb @b - jmp .loope -.notfound: - stc -.done: - pop bx -.done2: - pop bx - ret - -lb_to_sector: - xor edx, edx - div dword [lb_per_sec] - ret - -load_phys_sector_for_lb_force: -; in: eax = logical block, ds=0 -; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 -; out: 0000:1000 = physical sector data; si -> logical block -; out: eax = next physical sector -; out: CF=1 if read error -; destroys cx -; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector - call lb_to_sector - or si, dx - jnz @f - mov si, 1800h - jmp .done -@@: - mov si, 1000h - imul dx, [lb_size] - add si, dx - mov cx, 1 - push es bx - push ds - pop es - mov bx, 1000h - call read_sectors - pop bx es - inc eax -.done: - ret - -normalize: -; in: es:bx = far pointer -; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) - push ax bx - mov ax, es - shr bx, 4 - add ax, bx - mov es, ax - pop bx ax - and bx, 0x0F - ret - -read_many_bytes: - and [first_byte], 0 -read_many_bytes.with_first: -; read esi bytes from logical block dx:ax to buffer es:bx -; out: CF=1 <=> disk error - push di -; load first physical sector - push bx si - mov si, [first_byte] - call load_phys_sector_for_lb_force - jnc @f - pop si bx -.ret: - pop di - ret -@@: - add si, [first_byte] - mov ecx, 1800h - sub cx, si - mov ebx, esi - pop bx - sub ebx, ecx - jnc @f - add cx, bx - xor ebx, ebx -@@: - pop di - sub [cur_limit], ecx - rep movsb - mov esi, ebx - mov bx, di - call normalize -; load other physical sectors -; read esi bytes from physical sector eax to buffer es:bx - test esi, esi - jz .ret - push esi - add esi, 0x7FF - and si, not 0x7FF - cmp esi, [cur_limit] - jbe .okplace -.noplace: - sub esi, 800h -.okplace: - shr esi, 11 ; si = number of sectors - mov cx, si - jz @f - call read_sectors -@@: - pop esi - jc .ret - movzx ecx, cx - add eax, ecx - shl ecx, 11 - sub [cur_limit], ecx - sub esi, ecx - jc .big - jz .nopost - push bx es - push ds - pop es - mov bx, 1000h - mov cx, 1 - call read_sectors - pop es di - jc .ret2 - mov cx, si - mov si, 1000h - sub word [cur_limit], cx - sbb word [cur_limit+2], 0 - rep movsb - mov bx, di - call normalize -.nopost: - clc -.ret2: - pop di - ret -.big: - mov ax, es - sub ax, 80h - mov es, ax - add bx, 800h - add bx, si - call normalize - sub [cur_limit], esi - jmp .nopost - -; Callback function for secondary loader -callback: -; in: ax = function number; only function 1 is defined for now - dec ax - jz callback_readfile - dec ax - jz callback_continueread - stc ; unsupported function - retf - -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call load_file - clc ; function is supported - retf - -callback_continueread: -; function 2: continue to read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error -; out: dx:ax = file size - les bx, [di] - call normalize - movzx esi, word [di+4] ; si = limit in 4K blocks - shl esi, 12 ; bp:si = limit in bytes - push cs - pop ds - mov [cur_limit], esi - mov di, [cur_chunk] - call loadloop.loadnew - clc ; function is supported - retf - -secondary_loader_info: - dw 0, 0x1000 - dw 0x30000 / 0x1000 - db 'kord/loader',0 -aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 - -align 2 -cachelist: -.head dw cachelist -.tail dw cachelist -free_cache_item dw 0 -last_cache_item dw 0x8400 - -use_path_table db 0 -bootdrive db ? -align 2 -lb_size dw ? ; Logical Block size in bytes - dw 0 ; to allow access dword [lb_size] -lb_per_sec dw ? ; Logical Blocks per physical sector - dw 0 ; to allow access dword [lb_per_sec] -free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) -size_rest dw ? ; free space in cache (in blocks) -cache_size dw ? -cache_start dw ? -pathtable_size dw ? -pathtable_start dw ? -root_location dd ? -cur_desc_end dw ? -cur_nocache_len dd ? -cur_limit dd ? -cur_unit_limit dd ? -overflow dw ? -cur_chunk dw ? -first_byte dw ? -cur_start dd ? - -;times 83FEh-$ db 0 - db 43h -; just to make file 2048 bytes long :) - db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' - - dw 0xAA55 ; this is not required for CD, but to be consistent... +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + + jmp far 0:real_start +; special text +org $+0x7C00 +real_start: +; initialize + xor ax, ax + mov ss, ax + mov sp, 0x7C00 + mov ds, ax + mov es, ax + cld + sti + mov [bootdrive], dl +; check LBA support + mov ah, 41h + mov bx, 55AAh + int 13h + mov si, aNoLBA + jc err_ + cmp bx, 0AA55h + jnz err_ + test cl, 1 + jz err_ +; get file system information +; scan for Primary Volume Descriptor + db 66h + push 10h-1 + pop eax +pvd_scan_loop: + mov cx, 1 + inc eax + mov bx, 0x1000 + call read_sectors + jnc @f +fatal_read_err: + mov si, aReadError +err_: + call out_string + mov si, aPressAnyKey + call out_string + xor ax, ax + int 16h + int 18h + jmp $ +@@: + push ds + pop es + cmp word [bx+1], 'CD' + jnz pvd_scan_loop + cmp word [bx+3], '00' + jnz pvd_scan_loop + cmp byte [bx+5], '1' + jnz pvd_scan_loop +; we have found ISO9660 descriptor, look for type + cmp byte [bx], 1 ; Primary Volume Descriptor? + jz pvd_found + cmp byte [bx], 0xFF ; Volume Descriptor Set Terminator? + jnz pvd_scan_loop +; Volume Descriptor Set Terminator reached, no PVD found - fatal error + mov si, no_pvd + jmp err_ +pvd_found: + add bx, 80h + mov ax, [bx] + mov [lb_size], ax +; calculate number of logical blocks in one sector + mov ax, 800h + cwd + div word [bx] + mov [lb_per_sec], ax +; get location of root directory + mov di, root_location + movzx eax, byte [bx+1Dh] + add eax, [bx+1Eh] + stosd +; get memory size + int 12h + mov si, nomem_str + cmp ax, 71000h / 400h + jb err_ + shr ax, 1 + sub ax, 60000h / 800h + mov [size_rest], ax + mov [free_ptr], 60000h / 800h +; load path table +; if size > 62K => it's very strange, avoid using it +; if size > (size of cache)/2 => avoid using it too + mov ecx, [bx+4] + cmp ecx, 0x10000 - 0x800 + ja nopathtable + shr ax, 1 + cmp ax, 0x20 + jae @f + shl ax, 11 + cmp cx, ax + ja nopathtable +@@: +; size is ok, try to load it + mov [pathtable_size], cx + mov eax, [bx+12] + xor edx, edx + div dword [lb_per_sec] + imul dx, [bx] + mov [pathtable_start], dx + add cx, dx + call cx_to_sectors + xor bx, bx + push 6000h + pop es + call read_sectors + jc nopathtable +; path table has been loaded + inc [use_path_table] + sub [size_rest], cx + add [free_ptr], cx +nopathtable: +; init cache + mov ax, [size_rest] + mov [cache_size], ax + mov ax, [free_ptr] + mov [cache_start], ax +; load secondary loader + mov di, secondary_loader_info + call load_file + test bx, bx + jnz noloader +; set registers for secondary loader + mov ah, [bootdrive] + mov al, 'c' + mov bx, 'is' + mov si, callback + jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 + +noloader: + mov si, aKernelNotFound + jmp err_ + +read_sectors: +; es:bx = pointer to data +; eax = first sector +; cx = number of sectors + pushad + push ds +do_read_sectors: + push ax + push cx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + db 66h + push 0 + push eax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [cs:bootdrive] + mov ah, 42h + int 13h + jc diskreaderr +; restore stack + add sp, 10h +; increase current sector & buffer; decrease number of sectors + movzx esi, cx + mov ax, es + shl cx, 7 + add ax, cx + mov es, ax + pop cx + pop ax + add eax, esi + sub cx, si + jnz do_read_sectors + pop ds + popad + ret +diskreaderr: + add sp, 10h + 2*2 + pop ds + popad + stc +out_string.ret: + ret + +out_string: +; in: ds:si -> ASCIIZ string + lodsb + test al, al + jz .ret + mov ah, 0Eh + mov bx, 7 + int 10h + jmp out_string + +aNoLBA db 'The drive does not support LBA!',0 +aReadError db 'Read error',0 +no_pvd db 'Primary Volume Descriptor not found!',0 +nomem_str db 'No memory',0 +aPressAnyKey db 13,10,'Press any key...',13,10,0 + +load_file: +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) +; parse path to the file + lea si, [di+6] + mov eax, [cs:root_location] + cmp [cs:use_path_table], 0 + jz parse_dir +; scan for path in path table + push di + push 6000h + pop es + mov di, [cs:pathtable_start] ; es:di = pointer to current entry in path table + mov dx, 1 ; dx = number of current entry in path table, start from 1 + mov cx, [cs:pathtable_size] +pathtable_newparent: + mov bx, dx ; bx = number of current parent in path table: root = 1 +scan_path_table_e: + call is_last_component + jnc path_table_scanned +scan_path_table_i: + cmp word [es:di+6], bx + jb .next + ja path_table_notfound + call test_filename1 + jc .next +@@: + lodsb + cmp al, '/' + jnz @b + jmp pathtable_newparent +.next: +; go to next entry + inc dx + movzx ax, byte [es:di] + add ax, 8+1 + and al, not 1 + add di, ax + sub cx, ax + ja scan_path_table_i +path_table_notfound: + pop di + mov ax, -1 + mov dx, ax + mov bx, 2 ; file not found + ret +path_table_scanned: + movzx eax, byte [es:di+1] + add eax, [es:di+2] + pop di +parse_dir: +; eax = logical block, ds:di -> information structure, ds:si -> file name +; was the folder already read? + push di ds + push cs + pop ds + mov [cur_desc_end], 2000h + mov bx, cachelist +.scan1: + mov bx, [bx+2] + cmp bx, cachelist + jz .notfound + cmp [bx+4], eax + jnz .scan1 +.found: +; yes; delete this item from the list (the following code will append this item to the tail) + mov di, [bx] + push word [bx+2] + pop word [di+2] + mov di, [bx+2] + push word [bx] + pop word [di] + mov di, bx + jmp .scan +.notfound: +; no; load first sector of the folder to get its size + push eax + push si + mov si, 1 + call load_phys_sector_for_lb_force + mov bx, si + pop si + pop eax + jnc @f +; read error - return +.readerr: + pop ds +.readerr2: + pop di + mov ax, -1 + mov dx, ax + mov bx, 3 + ret +@@: +; first item of the folder describes the folder itself +; do not cache too big folders: size < 64K and size <= (total cache size)/2 + cmp word [bx+12], 0 + jnz .nocache + mov cx, [cache_size] ; cx = cache size in sectors + shr cx, 1 ; cx = (cache size)/2 + cmp cx, 0x20 + jae @f + shl cx, 11 + cmp [bx+10], cx + ja .nocache +@@: +; we want to cache this folder; get space for it + mov cx, [bx+10] + call cx_to_sectors + jnz .yescache +.nocache: + push dword [bx+10] + pop dword [cur_nocache_len] + call lb_to_sector + push ds + pop es + pop ds +.nocache_loop: + push eax + mov dx, 1800h + call scan_for_filename_in_sector + mov cx, dx + pop eax + jnc .j_scandone + sub cx, bx + sub word [es:cur_nocache_len], cx + sbb word [es:cur_nocache_len+2], 0 + jb .j_scandone + ja @f + cmp word [es:cur_nocache_len], 0 + jz .j_scandone +@@: + mov cx, 1 + inc eax + push es + mov bx, 1000h + call read_sectors + pop es + jc .readerr2 + jmp .nocache_loop +.j_scandone: + jmp .scandone +.yescache: + push bx + mov bx, [cachelist.head] +.freeloop: + cmp cx, [size_rest] + jbe .sizeok +@@: +; if we are here: there is not enough free space, so we must delete old folders' data +; N.B. We know that after deleting some folders the space will be available (size <= (total cache size)/2). +; one loop iteration: delete data of one folder + pusha + mov dx, [bx+10] + mov es, dx ; es = segment of folder data to be deleted + xor di, di + mov ax, [bx+8] + add ax, 0x7FF + rcr ax, 1 + shr ax, 10 + push ax + shl ax, 11-4 ; get number of paragraphs in folder data to be deleted + mov cx, [cache_size] + add cx, [cache_start] + push ds + push ax + add ax, dx + mov ds, ax + pop ax + shl cx, 11-4 + sub cx, dx ; cx = number of paragraphs to be moved + push si + xor si, si +; move cx paragraphs from ds:si to es:di to get free space in the end of cache +@@: + sub cx, 1000h + jbe @f + push cx + mov cx, 8000h + rep movsw + mov cx, ds + add cx, 1000h + mov ds, cx + mov cx, es + add cx, 1000h + mov es, cx + pop cx + jmp @b +@@: + add cx, 1000h + shl cx, 3 + rep movsw + pop si + pop ds +; correct positions in cache for existing items + mov cx, 80h + mov di, 8400h +.correct: + cmp [di+10], dx + jbe @f + sub [di+10], ax +@@: + add di, 12 + loop .correct +; some additional space is free now + pop ax + add [size_rest], ax + sub [free_ptr], ax +; add cache item to the list of free items + mov dx, [bx] + mov ax, [free_cache_item] + mov [bx], ax + mov [free_cache_item], bx + mov bx, dx +; current iteration done + popa + jmp .freeloop +.sizeok: + mov [cachelist.head], bx + mov word [bx+2], cachelist +; allocate new item in cache + mov di, [free_cache_item] + test di, di + jz .nofree + push word [di] + pop [free_cache_item] + jmp @f +.nofree: + mov di, [last_cache_item] + add [last_cache_item], 12 +@@: + pop bx + push si di +; mov [di+4], eax ; start of folder + scasd + stosd + push ax + mov ax, [free_ptr] + shl ax, 11-4 + mov [di+10-8], ax + mov es, ax + pop ax + add [free_ptr], cx + sub [size_rest], cx +; read folder data +; first sector is already in memory, 0000:bx + pusha + mov cx, [bx+10] + mov [di+8-8], cx ; folder size in bytes + mov si, bx + xor di, di + mov cx, 0x1800 + sub cx, si + rep movsb + pop ax + push di + popa +; read rest of folder + mov esi, dword [lb_per_sec] + add eax, esi + dec si + not si + and ax, si + mov si, word [bx+10] + mov bx, di + pop di + sub si, bx + jbe @f + mov [cur_limit], esi + call read_many_bytes + pop si + jnc .scan + jmp .readerr +@@: + pop si +.scan: +; now we have required cache item; append it to the end of list + mov bx, [cachelist.tail] + mov [cachelist.tail], di + mov [di+2], bx + mov word [di], cachelist + mov [bx], di +; scan for given filename + mov es, [di+10] + mov dx, [di+8] + pop ds + xor bx, bx + call scan_for_filename_in_sector +.scandone: + push cs + pop es + mov bx, 2000h + cmp bx, [es:cur_desc_end] + jnz filefound +j_notfound: + jmp path_table_notfound +filefound: +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jnz @b +@@: + mov cl, [es:bx+8] + test al, al + jz @f +; parse next component of file name + test cl, 2 ; directory? + jz j_notfound + mov eax, [es:bx] + pop di + jmp parse_dir +@@: + test cl, 2 ; directory? + jnz j_notfound ; do not allow read directories as regular files +; ok, now load the file + pop di + les bx, [di] + call normalize + movzx esi, word [di+4] ; esi = limit in 4K blocks + shl esi, 12 ; esi = limit in bytes + push cs + pop ds + mov [cur_limit], esi + mov di, 2000h +loadloop: + and [cur_start], 0 +.loadnew: + mov esi, [cur_limit] + mov eax, [cur_start] + add esi, eax + mov [overflow], 1 + sub esi, [di+4] + jb @f + xor esi, esi + dec [overflow] +@@: + add esi, [di+4] ; esi = number of bytes to read + mov [cur_start], esi + sub esi, eax + jz .loadcontinue + xor edx, edx + div dword [lb_size] ; eax = number of logical blocks to skip, + mov [first_byte], dx; [first_byte] = number of bytes to skip in 1st block + cmp byte [di+10], 0 + jnz .interleaved + add eax, [di] +; read esi bytes from logical block eax to buffer es:bx + call read_many_bytes.with_first + jc .readerr3 +.loadcontinue: + mov [cur_chunk], di + add di, 11 + cmp di, [cur_desc_end] + jae @f + cmp [cur_limit], 0 + jnz loadloop +@@: + mov bx, [overflow] +.calclen: +; calculate length of file + xor ax, ax + xor dx, dx + mov di, 2000h +@@: + add ax, [di+4] + adc dx, [di+6] + add di, 11 + cmp di, [cur_desc_end] + jb @b + ret +.interleaved: + mov [cur_unit_limit], esi + push esi +; skip first blocks + movzx ecx, byte [di+9] ; Unit Size + movzx esi, byte [di+10] ; Interleave Gap + add si, cx + mov edx, [di] +@@: + sub eax, ecx + jb @f + add edx, esi + jmp @b +@@: + add ecx, eax ; ecx = number of logical blocks to skip + lea eax, [ecx+edx] ; eax = first logical block + pop esi +.interleaved_loop: +; get number of bytes in current file unit + push eax + movzx eax, byte [di+9] + sub ax, cx + imul eax, dword [lb_size] + cmp eax, esi + ja .i2 +.i1: + xchg esi, eax +.i2: + pop eax + sub [cur_unit_limit], esi + push eax +; read esi bytes from logical block eax to buffer es:bx + call read_many_bytes.with_first + pop eax + jnc @f +.readerr3: + mov bx, 3 + jmp .calclen +@@: + mov esi, [cur_unit_limit] + test esi, esi + jz .loadcontinue + movzx ecx, byte [di+9] ; add Unit Size + add cl, byte [di+10] ; add Interleave Gap + adc ch, 0 + add eax, ecx + xor cx, cx + mov [first_byte], cx + jmp .interleaved_loop + +cx_to_sectors: + add cx, 7FFh + rcr cx, 1 + shr cx, 10 + ret + +is_last_component: +; in: ds:si -> name +; out: CF set <=> current component is not last (=> folder) + push si +@@: + lodsb + test al, al + jz @f + cmp al, '/' + jnz @b + stc +@@: + pop si + ret + +test_filename1: +; in: ds:si -> filename, es:di -> path table item +; out: CF set <=> no match + pusha + mov cl, [es:di] + add di, 8 + jmp test_filename2.start +test_filename2: +; in: ds:si -> filename, es:bx -> directory item +; out: CF set <=> no match + pusha + mov cl, [es:bx+32] + lea di, [bx+33] +.start: + mov ch, 0 +@@: + lodsb + test al, al + jz .test1 + cmp al, '/' + jz .test1 + call toupper + mov ah, al + mov al, [es:di] + call toupper + inc di + cmp al, ah + loopz @b + jnz .next1 +; if we have reached this point: current name is done + lodsb + test al, al + jz .ret + cmp al, '/' + jz .ret +; if we have reached this point: current name is done, but input name continues +; so they do not match + jmp .next1 +.test1: +; if we have reached this point: input name is done, but current name continues +; "filename.ext;version" in ISO-9660 represents file "filename.ext" +; "filename." and "filename.;version" are also possible for "filename" + cmp byte [es:di], '.' + jnz @f + inc di + dec cx + jz .ret +@@: + cmp byte [es:di], ';' + jnz .next1 + jmp .ret +.next1: + stc +.ret: + popa + ret + +toupper: +; in: al=symbol +; out: al=symbol in uppercase + cmp al, 'a' + jb .ret + cmp al, 'z' + ja .ret + sub al, 'a'-'A' +.ret: + ret + +scan_for_filename_in_sector: +; in: ds:si->filename, es:bx->folder data, dx=limit +; out: CF=0 if found + push bx +.loope: + push bx +.loop: + cmp bx, dx + jae .notfound + cmp byte [es:bx], 0 + jz .loopd + test byte [es:bx+25], 4 ; ignore files with Associated bit + jnz .next + call test_filename2 + jc .next + push ds es di + push es + pop ds + push cs + pop es + mov di, [es:cur_desc_end] + movzx eax, byte [bx+1] + add eax, [bx+2] + stosd ; first logical block + mov eax, [bx+10] + stosd ; length + mov al, [bx+25] + stosb ; flags + mov ax, [bx+26] + stosw ; File Unit size, Interleave Gap size + mov [es:cur_desc_end], di + cmp di, 3000h + pop di es ds + jae .done + test byte [es:bx+25], 80h + jz .done +.next: + add bl, [es:bx] + adc bh, 0 + jmp .loop +.loopd: + mov ax, bx + pop bx +@@: + add bx, [cs:lb_size] + jz .done2 + cmp bx, ax + jb @b + jmp .loope +.notfound: + stc +.done: + pop bx +.done2: + pop bx + ret + +lb_to_sector: + xor edx, edx + div dword [lb_per_sec] + ret + +load_phys_sector_for_lb_force: +; in: eax = logical block, ds=0 +; in: si=0 - accept 0 logical blocks, otherwise force read at least 1 +; out: 0000:1000 = physical sector data; si -> logical block +; out: eax = next physical sector +; out: CF=1 if read error +; destroys cx +; this procedure reads 0-3 or 1-4 logical blocks, up to the end of physical sector + call lb_to_sector + or si, dx + jnz @f + mov si, 1800h + jmp .done +@@: + mov si, 1000h + imul dx, [lb_size] + add si, dx + mov cx, 1 + push es bx + push ds + pop es + mov bx, 1000h + call read_sectors + pop bx es + inc eax +.done: + ret + +normalize: +; in: es:bx = far pointer +; out: es:bx = normalized pointer (i.e. 0 <= bx < 0x10) + push ax bx + mov ax, es + shr bx, 4 + add ax, bx + mov es, ax + pop bx ax + and bx, 0x0F + ret + +read_many_bytes: + and [first_byte], 0 +read_many_bytes.with_first: +; read esi bytes from logical block dx:ax to buffer es:bx +; out: CF=1 <=> disk error + push di +; load first physical sector + push bx si + mov si, [first_byte] + call load_phys_sector_for_lb_force + jnc @f + pop si bx +.ret: + pop di + ret +@@: + add si, [first_byte] + mov ecx, 1800h + sub cx, si + mov ebx, esi + pop bx + sub ebx, ecx + jnc @f + add cx, bx + xor ebx, ebx +@@: + pop di + sub [cur_limit], ecx + rep movsb + mov esi, ebx + mov bx, di + call normalize +; load other physical sectors +; read esi bytes from physical sector eax to buffer es:bx + test esi, esi + jz .ret + push esi + add esi, 0x7FF + and si, not 0x7FF + cmp esi, [cur_limit] + jbe .okplace +.noplace: + sub esi, 800h +.okplace: + shr esi, 11 ; si = number of sectors + mov cx, si + jz @f + call read_sectors +@@: + pop esi + jc .ret + movzx ecx, cx + add eax, ecx + shl ecx, 11 + sub [cur_limit], ecx + sub esi, ecx + jc .big + jz .nopost + push bx es + push ds + pop es + mov bx, 1000h + mov cx, 1 + call read_sectors + pop es di + jc .ret2 + mov cx, si + mov si, 1000h + sub word [cur_limit], cx + sbb word [cur_limit+2], 0 + rep movsb + mov bx, di + call normalize +.nopost: + clc +.ret2: + pop di + ret +.big: + mov ax, es + sub ax, 80h + mov es, ax + add bx, 800h + add bx, si + call normalize + sub [cur_limit], esi + jmp .nopost + +; Callback function for secondary loader +callback: +; in: ax = function number; only function 1 is defined for now + dec ax + jz callback_readfile + dec ax + jz callback_continueread + stc ; unsupported function + retf + +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call load_file + clc ; function is supported + retf + +callback_continueread: +; function 2: continue to read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=3 - read error +; out: dx:ax = file size + les bx, [di] + call normalize + movzx esi, word [di+4] ; si = limit in 4K blocks + shl esi, 12 ; bp:si = limit in bytes + push cs + pop ds + mov [cur_limit], esi + mov di, [cur_chunk] + call loadloop.loadnew + clc ; function is supported + retf + +secondary_loader_info: + dw 0, 0x1000 + dw 0x30000 / 0x1000 + db 'kord/loader',0 +aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 + +align 2 +cachelist: +.head dw cachelist +.tail dw cachelist +free_cache_item dw 0 +last_cache_item dw 0x8400 + +use_path_table db 0 +bootdrive db ? +align 2 +lb_size dw ? ; Logical Block size in bytes + dw 0 ; to allow access dword [lb_size] +lb_per_sec dw ? ; Logical Blocks per physical sector + dw 0 ; to allow access dword [lb_per_sec] +free_ptr dw ? ; first free block in cache (cache block = sector = 0x800 bytes) +size_rest dw ? ; free space in cache (in blocks) +cache_size dw ? +cache_start dw ? +pathtable_size dw ? +pathtable_start dw ? +root_location dd ? +cur_desc_end dw ? +cur_nocache_len dd ? +cur_limit dd ? +cur_unit_limit dd ? +overflow dw ? +cur_chunk dw ? +first_byte dw ? +cur_start dd ? + +;times 83FEh-$ db 0 + db 43h +; just to make file 2048 bytes long :) + db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' + + dw 0xAA55 ; this is not required for CD, but to be consistent... diff --git a/kernel/trunk/sec_loader/trunk/boot/fat1x/bootsect.asm b/kernel/trunk/sec_loader/trunk/boot/fat1x/bootsect.asm index 772829f06..9b84a85e8 100644 --- a/kernel/trunk/sec_loader/trunk/boot/fat1x/bootsect.asm +++ b/kernel/trunk/sec_loader/trunk/boot/fat1x/bootsect.asm @@ -1,392 +1,392 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -use_lba = 0 - org 0x7C00 - jmp start - nop -; FAT parameters, BPB -; note: they can be changed at install, replaced with real values -; these settings are for most typical 1.44M floppies - db 'KOLIBRI ' ; BS_OEMName, ignored - dw 200h ; BPB_BytsPerSec -BPB_SecsPerClus db 1 -BPB_RsvdSecCnt dw 1 -BPB_NumFATs db 2 -BPB_RootEntCnt dw 0xE0 - dw 2880 ; BPB_TotSec16 - db 0xF0 ; BPB_Media -BPB_FATSz16 dw 9 -BPB_SecPerTrk dw 18 -BPB_NumHeads dw 2 -BPB_HiddSec dd 0 - dd 0 ; BPB_TotSec32 -BS_DrvNum db 0 - db 0 ; BS_Reserved1 - db ')' ; BS_BootSig - dd 12344321h ; BS_VolID -filename: - db 'KORD.OS ' ; BS_VolLab - db 'FAT12 ' ; BS_FilSysType -; Used memory map: -; 8000:0000 - current directory -; 9000:0000 - root directory data [cached] -start: - xor ax, ax - mov ss, ax - mov sp, 0x7C00 - mov ds, ax - mov bp, sp - cld - sti - mov [bp+BS_DrvNum-0x7C00], dl -if use_lba - mov ah, 41h - mov bx, 55AAh - int 13h - mov si, aNoLBA - jc err_ - cmp bx, 0AA55h - jnz err_ - test cx, 1 - jz err_ -else - mov ah, 8 - int 13h - jc @f ; on error, assume that BPB geometry is valid - mov al, dh - mov ah, 0 - inc ax - mov [bp+BPB_NumHeads-0x7C00], ax - and cx, 3Fh - mov [bp+BPB_SecPerTrk-0x7C00], cx -@@: -end if -; get FAT parameters - xor bx, bx - mov al, [bp+BPB_NumFATs-0x7C00] - mov ah, 0 - mul [bp+BPB_FATSz16-0x7C00] - add ax, [bp+BPB_RsvdSecCnt-0x7C00] - adc dx, bx - push dx - push ax ; root directory start = dword [bp-4] - mov cx, [bp+BPB_RootEntCnt-0x7C00] - add cx, 0xF - rcr cx, 1 - shr cx, 3 ; cx = size of root directory in sectors - add ax, cx - adc dx, bx - push dx - push ax ; data start = dword [bp-8] -; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) - cmp cx, 0x10 - jb @f - mov cx, 0x10 -@@: - mov ax, [bp-4] - mov dx, [bp-2] - push 0x9000 - pop es - call read_sectors - add word [bp-4], cx ; dword [bp-4] = start of non-cached root data - adc word [bp-2], bx -; load kordldr.f12 - mov si, main_loader - call lookup_in_root_dir - jc noloader - test byte [es:di+11], 10h ; directory? - jz kordldr_ok -noloader: - mov si, aLoaderNotFound -err_: - call out_string - mov si, aPressAnyKey - call out_string - xor ax, ax - int 16h - int 18h - jmp $ -kordldr_ok: - mov ax, [es:di+26] ; get file cluster - mov bx, 0x7E00 - xor cx, cx - mov es, cx - sub ax, 2 - jc noloader - push bx ; save return address: bx = 7E00 - mov cl, [bp+BPB_SecsPerClus-0x7C00] - mul cx -; fall through - 'ret' in read_sectors will return to 7E00 - -read_sectors2: -; same as read_sectors, but dx:ax is relative to start of data - add ax, [bp-8] - adc dx, [bp-6] -read_sectors: -; ss:bp = 0:7C00 -; es:bx = pointer to data -; dx:ax = first sector -; cx = number of sectors - pusha - add ax, word [bp+BPB_HiddSec-0x7C00] - adc dx, word [bp+BPB_HiddSec+2-0x7C00] -if use_lba - push ds -do_read_sectors: - push ax - push cx - push dx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - push 0 - push 0 - push dx - push ax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [bp+BS_DrvNum-0x7C00] - mov ah, 42h - int 13h - mov si, aReadError - jc err_ -; restore stack - add sp, 10h -; increase current sector & buffer; decrease number of sectors - mov si, cx - mov ax, es - shl cx, 5 - add ax, cx - mov es, ax - pop dx - pop cx - pop ax - add ax, si - adc dx, 0 - sub cx, si - jnz do_read_sectors - pop ds - popa - ret -else -do_read_sectors: - pusha - pop di - push bx - -; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx - mov si, ax - xchg ax, dx - xor dx, dx - div [bp+BPB_SecPerTrk-0x7C00] - push ax - mov ax, si - div [bp+BPB_SecPerTrk-0x7C00] - mov bx, dx ; bx=sector-1 - pop dx - -; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx - div [bp+BPB_NumHeads-0x7C00] - -; number of sectors: read no more than to end of track - push bx - sub bx, [bp+BPB_SecPerTrk-0x7C00] - neg bx - cmp cx, bx - jbe @f - mov cx, bx -@@: - pop bx - - inc bx -; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format - mov di, cx - mov dh, dl - mov dl, [bp+BS_DrvNum-0x7C00] - shl ah, 6 - mov ch, al - mov al, cl - mov cl, bl - or cl, ah - pop bx - mov si, 3 - mov ah, 2 -@@: - push ax - int 13h - jnc @f - xor ax, ax - int 13h ; reset drive - pop ax - dec si - jnz @b - mov si, aReadError - jmp err_ -@@: - pop ax - mov ax, es - mov cx, di - shl cx, 5 - add ax, cx - mov es, ax - push di - popa - add ax, di - adc dx, 0 - sub cx, di - jnz do_read_sectors - popa - ret -end if - -scan_for_filename: -; in: ds:si -> 11-bytes FAT name -; in: es:0 -> part of directory data -; in: cx = number of entries -; out: if found: CF=0, ZF=1, es:di -> directory entry -; out: if not found, but continue required: CF=1 and ZF=0 -; out: if not found and zero item reached: CF=1 and ZF=1 - xor di, di - push cx -sloop: - cmp byte [es:di], 0 - jz snotfound - test byte [es:di+11], 8 ; volume label? - jnz scont ; ignore volume labels - pusha - mov cx, 11 - repz cmpsb - popa - jz sdone -scont: - add di, 0x20 - loop sloop - inc cx ; clear ZF flag -snotfound: - stc -sdone: - pop cx -lrdret: - ret - -lookup_in_root_dir: -; ss:bp = 0:7C00 -; in: ds:si -> 11-bytes FAT name -; out: if found: CF=0, es:di -> directory entry -; out: if not found: CF=1 - mov cx, [bp+BPB_RootEntCnt-0x7C00] - push cx -; first, look in root directory cache - push 0x9000 - pop es - test ch, ch - jz @f - mov cx, 0x100 -@@: - mov ax, [bp-4] - mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory -lrdloop: - call scan_for_filename - pop bx - jz lrdret - sub bx, cx - mov cx, bx - stc - jz lrdret -; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries - push cx - cmp ch, 0x8 - jb @f - mov cx, 0x800 -@@: - push 0x8000 - pop es - push cx - push es - xor bx, bx - add cx, 0xF - shr cx, 4 - call read_sectors - pop es - add ax, cx - adc dx, bx - pop cx - jmp lrdloop - -out_string: -; in: ds:si -> ASCIIZ string - lodsb - test al, al - jz lrdret - mov ah, 0Eh - mov bx, 7 - int 10h - jmp out_string - -aReadError db 'Read error',0 -if use_lba -aNoLBA db 'The drive does not support LBA!',0 -end if -aLoaderNotFound db 'Loader not found',0 -aPressAnyKey db 13,10,'Press any key...',13,10,0 -main_loader db 'KORDLDR F1X' - -if use_lba - db 0 ; make bootsector 512 bytes in length -end if - -; bootsector signature - dw 0xAA55 - -; display offsets of all procedures used by kordldr.f12.asm -macro show [procedure] -{ - bits = 16 - display `procedure,' = ' - repeat bits/4 - d = '0' + procedure shr (bits - %*4) and 0Fh - if d > '9' - d = d + 'A'-'9'-1 - end if - display d - end repeat - display 13,10 -} - -show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +use_lba = 0 + org 0x7C00 + jmp start + nop +; FAT parameters, BPB +; note: they can be changed at install, replaced with real values +; these settings are for most typical 1.44M floppies + db 'KOLIBRI ' ; BS_OEMName, ignored + dw 200h ; BPB_BytsPerSec +BPB_SecsPerClus db 1 +BPB_RsvdSecCnt dw 1 +BPB_NumFATs db 2 +BPB_RootEntCnt dw 0xE0 + dw 2880 ; BPB_TotSec16 + db 0xF0 ; BPB_Media +BPB_FATSz16 dw 9 +BPB_SecPerTrk dw 18 +BPB_NumHeads dw 2 +BPB_HiddSec dd 0 + dd 0 ; BPB_TotSec32 +BS_DrvNum db 0 + db 0 ; BS_Reserved1 + db ')' ; BS_BootSig + dd 12344321h ; BS_VolID +filename: + db 'KORD.OS ' ; BS_VolLab + db 'FAT12 ' ; BS_FilSysType +; Used memory map: +; 8000:0000 - current directory +; 9000:0000 - root directory data [cached] +start: + xor ax, ax + mov ss, ax + mov sp, 0x7C00 + mov ds, ax + mov bp, sp + cld + sti + mov [bp+BS_DrvNum-0x7C00], dl +if use_lba + mov ah, 41h + mov bx, 55AAh + int 13h + mov si, aNoLBA + jc err_ + cmp bx, 0AA55h + jnz err_ + test cx, 1 + jz err_ +else + mov ah, 8 + int 13h + jc @f ; on error, assume that BPB geometry is valid + mov al, dh + mov ah, 0 + inc ax + mov [bp+BPB_NumHeads-0x7C00], ax + and cx, 3Fh + mov [bp+BPB_SecPerTrk-0x7C00], cx +@@: +end if +; get FAT parameters + xor bx, bx + mov al, [bp+BPB_NumFATs-0x7C00] + mov ah, 0 + mul [bp+BPB_FATSz16-0x7C00] + add ax, [bp+BPB_RsvdSecCnt-0x7C00] + adc dx, bx + push dx + push ax ; root directory start = dword [bp-4] + mov cx, [bp+BPB_RootEntCnt-0x7C00] + add cx, 0xF + rcr cx, 1 + shr cx, 3 ; cx = size of root directory in sectors + add ax, cx + adc dx, bx + push dx + push ax ; data start = dword [bp-8] +; load start of root directory (no more than 0x2000 bytes = 0x10 sectors) + cmp cx, 0x10 + jb @f + mov cx, 0x10 +@@: + mov ax, [bp-4] + mov dx, [bp-2] + push 0x9000 + pop es + call read_sectors + add word [bp-4], cx ; dword [bp-4] = start of non-cached root data + adc word [bp-2], bx +; load kordldr.f12 + mov si, main_loader + call lookup_in_root_dir + jc noloader + test byte [es:di+11], 10h ; directory? + jz kordldr_ok +noloader: + mov si, aLoaderNotFound +err_: + call out_string + mov si, aPressAnyKey + call out_string + xor ax, ax + int 16h + int 18h + jmp $ +kordldr_ok: + mov ax, [es:di+26] ; get file cluster + mov bx, 0x7E00 + xor cx, cx + mov es, cx + sub ax, 2 + jc noloader + push bx ; save return address: bx = 7E00 + mov cl, [bp+BPB_SecsPerClus-0x7C00] + mul cx +; fall through - 'ret' in read_sectors will return to 7E00 + +read_sectors2: +; same as read_sectors, but dx:ax is relative to start of data + add ax, [bp-8] + adc dx, [bp-6] +read_sectors: +; ss:bp = 0:7C00 +; es:bx = pointer to data +; dx:ax = first sector +; cx = number of sectors + pusha + add ax, word [bp+BPB_HiddSec-0x7C00] + adc dx, word [bp+BPB_HiddSec+2-0x7C00] +if use_lba + push ds +do_read_sectors: + push ax + push cx + push dx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + push 0 + push 0 + push dx + push ax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [bp+BS_DrvNum-0x7C00] + mov ah, 42h + int 13h + mov si, aReadError + jc err_ +; restore stack + add sp, 10h +; increase current sector & buffer; decrease number of sectors + mov si, cx + mov ax, es + shl cx, 5 + add ax, cx + mov es, ax + pop dx + pop cx + pop ax + add ax, si + adc dx, 0 + sub cx, si + jnz do_read_sectors + pop ds + popa + ret +else +do_read_sectors: + pusha + pop di + push bx + +; (dword in dx:ax) / (SectorsPerTrack) -> (dword in dx:ax), remainder bx + mov si, ax + xchg ax, dx + xor dx, dx + div [bp+BPB_SecPerTrk-0x7C00] + push ax + mov ax, si + div [bp+BPB_SecPerTrk-0x7C00] + mov bx, dx ; bx=sector-1 + pop dx + +; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx + div [bp+BPB_NumHeads-0x7C00] + +; number of sectors: read no more than to end of track + push bx + sub bx, [bp+BPB_SecPerTrk-0x7C00] + neg bx + cmp cx, bx + jbe @f + mov cx, bx +@@: + pop bx + + inc bx +; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format + mov di, cx + mov dh, dl + mov dl, [bp+BS_DrvNum-0x7C00] + shl ah, 6 + mov ch, al + mov al, cl + mov cl, bl + or cl, ah + pop bx + mov si, 3 + mov ah, 2 +@@: + push ax + int 13h + jnc @f + xor ax, ax + int 13h ; reset drive + pop ax + dec si + jnz @b + mov si, aReadError + jmp err_ +@@: + pop ax + mov ax, es + mov cx, di + shl cx, 5 + add ax, cx + mov es, ax + push di + popa + add ax, di + adc dx, 0 + sub cx, di + jnz do_read_sectors + popa + ret +end if + +scan_for_filename: +; in: ds:si -> 11-bytes FAT name +; in: es:0 -> part of directory data +; in: cx = number of entries +; out: if found: CF=0, ZF=1, es:di -> directory entry +; out: if not found, but continue required: CF=1 and ZF=0 +; out: if not found and zero item reached: CF=1 and ZF=1 + xor di, di + push cx +sloop: + cmp byte [es:di], 0 + jz snotfound + test byte [es:di+11], 8 ; volume label? + jnz scont ; ignore volume labels + pusha + mov cx, 11 + repz cmpsb + popa + jz sdone +scont: + add di, 0x20 + loop sloop + inc cx ; clear ZF flag +snotfound: + stc +sdone: + pop cx +lrdret: + ret + +lookup_in_root_dir: +; ss:bp = 0:7C00 +; in: ds:si -> 11-bytes FAT name +; out: if found: CF=0, es:di -> directory entry +; out: if not found: CF=1 + mov cx, [bp+BPB_RootEntCnt-0x7C00] + push cx +; first, look in root directory cache + push 0x9000 + pop es + test ch, ch + jz @f + mov cx, 0x100 +@@: + mov ax, [bp-4] + mov dx, [bp-2] ; dx:ax = starting sector of not cached data of root directory +lrdloop: + call scan_for_filename + pop bx + jz lrdret + sub bx, cx + mov cx, bx + stc + jz lrdret +; read no more than 0x10000 bytes, or 0x10000/0x20 = 0x800 entries + push cx + cmp ch, 0x8 + jb @f + mov cx, 0x800 +@@: + push 0x8000 + pop es + push cx + push es + xor bx, bx + add cx, 0xF + shr cx, 4 + call read_sectors + pop es + add ax, cx + adc dx, bx + pop cx + jmp lrdloop + +out_string: +; in: ds:si -> ASCIIZ string + lodsb + test al, al + jz lrdret + mov ah, 0Eh + mov bx, 7 + int 10h + jmp out_string + +aReadError db 'Read error',0 +if use_lba +aNoLBA db 'The drive does not support LBA!',0 +end if +aLoaderNotFound db 'Loader not found',0 +aPressAnyKey db 13,10,'Press any key...',13,10,0 +main_loader db 'KORDLDR F1X' + +if use_lba + db 0 ; make bootsector 512 bytes in length +end if + +; bootsector signature + dw 0xAA55 + +; display offsets of all procedures used by kordldr.f12.asm +macro show [procedure] +{ + bits = 16 + display `procedure,' = ' + repeat bits/4 + d = '0' + procedure shr (bits - %*4) and 0Fh + if d > '9' + d = d + 'A'-'9'-1 + end if + display d + end repeat + display 13,10 +} + +show read_sectors, read_sectors2, lookup_in_root_dir, scan_for_filename, err_, noloader diff --git a/kernel/trunk/sec_loader/trunk/boot/fat1x/kordldr.f1x.asm b/kernel/trunk/sec_loader/trunk/boot/fat1x/kordldr.f1x.asm index 6f2348ae6..92a851c36 100644 --- a/kernel/trunk/sec_loader/trunk/boot/fat1x/kordldr.f1x.asm +++ b/kernel/trunk/sec_loader/trunk/boot/fat1x/kordldr.f1x.asm @@ -1,667 +1,668 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - - org 0x7E00 -; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here -; ss:bp = 0:7C00 -virtual at bp - rb 3 ; BS_jmpBoot - rb 8 ; BS_OEMName, ignored - dw ? ; BPB_BytsPerSec -BPB_SecsPerClus db ? -BPB_RsvdSecCnt dw ? -BPB_NumFATs db ? -BPB_RootEntCnt dw ? -BPB_TotSec16 dw ? - db ? ; BPB_Media -BPB_FATSz16 dw ? -BPB_SecPerTrk dw ? -BPB_NumHeads dw ? -BPB_HiddSec dd ? -BPB_TotSec32 dd ? -BS_DrvNum db ? -fat_type db ? ; this is BS_Reserved1, - ; we use it to save FS type: 0=FAT12, 1=FAT16 - db ? ; BS_BootSig -num_sectors dd ? ; BS_VolID -; rb 11 ; BS_VolLab -; rb 3 ; BS_FilSysType, first 3 bytes -read_sectors dw ? -read_sectors2 dw ? -lookup_in_root_dir dw ? -scan_for_filename dw ? -err_ dw ? -noloader dw ? -cachelimit dw ? -filesize: ; will be used to save file size - rb 5 ; BS_FilSysType, last 5 bytes -; following variables are located in the place of starting code; -; starting code is no more used at this point -sect_per_clus dw ? -cur_cluster dw ? -next_cluster dw ? -flags dw ? -cur_delta dd ? -end virtual - -; procedures from boot sector -; LBA version -lba_read_sectors = 7CE2h -lba_read_sectors2 = 7CDCh -lba_lookup_in_root_dir = 7D4Fh -lba_scan_for_filename = 7D2Dh -lba_err = 7CB5h -lba_noloader = 7CB2h -; CHS version -chs_read_sectors = 7CDEh -chs_read_sectors2 = 7CD8h -chs_lookup_in_root_dir = 7D70h -chs_scan_for_filename = 7D4Eh -chs_err = 7CB1h -chs_noloader = 7CAEh - - push ax cx ; save our position on disk - push ss - pop es -; determine version of bootsector (LBA vs CHS) -; mov [read_sectors], chs_read_sectors -; mov [read_sectors2], chs_read_sectors2 -; mov [lookup_in_root_dir], chs_lookup_in_root_dir -; mov [scan_for_filename], chs_scan_for_filename -; mov [err], chs_err -; mov [noloader], chs_noloader - lea di, [read_sectors] - mov si, chs_proc_addresses - mov cx, 6*2 - cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' - jz @f - add si, cx -; mov [read_sectors], lba_read_sectors -; mov [read_sectors2], lba_read_sectors2 -; mov [lookup_in_root_dir], lba_lookup_in_root_dir -; mov [scan_for_filename], lba_scan_for_filename -; mov [err], lba_err -; mov [noloader], lba_noloader -@@: - rep movsb - mov cl, [BPB_SecsPerClus] - mov [sect_per_clus], cx - xor bx, bx -; determine size of cache for folders - int 12h ; ax = size of available base memory in Kb - sub ax, 94000h / 1024 - jae @f -nomem: - mov si, nomem_str - jmp [err_] -@@: - shr ax, 3 - mov [cachelimit], ax ; size of cache - 1 -; get type of file system - FAT12 or FAT16? -; calculate number of clusters - mov ax, [BPB_TotSec16] - xor dx, dx - test ax, ax - jnz @f - mov ax, word [BPB_TotSec32] - mov dx, word [BPB_TotSec32+2] -@@: - sub ax, [bp-8] ; dword [bp-8] = first data sector - sbb dx, [bp-6] - jb j_noloader - div [sect_per_clus] -; ax = number of clusters -; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes - mov [fat_type], ch - cmp ax, 0xFF5 - jb init_fat12 - inc [fat_type] -init_fat16: -; no sectors loaded - mov di, 0x8200 - xor ax, ax - mov cx, 0x100/2 - rep stosw - jmp init_fat_done -init_fat12: -; read FAT - push 0x6000 - pop es - mov ax, [BPB_RsvdSecCnt] - mov cx, [BPB_FATSz16] - cmp cx, 12 - jb @f - mov cx, 12 -@@: - xor dx, dx - call [read_sectors] -init_fat_done: -; if cluster = sector, we need to read second part of our file -; (bootsector loads only first cluster of kordldr.f1x) - pop cx ax ; restore our position on disk - cmp cx, 1 - ja kordldr_full - sub ax, [bp-8] - inc ax - inc ax ; ax = first cluster of kordldr.f12 - call get_next_cluster - jc @f -j_noloader: - jmp [noloader] -@@: - dec ax - dec ax - push 0x800 - pop es - call [read_sectors2] -kordldr_full: -; ...continue loading... - mov di, secondary_loader_info - call load_file - test bx, bx - mov bx, [err_] - jz @f - mov si, aKernelNotFound - jmp bx -@@: -; for subsequent calls to callback function, hook error handler -; mov byte [bx], 0xE9 ; 'jmp' opcode -; mov ax, hooked_err - 3 -; sub ax, bx -; mov word [bx+1], ax -; push hooked_err / ret - mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) - mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) -; set registers for secondary loader - mov ah, [BS_DrvNum] - mov al, 'f' - test ah, ah - jns @f - sub ah, 80h - mov al, 'h' -@@: - mov bx, '12' - cmp [fat_type], 0 - jz @f - mov bh, '6' -@@: - mov si, callback ; ds:si = far pointer to callback procedure - jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 - -nomem_str db 'No memory',0 - -chs_proc_addresses: - dw chs_read_sectors - dw chs_read_sectors2 - dw chs_lookup_in_root_dir - dw chs_scan_for_filename - dw chs_err - dw chs_noloader -lba_proc_addresses: - dw lba_read_sectors - dw lba_read_sectors2 - dw lba_lookup_in_root_dir - dw lba_scan_for_filename - dw lba_err - dw lba_noloader - -get_next_cluster: -; in: ax = cluster -; out: if there is next cluster: CF=1, ax = next cluster -; out: if there is no next cluster: CF=0 - push si - cmp [fat_type], 0 - jnz gnc16 -; for FAT12 - push ds - push 0x6000 - pop ds - mov si, ax - shr si, 1 - add si, ax - test al, 1 - lodsw - jz @f - shr ax, 4 -@@: - and ax, 0xFFF - cmp ax, 0xFF7 - pop ds si - ret -; for FAT16 -gnc16: -; each sector contains 200h bytes = 100h FAT entries -; so ah = # of sector, al = offset in sector - mov si, ax - mov ah, 0 - shr si, 8 -; calculate segment for this sector of FAT table -; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) -; segment = 6000 + 20*si, offset = 0 - push es - push si - shl si, 5 - add si, 0x6000 - mov es, si - pop si - cmp byte [ss:0x8200+si], ah ; sector already loaded? - jnz @f -; load corresponding sector - pusha - push es - xor bx, bx - mov ax, [BPB_RsvdSecCnt] - xor dx, dx - add ax, si - adc dx, bx - mov cx, 1 ; read 1 sector - call [read_sectors] - pop es - popa -@@: - mov si, ax - add si, si -; mov ax, [es:si] - lods word [es:si] - pop es - cmp ax, 0xFFF7 - pop si - ret - -if $ > 0x8000 -error 'get_next_cluster must fit in first sector of kordldr.f1x!' -end if - -load_file: -; in: ss:bp = 0:7C00 -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) - xor ax, ax ; start from root directory - mov dx, -1 - mov word [filesize], dx - mov word [filesize+2], dx ; initialize file size with invalid value - lea si, [di+6] -parse_dir_loop: -; convert name to FAT name - push di - push ax - push ss - pop es -; convert ASCIIZ filename to FAT name - mov di, filename - push di - mov cx, 8+3 - mov al, ' ' - rep stosb - pop di - mov cl, 8 ; 8 symbols per name - mov bl, 1 -nameloop: - lodsb - test al, al - jz namedone - cmp al, '/' - jz namedone - cmp al, '.' - jz namedot - dec cx - js badname - cmp al, 'a' - jb @f - cmp al, 'z' - ja @f - sub al, 'a'-'A' -@@: - stosb - jmp nameloop -namedot: - inc bx - jp badname - add di, cx - mov cl, 3 - jmp nameloop -badname: ; do not make direct js/jp to notfound_pop: - ; this generates long forms of conditional jumps and results in longer code - jmp notfound_pop -namedone: -; scan directory - pop ax ; ax = cluster of directory or 0 for root - push ds - push si - push es - pop ds - mov si, filename ; ds:si -> filename in FAT style - test ax, ax - jnz lookup_in_notroot_dir -; for root directory, use the subroutine from bootsector - call [lookup_in_root_dir] - jmp lookup_done -lookup_in_notroot_dir: -; for other directories, read a folder sector-by-sector and scan -; first, try to use the cache - push ds - push cs - pop ds - mov bx, [cachelimit] - add bx, bx - mov di, foldcache_mark -@@: - mov dx, [foldcache_clus+di-foldcache_mark+bx] - cmp dx, ax - jz cacheok - test dx, dx - jz cacheadd ; the cache has place for new entry - dec bx - dec bx - jns @b -; the folder is not present in the cache, so add it -; the cache is full; find the oldest entry and replace it with the new one - mov dx, [cachelimit] -@@: - inc bx - inc bx - cmp word [di+bx], dx ; marks have values 0 through [cachelimit] - jnz @b -cacheadd: - or word [di+bx], 0xFFFF ; very big value, it will be changed soon - mov [foldcache_clus+di-foldcache_mark+bx], ax - and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet -cacheok: -; update cache marks - mov dx, [di+bx] - mov cx, [foldcache_size+di-foldcache_mark+bx] - mov di, [cachelimit] - add di, di -cacheupdate: - cmp [foldcache_mark+di], dx - adc [foldcache_mark+di], 0 - dec di - dec di - jns cacheupdate - and [foldcache_mark+bx], 0 -; done, bx contains (position in cache)*2 - pop ds -; mov dx, bx -; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 -; add dx, 0x9200 - lea dx, [bx+0x92] - xchg dl, dh - mov es, dx - jcxz not_in_cache - call [scan_for_filename] - jz lookup_done -not_in_cache: -; cache miss, read folder data from disk - mov bx, cx - shr bx, 4 - shl cx, 5 - mov di, cx ; es:di -> free space in cache entry -; external loop: scan clusters -folder_next_cluster: -; internal loop: scan sectors in cluster - mov cx, [sect_per_clus] - push ax - dec ax - dec ax - mul cx - add ax, [bp-8] - adc dx, [bp-6] ; dx:ax = absolute sector -folder_next_sector: -; skip first bx sectors - dec bx - jns folder_skip_sector - push cx - push es di - push 0x8000 - pop es - xor bx, bx - mov cx, 1 - push es - call [read_sectors] -; copy data to the cache... - pop ds - pop di es - cmp di, 0x2000 ; ...if there is free space, of course - jae @f - push si di - mov cx, 0x100 - xor si, si - rep movsw - mov di, es - shr di, 8 - add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache - pop di si -@@: - push es - push 0x8000 - pop es - push cs - pop ds - mov cx, 0x10 - call [scan_for_filename] - pop es - pop cx - jz lookup_done_pop -folder_skip_sector: - inc ax - jnz @f - inc dx -@@: - loop folder_next_sector - pop ax ; ax = current cluster - call get_next_cluster - jc folder_next_cluster - stc - push ax -lookup_done_pop: - pop ax -lookup_done: - pop si - pop ds -; CF=1 <=> failed - jnc found -notfound: - pop di - mov bx, 2 ; file not found - mov ax, 0xFFFF - mov dx, ax ; invalid file size - ret -notfound_pop: - pop ax - jmp notfound -found: - mov ax, [es:di+26] ; get cluster - test byte [es:di+11], 10h ; directory? - jz regular_file - cmp byte [si-1], 0 - jz notfound ; don't read directories as a regular files -; ok, we have found a directory and the caller requested a file into it - pop di - jmp parse_dir_loop ; restart with new cluster in ax -regular_file: - cmp byte [si-1], 0 - jnz notfound ; file does not contain another files -; ok, we have found a regular file and the caller requested it -; save file size - mov dx, [es:di+28] - mov [filesize], dx - mov dx, [es:di+30] - mov [filesize+2], dx - pop di - mov si, [di+4] - shl si, 3 - push si ; [ds:di+4] = limit in 4K blocks - les bx, [di] ; es:bx -> buffer -clusloop: -; ax = first cluster, top of stack contains limit in sectors - mov si, ax ; remember current cluster - xor cx, cx ; cx will contain number of consecutive clusters - mov word [cur_delta], cx - mov word [cur_delta+2], cx - mov di, ax -clusfind: - inc di - inc cx - call get_next_cluster - jnc clusread - cmp ax, di - jz clusfind - stc -clusread: - pop di ; limit in sectors - push ax ; save next cluster - pushf ; save flags -; read cx clusters, starting from si -; calculate number of sectors - xchg ax, cx - mul [sect_per_clus] -; dx:ax = number of sectors; compare with limit - mov word [num_sectors], ax - mov word [num_sectors+2], dx - jmp @f -continue_load_file: - les bx, [di] ; es:bx -> buffer - mov di, [di+4] ; ds:di = limit in 4K blocks - shl di, 3 ; now di = limit in sectors - mov ax, word [num_sectors] - mov dx, word [num_sectors+2] - mov si, [cur_cluster] - push [next_cluster] - push [flags] - or ax, dx - jz nextclus -@@: - test dx, dx - jnz clusdecrease - push dx ; limit was not exceeded - cmp ax, di - jbe @f - pop ax -clusdecrease: - push 1 ; limit was exceeded - mov ax, di -@@: - sub di, ax ; calculate new limit - sub word [num_sectors], ax - sbb word [num_sectors+2], 0 -; calculate starting sector - xchg ax, cx - lea ax, [si-2] - mul [sect_per_clus] - add ax, word [cur_delta] - adc dx, word [cur_delta+2] - add word [cur_delta], cx - adc word [cur_delta+2], 0 -; read - call [read_sectors2] - pop dx -; next cluster? -nextclus: - popf - pop ax - mov [cur_cluster], si - mov [next_cluster], ax - pushf - pop [flags] - jnc @f ; no next cluster => return - mov dl, 1 ; dh=0 in any case - test di, di - jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded - push di - jmp clusloop ; all is ok, continue -hooked_err: - mov sp, 7C00h-12-2 ; restore stack - mov dx, 3 ; return: read error -@@: - mov bx, dx - mov ax, [filesize] - mov dx, [filesize+2] - ret - -; Callback function for secondary loader -callback: -; in: ax = function number; only functions 1 and 2 are defined for now -; save caller's stack - mov dx, ss - mov cx, sp -; set our stack (required because we need ss=0) - xor si, si - mov ss, si - mov sp, 7C00h-8 - mov bp, 7C00h - push dx - push cx -; call our function - stc ; unsupported function - dec ax - jz callback_readfile - dec ax - jnz callback_ret -; function 2: continue loading file -; can be called only after function 1 returned value bx=1 (only part of file was loaded) -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error -; out: dx:ax = file size - call continue_load_file - jmp callback_ret_succ -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call load_file -callback_ret_succ: - clc ; function is supported -callback_ret: -; restore caller's stack - pop cx - pop ss - mov sp, cx -; return to caller - retf - -secondary_loader_info: - dw 0, 0x1000 - dw 0x30000 / 0x1000 - db 'kord/loader',0 -aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 - -foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache -foldcache_mark rw 7 -foldcache_size rw 7 -filename rb 11 -if $ > 0x8200 -error: table overwritten -end if +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + + org 0x7E00 +; the KordOS FAT12/FAT16 bootsector loads first cluster of this file to 0:7E00 and transfers control to here +; ss:bp = 0:7C00 +virtual at bp + rb 3 ; BS_jmpBoot + rb 8 ; BS_OEMName, ignored + dw ? ; BPB_BytsPerSec +BPB_SecsPerClus db ? +BPB_RsvdSecCnt dw ? +BPB_NumFATs db ? +BPB_RootEntCnt dw ? +BPB_TotSec16 dw ? + db ? ; BPB_Media +BPB_FATSz16 dw ? +BPB_SecPerTrk dw ? +BPB_NumHeads dw ? +BPB_HiddSec dd ? +BPB_TotSec32 dd ? +BS_DrvNum db ? +fat_type db ? ; this is BS_Reserved1, + ; we use it to save FS type: 0=FAT12, 1=FAT16 + db ? ; BS_BootSig +num_sectors dd ? ; BS_VolID +; rb 11 ; BS_VolLab +; rb 3 ; BS_FilSysType, first 3 bytes +read_sectors dw ? +read_sectors2 dw ? +lookup_in_root_dir dw ? +scan_for_filename dw ? +err_ dw ? +noloader dw ? +cachelimit dw ? +filesize: ; will be used to save file size + rb 5 ; BS_FilSysType, last 5 bytes +; following variables are located in the place of starting code; +; starting code is no more used at this point +sect_per_clus dw ? +cur_cluster dw ? +next_cluster dw ? +flags dw ? +cur_delta dd ? +end virtual + +; procedures from boot sector +; LBA version +lba_read_sectors = 7CE2h +lba_read_sectors2 = 7CDCh +lba_lookup_in_root_dir = 7D4Fh +lba_scan_for_filename = 7D2Dh +lba_err = 7CB5h +lba_noloader = 7CB2h +; CHS version +chs_read_sectors = 7CDEh +chs_read_sectors2 = 7CD8h +chs_lookup_in_root_dir = 7D70h +chs_scan_for_filename = 7D4Eh +chs_err = 7CB1h +chs_noloader = 7CAEh + + push ax cx ; save our position on disk + push ss + pop es +; determine version of bootsector (LBA vs CHS) +; mov [read_sectors], chs_read_sectors +; mov [read_sectors2], chs_read_sectors2 +; mov [lookup_in_root_dir], chs_lookup_in_root_dir +; mov [scan_for_filename], chs_scan_for_filename +; mov [err], chs_err +; mov [noloader], chs_noloader + lea di, [read_sectors] + mov si, chs_proc_addresses + mov cx, 6*2 + cmp word [chs_scan_for_filename], 0xFF31 ; 'xor di,di' + jz @f + add si, cx +; mov [read_sectors], lba_read_sectors +; mov [read_sectors2], lba_read_sectors2 +; mov [lookup_in_root_dir], lba_lookup_in_root_dir +; mov [scan_for_filename], lba_scan_for_filename +; mov [err], lba_err +; mov [noloader], lba_noloader +@@: + rep movsb + mov cl, [BPB_SecsPerClus] + mov [sect_per_clus], cx + xor bx, bx +; determine size of cache for folders + int 12h ; ax = size of available base memory in Kb + sub ax, 94000h / 1024 + jae @f +nomem: + mov si, nomem_str + jmp [err_] +@@: + shr ax, 3 + mov [cachelimit], ax ; size of cache - 1 +; get type of file system - FAT12 or FAT16? +; calculate number of clusters + mov ax, [BPB_TotSec16] + xor dx, dx + test ax, ax + jnz @f + mov ax, word [BPB_TotSec32] + mov dx, word [BPB_TotSec32+2] +@@: + sub ax, [bp-8] ; dword [bp-8] = first data sector + sbb dx, [bp-6] + jb j_noloader + div [sect_per_clus] +; ax = number of clusters +; note: this is loader for FAT12/FAT16, so 'div' does not overflow on correct volumes + mov [fat_type], ch + cmp ax, 0xFF5 + jb init_fat12 + inc [fat_type] +init_fat16: +; no sectors loaded + mov di, 0x8200 + xor ax, ax + mov cx, 0x100/2 + rep stosw + jmp init_fat_done +init_fat12: +; read FAT + push 0x6000 + pop es + mov ax, [BPB_RsvdSecCnt] + mov cx, [BPB_FATSz16] + cmp cx, 12 + jb @f + mov cx, 12 +@@: + xor dx, dx + call [read_sectors] +init_fat_done: +; if cluster = sector, we need to read second part of our file +; (bootsector loads only first cluster of kordldr.f1x) + pop cx ax ; restore our position on disk + cmp cx, 1 + ja kordldr_full + sub ax, [bp-8] + inc ax + inc ax ; ax = first cluster of kordldr.f12 + call get_next_cluster + jc @f +j_noloader: + jmp [noloader] +@@: + dec ax + dec ax + push 0x800 + pop es + call [read_sectors2] +kordldr_full: +; ...continue loading... + mov di, secondary_loader_info + call load_file + test bx, bx + mov bx, [err_] + jz @f + mov si, aKernelNotFound + jmp bx +@@: +; for subsequent calls to callback function, hook error handler +; mov byte [bx], 0xE9 ; 'jmp' opcode +; mov ax, hooked_err - 3 +; sub ax, bx +; mov word [bx+1], ax +; push hooked_err / ret + mov word [bx], 0x68 + ((hooked_err and 0xFF) shl 8) + mov word [bx+2], (hooked_err shr 8) + (0xC3 shl 8) +; set registers for secondary loader + mov ah, [BS_DrvNum] + mov al, 'f' + test ah, ah + jns @f + sub ah, 80h + mov al, 'h' +@@: + mov bx, '12' + cmp [fat_type], 0 + jz @f + mov bh, '6' +@@: + mov si, callback ; ds:si = far pointer to callback procedure + jmp far [si-callback+secondary_loader_info] ; jump to 1000:0000 + +nomem_str db 'No memory',0 + +chs_proc_addresses: + dw chs_read_sectors + dw chs_read_sectors2 + dw chs_lookup_in_root_dir + dw chs_scan_for_filename + dw chs_err + dw chs_noloader +lba_proc_addresses: + dw lba_read_sectors + dw lba_read_sectors2 + dw lba_lookup_in_root_dir + dw lba_scan_for_filename + dw lba_err + dw lba_noloader + +get_next_cluster: +; in: ax = cluster +; out: if there is next cluster: CF=1, ax = next cluster +; out: if there is no next cluster: CF=0 + push si + cmp [fat_type], 0 + jnz gnc16 +; for FAT12 + push ds + push 0x6000 + pop ds + mov si, ax + shr si, 1 + add si, ax + test al, 1 + lodsw + jz @f + shr ax, 4 +@@: + and ax, 0xFFF + cmp ax, 0xFF7 + pop ds si + ret +; for FAT16 +gnc16: +; each sector contains 200h bytes = 100h FAT entries +; so ah = # of sector, al = offset in sector + mov si, ax + mov ah, 0 + shr si, 8 +; calculate segment for this sector of FAT table +; base for FAT table is 6000:0000, so the sector #si has to be loaded to (60000 + 200*si) +; segment = 6000 + 20*si, offset = 0 + push es + push si + shl si, 5 + add si, 0x6000 + mov es, si + pop si + cmp byte [ss:0x8200+si], ah ; sector already loaded? + jnz @f +; load corresponding sector + pusha + push es + xor bx, bx + mov ax, [BPB_RsvdSecCnt] + xor dx, dx + add ax, si + adc dx, bx + mov cx, 1 ; read 1 sector + call [read_sectors] + pop es + popa +@@: + mov si, ax + add si, si +; mov ax, [es:si] + lods word [es:si] + pop es + cmp ax, 0xFFF7 + pop si + ret + +if $ > 0x8000 +error 'get_next_cluster must fit in first sector of kordldr.f1x!' +end if + +load_file: +; in: ss:bp = 0:7C00 +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) + xor ax, ax ; start from root directory + mov dx, -1 + mov word [filesize], dx + mov word [filesize+2], dx ; initialize file size with invalid value + lea si, [di+6] +parse_dir_loop: +; convert name to FAT name + push di + push ax + push ss + pop es +; convert ASCIIZ filename to FAT name + mov di, filename + push di + mov cx, 8+3 + mov al, ' ' + rep stosb + pop di + mov cl, 8 ; 8 symbols per name + mov bl, 1 +nameloop: + lodsb + test al, al + jz namedone + cmp al, '/' + jz namedone + cmp al, '.' + jz namedot + dec cx + js badname + cmp al, 'a' + jb @f + cmp al, 'z' + ja @f + sub al, 'a'-'A' +@@: + stosb + jmp nameloop +namedot: + inc bx + jp badname + add di, cx + mov cl, 3 + jmp nameloop +badname: ; do not make direct js/jp to notfound_pop: + ; this generates long forms of conditional jumps and results in longer code + jmp notfound_pop +namedone: +; scan directory + pop ax ; ax = cluster of directory or 0 for root + push ds + push si + push es + pop ds + mov si, filename ; ds:si -> filename in FAT style + test ax, ax + jnz lookup_in_notroot_dir +; for root directory, use the subroutine from bootsector + call [lookup_in_root_dir] + jmp lookup_done +lookup_in_notroot_dir: +; for other directories, read a folder sector-by-sector and scan +; first, try to use the cache + push ds + push cs + pop ds + mov bx, [cachelimit] + add bx, bx + mov di, foldcache_mark +@@: + mov dx, [foldcache_clus+di-foldcache_mark+bx] + cmp dx, ax + jz cacheok + test dx, dx + jz cacheadd ; the cache has place for new entry + dec bx + dec bx + jns @b +; the folder is not present in the cache, so add it +; the cache is full; find the oldest entry and replace it with the new one + mov dx, [cachelimit] +@@: + inc bx + inc bx + cmp word [di+bx], dx ; marks have values 0 through [cachelimit] + jnz @b +cacheadd: + or word [di+bx], 0xFFFF ; very big value, it will be changed soon + mov [foldcache_clus+di-foldcache_mark+bx], ax + and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet +cacheok: +; update cache marks + mov dx, [di+bx] + mov cx, [foldcache_size+di-foldcache_mark+bx] + mov di, [cachelimit] + add di, di +cacheupdate: + cmp [foldcache_mark+di], dx + adc [foldcache_mark+di], 0 + dec di + dec di + jns cacheupdate + and [foldcache_mark+bx], 0 +; done, bx contains (position in cache)*2 + pop ds +; mov dx, bx +; shl dx, 8 ; dx = (position in cache)*0x2000/0x10 +; add dx, 0x9200 + lea dx, [bx+0x92] + xchg dl, dh + mov es, dx + jcxz not_in_cache + call [scan_for_filename] + jz lookup_done +not_in_cache: +; cache miss, read folder data from disk + mov bx, cx + shr bx, 4 + shl cx, 5 + mov di, cx ; es:di -> free space in cache entry +; external loop: scan clusters +folder_next_cluster: +; internal loop: scan sectors in cluster + mov cx, [sect_per_clus] + push ax + dec ax + dec ax + mul cx + add ax, [bp-8] + adc dx, [bp-6] ; dx:ax = absolute sector +folder_next_sector: +; skip first bx sectors + dec bx + jns folder_skip_sector + push cx + push es di + push 0x8000 + pop es + xor bx, bx + mov cx, 1 + push es + call [read_sectors] +; copy data to the cache... + pop ds + pop di es + cmp di, 0x2000 ; ...if there is free space, of course + jae @f + push si di + mov cx, 0x100 + xor si, si + rep movsw + mov di, es + shr di, 8 + add [ss:foldcache_size+di-0x92], 0x10 ; 0x10 new entries in the cache + pop di si +@@: + push es + push 0x8000 + pop es + push cs + pop ds + mov cx, 0x10 + call [scan_for_filename] + pop es + pop cx + jz lookup_done_pop +folder_skip_sector: + inc ax + jnz @f + inc dx +@@: + loop folder_next_sector + pop ax ; ax = current cluster + call get_next_cluster + jc folder_next_cluster + stc + push ax +lookup_done_pop: + pop ax +lookup_done: + pop si + pop ds +; CF=1 <=> failed + jnc found +notfound: + pop di + mov bx, 2 ; file not found + mov ax, 0xFFFF + mov dx, ax ; invalid file size + ret +notfound_pop: + pop ax + jmp notfound +found: + mov ax, [es:di+26] ; get cluster + test byte [es:di+11], 10h ; directory? + jz regular_file + cmp byte [si-1], 0 + jz notfound ; don't read directories as a regular files +; ok, we have found a directory and the caller requested a file into it + pop di + jmp parse_dir_loop ; restart with new cluster in ax +regular_file: + cmp byte [si-1], 0 + jnz notfound ; file does not contain another files +; ok, we have found a regular file and the caller requested it +; save file size + mov dx, [es:di+28] + mov [filesize], dx + mov dx, [es:di+30] + mov [filesize+2], dx + pop di + mov si, [di+4] + shl si, 3 + push si ; [ds:di+4] = limit in 4K blocks + les bx, [di] ; es:bx -> buffer +clusloop: +; ax = first cluster, top of stack contains limit in sectors + mov si, ax ; remember current cluster + xor cx, cx ; cx will contain number of consecutive clusters + mov word [cur_delta], cx + mov word [cur_delta+2], cx + mov di, ax +clusfind: + inc di + inc cx + call get_next_cluster + jnc clusread + cmp ax, di + jz clusfind + stc +clusread: + pop di ; limit in sectors + push ax ; save next cluster + pushf ; save flags +; read cx clusters, starting from si +; calculate number of sectors + xchg ax, cx + mul [sect_per_clus] +; dx:ax = number of sectors; compare with limit + mov word [num_sectors], ax + mov word [num_sectors+2], dx + jmp @f +continue_load_file: + les bx, [di] ; es:bx -> buffer + mov di, [di+4] ; ds:di = limit in 4K blocks + shl di, 3 ; now di = limit in sectors + mov ax, word [num_sectors] + mov dx, word [num_sectors+2] + mov si, [cur_cluster] + push [next_cluster] + push [flags] + or ax, dx + jz nextclus +@@: + test dx, dx + jnz clusdecrease + push dx ; limit was not exceeded + cmp ax, di + jbe @f + pop ax +clusdecrease: + push 1 ; limit was exceeded + mov ax, di +@@: + sub di, ax ; calculate new limit + sub word [num_sectors], ax + sbb word [num_sectors+2], 0 +; calculate starting sector + xchg ax, cx + lea ax, [si-2] + mul [sect_per_clus] + add ax, word [cur_delta] + adc dx, word [cur_delta+2] + add word [cur_delta], cx + adc word [cur_delta+2], 0 +; read + call [read_sectors2] + pop dx +; next cluster? +nextclus: + popf + pop ax + mov [cur_cluster], si + mov [next_cluster], ax + pushf + pop [flags] + jnc @f ; no next cluster => return + mov dl, 1 ; dh=0 in any case + test di, di + jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded + push di + jmp clusloop ; all is ok, continue +hooked_err: + mov sp, 7C00h-12-2 ; restore stack + mov dx, 3 ; return: read error +@@: + mov bx, dx + mov ax, [filesize] + mov dx, [filesize+2] + ret + +; Callback function for secondary loader +callback: +; in: ax = function number; only functions 1 and 2 are defined for now +; save caller's stack + mov dx, ss + mov cx, sp +; set our stack (required because we need ss=0) + xor si, si + mov ss, si + mov sp, 7C00h-8 + mov bp, 7C00h + push dx + push cx +; call our function + stc ; unsupported function + dec ax + jz callback_readfile + dec ax + jnz callback_ret +; function 2: continue loading file +; can be called only after function 1 returned value bx=1 (only part of file was loaded) +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error +; out: dx:ax = file size + call continue_load_file + jmp callback_ret_succ +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call load_file +callback_ret_succ: + clc ; function is supported +callback_ret: +; restore caller's stack + pop cx + pop ss + mov sp, cx +; return to caller + retf + +secondary_loader_info: + dw 0, 0x1000 + dw 0x30000 / 0x1000 + db 'kord/loader',0 +aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 + +foldcache_clus dw 0,0,0,0,0,0,0 ; start with no folders in cache +foldcache_mark rw 7 +foldcache_size rw 7 +filename rb 11 +if $ > 0x8200 +error: + table overwritten +end if diff --git a/kernel/trunk/sec_loader/trunk/boot/fat32/bootsect.asm b/kernel/trunk/sec_loader/trunk/boot/fat32/bootsect.asm index 3dbee8865..69f16c459 100644 --- a/kernel/trunk/sec_loader/trunk/boot/fat32/bootsect.asm +++ b/kernel/trunk/sec_loader/trunk/boot/fat32/bootsect.asm @@ -1,358 +1,358 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -use_lba = 0 - org 0x7C00 - jmp start - nop -; FAT parameters, BPB -; they must be changed at install, replaced with real values - rb 8 ; BS_OEMName, ignored - dw 200h ; BPB_BytsPerSec -BPB_SecsPerClus db ? -BPB_RsvdSecCnt dw ? -BPB_NumFATs db ? -BPB_RootEntCnt dw ? - dw ? ; BPB_TotSec16 - db ? ; BPB_Media - dw ? ; BPB_FATSz16 = 0 for FAT32 -BPB_SecPerTrk dw ? -BPB_NumHeads dw ? -BPB_HiddSec dd ? - dd ? ; BPB_TotSec32 -BPB_FATSz32 dd ? -BPB_ExtFlags dw ? - dw ? ; BPB_FSVer -BPB_RootClus dd ? - dw ? ; BPB_FSInfo -BPB_BkBootSec dw ? - rb 12 ; BPB_Reserved -BS_DrvNum db ? - db ? ; BS_Reserved1 - db ? ; BS_BootSig - dd ? ; BS_VolID - rb 11 ; BS_VolLab - rb 8 ; - -curseg dw 0x8000 - -start: - xor ax, ax - mov ss, ax - mov sp, 0x7C00 - mov ds, ax - mov bp, sp - cld - sti - push dx ; byte [bp-2] = boot drive -if use_lba - mov ah, 41h - mov bx, 55AAh - int 13h - mov si, aNoLBA - jc err_ - cmp bx, 0AA55h - jnz err_ - test cl, 1 - jz err_ -else - mov ah, 8 - int 13h - jc @f - movzx ax, dh - inc ax - mov [bp+BPB_NumHeads-0x7C00], ax - and cx, 3Fh - mov [bp+BPB_SecPerTrk-0x7C00], cx -@@: -end if -; get FAT parameters - xor bx, bx - movzx eax, [bp+BPB_NumFATs-0x7C00] - mul [bp+BPB_FATSz32-0x7C00] - movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] - push ecx ; FAT start = dword [bp-6] - add eax, ecx - push eax ; data start = dword [bp-10] - ;push dword -1 ; dword [bp-14] = current sector for FAT cache - db 66h - push -1 ; dword [bp-14] = current sector for FAT cache - mov eax, [bp+BPB_RootClus-0x7C00] - mov si, main_loader - call lookup_in_dir - jnc kordldr_ok -noloader: - mov si, aLoaderNotFound -err_: - call out_string - mov si, aPressAnyKey - call out_string - xor ax, ax - int 16h - int 18h - jmp $ -kordldr_ok: - mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) - mov ax, [es:di+26] ; loword(eax) = loword(cluster) - mov es, bx ; es = 0 - mov bx, 0x7E00 - push bx ; save return address: bx = 7E00 -; fall through - 'ret' in read_cluster will return to 7E00 - -read_cluster: -; ss:bp = 0:7C00 -; es:bx = pointer to data -; eax = cluster - sub eax, 2 - movzx ecx, [bp+BPB_SecsPerClus-0x7C00] - mul ecx - -read_sectors2: -; same as read_sectors32, but eax is relative to start of data - add eax, [bp-10] -read_sectors32: -; ss:bp = 0:7C00 -; es:bx = pointer to data -; eax = first sector -; cx = number of sectors -; some high words of 32-bit registers are destroyed! - pusha - add eax, [bp+BPB_HiddSec-0x7C00] -if use_lba - push ds -do_read_sectors: - push ax - push cx - cmp cx, 0x7F - jbe @f - mov cx, 0x7F -@@: -; create disk address packet on the stack -; dq starting LBA - push 0 - push 0 - push eax -; dd buffer - push es - push bx -; dw number of blocks to transfer (no more than 0x7F) - push cx -; dw packet size in bytes - push 10h -; issue BIOS call - push ss - pop ds - mov si, sp - mov dl, [bp-2] - mov ah, 42h - int 13h - mov si, aReadError - jc err_ -; restore stack - add sp, 10h -; increase current sector & buffer; decrease number of sectors - movzx esi, cx - mov ax, es - shl cx, 5 - add ax, cx - mov es, ax - pop cx - pop ax - add eax, esi - sub cx, si - jnz do_read_sectors - pop ds - popa - ret -else -do_read_sectors: - pusha - pop edi ; loword(edi) = di, hiword(edi) = si - push bx - -; eax / (SectorsPerTrack) -> eax, remainder bx - movzx esi, [bp+BPB_SecPerTrk-0x7C00] - xor edx, edx - div esi - mov bx, dx ; bx=sector-1 - -; eax -> dx:ax - push eax - pop ax - pop dx -; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx - div [bp+BPB_NumHeads-0x7C00] - -; number of sectors: read no more than to end of track - sub si, bx - cmp cx, si - jbe @f - mov cx, si -@@: - - inc bx -; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format - movzx edi, cx - mov dh, dl - mov dl, [bp-2] - shl ah, 6 - mov ch, al - mov al, cl - mov cl, bl - or cl, ah - pop bx - mov si, 3 - mov ah, 2 -@@: - push ax - int 13h - jnc @f - xor ax, ax - int 13h ; reset drive - pop ax - dec si - jnz @b - mov si, aReadError - jmp err_ -@@: - pop ax - mov ax, es - mov cx, di - shl cx, 5 - add ax, cx - mov es, ax - push edi - popa - add eax, edi - sub cx, di - jnz do_read_sectors - popa - ret -end if - -lookup_in_dir: -; in: ds:si -> 11-bytes FAT name -; in: eax = cluster -; in: bx = 0 -; out: if found: CF=0, es:di -> directory entry -; out: if not found: CF=1 -; push 0x8000 -; pop es -; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 - mov es, [bp-7C00h + curseg] - push es - push eax - call read_cluster - mov ax, es - cmp ah, 82h - jb @f - mov ax, 8200h -@@: - mov [bp-7C00h + curseg], ax - pop eax - pop es -; scan for filename - shl cx, 4 - xor di, di -sloop: - cmp byte [es:di], bl - jz snotfound - test byte [es:di+11], 8 ; volume label? - jnz scont ; ignore volume labels - pusha - mov cx, 11 - repz cmpsb - popa - jz sdone -scont: - add di, 0x20 - loop sloop -; next cluster - push 0x6000 - pop es - push es ax - shr eax, 7 - cmp eax, [bp-14] - mov [bp-14], eax - jz @f - add eax, [bp-6] - mov cx, 1 - call read_sectors32 -@@: - pop di es - and di, 0x7F - shl di, 2 - and byte [es:di+3], 0x0F - mov eax, [es:di] - ;and eax, 0x0FFFFFFF - cmp eax, 0x0FFFFFF7 - jb lookup_in_dir -snotfound: - stc -sdone: - ret - -out_string: -; in: ds:si -> ASCIIZ string - lodsb - test al, al - jz sdone - mov ah, 0Eh - mov bx, 7 - int 10h - jmp out_string - -aReadError db 'Read error',0 -if use_lba -aNoLBA db 'The drive does not support LBA!',0 -end if -aLoaderNotFound db 'Loader not found',0 -aPressAnyKey db 13,10,'Press any key...',13,10,0 -main_loader db 'KORDLDR F32' - - db 56h -; just to make file 512 bytes long :) - db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' - -; bootsector signature - dw 0xAA55 - -; display offsets of all procedures used by kordldr.f12.asm -macro show [procedure] -{ - bits = 16 - display `procedure,' = ' - repeat bits/4 - d = '0' + procedure shr (bits - %*4) and 0Fh - if d > '9' - d = d + 'A'-'9'-1 - end if - display d - end repeat - display 13,10 -} - -show read_sectors32, read_sectors2, err_, noloader +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +use_lba = 0 + org 0x7C00 + jmp start + nop +; FAT parameters, BPB +; they must be changed at install, replaced with real values + rb 8 ; BS_OEMName, ignored + dw 200h ; BPB_BytsPerSec +BPB_SecsPerClus db ? +BPB_RsvdSecCnt dw ? +BPB_NumFATs db ? +BPB_RootEntCnt dw ? + dw ? ; BPB_TotSec16 + db ? ; BPB_Media + dw ? ; BPB_FATSz16 = 0 for FAT32 +BPB_SecPerTrk dw ? +BPB_NumHeads dw ? +BPB_HiddSec dd ? + dd ? ; BPB_TotSec32 +BPB_FATSz32 dd ? +BPB_ExtFlags dw ? + dw ? ; BPB_FSVer +BPB_RootClus dd ? + dw ? ; BPB_FSInfo +BPB_BkBootSec dw ? + rb 12 ; BPB_Reserved +BS_DrvNum db ? + db ? ; BS_Reserved1 + db ? ; BS_BootSig + dd ? ; BS_VolID + rb 11 ; BS_VolLab + rb 8 ; + +curseg dw 0x8000 + +start: + xor ax, ax + mov ss, ax + mov sp, 0x7C00 + mov ds, ax + mov bp, sp + cld + sti + push dx ; byte [bp-2] = boot drive +if use_lba + mov ah, 41h + mov bx, 55AAh + int 13h + mov si, aNoLBA + jc err_ + cmp bx, 0AA55h + jnz err_ + test cl, 1 + jz err_ +else + mov ah, 8 + int 13h + jc @f + movzx ax, dh + inc ax + mov [bp+BPB_NumHeads-0x7C00], ax + and cx, 3Fh + mov [bp+BPB_SecPerTrk-0x7C00], cx +@@: +end if +; get FAT parameters + xor bx, bx + movzx eax, [bp+BPB_NumFATs-0x7C00] + mul [bp+BPB_FATSz32-0x7C00] + movzx ecx, [bp+BPB_RsvdSecCnt-0x7C00] + push ecx ; FAT start = dword [bp-6] + add eax, ecx + push eax ; data start = dword [bp-10] + ;push dword -1 ; dword [bp-14] = current sector for FAT cache + db 66h + push -1 ; dword [bp-14] = current sector for FAT cache + mov eax, [bp+BPB_RootClus-0x7C00] + mov si, main_loader + call lookup_in_dir + jnc kordldr_ok +noloader: + mov si, aLoaderNotFound +err_: + call out_string + mov si, aPressAnyKey + call out_string + xor ax, ax + int 16h + int 18h + jmp $ +kordldr_ok: + mov eax, [es:di+20-2] ; hiword(eax) = hiword(cluster) + mov ax, [es:di+26] ; loword(eax) = loword(cluster) + mov es, bx ; es = 0 + mov bx, 0x7E00 + push bx ; save return address: bx = 7E00 +; fall through - 'ret' in read_cluster will return to 7E00 + +read_cluster: +; ss:bp = 0:7C00 +; es:bx = pointer to data +; eax = cluster + sub eax, 2 + movzx ecx, [bp+BPB_SecsPerClus-0x7C00] + mul ecx + +read_sectors2: +; same as read_sectors32, but eax is relative to start of data + add eax, [bp-10] +read_sectors32: +; ss:bp = 0:7C00 +; es:bx = pointer to data +; eax = first sector +; cx = number of sectors +; some high words of 32-bit registers are destroyed! + pusha + add eax, [bp+BPB_HiddSec-0x7C00] +if use_lba + push ds +do_read_sectors: + push ax + push cx + cmp cx, 0x7F + jbe @f + mov cx, 0x7F +@@: +; create disk address packet on the stack +; dq starting LBA + push 0 + push 0 + push eax +; dd buffer + push es + push bx +; dw number of blocks to transfer (no more than 0x7F) + push cx +; dw packet size in bytes + push 10h +; issue BIOS call + push ss + pop ds + mov si, sp + mov dl, [bp-2] + mov ah, 42h + int 13h + mov si, aReadError + jc err_ +; restore stack + add sp, 10h +; increase current sector & buffer; decrease number of sectors + movzx esi, cx + mov ax, es + shl cx, 5 + add ax, cx + mov es, ax + pop cx + pop ax + add eax, esi + sub cx, si + jnz do_read_sectors + pop ds + popa + ret +else +do_read_sectors: + pusha + pop edi ; loword(edi) = di, hiword(edi) = si + push bx + +; eax / (SectorsPerTrack) -> eax, remainder bx + movzx esi, [bp+BPB_SecPerTrk-0x7C00] + xor edx, edx + div esi + mov bx, dx ; bx=sector-1 + +; eax -> dx:ax + push eax + pop ax + pop dx +; (dword in dx:ax) / (NumHeads) -> (word in ax), remainder dx + div [bp+BPB_NumHeads-0x7C00] + +; number of sectors: read no more than to end of track + sub si, bx + cmp cx, si + jbe @f + mov cx, si +@@: + + inc bx +; now ax=track, dl=head, dh=0, cl=number of sectors, ch=0, bl=sector; convert to int13 format + movzx edi, cx + mov dh, dl + mov dl, [bp-2] + shl ah, 6 + mov ch, al + mov al, cl + mov cl, bl + or cl, ah + pop bx + mov si, 3 + mov ah, 2 +@@: + push ax + int 13h + jnc @f + xor ax, ax + int 13h ; reset drive + pop ax + dec si + jnz @b + mov si, aReadError + jmp err_ +@@: + pop ax + mov ax, es + mov cx, di + shl cx, 5 + add ax, cx + mov es, ax + push edi + popa + add eax, edi + sub cx, di + jnz do_read_sectors + popa + ret +end if + +lookup_in_dir: +; in: ds:si -> 11-bytes FAT name +; in: eax = cluster +; in: bx = 0 +; out: if found: CF=0, es:di -> directory entry +; out: if not found: CF=1 +; push 0x8000 +; pop es +; read current cluster: first cluster goes to 8000:0000, others - to 8200:0000 + mov es, [bp-7C00h + curseg] + push es + push eax + call read_cluster + mov ax, es + cmp ah, 82h + jb @f + mov ax, 8200h +@@: + mov [bp-7C00h + curseg], ax + pop eax + pop es +; scan for filename + shl cx, 4 + xor di, di +sloop: + cmp byte [es:di], bl + jz snotfound + test byte [es:di+11], 8 ; volume label? + jnz scont ; ignore volume labels + pusha + mov cx, 11 + repz cmpsb + popa + jz sdone +scont: + add di, 0x20 + loop sloop +; next cluster + push 0x6000 + pop es + push es ax + shr eax, 7 + cmp eax, [bp-14] + mov [bp-14], eax + jz @f + add eax, [bp-6] + mov cx, 1 + call read_sectors32 +@@: + pop di es + and di, 0x7F + shl di, 2 + and byte [es:di+3], 0x0F + mov eax, [es:di] + ;and eax, 0x0FFFFFFF + cmp eax, 0x0FFFFFF7 + jb lookup_in_dir +snotfound: + stc +sdone: + ret + +out_string: +; in: ds:si -> ASCIIZ string + lodsb + test al, al + jz sdone + mov ah, 0Eh + mov bx, 7 + int 10h + jmp out_string + +aReadError db 'Read error',0 +if use_lba +aNoLBA db 'The drive does not support LBA!',0 +end if +aLoaderNotFound db 'Loader not found',0 +aPressAnyKey db 13,10,'Press any key...',13,10,0 +main_loader db 'KORDLDR F32' + + db 56h +; just to make file 512 bytes long :) + db 'd' xor 'i' xor 'a' xor 'm' xor 'o' xor 'n' xor 'd' + +; bootsector signature + dw 0xAA55 + +; display offsets of all procedures used by kordldr.f12.asm +macro show [procedure] +{ + bits = 16 + display `procedure,' = ' + repeat bits/4 + d = '0' + procedure shr (bits - %*4) and 0Fh + if d > '9' + d = d + 'A'-'9'-1 + end if + display d + end repeat + display 13,10 +} + +show read_sectors32, read_sectors2, err_, noloader diff --git a/kernel/trunk/sec_loader/trunk/boot/fat32/kordldr.f32.asm b/kernel/trunk/sec_loader/trunk/boot/fat32/kordldr.f32.asm index 9913b442b..9aa9798bf 100644 --- a/kernel/trunk/sec_loader/trunk/boot/fat32/kordldr.f32.asm +++ b/kernel/trunk/sec_loader/trunk/boot/fat32/kordldr.f32.asm @@ -1,672 +1,672 @@ -; Copyright (c) 2008-2009, diamond -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - - org 0x7E00 -; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here -; ss:bp = 0:7C00 -; ds = 0 -virtual at bp - rb 3 ; BS_jmpBoot - rb 8 ; BS_OEMName, ignored - dw ? ; BPB_BytsPerSec -BPB_SecsPerClus db ? -BPB_RsvdSecCnt dw ? -BPB_NumFATs db ? -BPB_RootEntCnt dw ? - dw ? ; BPB_TotSec16 - db ? ; BPB_Media - dw ? ; BPB_FATSz16 = 0 for FAT32 -BPB_SecPerTrk dw ? -BPB_NumHeads dw ? -BPB_HiddSec dd ? - dd ? ; BPB_TotSec32 -BPB_FATSz32 dd ? -BPB_ExtFlags dw ? - dw ? ; BPB_FSVer -BPB_RootClus dd ? -filesize: - dw ? ; BPB_FSInfo - dw ? ; BPB_BkBootSec - rb 12 ; BPB_Reserved -BS_DrvNum db ? - db ? ; BS_Reserved1 - db ? ; BS_BootSig - dd ? ; BS_VolID -; rb 11 ; BS_VolLab -; rb 5 ; BS_FilSysType, first 5 bytes -read_sectors32 dw ? -read_sectors2 dw ? -err_ dw ? -noloader dw ? -cachelimit dw ? -fatcachehead rw 2 -fatcacheend dw ? - rb 3 ; BS_FilSysType, last 3 bytes -curseg dw ? -num_sectors dd ? -cur_cluster dd ? -next_cluster dd ? -flags dw ? -cur_delta dd ? -end virtual - -; procedures from boot sector -; LBA version -lba_read_sectors2 = 7CD6h -lba_err = 7CAAh -lba_noloader = 7CA7h ; = lba_err - 3 -; CHS version -chs_read_sectors2 = 7CD2h -chs_err = 7CA6h -chs_noloader = 7CA3h ; = chs_err - 3 - - push eax cx ; save our position on disk -; determine version of bootsector (LBA vs CHS) - mov [read_sectors2], chs_read_sectors2 - mov bx, chs_err - mov [err_], bx -; mov [noloader], chs_noloader - cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version - jz @f - add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 - add [err_], lba_err - chs_err -; mov [noloader], lba_noloader -@@: - xor bx, bx -; determine size of cache for folders - int 12h ; ax = size of available base memory in Kb - sub ax, 92000h / 1024 - jae @f -nomem: - mov si, nomem_str - jmp [err_] -@@: - shr ax, 3 - mov [cachelimit], ax ; size of cache - 1 - mov es, bx -; no folders in cache yet - mov di, foldcache_clus - mov cx, 8*4/2 + 1 - xor ax, ax - rep stosw -; bootsector code caches one FAT sector, [bp-14], in 6000:0000 -; initialize our (more advanced) FAT caching from this - mov di, 8400h - mov cx, di - lea si, [fatcachehead] - mov [si], si ; no sectors in cache: - mov [si+2], si ; 'prev' & 'next' links point to self - mov [fatcacheend], di ; first free item = 8400h - stosw ; 'next cached sector' link - stosw ; 'prev cached sector' link - mov eax, [bp-14] - stosd ; first sector number in cache - test eax, eax - js @f - mov [si], cx ; 'first cached sector' link = 8400h - mov [si+2], cx ; 'next cached sector' link = 8400h - mov [fatcacheend], di ; first free item = 8406h -@@: -; if cluster = sector, we need to read second part of our file -; (bootsector loads only first cluster of kordldr.f32) - pop cx eax ; restore our position on disk - cmp cx, 1 - ja kordldr_full - sub eax, [bp-10] - inc eax - inc eax ; eax = first cluster of kordldr.f32 - call get_next_cluster - jc @f -; jmp [noloader] - mov ax, [err_] - sub ax, 3 - jmp ax -@@: - dec eax - dec eax - push 0x800 - pop es - call [read_sectors2] -kordldr_full: -; bootsector code has read some data of root directory to 8000:0000 -; initialize our folder caching from this - mov eax, [BPB_RootClus] - mov [foldcache_clus], eax - mov cx, [curseg] - mov ax, 8000h - sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) - shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) - mov [foldcache_size], cx - shl cx, 4 - push ds - mov ds, ax - push 0x9000 - pop es - xor si, si - xor di, di - rep movsw - pop ds -; ...continue loading... - mov di, secondary_loader_info - call load_file - test bx, bx - mov bx, [err_] - jz @f - mov si, aKernelNotFound - jmp bx -@@: -; for subsequent calls to callback function, hook error handler -; push hooked_err / ret - mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) -; set registers for secondary loader - mov ah, [bp-2] ; drive id - mov al, 'f' - btr ax, 15 - jnc @f - mov al, 'h' -@@: - mov bx, '32' - mov si, callback - jmp far [si+secondary_loader_info-callback] - -nomem_str db 'No memory',0 - -cluster2sector: - sub eax, 2 -clustersz2sectorsz: - movzx ecx, [BPB_SecsPerClus] - mul ecx - ret - -get_next_cluster: -; in: eax = cluster -; out: if there is next cluster: CF=1, eax = next cluster -; out: if there is no next cluster: CF=0 - push di bx - push ds - push ss - pop ds - push ax - shr eax, 7 -; eax = FAT sector number; look in cache - mov di, 8400h -.cache_lookup: - cmp di, [fatcacheend] - jae .not_in_cache - scasd - scasd - jnz .cache_lookup -.in_cache: - sub di, 8 -; delete this sector from the list - push si - mov si, [di] - mov bx, [di+2] - mov [si+2], bx - mov [bx], si - pop si - jmp @f -.not_in_cache: -; cache miss -; cache is full? - mov di, [fatcacheend] - cmp di, 8C00h - jnz .cache_not_full -; yes, delete the oldest entry - mov di, [fatcachehead] - mov bx, [di] - mov [fatcachehead], bx - push word [di+2] - pop word [bx+2] - jmp .cache_append -.cache_not_full: -; no, allocate new sector - add [fatcacheend], 8 -.cache_append: -; read FAT - mov [di+4], eax - push es - pushad - lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] ; +0x10000 - for FASM - shl cx, 9-3 - mov es, cx - xor bx, bx - mov cx, 1 - add eax, [bp-6] ; FAT start - sub eax, [bp-10] - call [read_sectors2] - popad - pop es -@@: -; add new sector to the end of list - mov bx, di - xchg bx, [fatcachehead+2] - push word [bx] - pop word [di] - mov [bx], di - mov [di+2], bx -; get requested item - lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] - pop di - and di, 0x7F - shl di, 2 - shl ax, 9-3 - mov ds, ax - and byte [di+3], 0x0F - mov eax, [di] - pop ds - pop bx di - ;and eax, 0x0FFFFFFF - cmp eax, 0x0FFFFFF7 - ret - -if $ > 0x8000 -error 'get_next_cluster must fit in first sector of kordldr.f32!' -end if - -load_file: -; in: ss:bp = 0:7C00 -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found -; out: dx:ax = file size (0xFFFFFFFF if file not found) - mov eax, [BPB_RootClus] ; start from root directory - or dword [filesize], -1 ; initialize file size with invalid value - lea si, [di+6] -parse_dir_loop: -; convert name to FAT name - push di - push ax - push ss - pop es -; convert ASCIIZ filename to FAT name -filename equ bp - mov di, filename - push di - mov cx, 8+3 - mov al, ' ' - rep stosb - pop di - mov cl, 8 ; 8 symbols per name - mov bl, 1 -nameloop: - lodsb - test al, al - jz namedone - cmp al, '/' - jz namedone - cmp al, '.' - jz namedot - dec cx - js badname - cmp al, 'a' - jb @f - cmp al, 'z' - ja @f - sub al, 'a'-'A' -@@: - stosb - jmp nameloop -namedot: - inc bx - jp badname - add di, cx - mov cl, 3 - jmp nameloop -badname: ; do not make direct js/jp to notfound_pop: - ; this generates long forms of conditional jumps and results in longer code - jmp notfound_pop -namedone: -; scan directory - pop ax ; eax = cluster of directory - ; high word of eax is preserved by operations above - push ds - push si -; read a folder sector-by-sector and scan -; first, try to use the cache - push ss - pop ds - mov di, foldcache_mark - xor bx, bx - mov cx, [cachelimit] -@@: - lea si, [di+bx] - mov edx, dword [foldcache_clus+si-foldcache_mark+bx] - cmp edx, eax - jz cacheok - test edx, edx - jz cacheadd ; the cache has place for new entry - inc bx - inc bx - dec cx - jns @b -; the folder is not present in the cache, so add it -; the cache is full; find the oldest entry and replace it with the new one - mov bx, -2 - mov dx, [cachelimit] -@@: - inc bx - inc bx - cmp word [di+bx], dx ; marks have values 0 through [cachelimit] - jnz @b - lea si, [di+bx] -cacheadd: - or word [di+bx], 0xFFFF ; very big value, it will be changed soon - and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet - mov dword [foldcache_clus+si-foldcache_mark+bx], eax -cacheok: -; update cache marks - mov dx, [di+bx] - mov cx, [foldcache_size+di-foldcache_mark+bx] - mov di, [cachelimit] - add di, di -cacheupdate: - cmp [foldcache_mark+di], dx - adc [foldcache_mark+di], 0 - dec di - dec di - jns cacheupdate - and [foldcache_mark+bx], 0 -; done, bx contains (position in cache)*2 - ;mov dx, bx - ;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 - ;add dx, 0x9000 - lea dx, [bx + 0x90] - xchg dl, dh - mov ds, dx - mov si, filename ; ss:si -> filename in FAT style - call scan_for_filename - jz lookup_done -; cache miss, read folder data from disk - mov bx, cx - shr bx, 4 - shl cx, 5 - mov di, cx ; es:di -> free space in cache entry -; external loop: scan clusters -folder_next_cluster: -; internal loop: scan sectors in cluster - push eax - call cluster2sector -folder_next_sector: -; skip first bx sectors - dec bx - jns folder_skip_sector - push cx - push es di - push 0x8000 - pop es - xor bx, bx - mov cx, 1 - push es - push eax - call [read_sectors2] - pop eax -; copy data to the cache... - pop ds - pop di es - cmp di, 0x2000 ; ...if there is free space, of course - jae @f - pusha - mov cx, 0x100 - xor si, si - rep movsw - mov di, es - shr di, 8 - add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache - popa -@@: - push es - mov cl, 0x10 ; ch=0 at this point - call scan_for_filename - pop es - pop cx - jz lookup_done_pop -folder_skip_sector: - inc eax - loop folder_next_sector - pop eax ; eax = current cluster - call get_next_cluster - jc folder_next_cluster - stc - push eax -lookup_done_pop: - pop eax -lookup_done: - pop si -; CF=1 <=> failed - jnc found - pop ds -notfound: - pop di -notfound2: - mov bx, 2 ; file not found - mov ax, 0xFFFF - mov dx, ax ; invalid file size - ret -notfound_pop: - pop ax - jmp notfound -found: - mov eax, [di+20-2] - mov edx, [di+28] - mov ax, [di+26] ; get cluster - test byte [di+11], 10h ; directory? - pop ds - pop di - jz regular_file - cmp byte [si-1], 0 - jz notfound2 ; don't read directories as regular files -; ok, we have found a directory and the caller requested a file into it - jmp parse_dir_loop ; restart with new cluster in ax -regular_file: - cmp byte [si-1], 0 - jnz notfound2 ; file does not contain another files -; ok, we have found a regular file and the caller requested it -; save file size - mov [filesize], edx - mov si, [di+4] ; [ds:di+4] = limit in 4K blocks - shl si, 3 - push si - les bx, [di] ; es:bx -> buffer -clusloop: -; eax = first cluster, top of stack contains limit in sectors - mov esi, eax ; remember current cluster - xor ecx, ecx ; ecx will contain number of consecutive clusters - mov [cur_delta], ecx - mov edi, eax -clusfind: - inc edi - inc ecx - call get_next_cluster - jnc clusread - cmp eax, edi - jz clusfind - stc -clusread: - pop di ; limit in sectors - movzx edi, di - push eax ; save next cluster - pushf ; save flags -; read cx clusters, starting from si -; calculate number of sectors - xchg eax, ecx - call clustersz2sectorsz - mov [num_sectors], eax - jmp @f -continue_load_file: - les bx, [di] ; es:bx -> buffer - movzx edi, word [di+4] ; di = limit in 4K blocks - shl di, 3 ; now di = limit in sectors - mov eax, [num_sectors] - mov esi, [cur_cluster] - push [next_cluster] - push [flags] - test eax, eax - jz nextclus -@@: -; eax = number of sectors; compare with limit - cmp eax, edi - seta dl - push dx ; limit was exceeded? - jbe @f - mov eax, edi -@@: - sub di, ax ; calculate new limit - sub [num_sectors], eax - mov [cur_cluster], esi -; calculate starting sector - push ax - xchg eax, esi - call cluster2sector - pop cx - add eax, [cur_delta] - add [cur_delta], ecx -; read - call [read_sectors2] - pop dx -; next cluster? -nextclus: - popf - pop eax - mov [next_cluster], eax - pushf - pop [flags] - jnc @f ; no next cluster => return - mov dl, 1 ; dh=0 in any case - test di, di - jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded - push di - jmp clusloop ; all is ok, continue -hooked_err: - mov sp, 7C00h-14-2 ; restore stack - mov dx, 3 ; return: read error -@@: - mov bx, dx - mov ax, [filesize] - mov dx, [filesize+2] - ret - -scan_for_filename: -; in: ss:si -> 11-bytes FAT name -; in: ds:0 -> part of directory data -; in: cx = number of entries -; in: bh = 0 -; out: if found: CF=0, ZF=1, es:di -> directory entry -; out: if not found, but continue required: CF=1 and ZF=0 -; out: if not found and zero item reached: CF=1 and ZF=1 - push ds - pop es - xor di, di - push cx - jcxz snoent -sloop: - cmp byte [di], bh - jz snotfound - test byte [di+11], 8 ; volume label? - jnz scont ; ignore volume labels - pusha - mov cx, 11 - repz cmps byte [ss:si], byte [es:di] - popa - jz sdone -scont: - add di, 0x20 - loop sloop -snoent: - inc cx ; clear ZF flag -snotfound: - stc -sdone: - pop cx -lrdret: - ret - -; Callback function for secondary loader -callback: -; in: ax = function number; only functions 1 and 2 are defined for now -; save caller's stack - mov dx, ss - mov cx, sp -; set our stack (required because we need ss=0) - xor si, si - mov ss, si - mov sp, 7C00h-10 - mov bp, 7C00h - push dx - push cx -; call our function - stc ; unsupported function - dec ax - jz callback_readfile - dec ax - jnz callback_ret -; function 2: continue loading file -; can be called only after function 1 returned value bx=1 (only part of file was loaded) -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error -; out: dx:ax = file size - call continue_load_file - jmp callback_ret_succ -callback_readfile: -; function 1: read file -; in: ds:di -> information structure -; dw:dw address -; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) -; ASCIIZ name -; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error -; out: dx:ax = file size (0xFFFFFFFF if file was not found) - call load_file -callback_ret_succ: - clc ; function is supported -callback_ret: -; restore caller's stack - pop cx - pop ss - mov sp, cx -; return to caller - retf - -secondary_loader_info: - dw 0, 0x1000 - dw 0x30000 / 0x1000 - db 'kord/loader',0 -aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 - -;if $ > 0x8200 -;error 'total size of kordldr.f32 must not exceed 1024 bytes!' -;end if - -;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache -;foldcache_mark dw 0 -; rw 7 -;foldcache_size rw 8 -foldcache_clus rd 8 -foldcache_mark rw 8 -foldcache_size rw 8 +; Copyright (c) 2008-2009, diamond +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + + org 0x7E00 +; the KordOS FAT32 bootsector loads first cluster of this file to 0:7E00 and transfers control to here +; ss:bp = 0:7C00 +; ds = 0 +virtual at bp + rb 3 ; BS_jmpBoot + rb 8 ; BS_OEMName, ignored + dw ? ; BPB_BytsPerSec +BPB_SecsPerClus db ? +BPB_RsvdSecCnt dw ? +BPB_NumFATs db ? +BPB_RootEntCnt dw ? + dw ? ; BPB_TotSec16 + db ? ; BPB_Media + dw ? ; BPB_FATSz16 = 0 for FAT32 +BPB_SecPerTrk dw ? +BPB_NumHeads dw ? +BPB_HiddSec dd ? + dd ? ; BPB_TotSec32 +BPB_FATSz32 dd ? +BPB_ExtFlags dw ? + dw ? ; BPB_FSVer +BPB_RootClus dd ? +filesize: + dw ? ; BPB_FSInfo + dw ? ; BPB_BkBootSec + rb 12 ; BPB_Reserved +BS_DrvNum db ? + db ? ; BS_Reserved1 + db ? ; BS_BootSig + dd ? ; BS_VolID +; rb 11 ; BS_VolLab +; rb 5 ; BS_FilSysType, first 5 bytes +read_sectors32 dw ? +read_sectors2 dw ? +err_ dw ? +noloader dw ? +cachelimit dw ? +fatcachehead rw 2 +fatcacheend dw ? + rb 3 ; BS_FilSysType, last 3 bytes +curseg dw ? +num_sectors dd ? +cur_cluster dd ? +next_cluster dd ? +flags dw ? +cur_delta dd ? +end virtual + +; procedures from boot sector +; LBA version +lba_read_sectors2 = 7CD6h +lba_err = 7CAAh +lba_noloader = 7CA7h ; = lba_err - 3 +; CHS version +chs_read_sectors2 = 7CD2h +chs_err = 7CA6h +chs_noloader = 7CA3h ; = chs_err - 3 + + push eax cx ; save our position on disk +; determine version of bootsector (LBA vs CHS) + mov [read_sectors2], chs_read_sectors2 + mov bx, chs_err + mov [err_], bx +; mov [noloader], chs_noloader + cmp byte [bx], 0xE8 ; [chs_err] = 0xE8 for CHS version, 0x14 for LBA version + jz @f + add [read_sectors2], lba_read_sectors2 - chs_read_sectors2 + add [err_], lba_err - chs_err +; mov [noloader], lba_noloader +@@: + xor bx, bx +; determine size of cache for folders + int 12h ; ax = size of available base memory in Kb + sub ax, 92000h / 1024 + jae @f +nomem: + mov si, nomem_str + jmp [err_] +@@: + shr ax, 3 + mov [cachelimit], ax ; size of cache - 1 + mov es, bx +; no folders in cache yet + mov di, foldcache_clus + mov cx, 8*4/2 + 1 + xor ax, ax + rep stosw +; bootsector code caches one FAT sector, [bp-14], in 6000:0000 +; initialize our (more advanced) FAT caching from this + mov di, 8400h + mov cx, di + lea si, [fatcachehead] + mov [si], si ; no sectors in cache: + mov [si+2], si ; 'prev' & 'next' links point to self + mov [fatcacheend], di ; first free item = 8400h + stosw ; 'next cached sector' link + stosw ; 'prev cached sector' link + mov eax, [bp-14] + stosd ; first sector number in cache + test eax, eax + js @f + mov [si], cx ; 'first cached sector' link = 8400h + mov [si+2], cx ; 'next cached sector' link = 8400h + mov [fatcacheend], di ; first free item = 8406h +@@: +; if cluster = sector, we need to read second part of our file +; (bootsector loads only first cluster of kordldr.f32) + pop cx eax ; restore our position on disk + cmp cx, 1 + ja kordldr_full + sub eax, [bp-10] + inc eax + inc eax ; eax = first cluster of kordldr.f32 + call get_next_cluster + jc @f +; jmp [noloader] + mov ax, [err_] + sub ax, 3 + jmp ax +@@: + dec eax + dec eax + push 0x800 + pop es + call [read_sectors2] +kordldr_full: +; bootsector code has read some data of root directory to 8000:0000 +; initialize our folder caching from this + mov eax, [BPB_RootClus] + mov [foldcache_clus], eax + mov cx, [curseg] + mov ax, 8000h + sub cx, ax ; cx = size of data read in paragraphs (0x10 bytes) + shr cx, 1 ; cx = size of folder data read in entries (0x20 bytes) + mov [foldcache_size], cx + shl cx, 4 + push ds + mov ds, ax + push 0x9000 + pop es + xor si, si + xor di, di + rep movsw + pop ds +; ...continue loading... + mov di, secondary_loader_info + call load_file + test bx, bx + mov bx, [err_] + jz @f + mov si, aKernelNotFound + jmp bx +@@: +; for subsequent calls to callback function, hook error handler +; push hooked_err / ret + mov dword [bx], 0x68 + (hooked_err shl 8) + (0xC3 shl 24) +; set registers for secondary loader + mov ah, [bp-2] ; drive id + mov al, 'f' + btr ax, 15 + jnc @f + mov al, 'h' +@@: + mov bx, '32' + mov si, callback + jmp far [si+secondary_loader_info-callback] + +nomem_str db 'No memory',0 + +cluster2sector: + sub eax, 2 +clustersz2sectorsz: + movzx ecx, [BPB_SecsPerClus] + mul ecx + ret + +get_next_cluster: +; in: eax = cluster +; out: if there is next cluster: CF=1, eax = next cluster +; out: if there is no next cluster: CF=0 + push di bx + push ds + push ss + pop ds + push ax + shr eax, 7 +; eax = FAT sector number; look in cache + mov di, 8400h +.cache_lookup: + cmp di, [fatcacheend] + jae .not_in_cache + scasd + scasd + jnz .cache_lookup +.in_cache: + sub di, 8 +; delete this sector from the list + push si + mov si, [di] + mov bx, [di+2] + mov [si+2], bx + mov [bx], si + pop si + jmp @f +.not_in_cache: +; cache miss +; cache is full? + mov di, [fatcacheend] + cmp di, 8C00h + jnz .cache_not_full +; yes, delete the oldest entry + mov di, [fatcachehead] + mov bx, [di] + mov [fatcachehead], bx + push word [di+2] + pop word [bx+2] + jmp .cache_append +.cache_not_full: +; no, allocate new sector + add [fatcacheend], 8 +.cache_append: +; read FAT + mov [di+4], eax + push es + pushad + lea cx, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] ; +0x10000 - for FASM + shl cx, 9-3 + mov es, cx + xor bx, bx + mov cx, 1 + add eax, [bp-6] ; FAT start + sub eax, [bp-10] + call [read_sectors2] + popad + pop es +@@: +; add new sector to the end of list + mov bx, di + xchg bx, [fatcachehead+2] + push word [bx] + pop word [di] + mov [bx], di + mov [di+2], bx +; get requested item + lea ax, [di + 0x10000 - 0x8400 + (0x6000 shr (9-3))] + pop di + and di, 0x7F + shl di, 2 + shl ax, 9-3 + mov ds, ax + and byte [di+3], 0x0F + mov eax, [di] + pop ds + pop bx di + ;and eax, 0x0FFFFFFF + cmp eax, 0x0FFFFFF7 + ret + +if $ > 0x8000 +error 'get_next_cluster must fit in first sector of kordldr.f32!' +end if + +load_file: +; in: ss:bp = 0:7C00 +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found +; out: dx:ax = file size (0xFFFFFFFF if file not found) + mov eax, [BPB_RootClus] ; start from root directory + or dword [filesize], -1 ; initialize file size with invalid value + lea si, [di+6] +parse_dir_loop: +; convert name to FAT name + push di + push ax + push ss + pop es +; convert ASCIIZ filename to FAT name +filename equ bp + mov di, filename + push di + mov cx, 8+3 + mov al, ' ' + rep stosb + pop di + mov cl, 8 ; 8 symbols per name + mov bl, 1 +nameloop: + lodsb + test al, al + jz namedone + cmp al, '/' + jz namedone + cmp al, '.' + jz namedot + dec cx + js badname + cmp al, 'a' + jb @f + cmp al, 'z' + ja @f + sub al, 'a'-'A' +@@: + stosb + jmp nameloop +namedot: + inc bx + jp badname + add di, cx + mov cl, 3 + jmp nameloop +badname: ; do not make direct js/jp to notfound_pop: + ; this generates long forms of conditional jumps and results in longer code + jmp notfound_pop +namedone: +; scan directory + pop ax ; eax = cluster of directory + ; high word of eax is preserved by operations above + push ds + push si +; read a folder sector-by-sector and scan +; first, try to use the cache + push ss + pop ds + mov di, foldcache_mark + xor bx, bx + mov cx, [cachelimit] +@@: + lea si, [di+bx] + mov edx, dword [foldcache_clus+si-foldcache_mark+bx] + cmp edx, eax + jz cacheok + test edx, edx + jz cacheadd ; the cache has place for new entry + inc bx + inc bx + dec cx + jns @b +; the folder is not present in the cache, so add it +; the cache is full; find the oldest entry and replace it with the new one + mov bx, -2 + mov dx, [cachelimit] +@@: + inc bx + inc bx + cmp word [di+bx], dx ; marks have values 0 through [cachelimit] + jnz @b + lea si, [di+bx] +cacheadd: + or word [di+bx], 0xFFFF ; very big value, it will be changed soon + and [foldcache_size+di-foldcache_mark+bx], 0 ; no folder items yet + mov dword [foldcache_clus+si-foldcache_mark+bx], eax +cacheok: +; update cache marks + mov dx, [di+bx] + mov cx, [foldcache_size+di-foldcache_mark+bx] + mov di, [cachelimit] + add di, di +cacheupdate: + cmp [foldcache_mark+di], dx + adc [foldcache_mark+di], 0 + dec di + dec di + jns cacheupdate + and [foldcache_mark+bx], 0 +; done, bx contains (position in cache)*2 + ;mov dx, bx + ;shl dx, 8 ; dx = (position in cache)*0x2000/0x10 + ;add dx, 0x9000 + lea dx, [bx + 0x90] + xchg dl, dh + mov ds, dx + mov si, filename ; ss:si -> filename in FAT style + call scan_for_filename + jz lookup_done +; cache miss, read folder data from disk + mov bx, cx + shr bx, 4 + shl cx, 5 + mov di, cx ; es:di -> free space in cache entry +; external loop: scan clusters +folder_next_cluster: +; internal loop: scan sectors in cluster + push eax + call cluster2sector +folder_next_sector: +; skip first bx sectors + dec bx + jns folder_skip_sector + push cx + push es di + push 0x8000 + pop es + xor bx, bx + mov cx, 1 + push es + push eax + call [read_sectors2] + pop eax +; copy data to the cache... + pop ds + pop di es + cmp di, 0x2000 ; ...if there is free space, of course + jae @f + pusha + mov cx, 0x100 + xor si, si + rep movsw + mov di, es + shr di, 8 + add [ss:foldcache_size+di-0x90], 0x10 ; 0x10 new entries in the cache + popa +@@: + push es + mov cl, 0x10 ; ch=0 at this point + call scan_for_filename + pop es + pop cx + jz lookup_done_pop +folder_skip_sector: + inc eax + loop folder_next_sector + pop eax ; eax = current cluster + call get_next_cluster + jc folder_next_cluster + stc + push eax +lookup_done_pop: + pop eax +lookup_done: + pop si +; CF=1 <=> failed + jnc found + pop ds +notfound: + pop di +notfound2: + mov bx, 2 ; file not found + mov ax, 0xFFFF + mov dx, ax ; invalid file size + ret +notfound_pop: + pop ax + jmp notfound +found: + mov eax, [di+20-2] + mov edx, [di+28] + mov ax, [di+26] ; get cluster + test byte [di+11], 10h ; directory? + pop ds + pop di + jz regular_file + cmp byte [si-1], 0 + jz notfound2 ; don't read directories as regular files +; ok, we have found a directory and the caller requested a file into it + jmp parse_dir_loop ; restart with new cluster in ax +regular_file: + cmp byte [si-1], 0 + jnz notfound2 ; file does not contain another files +; ok, we have found a regular file and the caller requested it +; save file size + mov [filesize], edx + mov si, [di+4] ; [ds:di+4] = limit in 4K blocks + shl si, 3 + push si + les bx, [di] ; es:bx -> buffer +clusloop: +; eax = first cluster, top of stack contains limit in sectors + mov esi, eax ; remember current cluster + xor ecx, ecx ; ecx will contain number of consecutive clusters + mov [cur_delta], ecx + mov edi, eax +clusfind: + inc edi + inc ecx + call get_next_cluster + jnc clusread + cmp eax, edi + jz clusfind + stc +clusread: + pop di ; limit in sectors + movzx edi, di + push eax ; save next cluster + pushf ; save flags +; read cx clusters, starting from si +; calculate number of sectors + xchg eax, ecx + call clustersz2sectorsz + mov [num_sectors], eax + jmp @f +continue_load_file: + les bx, [di] ; es:bx -> buffer + movzx edi, word [di+4] ; di = limit in 4K blocks + shl di, 3 ; now di = limit in sectors + mov eax, [num_sectors] + mov esi, [cur_cluster] + push [next_cluster] + push [flags] + test eax, eax + jz nextclus +@@: +; eax = number of sectors; compare with limit + cmp eax, edi + seta dl + push dx ; limit was exceeded? + jbe @f + mov eax, edi +@@: + sub di, ax ; calculate new limit + sub [num_sectors], eax + mov [cur_cluster], esi +; calculate starting sector + push ax + xchg eax, esi + call cluster2sector + pop cx + add eax, [cur_delta] + add [cur_delta], ecx +; read + call [read_sectors2] + pop dx +; next cluster? +nextclus: + popf + pop eax + mov [next_cluster], eax + pushf + pop [flags] + jnc @f ; no next cluster => return + mov dl, 1 ; dh=0 in any case + test di, di + jz @f ; if there is next cluster but current limit is 0 => return: limit exceeded + push di + jmp clusloop ; all is ok, continue +hooked_err: + mov sp, 7C00h-14-2 ; restore stack + mov dx, 3 ; return: read error +@@: + mov bx, dx + mov ax, [filesize] + mov dx, [filesize+2] + ret + +scan_for_filename: +; in: ss:si -> 11-bytes FAT name +; in: ds:0 -> part of directory data +; in: cx = number of entries +; in: bh = 0 +; out: if found: CF=0, ZF=1, es:di -> directory entry +; out: if not found, but continue required: CF=1 and ZF=0 +; out: if not found and zero item reached: CF=1 and ZF=1 + push ds + pop es + xor di, di + push cx + jcxz snoent +sloop: + cmp byte [di], bh + jz snotfound + test byte [di+11], 8 ; volume label? + jnz scont ; ignore volume labels + pusha + mov cx, 11 + repz cmps byte [ss:si], byte [es:di] + popa + jz sdone +scont: + add di, 0x20 + loop sloop +snoent: + inc cx ; clear ZF flag +snotfound: + stc +sdone: + pop cx +lrdret: + ret + +; Callback function for secondary loader +callback: +; in: ax = function number; only functions 1 and 2 are defined for now +; save caller's stack + mov dx, ss + mov cx, sp +; set our stack (required because we need ss=0) + xor si, si + mov ss, si + mov sp, 7C00h-10 + mov bp, 7C00h + push dx + push cx +; call our function + stc ; unsupported function + dec ax + jz callback_readfile + dec ax + jnz callback_ret +; function 2: continue loading file +; can be called only after function 1 returned value bx=1 (only part of file was loaded) +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; out: bx=0 - ok, bx=1 - still only part of file was loaded, bx=3 - read error +; out: dx:ax = file size + call continue_load_file + jmp callback_ret_succ +callback_readfile: +; function 1: read file +; in: ds:di -> information structure +; dw:dw address +; dw limit in 4Kb blocks (0x1000 bytes) (must be non-zero and not greater than 0x100) +; ASCIIZ name +; out: bx=0 - ok, bx=1 - file is too big, only part of file was loaded, bx=2 - file not found, bx=3 - read error +; out: dx:ax = file size (0xFFFFFFFF if file was not found) + call load_file +callback_ret_succ: + clc ; function is supported +callback_ret: +; restore caller's stack + pop cx + pop ss + mov sp, cx +; return to caller + retf + +secondary_loader_info: + dw 0, 0x1000 + dw 0x30000 / 0x1000 + db 'kord/loader',0 +aKernelNotFound db 'Fatal error: cannot load the secondary loader',0 + +;if $ > 0x8200 +;error 'total size of kordldr.f32 must not exceed 1024 bytes!' +;end if + +;foldcache_clus dd 0,0,0,0,0,0,0,0 ; start with no folders in cache +;foldcache_mark dw 0 +; rw 7 +;foldcache_size rw 8 +foldcache_clus rd 8 +foldcache_mark rw 8 +foldcache_size rw 8 diff --git a/kernel/trunk/sec_loader/trunk/boot/mkfloppy.inc b/kernel/trunk/sec_loader/trunk/boot/mkfloppy.inc index 1f21abab4..8acaeba40 100644 --- a/kernel/trunk/sec_loader/trunk/boot/mkfloppy.inc +++ b/kernel/trunk/sec_loader/trunk/boot/mkfloppy.inc @@ -1,90 +1,91 @@ -; --------------------------------------------------------------------------- -; mkfloppy.inc -; --------------------------------------------------------------------------- -; Created by Phantom-84 -; --------------------------------------------------------------------------- - -FA_RO equ 01h -FA_HID equ 02h -FA_SYS equ 04h -FA_VOL equ 08h -FA_DIR equ 10h -FA_ARC equ 20h - -DSTAMP equ 28C1h -TSTAMP equ 6000h - -root_size=0 - -macro reset id -{ -local count, cur, disp, val, var -times 511-($+511) mod 512 db 0 -if id#_size>0 -count=(id#_size+511)/512 -cur=id#_base/512-(33-2) -repeat count -if %=count -val=0FFFh -else -val=cur+1 -end if -if cur and 1 -val=val shl 4 -end if -disp=(cur*3)/2 -load var word from 512+disp -var=var or val -store word var at 512+disp -store word var at 10*512+disp -cur=cur+1 -end repeat -end if -} - -macro dent id, name, attr -{ -@@ db name -times @b+11-$ db 32 -db attr -dw 0, TSTAMP, DSTAMP, DSTAMP, 0, TSTAMP, DSTAMP -if id#_size=0 -dw 0 -else -dw id#_base/512-(33-2) -end if -if (attr) and FA_DIR -dd 0 -else -dd id#_size -end if -} - -macro orgdir id, parentid -{ -id#_base: -dent id, ".", FA_DIR -dent parentid, "..", FA_DIR -} - -macro findir id -{ -id#_size=$-id#_base -reset id -} - -macro stod id, parentid -{ -orgdir id, parentid -id -findir id -} - -macro stof id, name -{ -id#_base: file name -id#_size=$-id#_base -reset id -} - -defdir fix macro \ No newline at end of file +; --------------------------------------------------------------------------- +; mkfloppy.inc +; --------------------------------------------------------------------------- +; Created by Phantom-84 +; --------------------------------------------------------------------------- + +FA_RO equ 01h +FA_HID equ 02h +FA_SYS equ 04h +FA_VOL equ 08h +FA_DIR equ 10h +FA_ARC equ 20h + +DSTAMP equ 28C1h +TSTAMP equ 6000h + +root_size=0 + +macro reset id +{ +local count, cur, disp, val, var +times 511-($+511) mod 512 db 0 +if id#_size>0 +count=(id#_size+511)/512 +cur=id#_base/512-(33-2) +repeat count +if %=count +val=0FFFh +else +val=cur+1 +end if +if cur and 1 +val=val shl 4 +end if +disp=(cur*3)/2 +load var word from 512+disp +var=var or val +store word var at 512+disp +store word var at 10*512+disp +cur=cur+1 +end repeat +end if +} + +macro dent id, name, attr +{ +@@ db name +times @b+11-$ db 32 +db attr +dw 0, TSTAMP, DSTAMP, DSTAMP, 0, TSTAMP, DSTAMP +if id#_size=0 +dw 0 +else +dw id#_base/512-(33-2) +end if +if (attr) and FA_DIR +dd 0 +else +dd id#_size +end if +} + +macro orgdir id, parentid +{ +id#_base: +dent id, ".", FA_DIR +dent parentid, "..", FA_DIR +} + +macro findir id +{ +id#_size=$-id#_base +reset id +} + +macro stod id, parentid +{ +orgdir id, parentid +id +findir id +} + +macro stof id, name +{ +id#_base: + file name +id#_size=$-id#_base +reset id +} + +defdir fix macro diff --git a/kernel/trunk/sec_loader/trunk/boot_st.inc b/kernel/trunk/sec_loader/trunk/boot_st.inc index 3abf541a0..9a20931fb 100644 --- a/kernel/trunk/sec_loader/trunk/boot_st.inc +++ b/kernel/trunk/sec_loader/trunk/boot_st.inc @@ -1,68 +1,68 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -;====================================================================== -; -; BOOT DATA -; -;====================================================================== - - -version db 'Secondary Loader v 0.010',0 -version_end: - -select_section db 'Select section:' -select_section_end: -section_description db 'Section description:' -section_description_end: -soft_mes db 'Soft (c) 2008-2009' -soft_mes_end: - -badprocessor db '>Fatal - CPU 586+ required.',0 -error_ini_f1 db '>Error: cannot load ini file, buffer is full',0 -error_ini_f2 db '>Error: ini file not found',0 -error_ini_f3 db '>Error: cannot read ini file',0 -error_ini_nf db '>Error: unrecognized error when loading ini file',0 -not_found_sec_loader db '>Not found section [loader]',0 -not_found_def_sect db '>Not found value default in section [loader]',0 -default_eq_loader db '>Error in section [loader] parametr default=loader',0 -found_equal_default db '>Found equal parametr default will be use first value',0 -found_equal_timeout db '>Found equal parametr timeout will be use first value',0 -set_default_timeout_val db '>Section timeout has incorrect value, will be use default value',0 -error_ini_common db ">I will use predefined settings and try to boot. Let's hope for the best..." - db 13,10,"Press any key to continue...",0 -load_ini db '>Ini file loaded successfully',0 -parse_ini_end db '>End parsing ini file',0 -point_to_default_sec_not_found db '>Point to default section is not found in ini file',0 -incorect_section_define db ">Incorect section define not found ']'",0 -default_section_name db '"Section unname"' - -start_msg db "Press any key to change default section, press [Enter] to continue booting" -start_msg_e: -time_msg db "or wait 4 seconds before default continuation" -time_msg_e: -time_str db "seconds before default continuation" -time_str_e: +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + + +version db 'Secondary Loader v 0.010',0 +version_end: + +select_section db 'Select section:' +select_section_end: +section_description db 'Section description:' +section_description_end: +soft_mes db 'Soft (c) 2008-2009' +soft_mes_end: + +badprocessor db '>Fatal - CPU 586+ required.',0 +error_ini_f1 db '>Error: cannot load ini file, buffer is full',0 +error_ini_f2 db '>Error: ini file not found',0 +error_ini_f3 db '>Error: cannot read ini file',0 +error_ini_nf db '>Error: unrecognized error when loading ini file',0 +not_found_sec_loader db '>Not found section [loader]',0 +not_found_def_sect db '>Not found value default in section [loader]',0 +default_eq_loader db '>Error in section [loader] parametr default=loader',0 +found_equal_default db '>Found equal parametr default will be use first value',0 +found_equal_timeout db '>Found equal parametr timeout will be use first value',0 +set_default_timeout_val db '>Section timeout has incorrect value, will be use default value',0 +error_ini_common db ">I will use predefined settings and try to boot. Let's hope for the best..." + db 13,10,"Press any key to continue...",0 +load_ini db '>Ini file loaded successfully',0 +parse_ini_end db '>End parsing ini file',0 +point_to_default_sec_not_found db '>Point to default section is not found in ini file',0 +incorect_section_define db ">Incorect section define not found ']'",0 +default_section_name db '"Section unname"' + +start_msg db "Press any key to change default section, press [Enter] to continue booting" +start_msg_e: +time_msg db "or wait 4 seconds before default continuation" +time_msg_e: +time_str db "seconds before default continuation" +time_str_e: diff --git a/kernel/trunk/sec_loader/trunk/debug_msg.inc b/kernel/trunk/sec_loader/trunk/debug_msg.inc index 42a5c2804..5a8a0ac41 100644 --- a/kernel/trunk/sec_loader/trunk/debug_msg.inc +++ b/kernel/trunk/sec_loader/trunk/debug_msg.inc @@ -1,77 +1,77 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -;Тут определены все сообщения, которые нужны в процессе отладки, и совсем не нужны в рабочей копии программы. -If DEBUG -cseg_msg db ' - Adress of code segment',0 -stack_msg db 'Set stack & segments is have completed',0 -show_string db 'Have loaded size:' -show_decode db ' ',0 -show_db1 db ' -Message debug1',0 -show_db2 db ' -Message debug2',0 - - -lm_l_found db '[loader] is found',0 -lm_lf_timeout db 'timeout is found',0 -lm_lf_default db 'name default is found and end parsing section',0 -lm_lf_section db 'found section [',0 -lm_lf_default_f db 'found default parametr',0 -lm_l_end db 'section [loader] is end',0 -show_all_sect db 'SHOW ALL Sections',0 -no_show_only_w db 'Not show sections - only work on default sect',0 -_not_found db '[ not found',0 -_found_1 db '[] found',0 -_found_2 db '[ found',0 -say_hello db 'Hello $)',0 -ramdiskFS_st db 'Start use_RamdiskFS macros',0 -free_memory_msg db ' -Kb availability system free memory',0 -RamdiskSize_msg db ' -Kb equal RamdiskSize',0 -RamdiskSector_msg db ' -byts RamdiskSector',0 -RamdiskCluster_msg db ' -RamdiskCluster',0 -RamdiskFile_msg db ' -size RamdiskFile',0 -fat_create_msg db ' -first create fat table, point to next block',0 -BPB_msg db ' -in byte, why we get data from move BPB struct',0 -firstDataSect_msg db ' -first data sector, offset to data in sectors',0 -size_root_dir_msg db ' -size root dir in sectrors',0 -DataClasters_msg db ' -size data in Clasters',0 -first_entry_in_fat db ' -data segment in FIRST entry FAT',0 -check_root_fat_ db ' : --------------',0 -check_name_fat_msg_y db 'Name is present that is BAD',0 -check_name_fat_msg_n db 'Name is not present that is GOOD',0 -name_of_seg_get_64 db ' -name of seg where we get 64 Kb of data',0 -convertion_file_name_msg_y db '->Destination name of file is GOOD',0 -convertion_file_name_msg_n db '->Destination name of file is BAD',0 -alarm_msg db '%%%%%%%% WARNING: MISS THE FILE %%%%%%%%%%%',0 -start_making_FAT12_msg db '>>>>>> Begin make a RAMDISK and FS after 1 Mb <<<<<<<',0 -make_fat12_RFS_msg db '-Make FAT12 Ram FS',0 -get_type_FS_msg db '-End make RamDisk',0 -seg_where_get_data db ' - Segment where we get data for move up file',0 -return_code_af_move db ' -return code after 0x87 int 0x15, move block',0 -return_code_af_fat_m db ' -return code after 0x87 int 0x15, move fat struc',0 - - - -end if +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +;Тут определены все сообщения, которые нужны в процессе отладки, и совсем не нужны в рабочей копии программы. +If DEBUG +cseg_msg db ' - Adress of code segment',0 +stack_msg db 'Set stack & segments is have completed',0 +show_string db 'Have loaded size:' +show_decode db ' ',0 +show_db1 db ' -Message debug1',0 +show_db2 db ' -Message debug2',0 + + +lm_l_found db '[loader] is found',0 +lm_lf_timeout db 'timeout is found',0 +lm_lf_default db 'name default is found and end parsing section',0 +lm_lf_section db 'found section [',0 +lm_lf_default_f db 'found default parametr',0 +lm_l_end db 'section [loader] is end',0 +show_all_sect db 'SHOW ALL Sections',0 +no_show_only_w db 'Not show sections - only work on default sect',0 +_not_found db '[ not found',0 +_found_1 db '[] found',0 +_found_2 db '[ found',0 +say_hello db 'Hello $)',0 +ramdiskFS_st db 'Start use_RamdiskFS macros',0 +free_memory_msg db ' -Kb availability system free memory',0 +RamdiskSize_msg db ' -Kb equal RamdiskSize',0 +RamdiskSector_msg db ' -byts RamdiskSector',0 +RamdiskCluster_msg db ' -RamdiskCluster',0 +RamdiskFile_msg db ' -size RamdiskFile',0 +fat_create_msg db ' -first create fat table, point to next block',0 +BPB_msg db ' -in byte, why we get data from move BPB struct',0 +firstDataSect_msg db ' -first data sector, offset to data in sectors',0 +size_root_dir_msg db ' -size root dir in sectrors',0 +DataClasters_msg db ' -size data in Clasters',0 +first_entry_in_fat db ' -data segment in FIRST entry FAT',0 +check_root_fat_ db ' : --------------',0 +check_name_fat_msg_y db 'Name is present that is BAD',0 +check_name_fat_msg_n db 'Name is not present that is GOOD',0 +name_of_seg_get_64 db ' -name of seg where we get 64 Kb of data',0 +convertion_file_name_msg_y db '->Destination name of file is GOOD',0 +convertion_file_name_msg_n db '->Destination name of file is BAD',0 +alarm_msg db '%%%%%%%% WARNING: MISS THE FILE %%%%%%%%%%%',0 +start_making_FAT12_msg db '>>>>>> Begin make a RAMDISK and FS after 1 Mb <<<<<<<',0 +make_fat12_RFS_msg db '-Make FAT12 Ram FS',0 +get_type_FS_msg db '-End make RamDisk',0 +seg_where_get_data db ' - Segment where we get data for move up file',0 +return_code_af_move db ' -return code after 0x87 int 0x15, move block',0 +return_code_af_fat_m db ' -return code after 0x87 int 0x15, move fat struc',0 + + + +end if diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/booteng.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/booteng.inc index bb6ec980f..270148e2e 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/booteng.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/booteng.inc @@ -1,98 +1,98 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; booteng.asm the module for Secondary Loader ;; -;; ;; -;; KolibriOS 16-bit loader module, ;; -;; based on bootcode for KolibriOS ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;====================================================================== -; -; BOOT DATA -; -;====================================================================== - -d80x25_bottom: - db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' - db 'NO WARRANTY ',186 - db 186,' See file COPYING for details ' - db ' ',186 - line_full_bottom -d80x25_bottom_num = 3 - -msg_apm db " APM x.x ", 0 -vervesa db "Version of Vesa: Vesa x.x",13,10,0 -novesa db "Display: EGA/CGA",13,10,0 -s_vesa db "Version of VESA: " - .ver db "?.?",13,10,0 - -gr_mode db "Select a videomode: ",13,10,0 - -vrrmprint db "Apply VRR? (picture frequency greater than 60Hz" - db " only for transfers:",13,10 - db 186," 1024*768->800*600 and 800*600->640*480) [1-yes,2-no]:",0 - - -ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 - -bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-use preloaded ram-image from kernel restart;" - db 13,10,186," " - db "4-create blank image]: ",0 -probetext db 13,10,13,10,186," Use standart graphics mode? [1-yes, " - db "2-probe bios (Vesa 3.0)]: ",0 -prnotfnd db "Fatal - Videomode not found.",0 -not386 db "Fatal - CPU 386+ required.",0 -btns db "Fatal - Can't determine color depth.",0 -fatalsel db "Fatal - Graphics mode not supported by hardware.",0 -pres_key db "Press any key to choose a new videomode.",0 -badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 -memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "Loading diskette: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 ; 0=floppy, 1=hd -start_msg db "Press [abc] to change settings, press [Enter] to continue booting",13,10,0 -time_msg db " or wait " -time_str db " 5 seconds" - db " before automatical continuation",13,10,0 -current_cfg_msg db "Current settings:",13,10,0 -curvideo_msg db " [a] Videomode: ",0 - -mode0 db "320x200, EGA/CGA 256 colors",13,10,0 -mode9 db "640x480, VGA 16 colors",13,10,0 - -usebd_msg db " [b] Add disks visible by BIOS:",0 -on_msg db " on",13,10,0 -off_msg db " off",13,10,0 -;readonly_msg db " only for reading",13,10,0 -vrrm_msg db " [c] Use VRR:",0 -preboot_device_msg db " [d] Floppy image: ",0 -preboot_device_msgs dw 0,pdm1,pdm2,pdm3 -pdm1 db "real floppy",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -pdm3 db "use already loaded image",13,10,0 -pdm4 db "create blank image",13,10,0 -loading_msg db "Loading KolibriOS...",0 -save_quest db "Remember current settings? [y/n]: ",0 -loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 - -_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 -_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 -_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 -_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 -_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 - -remark1 db "Default values were selected to match most of configurations, but not all.",0 -remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 -remark3 db "If the system does not boot, try to disable the item [b].",0 -remarks dw remark1, remark2, remark3 -num_remarks = 3 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; booteng.asm the module for Secondary Loader ;; +;; ;; +;; KolibriOS 16-bit loader module, ;; +;; based on bootcode for KolibriOS ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + +d80x25_bottom: + db 186,' KolibriOS is based on MenuetOS and comes with ABSOLUTELY ' + db 'NO WARRANTY ',186 + db 186,' See file COPYING for details ' + db ' ',186 + line_full_bottom +d80x25_bottom_num = 3 + +msg_apm db " APM x.x ", 0 +vervesa db "Version of Vesa: Vesa x.x",13,10,0 +novesa db "Display: EGA/CGA",13,10,0 +s_vesa db "Version of VESA: " + .ver db "?.?",13,10,0 + +gr_mode db "Select a videomode: ",13,10,0 + +vrrmprint db "Apply VRR? (picture frequency greater than 60Hz" + db " only for transfers:",13,10 + db 186," 1024*768->800*600 and 800*600->640*480) [1-yes,2-no]:",0 + + +ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 + +bdev db "Load ramdisk from [1-floppy; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-use preloaded ram-image from kernel restart;" + db 13,10,186," " + db "4-create blank image]: ",0 +probetext db 13,10,13,10,186," Use standart graphics mode? [1-yes, " + db "2-probe bios (Vesa 3.0)]: ",0 +prnotfnd db "Fatal - Videomode not found.",0 +not386 db "Fatal - CPU 386+ required.",0 +btns db "Fatal - Can't determine color depth.",0 +fatalsel db "Fatal - Graphics mode not supported by hardware.",0 +pres_key db "Press any key to choose a new videomode.",0 +badsect db 13,10,186," Fatal - Bad sector. Replace floppy.",0 +memmovefailed db 13,10,186," Fatal - Int 0x15 move failed.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "Loading diskette: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 ; 0=floppy, 1=hd +start_msg db "Press [abc] to change settings, press [Enter] to continue booting",13,10,0 +time_msg db " or wait " +time_str db " 5 seconds" + db " before automatical continuation",13,10,0 +current_cfg_msg db "Current settings:",13,10,0 +curvideo_msg db " [a] Videomode: ",0 + +mode0 db "320x200, EGA/CGA 256 colors",13,10,0 +mode9 db "640x480, VGA 16 colors",13,10,0 + +usebd_msg db " [b] Add disks visible by BIOS:",0 +on_msg db " on",13,10,0 +off_msg db " off",13,10,0 +;readonly_msg db " only for reading",13,10,0 +vrrm_msg db " [c] Use VRR:",0 +preboot_device_msg db " [d] Floppy image: ",0 +preboot_device_msgs dw 0,pdm1,pdm2,pdm3 +pdm1 db "real floppy",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +pdm3 db "use already loaded image",13,10,0 +pdm4 db "create blank image",13,10,0 +loading_msg db "Loading KolibriOS...",0 +save_quest db "Remember current settings? [y/n]: ",0 +loader_block_error db "Bootloader data invalid, I cannot continue. Stopped.",0 + +_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї',13,10,0 +_r1 db 186,' і 320x200 EGA/CGA 256 colors і і',13,10,0 +_r2 db 186,' і 640x480 VGA 16 colors і і',13,10,0 +_rs db 186,' і ????x????@?? SVGA VESA і і',13,10,0 +_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ',13,10,0 + +remark1 db "Default values were selected to match most of configurations, but not all.",0 +remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 +remark3 db "If the system does not boot, try to disable the item [b].",0 +remarks dw remark1, remark2, remark3 +num_remarks = 3 diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootet.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootet.inc index c29b2b64d..4655bf20c 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootet.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootet.inc @@ -1,119 +1,119 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; kolibri_ldm.asm the module for Secondary Loader ;; -;; ;; -;; KolibriOS 16-bit loader module, ;; -;; based on bootcode for KolibriOS ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;====================================================================== -; -; BOOT DATA -; -;====================================================================== - - -d80x25_bottom: - db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' - db 'NO WARRANTY ',186 - db 186,' See file COPYING for details ' - db ' ',186 - line_full_bottom -d80x25_bottom_num = 3 - -novesa db "Ekraan: EGA/CGA",13,10,0 -vervesa db "Vesa versioon: Vesa x.x",13,10,0 -vervesa_off=20 -msg_apm db " APM x.x ", 0 -gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " - db "[3] 1024x768, [4] 1280x1024",13,10 - db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " - db "[7] 1024x768, [8] 1280x1024",13,10 - db 186," EGA/CGA 256 vдrvi: [9] 320x200, " - db "VGA 16 vдrvi: [0] 640x480",13,10 - db 186," Vali reziim: ",0 -bt24 db "Bitti pikseli kohta: 24",13,10,0 -bt32 db "Bitti pikseli kohta: 32",13,10,0 -vrrmprint db "Kinnita VRR? (ekraani sagedus suurem kui 60Hz" - db " ainult:",13,10 - db 186," 1024*768->800*600 ja 800*600->640*480) [1-jah,2-ei]:",0 -;askmouse db " Hiir:" -; db " [1] PS/2 (USB), [2] Com1, [3] Com2." -; db " Vali port [1-3]: ",0 -;no_com1 db 13,10,186, " No COM1 mouse",0 -;no_com2 db 13,10,186, " No COM2 mouse",0 -;ask_dma db "Use DMA for HDD access? [1-yes, 2-only for reading, 3-no]: ",0 -ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 -;gr_direct db 186," Use direct LFB writing? " -; db "[1-yes/2-no] ? ",0 -;mem_model db 13,10,186," Motherboard memory [1-16 Mb / 2-32 Mb / " -; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 -;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 -bdev db "Paigalda mдluketas [1-diskett; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-kasuta eellaaditud mдluketast kerneli restardist;" - db 13,10,186," " - db "4-loo tьhi pilt]: ",0 -probetext db 13,10,13,10,186," Kasuta standartset graafika reziimi? [1-jah, " - db "2-leia biosist (Vesa 3.0)]: ",0 -;memokz256 db 13,10,186," RAM 256 Mb",0 -;memokz128 db 13,10,186," RAM 128 Mb",0 -;memokz64 db 13,10,186," RAM 64 Mb",0 -;memokz32 db 13,10,186," RAM 32 Mb",0 -;memokz16 db 13,10,186," RAM 16 Mb",0 -prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 -;modena db "Fataalne - VBE 0x112+ on vajalik.",0 -not386 db "Fataalne - CPU 386+ on vajalik.",0 -btns db "Fataalne - Ei suuda vдrvisьgavust mддratleda.",0 -fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 -badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 -memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaхnnestus.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "Loen disketti: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 ; 0=floppy, 1=hd -start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jдtkamiseks",13,10,0 -time_msg db " vхi oota " -time_str db " 5 sekundit" - db " automaatseks jдtkamiseks",13,10,0 -current_cfg_msg db "Praegused seaded:",13,10,0 -curvideo_msg db " [a] Videoreziim: ",0 -mode1 db "640x480",0 -mode2 db "800x600",0 -mode3 db "1024x768",0 -mode4 db "1280x1024",0 -modes_msg dw mode4,mode1,mode2,mode3 -modevesa20 db " koos LFB",0 -modevesa12 db ", VESA 1.2 Bnk",0 -mode9 db "320x200, EGA/CGA 256 vдrvi",0 -mode10 db "640x480, VGA 16 vдrvi",0 -probeno_msg db " (standard reziim)",0 -probeok_msg db " (kontrolli ebastandardseid reziime)",0 -;dma_msg db " [b] Kasuta DMA'd HDD juurdepддsuks:",0 -usebd_msg db " [b] Add disks visible by BIOS:",0 -on_msg db " sees",13,10,0 -off_msg db " vдljas",13,10,0 -;readonly_msg db " ainult lugemiseks",13,10,0 -vrrm_msg db " [c] Kasuta VRR:",0 -preboot_device_msg db " [d] Disketi kujutis: ",0 -preboot_device_msgs dw 0,pdm1,pdm2,pdm3 -pdm1 db "reaalne diskett",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -pdm3 db "kasuta juba laaditud kujutist",13,10,0 -pdm4 db "loo tьhi pilt",13,10,0 -loading_msg db "Laadin KolibriOS...",0 -save_quest db "Jдta meelde praegused seaded? [y/n]: ",0 -loader_block_error db "Alglaaduri andmed vigased, ei saa jдtkata. Peatatud.",0 - -remark1 db "Default values were selected to match most of configurations, but not all.",0 -remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 -remark3 db "If the system does not boot, try to disable the item [b].",0 -remarks dw remark1, remark2, remark3 -num_remarks = 3 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; kolibri_ldm.asm the module for Secondary Loader ;; +;; ;; +;; KolibriOS 16-bit loader module, ;; +;; based on bootcode for KolibriOS ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + + +d80x25_bottom: + db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' + db 'NO WARRANTY ',186 + db 186,' See file COPYING for details ' + db ' ',186 + line_full_bottom +d80x25_bottom_num = 3 + +novesa db "Ekraan: EGA/CGA",13,10,0 +vervesa db "Vesa versioon: Vesa x.x",13,10,0 +vervesa_off=20 +msg_apm db " APM x.x ", 0 +gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " + db "[3] 1024x768, [4] 1280x1024",13,10 + db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " + db "[7] 1024x768, [8] 1280x1024",13,10 + db 186," EGA/CGA 256 vдrvi: [9] 320x200, " + db "VGA 16 vдrvi: [0] 640x480",13,10 + db 186," Vali reziim: ",0 +bt24 db "Bitti pikseli kohta: 24",13,10,0 +bt32 db "Bitti pikseli kohta: 32",13,10,0 +vrrmprint db "Kinnita VRR? (ekraani sagedus suurem kui 60Hz" + db " ainult:",13,10 + db 186," 1024*768->800*600 ja 800*600->640*480) [1-jah,2-ei]:",0 +;askmouse db " Hiir:" +; db " [1] PS/2 (USB), [2] Com1, [3] Com2." +; db " Vali port [1-3]: ",0 +;no_com1 db 13,10,186, " No COM1 mouse",0 +;no_com2 db 13,10,186, " No COM2 mouse",0 +;ask_dma db "Use DMA for HDD access? [1-yes, 2-only for reading, 3-no]: ",0 +ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 +;gr_direct db 186," Use direct LFB writing? " +; db "[1-yes/2-no] ? ",0 +;mem_model db 13,10,186," Motherboard memory [1-16 Mb / 2-32 Mb / " +; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 +;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 +bdev db "Paigalda mдluketas [1-diskett; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-kasuta eellaaditud mдluketast kerneli restardist;" + db 13,10,186," " + db "4-loo tьhi pilt]: ",0 +probetext db 13,10,13,10,186," Kasuta standartset graafika reziimi? [1-jah, " + db "2-leia biosist (Vesa 3.0)]: ",0 +;memokz256 db 13,10,186," RAM 256 Mb",0 +;memokz128 db 13,10,186," RAM 128 Mb",0 +;memokz64 db 13,10,186," RAM 64 Mb",0 +;memokz32 db 13,10,186," RAM 32 Mb",0 +;memokz16 db 13,10,186," RAM 16 Mb",0 +prnotfnd db "Fataalne - Videoreziimi ei leitud.",0 +;modena db "Fataalne - VBE 0x112+ on vajalik.",0 +not386 db "Fataalne - CPU 386+ on vajalik.",0 +btns db "Fataalne - Ei suuda vдrvisьgavust mддratleda.",0 +fatalsel db "Fataalne - Graafilist reziimi riistvara ei toeta.",0 +badsect db 13,10,186," Fataalne - Vigane sektor. Asenda diskett.",0 +memmovefailed db 13,10,186," Fataalne - Int 0x15 liigutamine ebaхnnestus.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "Loen disketti: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 ; 0=floppy, 1=hd +start_msg db "Vajuta [abcd] seadete muutmiseks, vajuta [Enter] laadimise jдtkamiseks",13,10,0 +time_msg db " vхi oota " +time_str db " 5 sekundit" + db " automaatseks jдtkamiseks",13,10,0 +current_cfg_msg db "Praegused seaded:",13,10,0 +curvideo_msg db " [a] Videoreziim: ",0 +mode1 db "640x480",0 +mode2 db "800x600",0 +mode3 db "1024x768",0 +mode4 db "1280x1024",0 +modes_msg dw mode4,mode1,mode2,mode3 +modevesa20 db " koos LFB",0 +modevesa12 db ", VESA 1.2 Bnk",0 +mode9 db "320x200, EGA/CGA 256 vдrvi",0 +mode10 db "640x480, VGA 16 vдrvi",0 +probeno_msg db " (standard reziim)",0 +probeok_msg db " (kontrolli ebastandardseid reziime)",0 +;dma_msg db " [b] Kasuta DMA'd HDD juurdepддsuks:",0 +usebd_msg db " [b] Add disks visible by BIOS:",0 +on_msg db " sees",13,10,0 +off_msg db " vдljas",13,10,0 +;readonly_msg db " ainult lugemiseks",13,10,0 +vrrm_msg db " [c] Kasuta VRR:",0 +preboot_device_msg db " [d] Disketi kujutis: ",0 +preboot_device_msgs dw 0,pdm1,pdm2,pdm3 +pdm1 db "reaalne diskett",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +pdm3 db "kasuta juba laaditud kujutist",13,10,0 +pdm4 db "loo tьhi pilt",13,10,0 +loading_msg db "Laadin KolibriOS...",0 +save_quest db "Jдta meelde praegused seaded? [y/n]: ",0 +loader_block_error db "Alglaaduri andmed vigased, ei saa jдtkata. Peatatud.",0 + +remark1 db "Default values were selected to match most of configurations, but not all.",0 +remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 +remark3 db "If the system does not boot, try to disable the item [b].",0 +remarks dw remark1, remark2, remark3 +num_remarks = 3 diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootge.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootge.inc index 11b157a64..4d2e5dc8c 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootge.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootge.inc @@ -1,118 +1,118 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;====================================================================== -; -; BOOT DATA -; -;====================================================================== - - -d80x25_bottom: -; db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' -; db 'NO WARRANTY ',186 -; db 186,' See file COPYING for details ' -; db ' ',186 - - db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' - db ' Garantie vertrieben ',186 - db 186,' Details stehen in der Datei COPYING ' - db ' ',186 - line_full_bottom -d80x25_bottom_num = 3 - -novesa db "Anzeige: EGA/CGA ",13,10,0 -vervesa db "Vesa-Version: Vesa ",13,10,0 -vervesa_off=22 -msg_apm db " APM x.x ", 0 -gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " - db "[3] 1024x768, [4] 1280x1024",13,10 - db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " - db "[7] 1024x768, [8] 1280x1024",13,10 - db 186," EGA/CGA 256 Farben: [9] 320x200, " - db "VGA 16 Farben: [0] 640x480",13,10 - db 186," Waehle Modus: ",0 -bt24 db "Bits Per Pixel: 24",13,10,0 -bt32 db "Bits Per Pixel: 32",13,10,0 -vrrmprint db "VRR verwenden? (Monitorfrequenz groesser als 60Hz" - db " only for transfers:",13,10 - db 186," 1024*768->800*600 und 800*600->640*480) [1-ja,2-nein]:",0 -;askmouse db " Maus angeschlossen an:" -; db " [1] PS/2 (USB), [2] Com1, [3] Com2." -; db " Waehle Port [1-3]: ",0 -;no_com1 db 13,10,186, " Keine COM1 Maus",0 -;no_com2 db 13,10,186, " Keine COM2 Maus",0 -;ask_dma db "Nutze DMA zum HDD Zugriff? [1-ja, 2-allein fur Lesen, 3-nein]: ",0 -ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 -;gr_direct db 186," Benutze direct LFB? " -; db "[1-ja/2-nein] ? ",0 -;mem_model db 13,10,186," Hauptspeicher [1-16 Mb / 2-32 Mb / " -; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 -;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 -bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-benutze ein bereits geladenes Kernel image;" - db 13,10,186," " - db "4-create blank image]: ",0 -probetext db 13,10,13,10,186," Nutze Standardgrafikmodi? [1-ja, " - db "2-BIOS Test (Vesa 3.0)]: ",0 -;memokz256 db 13,10,186," RAM 256 Mb",0 -;memokz128 db 13,10,186," RAM 128 Mb",0 -;memokz64 db 13,10,186," RAM 64 Mb",0 -;memokz32 db 13,10,186," RAM 32 Mb",0 -;memokz16 db 13,10,186," RAM 16 Mb",0 -prnotfnd db "Fatal - Videomodus nicht gefunden.",0 -;modena db "Fatal - VBE 0x112+ required.",0 -not386 db "Fatal - CPU 386+ benoetigt.",0 -btns db "Fatal - konnte Farbtiefe nicht erkennen.",0 -fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 -badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 -memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "Lade Diskette: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 ; 0=floppy, 1=hd -start_msg db "Druecke [abcd], um die Einstellungen zu aendern , druecke [Enter] zum starten",13,10,0 -time_msg db " oder warte " -time_str db " 5 Sekunden" - db " bis zum automatischen Start",13,10,0 -current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 -curvideo_msg db " [a] Videomodus: ",0 -mode1 db "640x480",0 -mode2 db "800x600",0 -mode3 db "1024x768",0 -mode4 db "1280x1024",0 -modes_msg dw mode4,mode1,mode2,mode3 -modevesa20 db " mit LFB",0 -modevesa12 db ", VESA 1.2 Bnk",0 -mode9 db "320x200, EGA/CGA 256 colors",0 -mode10 db "640x480, VGA 16 colors",0 -probeno_msg db " (Standard Modus)",0 -probeok_msg db " (teste nicht-standard Modi)",0 -;dma_msg db " [b] Nutze DMA zum HDD Aufschreiben:",0 -usebd_msg db " [b] Add disks visible by BIOS:",0 -on_msg db " an",13,10,0 -off_msg db " aus",13,10,0 -;readonly_msg db " fur Lesen",13,10,0 -vrrm_msg db " [c] Nutze VRR:",0 -preboot_device_msg db " [d] Diskettenimage: ",0 -preboot_device_msgs dw 0,pdm1,pdm2,pdm3 -pdm1 db "Echte Diskette",13,10,0 -pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -pdm3 db "Nutze bereits geladenes Image",13,10,0 -pdm4 db "create blank image",13,10,0 -loading_msg db "Lade KolibriOS...",0 -save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 -loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 - -remark1 db "Default values were selected to match most of configurations, but not all.",0 -remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 -remark3 db "If the system does not boot, try to disable the item [b].",0 -remarks dw remark1, remark2, remark3 -num_remarks = 3 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;====================================================================== +; +; BOOT DATA +; +;====================================================================== + + +d80x25_bottom: +; db 186,' KolibriOS based on MenuetOS and comes with ABSOLUTELY ' +; db 'NO WARRANTY ',186 +; db 186,' See file COPYING for details ' +; db ' ',186 + + db 186,' KolibriOS basiert auf MenuetOS und wird ohne jegliche ' + db ' Garantie vertrieben ',186 + db 186,' Details stehen in der Datei COPYING ' + db ' ',186 + line_full_bottom +d80x25_bottom_num = 3 + +novesa db "Anzeige: EGA/CGA ",13,10,0 +vervesa db "Vesa-Version: Vesa ",13,10,0 +vervesa_off=22 +msg_apm db " APM x.x ", 0 +gr_mode db 186," Vesa 2.0+ 16 M LFB: [1] 640x480, [2] 800x600, " + db "[3] 1024x768, [4] 1280x1024",13,10 + db 186," Vesa 1.2 16 M Bnk: [5] 640x480, [6] 800x600, " + db "[7] 1024x768, [8] 1280x1024",13,10 + db 186," EGA/CGA 256 Farben: [9] 320x200, " + db "VGA 16 Farben: [0] 640x480",13,10 + db 186," Waehle Modus: ",0 +bt24 db "Bits Per Pixel: 24",13,10,0 +bt32 db "Bits Per Pixel: 32",13,10,0 +vrrmprint db "VRR verwenden? (Monitorfrequenz groesser als 60Hz" + db " only for transfers:",13,10 + db 186," 1024*768->800*600 und 800*600->640*480) [1-ja,2-nein]:",0 +;askmouse db " Maus angeschlossen an:" +; db " [1] PS/2 (USB), [2] Com1, [3] Com2." +; db " Waehle Port [1-3]: ",0 +;no_com1 db 13,10,186, " Keine COM1 Maus",0 +;no_com2 db 13,10,186, " Keine COM2 Maus",0 +;ask_dma db "Nutze DMA zum HDD Zugriff? [1-ja, 2-allein fur Lesen, 3-nein]: ",0 +ask_bd db "Add disks visible by BIOS emulated in V86-mode? [1-yes, 2-no]: ",0 +;gr_direct db 186," Benutze direct LFB? " +; db "[1-ja/2-nein] ? ",0 +;mem_model db 13,10,186," Hauptspeicher [1-16 Mb / 2-32 Mb / " +; db "3-64Mb / 4-128 Mb / 5-256 Mb] ? ",0 +;bootlog db 13,10,186," After bootlog display [1-continue/2-pause] ? ",0 +bdev db "Lade die Ramdisk von [1-Diskette; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-benutze ein bereits geladenes Kernel image;" + db 13,10,186," " + db "4-create blank image]: ",0 +probetext db 13,10,13,10,186," Nutze Standardgrafikmodi? [1-ja, " + db "2-BIOS Test (Vesa 3.0)]: ",0 +;memokz256 db 13,10,186," RAM 256 Mb",0 +;memokz128 db 13,10,186," RAM 128 Mb",0 +;memokz64 db 13,10,186," RAM 64 Mb",0 +;memokz32 db 13,10,186," RAM 32 Mb",0 +;memokz16 db 13,10,186," RAM 16 Mb",0 +prnotfnd db "Fatal - Videomodus nicht gefunden.",0 +;modena db "Fatal - VBE 0x112+ required.",0 +not386 db "Fatal - CPU 386+ benoetigt.",0 +btns db "Fatal - konnte Farbtiefe nicht erkennen.",0 +fatalsel db "Fatal - Grafikmodus nicht unterstuetzt.",0 +badsect db 13,10,186," Fatal - Sektorfehler, Andere Diskette neutzen.",0 +memmovefailed db 13,10,186," Fatal - Int 0x15 Fehler.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "Lade Diskette: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 ; 0=floppy, 1=hd +start_msg db "Druecke [abcd], um die Einstellungen zu aendern , druecke [Enter] zum starten",13,10,0 +time_msg db " oder warte " +time_str db " 5 Sekunden" + db " bis zum automatischen Start",13,10,0 +current_cfg_msg db "Aktuelle Einstellungen:",13,10,0 +curvideo_msg db " [a] Videomodus: ",0 +mode1 db "640x480",0 +mode2 db "800x600",0 +mode3 db "1024x768",0 +mode4 db "1280x1024",0 +modes_msg dw mode4,mode1,mode2,mode3 +modevesa20 db " mit LFB",0 +modevesa12 db ", VESA 1.2 Bnk",0 +mode9 db "320x200, EGA/CGA 256 colors",0 +mode10 db "640x480, VGA 16 colors",0 +probeno_msg db " (Standard Modus)",0 +probeok_msg db " (teste nicht-standard Modi)",0 +;dma_msg db " [b] Nutze DMA zum HDD Aufschreiben:",0 +usebd_msg db " [b] Add disks visible by BIOS:",0 +on_msg db " an",13,10,0 +off_msg db " aus",13,10,0 +;readonly_msg db " fur Lesen",13,10,0 +vrrm_msg db " [c] Nutze VRR:",0 +preboot_device_msg db " [d] Diskettenimage: ",0 +preboot_device_msgs dw 0,pdm1,pdm2,pdm3 +pdm1 db "Echte Diskette",13,10,0 +pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +pdm3 db "Nutze bereits geladenes Image",13,10,0 +pdm4 db "create blank image",13,10,0 +loading_msg db "Lade KolibriOS...",0 +save_quest db "Aktuelle Einstellungen speichern? [y/n]: ",0 +loader_block_error db "Bootloader Daten ungueltig, Kann nicht fortfahren. Angehalten.",0 + +remark1 db "Default values were selected to match most of configurations, but not all.",0 +remark2 db "If you have LCD-monitor, disable VRR in the item [c] - you do not need it.",0 +remark3 db "If the system does not boot, try to disable the item [b].",0 +remarks dw remark1, remark2, remark3 +num_remarks = 3 diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootru.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootru.inc index c6630991e..d4ec4c7c1 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootru.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootru.inc @@ -1,87 +1,87 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;================================================================= -; -; BOOT DATA -; -;================================================================= - - -d80x25_bottom: - db 186,' Kolibri OS ®б­®ў ­  ­  Menuet OS Ё ­Ґ ЇаҐ¤®бв ў«пҐв ' - db '­ЁЄ ЄЁе Ј аa­вЁ©. ',186 - db 186,' Џ®¤а®Ў­ҐҐ ᬮваЁвҐ ў д ©«Ґ COPYING.TXT ' - db ' ',186 - line_full_bottom -msg_apm db " APM x.x ", 0 -novesa db "‚Ё¤Ґ®Є ав : EGA/CGA",13,10,0 -s_vesa db "‚ҐабЁп VESA: " - .ver db "?.?",13,10,0 - -gr_mode db "‚лЎҐаЁвҐ ўЁ¤Ґ®аҐ¦Ё¬: ",13,10,0 -vrrmprint db "€бЇ®«м§®ў вм VRR? (з бв®в  Є ¤а®ў ўлиҐ 60 ѓж" - db " в®«мЄ® ¤«п ЇҐаҐе®¤®ў:",13,10 - db 186," 1024*768>800*600 Ё 800*600>640*480) [1-¤ , 2-­Ґв]: ",0 -;ask_dma db "€бЇ®«м§®ў вм DMA ¤«п ¤®бвгЇ  Є HDD? [1-¤ , 2-в®«мЄ® з⥭ЁҐ, 3-­Ґв]: ",0 -ask_bd db "„®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS ў ०Ё¬Ґ V86? [1-¤ , 2-­Ґв]: ",0 -bdev db "‡ Јаг§Ёвм ®Ўа § Ё§ [1-¤ЁбЄҐв ; 2-C:\kolibri.img (FAT32);" - db 13,10,186," " - db "3-ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §;" - db 13,10,186," " - db "4-б®§¤ вм зЁбвл© ®Ўа §]: ",0 -prnotfnd db "ЋиЁЎЄ  - ‚Ё¤Ґ®аҐ¦Ё¬ ­Ґ ­ ©¤Ґ­.",0 -not386 db "ЋиЁЎЄ  - ’ॡгҐвбп Їа®жҐбб®а 386+.",0 -fatalsel db "ЋиЁЎЄ  - ‚лЎа ­­л© ўЁ¤Ґ®аҐ¦Ё¬ ­Ґ Ї®¤¤Ґа¦Ёў Ґвбп.",0 -pres_key db "Ќ ¦Ё¬ЁвҐ «оЎго Є« ўЁиг, ¤«п ЇҐаҐе®¤  ў ўлЎ®а ०Ё¬®ў.",0 -badsect db 13,10,186," ЋиЁЎЄ  - „ЁбЄҐв  Ї®ўаҐ¦¤Ґ­ . Џ®Їа®Ўг©вҐ ¤агЈго.",0 -memmovefailed db 13,10,186," ЋиЁЎЄ  - Int 0x15 move failed.",0 -okt db " ... OK" -linef db 13,10,0 -diskload db "‡ Јаг§Є  ¤ЁбЄҐвл: 00 %",8,8,8,8,0 -pros db "00" -backspace2 db 8,8,0 -boot_dev db 0 -start_msg db "Ќ ¦¬ЁвҐ [abc] ¤«п Ё§¬Ґ­Ґ­Ёп ­ бв஥Є, [Enter] ¤«п Їа®¤®«¦Ґ­Ёп § Јаг§ЄЁ",13,10,0 -time_msg db " Ё«Ё Ї®¤®¦¤ЁвҐ " -time_str db " 5 ᥪ㭤 " - db " ¤®  ўв®¬ вЁзҐбЄ®Ј® Їа®¤®«¦Ґ­Ёп",13,10,0 -current_cfg_msg db "’ҐЄгйЁҐ ­ бва®©ЄЁ:",13,10,0 -curvideo_msg db " [a] ‚Ё¤Ґ®аҐ¦Ё¬: ",0 - - -mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 -mode9 db "640x480, VGA 16 梥⮢",13,10,0 - -usebd_msg db " [b] „®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS:",0 -on_msg db " ўЄ«",13,10,0 -off_msg db " ўлЄ«",13,10,0 -readonly_msg db " в®«мЄ® з⥭ЁҐ",13,10,0 -vrrm_msg db " [c] €бЇ®«м§®ў ­ЁҐ VRR:",0 -;preboot_device_msg db " [d] ЋЎа § ¤ЁбЄҐвл: ",0 -;preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 -;pdm1 db "­ бв®пй п ¤ЁбЄҐв ",13,10,0 -;pdm2 db "C:\kolibri.img (FAT32)",13,10,0 -;pdm3 db "ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §",13,10,0 -;pdm4 db "б®§¤ вм зЁбвл© ®Ўа §",13,10,0 -loading_msg db "€¤св § Јаг§Є  KolibriOS...",0 -save_quest db "‡ Ї®¬­Ёвм ⥪гйЁҐ ­ бва®©ЄЁ? [y/n]: ",0 -loader_block_error db "ЋиЁЎЄ  ў ¤ ­­ле ­ з «м­®Ј® § Јаг§зЁЄ , Їа®¤®«¦Ґ­ЁҐ ­Ґў®§¬®¦­®.",0 - - -_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї ',13,10,0 -_r1 db 186,' і 320x200 EGA/CGA 256 梥⮢ і і ',13,10,0 -_r2 db 186,' і 640x480 VGA 16 梥⮢ і і ',13,10,0 -_rs db 186,' і ????x????@?? SVGA VESA і і ',13,10,0 -_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ ',13,10,0 - - -remark1 db "‡­ зҐ­Ёп Ї® 㬮«з ­Ёо ўлЎа ­л ¤«п 㤮Ўбвў  Ў®«миЁ­бвў , ­® ­Ґ ўбҐе.",0 -remark2 db "…б«Ё г ‚ б LCD-¬®­Ёв®а, ®вЄ«озЁвҐ VRR ў Їг­ЄвҐ [c] - ®­ ‚ ¬ ­Ґ ­г¦Ґ­.",0 -remark3 db "…б«Ё г ‚ б ­Ґ Јаг§Ёвбп бЁб⥬ , Ї®Їа®Ўг©вҐ ®вЄ«озЁвм Їг­Єв [b].",0 -remarks dw remark1, remark2, remark3 -num_remarks = 3 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;================================================================= +; +; BOOT DATA +; +;================================================================= + + +d80x25_bottom: + db 186,' Kolibri OS ®б­®ў ­  ­  Menuet OS Ё ­Ґ ЇаҐ¤®бв ў«пҐв ' + db '­ЁЄ ЄЁе Ј аa­вЁ©. ',186 + db 186,' Џ®¤а®Ў­ҐҐ ᬮваЁвҐ ў д ©«Ґ COPYING.TXT ' + db ' ',186 + line_full_bottom +msg_apm db " APM x.x ", 0 +novesa db "‚Ё¤Ґ®Є ав : EGA/CGA",13,10,0 +s_vesa db "‚ҐабЁп VESA: " + .ver db "?.?",13,10,0 + +gr_mode db "‚лЎҐаЁвҐ ўЁ¤Ґ®аҐ¦Ё¬: ",13,10,0 +vrrmprint db "€бЇ®«м§®ў вм VRR? (з бв®в  Є ¤а®ў ўлиҐ 60 ѓж" + db " в®«мЄ® ¤«п ЇҐаҐе®¤®ў:",13,10 + db 186," 1024*768>800*600 Ё 800*600>640*480) [1-¤ , 2-­Ґв]: ",0 +;ask_dma db "€бЇ®«м§®ў вм DMA ¤«п ¤®бвгЇ  Є HDD? [1-¤ , 2-в®«мЄ® з⥭ЁҐ, 3-­Ґв]: ",0 +ask_bd db "„®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS ў ०Ё¬Ґ V86? [1-¤ , 2-­Ґв]: ",0 +bdev db "‡ Јаг§Ёвм ®Ўа § Ё§ [1-¤ЁбЄҐв ; 2-C:\kolibri.img (FAT32);" + db 13,10,186," " + db "3-ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §;" + db 13,10,186," " + db "4-б®§¤ вм зЁбвл© ®Ўа §]: ",0 +prnotfnd db "ЋиЁЎЄ  - ‚Ё¤Ґ®аҐ¦Ё¬ ­Ґ ­ ©¤Ґ­.",0 +not386 db "ЋиЁЎЄ  - ’ॡгҐвбп Їа®жҐбб®а 386+.",0 +fatalsel db "ЋиЁЎЄ  - ‚лЎа ­­л© ўЁ¤Ґ®аҐ¦Ё¬ ­Ґ Ї®¤¤Ґа¦Ёў Ґвбп.",0 +pres_key db "Ќ ¦Ё¬ЁвҐ «оЎго Є« ўЁиг, ¤«п ЇҐаҐе®¤  ў ўлЎ®а ०Ё¬®ў.",0 +badsect db 13,10,186," ЋиЁЎЄ  - „ЁбЄҐв  Ї®ўаҐ¦¤Ґ­ . Џ®Їа®Ўг©вҐ ¤агЈго.",0 +memmovefailed db 13,10,186," ЋиЁЎЄ  - Int 0x15 move failed.",0 +okt db " ... OK" +linef db 13,10,0 +diskload db "‡ Јаг§Є  ¤ЁбЄҐвл: 00 %",8,8,8,8,0 +pros db "00" +backspace2 db 8,8,0 +boot_dev db 0 +start_msg db "Ќ ¦¬ЁвҐ [abc] ¤«п Ё§¬Ґ­Ґ­Ёп ­ бв஥Є, [Enter] ¤«п Їа®¤®«¦Ґ­Ёп § Јаг§ЄЁ",13,10,0 +time_msg db " Ё«Ё Ї®¤®¦¤ЁвҐ " +time_str db " 5 ᥪ㭤 " + db " ¤®  ўв®¬ вЁзҐбЄ®Ј® Їа®¤®«¦Ґ­Ёп",13,10,0 +current_cfg_msg db "’ҐЄгйЁҐ ­ бва®©ЄЁ:",13,10,0 +curvideo_msg db " [a] ‚Ё¤Ґ®аҐ¦Ё¬: ",0 + + +mode0 db "320x200, EGA/CGA 256 梥⮢",13,10,0 +mode9 db "640x480, VGA 16 梥⮢",13,10,0 + +usebd_msg db " [b] „®Ў ўЁвм ¤ЁбЄЁ, ўЁ¤Ё¬лҐ зҐаҐ§ BIOS:",0 +on_msg db " ўЄ«",13,10,0 +off_msg db " ўлЄ«",13,10,0 +readonly_msg db " в®«мЄ® з⥭ЁҐ",13,10,0 +vrrm_msg db " [c] €бЇ®«м§®ў ­ЁҐ VRR:",0 +;preboot_device_msg db " [d] ЋЎа § ¤ЁбЄҐвл: ",0 +;preboot_device_msgs dw 0,pdm1,pdm2,pdm3,pdm4 +;pdm1 db "­ бв®пй п ¤ЁбЄҐв ",13,10,0 +;pdm2 db "C:\kolibri.img (FAT32)",13,10,0 +;pdm3 db "ЁбЇ®«м§®ў вм 㦥 § Ја㦥­­л© ®Ўа §",13,10,0 +;pdm4 db "б®§¤ вм зЁбвл© ®Ўа §",13,10,0 +loading_msg db "€¤св § Јаг§Є  KolibriOS...",0 +save_quest db "‡ Ї®¬­Ёвм ⥪гйЁҐ ­ бва®©ЄЁ? [y/n]: ",0 +loader_block_error db "ЋиЁЎЄ  ў ¤ ­­ле ­ з «м­®Ј® § Јаг§зЁЄ , Їа®¤®«¦Ґ­ЁҐ ­Ґў®§¬®¦­®.",0 + + +_st db 186,' ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДї ',13,10,0 +_r1 db 186,' і 320x200 EGA/CGA 256 梥⮢ і і ',13,10,0 +_r2 db 186,' і 640x480 VGA 16 梥⮢ і і ',13,10,0 +_rs db 186,' і ????x????@?? SVGA VESA і і ',13,10,0 +_bt db 186,' АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДБДЩ ',13,10,0 + + +remark1 db "‡­ зҐ­Ёп Ї® 㬮«з ­Ёо ўлЎа ­л ¤«п 㤮Ўбвў  Ў®«миЁ­бвў , ­® ­Ґ ўбҐе.",0 +remark2 db "…б«Ё г ‚ б LCD-¬®­Ёв®а, ®вЄ«озЁвҐ VRR ў Їг­ЄвҐ [c] - ®­ ‚ ¬ ­Ґ ­г¦Ґ­.",0 +remark3 db "…б«Ё г ‚ б ­Ґ Јаг§Ёвбп бЁб⥬ , Ї®Їа®Ўг©вҐ ®вЄ«озЁвм Їг­Єв [b].",0 +remarks dw remark1, remark2, remark3 +num_remarks = 3 diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootstr.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootstr.inc index c2f2df132..7c6b3ab78 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootstr.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootstr.inc @@ -1,55 +1,56 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - - -; boot data: common strings (for all languages) -macro line_full_top { - db 201 - times 78 db 205 - db 187 -} -macro line_full_bottom { - db 200 - times 78 db 205 - db 188 -} -macro line_half { - db 186,' ' - times 76 db 0xc4 - db ' ',186 -} -macro line_space { - db 186 - times 78 db 32 - db 186 -} -d80x25_top: - line_full_top -cur_line_pos = 75 -; store byte ' ' at d80x25_top+cur_line_pos+1 -; store byte ' ' at d80x25_top+cur_line_pos -; store dword ' SVN' at d80x25_top+cur_line_pos-4 - -space_msg: line_space -;verstr: -; line_space -; version string -; db 186,32 -; repeat 78 -; load a byte from version+%-1 -; if a = 13 -; break -; end if -; db a -; end repeat -; repeat 78 - ($-verstr) -; db ' ' -; end repeat -; db 32,186 -; line_half - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +; boot data: common strings (for all languages) +macro line_full_top { + db 201 + times 78 db 205 + db 187 +} +macro line_full_bottom { + db 200 + times 78 db 205 + db 188 +} +macro line_half { + db 186,' ' + times 76 db 0xc4 + db ' ',186 +} +macro line_space { + db 186 + times 78 db 32 + db 186 +} +d80x25_top: + line_full_top +cur_line_pos = 75 +; store byte ' ' at d80x25_top+cur_line_pos+1 +; store byte ' ' at d80x25_top+cur_line_pos +; store dword ' SVN' at d80x25_top+cur_line_pos-4 + +space_msg: + line_space +;verstr: +; line_space +; version string +; db 186,32 +; repeat 78 +; load a byte from version+%-1 +; if a = 13 +; break +; end if +; db a +; end repeat +; repeat 78 - ($-verstr) +; db ' ' +; end repeat +; db 32,186 +; line_half + diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootvesa.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootvesa.inc index b6ee2bb0e..6193f0e60 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootvesa.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/bootvesa.inc @@ -1,754 +1,762 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -struc VBE_VGAInfo { - .VESASignature dd ? ; char - .VESAVersion dw ? ; short - .OemStringPtr dd ? ; char * - .Capabilities dd ? ; ulong - .VideoModePtr dd ? ; ulong - .TotalMemory dw ? ; short - ; VBE 2.0+ - .OemSoftwareRev db ? ; short - .OemVendorNamePtr dw ? ; char * - .OemProductNamePtr dw ? ; char * - .OemProductRevPtr dw ? ; char * - .reserved rb 222 ; char - .OemData rb 256 ; char -} - -struc VBE_ModeInfo { - .ModeAttributes dw ? ; short - .WinAAttributes db ? ; char - .WinBAttributes db ? ; char - .WinGranularity dw ? ; short - .WinSize dw ? ; short - .WinASegment dw ? ; ushort - .WinBSegment dw ? ; ushort - .WinFuncPtr dd ? ; void * - .BytesPerScanLine dw ? ; short - .XRes dw ? ; short - .YRes dw ? ; short - .XCharSize db ? ; char - .YCharSize db ? ; char - .NumberOfPlanes db ? ; char - .BitsPerPixel db ? ; char - .NumberOfBanks db ? ; char - .MemoryModel db ? ; char - .BankSize db ? ; char - .NumberOfImagePages db ? ; char - .res1 db ? ; char - .RedMaskSize db ? ; char - .RedFieldPosition db ? ; char - .GreenMaskSize db ? ; char - .GreenFieldPosition db ? ; char - .BlueMaskSize db ? ; char - .BlueFieldPosition db ? ; char - .RsvedMaskSize db ? ; char - .RsvedFieldPosition db ? ; char - .DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE - ; VBE 2.0+ - .PhysBasePtr dd ? ; ulong - .OffScreenMemOffset dd ? ; ulong - .OffScreenMemSize dw ? ; short - ; VBE 3.0+ - .LinbytesPerScanLine dw ? ; short - .BankNumberOfImagePages db ? ; char - .LinNumberOfImagePages db ? ; char - .LinRedMaskSize db ? ; char - .LinRedFieldPosition db ? ; char - .LingreenMaskSize db ? ; char - .LinGreenFieldPosition db ? ; char - .LinBlueMaskSize db ? ; char - .LinBlueFieldPosition db ? ; char - .LinRsvdMaskSize db ? ; char - .LinRsvdFieldPosition db ? ; char - .MaxPixelClock dd ? ; ulong - .res2 rb 190 ; char -} - -virtual at $A000 - vi VBE_VGAInfo - mi VBE_ModeInfo -modes_table: -end virtual -cursor_pos dw 0 ;временное хранение курсора. -home_cursor dw 0 ;current shows rows a table -end_cursor dw 0 ;end of position current shows rows a table -scroll_start dw 0 ;start position of scroll bar -scroll_end dw 0 ;end position of scroll bar -long_v_table equ 9 ;long of visible video table -size_of_step equ 10 -scroll_area_size equ (long_v_table-2) -int2str: - dec bl - jz @f - xor edx,edx - div ecx - push edx - call int2str - pop eax - @@: or al,0x30 - mov [ds:di],al - inc di - ret - -int2strnz: - cmp eax,ecx - jb @f - xor edx,edx - div ecx - push edx - call int2strnz - pop eax - @@: or al,0x30 - mov [es:di],al - inc di - ret - -;------------------------------------------------------- -;Write message about incorrect v_mode and write message about jmp on swith v_mode -v_mode_error: - _setcursor 19,2 - mov si, fatalsel - call printplain - _setcursor 20,2 - mov si,pres_key - call printplain - xor eax,eax - int 16h - jmp cfgmanager.d -;------------------------------------------------------- -; - - - -;------------------------------------------------------- -print_vesa_info: - _setcursor 5,2 - - mov [es:vi.VESASignature],'VBE2' - mov ax,0x4F00 - mov di,vi ;0xa000 - int 0x10 - or ah,ah - jz @f - mov [es:vi.VESASignature],'VESA' - mov ax,$4F00 - mov di,vi - int 0x10 - or ah,ah - jnz .exit - @@: - cmp [es:vi.VESASignature],'VESA' - jne .exit - cmp [es:vi.VESAVersion],0x0100 - jb .exit - jmp .vesaok2 - - .exit: - mov si,novesa - call printplain - ret - - .vesaok2: - mov ax,[es:vi.VESAVersion] - add ax,'00' - - mov [s_vesa.ver], ah - mov [s_vesa.ver+2], al - mov si,s_vesa - call printplain - - _setcursor 4,2 - mov si,word[es:vi.OemStringPtr] - mov di,si - - push ds - mov ds,word[es:vi.OemStringPtr+2] - call printplain - pop ds - - ret -;----------------------------------------------------------------------------- - -calc_vmodes_table: - pushad - -; push 0 -; pop es - - lfs si, [es:vi.VideoModePtr] - - mov bx,modes_table -;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ - mov word [es:bx],640 - mov word [es:bx+2],480 - mov word [es:bx+6],0x13 - - mov word [es:bx+10],640 - mov word [es:bx+12],480 - mov word [es:bx+16],0x12 - add bx,20 - .next_mode: - mov cx,word [fs:si] ; mode number - cmp cx,-1 - je .modes_ok.2 - - mov ax,0x4F01 - mov di,mi - int 0x10 - - or ah,ah - jnz .modes_ok.2;vesa_info.exit - - test [es:mi.ModeAttributes],00000001b ;videomode support ? - jz @f - test [es:mi.ModeAttributes],00010000b ;picture ? - jz @f - test [es:mi.ModeAttributes],10000000b ;LFB ? - jz @f - - cmp [es:mi.BitsPerPixel], 24 ;It show only videomodes to have support 24 and 32 bpp - jb @f - -; cmp [es:mi.BitsPerPixel],16 -; jne .l0 -; cmp [es:mi.GreenMaskSize],5 -; jne .l0 -; mov [es:mi.BitsPerPixel],15 - - -.l0: - cmp [es:mi.XRes],640 - jb @f - cmp [es:mi.YRes],480 - jb @f -; cmp [es:mi.BitsPerPixel],8 -; jb @f - - mov ax,[es:mi.XRes] - mov [es:bx+0],ax ; +0[2] : resolution X - mov ax,[es:mi.YRes] - mov [es:bx+2],ax ; +2[2] : resolution Y - mov ax,[es:mi.ModeAttributes] - mov [es:bx+4],ax ; +4[2] : attributes - - cmp [s_vesa.ver],'2' - jb .lp1 - - or cx,0x4000 ; use LFB -.lp1: mov [es:bx+6],cx ; +6 : mode number - movzx ax,byte [es:mi.BitsPerPixel] - mov word [es:bx+8],ax ; +8 : bits per pixel - add bx,size_of_step ; size of record - - @@: - add si,2 - jmp .next_mode - - .modes_ok.2: - - mov word[es:bx],-1 ;end video table - mov word[end_cursor],bx ;save end cursor position -;;;;;;;;;;;;;;;;;; -;Sort array -; mov si,modes_table -;.new_mode: -; mov ax,word [es:si] -; cmp ax,-1 -; je .exxit -; add ax,word [es:si+2] -; add ax,word [es:si+8] -; mov bp,si -;.again: -; add bp,12 -; mov bx,word [es:bp] -; cmp bx,-1 -; je .exit -; add bx,word [es:bp+2] -; add bx,word [es:bp+8] -; -; cmp ax,bx -; ja .loops -; jmp .again -;.loops: -; push dword [es:si] -; push dword [es:si+4] -; push dword [es:si+8] -; push dword [es:bp] -; push dword [es:bp+4] -; push dword [es:bp+8] -; -; pop dword [es:si+8] -; pop dword [es:si+4] -; pop dword [es:si] -; pop dword [es:bp+8] -; pop dword [es:bp+4] -; pop dword [es:bp] -; jmp .new_mode -; -;.exit: add si,12 -; jmp .new_mode -;.exxit: - popad - ret - -;----------------------------------------------------------------------------- - -draw_current_vmode: - push 0 - pop es - - mov si,word [cursor_pos] - - cmp word [es:si+6],0x12 - je .no_vesa_0x12 - - cmp word [es:si+6],0x13 - je .no_vesa_0x13 - - mov di,loader_block_error - movzx eax,word[es:si+0] - mov ecx,10 - call int2strnz - mov byte[es:di],'x' - inc di - movzx eax,word[es:si+2] - call int2strnz - mov byte[es:di],'x' - inc di - movzx eax,word[es:si+8] - call int2strnz - mov dword[es:di],0x00000d0a - mov si,loader_block_error - push ds - push es - pop ds - call printplain - pop ds - ret -.no_vesa_0x13: - mov si,mode0 - jmp .print -.no_vesa_0x12: - mov si,mode9 -.print: - call printplain - ret -;----------------------------------------------------------------------------- -check_first_parm: - mov si,word [preboot_graph] - test si,si - jnz .no_zero ;if no zero -.zerro: -; mov ax,modes_table -; mov word [cursor_pos],ax -; mov word [home_cursor],ax -; mov word [preboot_graph],ax -;SET default video of mode first probe will fined a move of work 1024x768@32 - - mov ax,1024 - mov bx,768 - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - mov ax,800 - mov bx,600 - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - mov ax,640 - mov bx,480 - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - - mov si,modes_table - jmp .ok_found_mode - - - -.no_zero: - mov bp,word [number_vm] - cmp bp,word [es:si+6] - jz .ok_found_mode - mov ax,word [x_save] - mov bx,word [y_save] - mov si,modes_table - call .loops - test ax,ax - jz .ok_found_mode - - mov si,modes_table -; cmp ax,modes_table -; jb .zerro ;check on correct if bellow -; cmp ax,word [end_cursor] -; ja .zerro ;check on correct if anymore - -.ok_found_mode: - mov word [home_cursor],si -; mov word [cursor_pos],si - mov word [preboot_graph],si - mov ax,si - - mov ecx,long_v_table - -.loop: add ax,size_of_step - cmp ax,word [end_cursor] - jae .next_step - loop .loop -.next_step: - sub ax,size_of_step*long_v_table - cmp ax,modes_table - jae @f - mov ax,modes_table -@@: - - mov word [home_cursor],ax - mov si,[preboot_graph] - mov word [cursor_pos],si - - push word [es:si] - pop word [x_save] - push word [es:si+2] - pop word [y_save] - push word [es:si+6] - pop word [number_vm] - - ret -;;;;;;;;;;;;;;;;;;;;;;;;;;; -.loops: - cmp ax,word [es:si] - jne .next - cmp bx,word [es:si+2] - jne .next - cmp word [es:si+8],32 - je .ok - cmp word [es:si+8],24 - je .ok -.next: add si,size_of_step - cmp word [es:si],-1 - je .exit - jmp .loops -.ok: xor ax,ax - ret -.exit: or ax,-1 - ret - - -;----------------------------------------------------------------------------- - -;default_vmode: - -;----------------------------------------------------------------------------- -draw_vmodes_table: - _setcursor 9, 2 - mov si,gr_mode - call printplain - - mov si,_st - call printplain - - push word [cursor_pos] - pop ax - push word [home_cursor] - pop si - mov cx,si - - cmp ax,si - je .ok - jb .low - - - add cx,size_of_step*long_v_table - - cmp ax,cx - jb .ok - - sub cx,size_of_step*long_v_table - add cx,size_of_step - cmp cx,word[end_cursor] - jae .ok - add si,size_of_step - push si - pop word [home_cursor] - jmp .ok - - -.low: sub cx,size_of_step - cmp cx,modes_table - jb .ok - push cx - push cx - pop word [home_cursor] - pop si - - -.ok: -; calculate scroll position - push si - mov ax, [end_cursor] - sub ax, modes_table - mov bx, size_of_step - cwd - div bx - mov si, ax ; si = size of list - mov ax, [home_cursor] - sub ax, modes_table - cwd - div bx - mov di, ax - mov ax, scroll_area_size*long_v_table - cwd - div si - test ax, ax - jnz @f - inc ax -@@: - cmp al, scroll_area_size - jb @f - mov al, scroll_area_size -@@: - mov cx, ax -; cx = scroll height -; calculate scroll pos - xor bx, bx ; initialize scroll pos - sub al, scroll_area_size+1 - neg al - sub si, long_v_table-1 - jbe @f - mul di - div si - mov bx, ax -@@: - inc bx - imul ax, bx, size_of_step - add ax, [home_cursor] - mov [scroll_start], ax - imul cx, size_of_step - add ax, cx - mov [scroll_end], ax - pop si - mov bp,long_v_table ;show rows -.@@_next_bit: -;clear cursor - mov ax,' ' - mov word[ds:_r1+21],ax - mov word[ds:_r1+50],ax - - mov word[ds:_r2+21],ax - mov word[ds:_r2+45],ax - - mov word[ds:_rs+21],ax - mov word[ds:_rs+46],ax -; draw string - cmp word [es:si+6],0x12 - je .show_0x12 - cmp word [es:si+6],0x13 - je .show_0x13 - - movzx eax,word[es:si] - cmp ax,-1 - je .@@_end - mov di,_rs+23 - mov ecx,10 - mov bl,4 - call int2str - movzx eax,word[es:si+2] - inc di - mov bl,4 - call int2str - - movzx eax,word[es:si+8] - inc di - mov bl,2 - call int2str - - cmp si, word [cursor_pos] - jne .next -;draw cursor - mov word[ds:_rs+21],'>>' - mov word[ds:_rs+46],'<<' - - - -.next: - push si - mov si,_rs -.@@_sh: -; add to the string pseudographics for scrollbar - pop bx - push bx - mov byte [si+53], ' ' - cmp bx, [scroll_start] - jb @f - cmp bx, [scroll_end] - jae @f - mov byte [si+53], 0xDB ; filled bar -@@: - push bx - add bx, size_of_step - cmp bx, [end_cursor] - jnz @f - mov byte [si+53], 31 ; 'down arrow' symbol -@@: - sub bx, [home_cursor] - cmp bx, size_of_step*long_v_table - jnz @f - mov byte [si+53], 31 ; 'down arrow' symbol -@@: - pop bx - cmp bx, [home_cursor] - jnz @f - mov byte [si+53], 30 ; 'up arrow' symbol -@@: - call printplain - pop si - add si,size_of_step - - dec bp - jnz .@@_next_bit - -.@@_end: - mov si,_bt - call printplain - ret -.show_0x13: - push si - - cmp si, word [cursor_pos] - jne @f - mov word[ds:_r1+21],'>>' - mov word[ds:_r1+50],'<<' -@@: - mov si,_r1 - jmp .@@_sh -.show_0x12: - push si - cmp si, word [cursor_pos] - jne @f - - mov word[ds:_r2+21],'>>' - mov word[ds:_r2+45],'<<' -@@: - mov si,_r2 - jmp .@@_sh - -;----------------------------------------------------------------------------- -;Clear arrea of current video page (0xb800) -clear_vmodes_table: - pusha - ; draw frames - push es - push 0xb800 - pop es - mov di,1444 - xor ax,ax - mov ah, 1*16+15 - mov cx,70 - mov bp,12 -.loop_start: - rep stosw - mov cx,70 - add di,20 - dec bp - jns .loop_start - pop es - popa - ret - -;----------------------------------------------------------------------------- - -set_vmode: - push 0 ;0;x1000 - pop es - - mov si,word [preboot_graph] ;[preboot_graph] - mov cx,word [es:si+6] ; number of mode - - - mov ax,word [es:si+0] ; resolution X - mov bx,word [es:si+2] ; resolution Y - - - mov word [es:0x900A],ax ; resolution X - mov word [es:0x900C],bx ; resolution Y - mov word [es:0x9008],cx ; number of mode - - cmp cx,0x12 - je .mode0x12_0x13 - cmp cx,0x13 - je .mode0x12_0x13 - - - cmp byte [s_vesa.ver],'2' - jb .vesa12 - -; VESA 2 and Vesa 3 - - mov ax,0x4f01 - and cx,0xfff - mov di,mi;0xa000 - int 0x10 - ; LFB - mov eax,[es:mi.PhysBasePtr];di+0x28] - mov [es:0x9018],eax - ; ---- vbe voodoo - BytesPerLine equ 0x10 - mov ax, [es:di+BytesPerLine] - mov [es:0x9001], ax - ; BPP - cmp [es:mi.BitsPerPixel],16 - jne .l0 - cmp [es:mi.GreenMaskSize],5 - jne .l0 - mov [es:mi.BitsPerPixel],15 -.l0: - mov al, byte [es:di+0x19] - mov [es:0x9000], al - jmp .exit - -.mode0x12_0x13: - mov byte [es:0x9000], 32 - or dword [es:0x9018], 0xFFFFFFFF; 0x800000 - - -; VESA 1.2 PM BANK SWITCH ADDRESS - -.vesa12: - - - mov ax,0x4f0A - xor bx,bx - int 0x10 - xor eax,eax - xor ebx,ebx - mov ax,es - shl eax,4 - mov bx,di - add eax,ebx - movzx ebx,word[es:di] - add eax,ebx - push 0x0000 - pop es - mov [es:0x9014],eax - .exit: - ret - - -; mov dword[es:0x9018],0x000A0000 -; ret - -;============================================================================= -;============================================================================= -;============================================================================= - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +struc VBE_VGAInfo { + .VESASignature dd ? ; char + .VESAVersion dw ? ; short + .OemStringPtr dd ? ; char * + .Capabilities dd ? ; ulong + .VideoModePtr dd ? ; ulong + .TotalMemory dw ? ; short + ; VBE 2.0+ + .OemSoftwareRev db ? ; short + .OemVendorNamePtr dw ? ; char * + .OemProductNamePtr dw ? ; char * + .OemProductRevPtr dw ? ; char * + .reserved rb 222 ; char + .OemData rb 256 ; char +} + +struc VBE_ModeInfo { + .ModeAttributes dw ? ; short + .WinAAttributes db ? ; char + .WinBAttributes db ? ; char + .WinGranularity dw ? ; short + .WinSize dw ? ; short + .WinASegment dw ? ; ushort + .WinBSegment dw ? ; ushort + .WinFuncPtr dd ? ; void * + .BytesPerScanLine dw ? ; short + .XRes dw ? ; short + .YRes dw ? ; short + .XCharSize db ? ; char + .YCharSize db ? ; char + .NumberOfPlanes db ? ; char + .BitsPerPixel db ? ; char + .NumberOfBanks db ? ; char + .MemoryModel db ? ; char + .BankSize db ? ; char + .NumberOfImagePages db ? ; char + .res1 db ? ; char + .RedMaskSize db ? ; char + .RedFieldPosition db ? ; char + .GreenMaskSize db ? ; char + .GreenFieldPosition db ? ; char + .BlueMaskSize db ? ; char + .BlueFieldPosition db ? ; char + .RsvedMaskSize db ? ; char + .RsvedFieldPosition db ? ; char + .DirectColorModeInfo db ? ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE + ; VBE 2.0+ + .PhysBasePtr dd ? ; ulong + .OffScreenMemOffset dd ? ; ulong + .OffScreenMemSize dw ? ; short + ; VBE 3.0+ + .LinbytesPerScanLine dw ? ; short + .BankNumberOfImagePages db ? ; char + .LinNumberOfImagePages db ? ; char + .LinRedMaskSize db ? ; char + .LinRedFieldPosition db ? ; char + .LingreenMaskSize db ? ; char + .LinGreenFieldPosition db ? ; char + .LinBlueMaskSize db ? ; char + .LinBlueFieldPosition db ? ; char + .LinRsvdMaskSize db ? ; char + .LinRsvdFieldPosition db ? ; char + .MaxPixelClock dd ? ; ulong + .res2 rb 190 ; char +} + +virtual at $A000 + vi VBE_VGAInfo + mi VBE_ModeInfo +modes_table: +end virtual +cursor_pos dw 0 ;временное хранение курсора. +home_cursor dw 0 ;current shows rows a table +end_cursor dw 0 ;end of position current shows rows a table +scroll_start dw 0 ;start position of scroll bar +scroll_end dw 0 ;end position of scroll bar +long_v_table equ 9 ;long of visible video table +size_of_step equ 10 +scroll_area_size equ (long_v_table-2) +int2str: + dec bl + jz @f + xor edx, edx + div ecx + push edx + call int2str + pop eax + @@: + or al, 0x30 + mov [ds:di], al + inc di + ret + +int2strnz: + cmp eax, ecx + jb @f + xor edx, edx + div ecx + push edx + call int2strnz + pop eax + @@: + or al, 0x30 + mov [es:di], al + inc di + ret + +;------------------------------------------------------- +;Write message about incorrect v_mode and write message about jmp on swith v_mode +v_mode_error: + _setcursor 19,2 + mov si, fatalsel + call printplain + _setcursor 20,2 + mov si, pres_key + call printplain + xor eax, eax + int 16h + jmp cfgmanager.d +;------------------------------------------------------- +; + + + +;------------------------------------------------------- +print_vesa_info: + _setcursor 5,2 + + mov [es:vi.VESASignature], 'VBE2' + mov ax, 0x4F00 + mov di, vi ;0xa000 + int 0x10 + or ah, ah + jz @f + mov [es:vi.VESASignature], 'VESA' + mov ax, $4F00 + mov di, vi + int 0x10 + or ah, ah + jnz .exit + @@: + cmp [es:vi.VESASignature], 'VESA' + jne .exit + cmp [es:vi.VESAVersion], 0x0100 + jb .exit + jmp .vesaok2 + + .exit: + mov si, novesa + call printplain + ret + + .vesaok2: + mov ax, [es:vi.VESAVersion] + add ax, '00' + + mov [s_vesa.ver], ah + mov [s_vesa.ver+2], al + mov si, s_vesa + call printplain + + _setcursor 4,2 + mov si, word[es:vi.OemStringPtr] + mov di, si + + push ds + mov ds, word[es:vi.OemStringPtr+2] + call printplain + pop ds + + ret +;----------------------------------------------------------------------------- + +calc_vmodes_table: + pushad + +; push 0 +; pop es + + lfs si, [es:vi.VideoModePtr] + + mov bx, modes_table +;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢ + mov word [es:bx], 640 + mov word [es:bx+2], 480 + mov word [es:bx+6], 0x13 + + mov word [es:bx+10], 640 + mov word [es:bx+12], 480 + mov word [es:bx+16], 0x12 + add bx, 20 + .next_mode: + mov cx, word [fs:si]; mode number + cmp cx, -1 + je .modes_ok.2 + + mov ax, 0x4F01 + mov di, mi + int 0x10 + + or ah, ah + jnz .modes_ok.2;vesa_info.exit + + test [es:mi.ModeAttributes], 00000001b ;videomode support ? + jz @f + test [es:mi.ModeAttributes], 00010000b ;picture ? + jz @f + test [es:mi.ModeAttributes], 10000000b ;LFB ? + jz @f + + cmp [es:mi.BitsPerPixel], 24 ;It show only videomodes to have support 24 and 32 bpp + jb @f + +; cmp [es:mi.BitsPerPixel],16 +; jne .l0 +; cmp [es:mi.GreenMaskSize],5 +; jne .l0 +; mov [es:mi.BitsPerPixel],15 + + +.l0: + cmp [es:mi.XRes], 640 + jb @f + cmp [es:mi.YRes], 480 + jb @f +; cmp [es:mi.BitsPerPixel],8 +; jb @f + + mov ax, [es:mi.XRes] + mov [es:bx+0], ax ; +0[2] : resolution X + mov ax, [es:mi.YRes] + mov [es:bx+2], ax ; +2[2] : resolution Y + mov ax, [es:mi.ModeAttributes] + mov [es:bx+4], ax ; +4[2] : attributes + + cmp [s_vesa.ver], '2' + jb .lp1 + + or cx, 0x4000 ; use LFB +.lp1: + mov [es:bx+6], cx ; +6 : mode number + movzx ax, byte [es:mi.BitsPerPixel] + mov word [es:bx+8], ax ; +8 : bits per pixel + add bx, size_of_step ; size of record + + @@: + add si, 2 + jmp .next_mode + + .modes_ok.2: + + mov word[es:bx], -1 ;end video table + mov word[end_cursor], bx ;save end cursor position +;;;;;;;;;;;;;;;;;; +;Sort array +; mov si,modes_table +;.new_mode: +; mov ax,word [es:si] +; cmp ax,-1 +; je .exxit +; add ax,word [es:si+2] +; add ax,word [es:si+8] +; mov bp,si +;.again: +; add bp,12 +; mov bx,word [es:bp] +; cmp bx,-1 +; je .exit +; add bx,word [es:bp+2] +; add bx,word [es:bp+8] +; +; cmp ax,bx +; ja .loops +; jmp .again +;.loops: +; push dword [es:si] +; push dword [es:si+4] +; push dword [es:si+8] +; push dword [es:bp] +; push dword [es:bp+4] +; push dword [es:bp+8] +; +; pop dword [es:si+8] +; pop dword [es:si+4] +; pop dword [es:si] +; pop dword [es:bp+8] +; pop dword [es:bp+4] +; pop dword [es:bp] +; jmp .new_mode +; +;.exit: add si,12 +; jmp .new_mode +;.exxit: + popad + ret + +;----------------------------------------------------------------------------- + +draw_current_vmode: + push 0 + pop es + + mov si, word [cursor_pos] + + cmp word [es:si+6], 0x12 + je .no_vesa_0x12 + + cmp word [es:si+6], 0x13 + je .no_vesa_0x13 + + mov di, loader_block_error + movzx eax, word[es:si+0] + mov ecx, 10 + call int2strnz + mov byte[es:di], 'x' + inc di + movzx eax, word[es:si+2] + call int2strnz + mov byte[es:di], 'x' + inc di + movzx eax, word[es:si+8] + call int2strnz + mov dword[es:di], 0x00000d0a + mov si, loader_block_error + push ds + push es + pop ds + call printplain + pop ds + ret +.no_vesa_0x13: + mov si, mode0 + jmp .print +.no_vesa_0x12: + mov si, mode9 +.print: + call printplain + ret +;----------------------------------------------------------------------------- +check_first_parm: + mov si, word [preboot_graph] + test si, si + jnz .no_zero ;if no zero +.zerro: +; mov ax,modes_table +; mov word [cursor_pos],ax +; mov word [home_cursor],ax +; mov word [preboot_graph],ax +;SET default video of mode first probe will fined a move of work 1024x768@32 + + mov ax, 1024 + mov bx, 768 + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + mov ax, 800 + mov bx, 600 + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + mov ax, 640 + mov bx, 480 + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + + mov si, modes_table + jmp .ok_found_mode + + + +.no_zero: + mov bp, word [number_vm] + cmp bp, word [es:si+6] + jz .ok_found_mode + mov ax, word [x_save] + mov bx, word [y_save] + mov si, modes_table + call .loops + test ax, ax + jz .ok_found_mode + + mov si, modes_table +; cmp ax,modes_table +; jb .zerro ;check on correct if bellow +; cmp ax,word [end_cursor] +; ja .zerro ;check on correct if anymore + +.ok_found_mode: + mov word [home_cursor], si +; mov word [cursor_pos],si + mov word [preboot_graph], si + mov ax, si + + mov ecx, long_v_table + +.loop: + add ax, size_of_step + cmp ax, word [end_cursor] + jae .next_step + loop .loop +.next_step: + sub ax, size_of_step*long_v_table + cmp ax, modes_table + jae @f + mov ax, modes_table +@@: + + mov word [home_cursor], ax + mov si, [preboot_graph] + mov word [cursor_pos], si + + push word [es:si] + pop word [x_save] + push word [es:si+2] + pop word [y_save] + push word [es:si+6] + pop word [number_vm] + + ret +;;;;;;;;;;;;;;;;;;;;;;;;;;; +.loops: + cmp ax, word [es:si] + jne .next + cmp bx, word [es:si+2] + jne .next + cmp word [es:si+8], 32 + je .ok + cmp word [es:si+8], 24 + je .ok +.next: + add si, size_of_step + cmp word [es:si], -1 + je .exit + jmp .loops +.ok: + xor ax, ax + ret +.exit: + or ax, -1 + ret + + +;----------------------------------------------------------------------------- + +;default_vmode: + +;----------------------------------------------------------------------------- +draw_vmodes_table: + _setcursor 9, 2 + mov si, gr_mode + call printplain + + mov si, _st + call printplain + + push word [cursor_pos] + pop ax + push word [home_cursor] + pop si + mov cx, si + + cmp ax, si + je .ok + jb .low + + + add cx, size_of_step*long_v_table + + cmp ax, cx + jb .ok + + sub cx, size_of_step*long_v_table + add cx, size_of_step + cmp cx, word[end_cursor] + jae .ok + add si, size_of_step + push si + pop word [home_cursor] + jmp .ok + + +.low: + sub cx, size_of_step + cmp cx, modes_table + jb .ok + push cx + push cx + pop word [home_cursor] + pop si + + +.ok: +; calculate scroll position + push si + mov ax, [end_cursor] + sub ax, modes_table + mov bx, size_of_step + cwd + div bx + mov si, ax ; si = size of list + mov ax, [home_cursor] + sub ax, modes_table + cwd + div bx + mov di, ax + mov ax, scroll_area_size*long_v_table + cwd + div si + test ax, ax + jnz @f + inc ax +@@: + cmp al, scroll_area_size + jb @f + mov al, scroll_area_size +@@: + mov cx, ax +; cx = scroll height +; calculate scroll pos + xor bx, bx ; initialize scroll pos + sub al, scroll_area_size+1 + neg al + sub si, long_v_table-1 + jbe @f + mul di + div si + mov bx, ax +@@: + inc bx + imul ax, bx, size_of_step + add ax, [home_cursor] + mov [scroll_start], ax + imul cx, size_of_step + add ax, cx + mov [scroll_end], ax + pop si + mov bp, long_v_table ;show rows +.@@_next_bit: +;clear cursor + mov ax, ' ' + mov word[ds:_r1+21], ax + mov word[ds:_r1+50], ax + + mov word[ds:_r2+21], ax + mov word[ds:_r2+45], ax + + mov word[ds:_rs+21], ax + mov word[ds:_rs+46], ax +; draw string + cmp word [es:si+6], 0x12 + je .show_0x12 + cmp word [es:si+6], 0x13 + je .show_0x13 + + movzx eax, word[es:si] + cmp ax, -1 + je .@@_end + mov di, _rs+23 + mov ecx, 10 + mov bl, 4 + call int2str + movzx eax, word[es:si+2] + inc di + mov bl, 4 + call int2str + + movzx eax, word[es:si+8] + inc di + mov bl, 2 + call int2str + + cmp si, word [cursor_pos] + jne .next +;draw cursor + mov word[ds:_rs+21], '>>' + mov word[ds:_rs+46], '<<' + + + +.next: + push si + mov si, _rs +.@@_sh: +; add to the string pseudographics for scrollbar + pop bx + push bx + mov byte [si+53], ' ' + cmp bx, [scroll_start] + jb @f + cmp bx, [scroll_end] + jae @f + mov byte [si+53], 0xDB ; filled bar +@@: + push bx + add bx, size_of_step + cmp bx, [end_cursor] + jnz @f + mov byte [si+53], 31 ; 'down arrow' symbol +@@: + sub bx, [home_cursor] + cmp bx, size_of_step*long_v_table + jnz @f + mov byte [si+53], 31 ; 'down arrow' symbol +@@: + pop bx + cmp bx, [home_cursor] + jnz @f + mov byte [si+53], 30 ; 'up arrow' symbol +@@: + call printplain + pop si + add si, size_of_step + + dec bp + jnz .@@_next_bit + +.@@_end: + mov si, _bt + call printplain + ret +.show_0x13: + push si + + cmp si, word [cursor_pos] + jne @f + mov word[ds:_r1+21], '>>' + mov word[ds:_r1+50], '<<' +@@: + mov si, _r1 + jmp .@@_sh +.show_0x12: + push si + cmp si, word [cursor_pos] + jne @f + + mov word[ds:_r2+21], '>>' + mov word[ds:_r2+45], '<<' +@@: + mov si, _r2 + jmp .@@_sh + +;----------------------------------------------------------------------------- +;Clear arrea of current video page (0xb800) +clear_vmodes_table: + pusha + ; draw frames + push es + push 0xb800 + pop es + mov di, 1444 + xor ax, ax + mov ah, 1*16+15 + mov cx, 70 + mov bp, 12 +.loop_start: + rep stosw + mov cx, 70 + add di, 20 + dec bp + jns .loop_start + pop es + popa + ret + +;----------------------------------------------------------------------------- + +set_vmode: + push 0 ;0;x1000 + pop es + + mov si, word [preboot_graph] ;[preboot_graph] + mov cx, word [es:si+6] ; number of mode + + + mov ax, word [es:si+0] ; resolution X + mov bx, word [es:si+2] ; resolution Y + + + mov word [es:0x900A], ax ; resolution X + mov word [es:0x900C], bx ; resolution Y + mov word [es:0x9008], cx ; number of mode + + cmp cx, 0x12 + je .mode0x12_0x13 + cmp cx, 0x13 + je .mode0x12_0x13 + + + cmp byte [s_vesa.ver], '2' + jb .vesa12 + +; VESA 2 and Vesa 3 + + mov ax, 0x4f01 + and cx, 0xfff + mov di, mi;0xa000 + int 0x10 + ; LFB + mov eax, [es:mi.PhysBasePtr];di+0x28] + mov [es:0x9018], eax + ; ---- vbe voodoo + BytesPerLine equ 0x10 + mov ax, [es:di+BytesPerLine] + mov [es:0x9001], ax + ; BPP + cmp [es:mi.BitsPerPixel], 16 + jne .l0 + cmp [es:mi.GreenMaskSize], 5 + jne .l0 + mov [es:mi.BitsPerPixel], 15 +.l0: + mov al, byte [es:di+0x19] + mov [es:0x9000], al + jmp .exit + +.mode0x12_0x13: + mov byte [es:0x9000], 32 + or dword [es:0x9018], 0xFFFFFFFF; 0x800000 + + +; VESA 1.2 PM BANK SWITCH ADDRESS + +.vesa12: + + + mov ax, 0x4f0A + xor bx, bx + int 0x10 + xor eax, eax + xor ebx, ebx + mov ax, es + shl eax, 4 + mov bx, di + add eax, ebx + movzx ebx, word[es:di] + add eax, ebx + push 0x0000 + pop es + mov [es:0x9014], eax + .exit: + ret + + +; mov dword[es:0x9018],0x000A0000 +; ret + +;============================================================================= +;============================================================================= +;============================================================================= + diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/et.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/et.inc index f294d2f7b..d10c66ec9 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/et.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/et.inc @@ -1,14 +1,14 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -; Full ASCII code font -; only х and д added -; Kaitz -ET_FNT: - fontfile file "ETFONT.FNT" - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; Full ASCII code font +; only х and д added +; Kaitz +ET_FNT: + fontfile file "ETFONT.FNT" + diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/kolibri_ldm.asm b/kernel/trunk/sec_loader/trunk/kolibri_ldm/kolibri_ldm.asm index 79e76690b..0074dcaeb 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/kolibri_ldm.asm +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/kolibri_ldm.asm @@ -1,808 +1,815 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Last modify Alexey Teplov 2008. All rights reserved. ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; kolibri_ldm.asm the module for Secondary Loader ;; -;; ;; -;; KolibriOS 16-bit loader module, ;; -;; based on bootcode for KolibriOS ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -include "lang.inc" - -macro _setcursor row,column -{ - mov dx, row*256 + column - call setcursor -} -long_v_table equ 9 ;long of visible video table -size_of_step equ 10 -d80x25_bottom_num equ 3 -d80x25_top_num equ 4 -;It's a module for Secondary Loader to load kolibri OS -; -start_of_code: - cld -; \begin{diamond}[02.12.2005] -; if bootloader sets ax = 'KL', then ds:si points to loader block -; cmp ax, 'KL' -; jnz @f -; mov word [cs:cfgmanager.loader_block], si -; mov word [cs:cfgmanager.loader_block+2], ds -;@@: -; \end{diamond}[02.12.2005] - -; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk -; (see comment to bx_from_load) -; cmp cx, 'HA' -; jnz no_hd_load -; cmp dx,'RD' -; jnz no_hd_load -; mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] -;no_hd_load: - -; set up stack - push cs - pop ss - xor ax,ax - mov sp,ax -; mov ax, 3000h -; mov ss, ax -; mov sp, 0EC00h -; set up segment registers - push cs - pop ds - push cs - pop es - -; set videomode - mov ax, 3 - int 0x10 - -;if lang eq ru - ; Load & set russian VGA font (RU.INC) - mov bp, RU_FNT1 ; RU_FNT1 - First part - mov bx, 1000h ; 768 bytes - mov cx, 30h ; 48 symbols - mov dx, 80h ; 128 - position of first symbol - mov ax, 1100h - int 10h - - mov bp, RU_FNT2 ; RU_FNT2 -Second part - mov bx, 1000h ; 512 bytes - mov cx, 20h ; 32 symbols - mov dx, 0E0h ; 224 - position of first symbol - mov ax, 1100h - int 10h - ; End set VGA russian font -;else if lang eq et -; mov bp, ET_FNT ; ET_FNT1 -; mov bx, 1000h ; -; mov cx, 255 ; 256 symbols -; xor dx, dx ; 0 - position of first symbol -; mov ax, 1100h -; int 10h -;end if - -; draw frames - push 0xb800 - pop es - xor di, di - mov ah, 1*16+15 - -; draw top - mov si, d80x25_top - mov cx, d80x25_top_num * 80 -@@: - lodsb - stosw - loop @b -; draw spaces - mov si, space_msg - mov dx, 25 - d80x25_top_num - d80x25_bottom_num -dfl1: - push si - mov cx, 80 -@@: - lodsb - stosw - loop @b - pop si - dec dx - jnz dfl1 -; draw bottom - mov si, d80x25_bottom - mov cx, d80x25_bottom_num * 80 -@@: - lodsb - stosw - loop @b - - mov byte [space_msg+80], 0 ; now space_msg is null terminated - - _setcursor d80x25_top_num,0 - - -; TEST FOR 386+ - - mov bx, 0x4000 - pushf - pop ax - mov dx, ax - xor ax, bx - push ax - popf - pushf - pop ax - and ax, bx - and dx, bx - cmp ax, dx - jnz cpugood - mov si, not386 -sayerr: - call print - jmp $ - cpugood: - - push 0 - popf - sti - -; set up esp - movzx esp, sp - - push 0 - pop es - and word [es:0x9031], 0 -; \begin{Mario79} -; find HDD IDE DMA PCI device -; check for PCI BIOS - mov ax, 0xB101 - int 0x1A - jc .nopci - cmp edx, 'PCI ' - jnz .nopci -; find PCI class code -; class 1 = mass storage -; subclass 1 = IDE controller -; a) class 1, subclass 1, programming interface 0x80 - mov ax, 0xB103 - mov ecx, 1*10000h + 1*100h + 0x80 - xor si, si ; device index = 0 - int 0x1A - jnc .found -; b) class 1, subclass 1, programming interface 0x8A - mov ax, 0xB103 - mov ecx, 1*10000h + 1*100h + 0x8A - xor si, si ; device index = 0 - int 0x1A - jnc .found -; c) class 1, subclass 1, programming interface 0x85 - mov ax, 0xB103 - mov ecx, 1*10000h + 1*100h + 0x85 - xor si, si - int 0x1A - jc .nopci -.found: -; get memory base - mov ax, 0xB10A - mov di, 0x20 ; memory base is config register at 0x20 - int 0x1A - jc .nopci - and cx, 0xFFF0 ; clear address decode type - mov [es:0x9031], cx -.nopci: -; \end{Mario79} - - mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование - out 0x60, al - xor cx, cx -wait_loop: ; variant 2 -; reading state of port of 8042 controller - in al, 64h - and al, 00000010b ; ready flag -; wait until 8042 controller is ready - loopnz wait_loop - -;;;/diamond today 5.02.2008 -; set keyboard typematic rate & delay - mov al, 0xf3 - out 0x60, al - xor cx, cx -@@: - in al, 64h - test al, 2 - loopnz @b - mov al, 0 - out 0x60, al - xor cx, cx -@@: - in al, 64h - test al, 2 - loopnz @b -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; --------------- APM --------------------- - and word [es:0x9044], 0 ; ver = 0.0 (APM not found) - mov ax, 0x5300 - xor bx, bx - int 0x15 - jc apm_end ; APM not found - test cx, 2 - jz apm_end ; APM 32-bit protected-mode interface not supported - mov [es:0x9044], ax ; Save APM Version - mov [es:0x9046], cx ; Save APM flags - - ; Write APM ver ---- - and ax, 0xf0f - add ax, '00' - mov si, msg_apm - mov [si + 5], ah - mov [si + 7], al - _setcursor 0, 3 - call printplain - ; ------------------ - - mov ax, 0x5304 ; Disconnect interface - xor bx, bx - int 0x15 - mov ax, 0x5303 ; Connect 32 bit mode interface - xor bx, bx - int 0x15 - - mov [es:0x9040], ebx - mov [es:0x9050], ax - mov [es:0x9052], cx - mov [es:0x9054], dx - -apm_end: - _setcursor d80x25_top_num, 0 - -;CHECK current of code - cmp [cfgmanager.loader_block], -1 - jz noloaderblock - les bx, [cfgmanager.loader_block] - cmp byte [es:bx], 1 - mov si, loader_block_error - jnz sayerr - push 0 - pop es - -noloaderblock: -; DISPLAY VESA INFORMATION - call print_vesa_info - call calc_vmodes_table - call check_first_parm ;check and enable cursor_pos - - -; \begin{diamond}[30.11.2005] -cfgmanager: -; settings: -; a) preboot_graph = graphical mode -; preboot_gprobe = probe this mode? -; b) preboot_dma = use DMA access? -; c) preboot_vrrm = use VRR? - -; determine default settings - mov [.bSettingsChanged], 0 - -;.preboot_gr_end: - mov di, preboot_device -; if image in memory is present and [preboot_device] is uninitialized, -; set it to use this preloaded image - cmp byte [di], 0 - jnz .preboot_device_inited - cmp [.loader_block], -1 - jz @f - les bx, [.loader_block] - test byte [es:bx+1], 1 - jz @f - mov byte [di], 3 - jmp .preboot_device_inited -@@: -; otherwise, set [preboot_device] to 1 (default value - boot from floppy) - mov byte [di], 1 -.preboot_device_inited: -; following 6 lines set variables to 1 if its current value is 0 - cmp byte [di+preboot_dma-preboot_device], 1 - adc byte [di+preboot_dma-preboot_device], 0 - cmp byte [di+preboot_biosdisk-preboot_device], 1 - adc byte [di+preboot_biosdisk-preboot_device], 0 - cmp byte [di+preboot_vrrm-preboot_device], 1 - adc byte [di+preboot_vrrm-preboot_device], 0 -; notify user - _setcursor 5,2 - - mov si, linef - call printplain - mov si, start_msg - call print - mov si, time_msg - call print -; get start time - call .gettime - mov [.starttime], eax - mov word [.timer], .newtimer - mov word [.timer+2], cs -.printcfg: - _setcursor 9,0 - mov si, current_cfg_msg - call print - mov si, curvideo_msg - call print - - call draw_current_vmode - - mov si, usebd_msg - cmp [preboot_biosdisk], 1 - call .say_on_off - mov si, vrrm_msg - cmp [preboot_vrrm], 1 - call .say_on_off -; mov si, preboot_device_msg -; call print -; mov al, [preboot_device] -; and eax, 7 -; mov si, [preboot_device_msgs+eax*2] -; call printplain -.show_remarks: -; show remarks in gray color - mov di, ((21-num_remarks)*80 + 2)*2 - push 0xB800 - pop es - mov cx, num_remarks - mov si, remarks -.write_remarks: - lodsw - push si - xchg ax, si - mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) - push di -.write_remark: - lodsb - test al, al - jz @f - stosw - jmp .write_remark -@@: - pop di - pop si - add di, 80*2 - loop .write_remarks -.wait: - _setcursor 25,0 ; out of screen -; set timer interrupt handler - cli - push 0 - pop es - push dword [es:8*4] - pop dword [.oldtimer] - push dword [.timer] - pop dword [es:8*4] -; mov eax, [es:8*4] -; mov [.oldtimer], eax -; mov eax, [.timer] -; mov [es:8*4], eax - sti -; wait for keypressed - xor ax,ax - int 16h - push ax -; restore timer interrupt -; push 0 -; pop es - mov eax, [.oldtimer] - mov [es:8*4], eax - mov [.timer], eax - _setcursor 7,0 - mov si, space_msg - call printplain -; clear remarks and restore normal attributes - push es - mov di, ((21-num_remarks)*80 + 2)*2 - push 0xB800 - pop es - mov cx, num_remarks - mov ax, ' ' + (1*16 + 15)*100h -@@: - push cx - mov cx, 76 - rep stosw - pop cx - add di, 4*2 - loop @b - pop es - pop ax -; switch on key - cmp al, 13 - jz .continue - or al, 20h - cmp al, 'a' - jz .change_a - cmp al, 'b' - jz .change_b - cmp al, 'c' - jnz .show_remarks - - _setcursor 15,0 - mov si, vrrmprint - call print - mov bx, '12' - call getkey - mov [preboot_vrrm], al - _setcursor 12,0 -.d: - mov [.bSettingsChanged], 1 - call clear_vmodes_table ;clear vmodes_table - jmp .printcfg -.change_a: -.loops: - call draw_vmodes_table - _setcursor 25,0 ; out of screen - xor ax,ax - int 0x16 -; call clear_table_cursor ;clear current position of cursor - - mov si,word [cursor_pos] - - cmp ah,0x48;x,0x48E0 ; up - jne .down - cmp si,modes_table - jbe .loops - sub word [cursor_pos],size_of_step - jmp .loops - -.down: cmp ah,0x50;x,0x50E0 ; down - jne .pgup - cmp word[es:si+10],-1 - je .loops - add word [cursor_pos],size_of_step - jmp .loops - -.pgup: cmp ah,0x49 ; page up - jne .pgdn - sub si, size_of_step*long_v_table - cmp si, modes_table - jae @f - mov si, modes_table -@@: - mov word [cursor_pos], si - mov si, word [home_cursor] - sub si, size_of_step*long_v_table - cmp si, modes_table - jae @f - mov si, modes_table -@@: - mov word [home_cursor], si - jmp .loops - -.pgdn: cmp ah,0x51 ; page down - jne .enter - mov ax, [end_cursor] - add si, size_of_step*long_v_table - cmp si, ax - jb @f - mov si, ax - sub si, size_of_step -@@: - mov word [cursor_pos], si - mov si, word [home_cursor] - sub ax, size_of_step*long_v_table - add si, size_of_step*long_v_table - cmp si, ax - jb @f - mov si, ax -@@: - mov word [home_cursor], si - jmp .loops - -.enter: cmp al,0x0D;x,0x1C0D ; enter - jne .loops - push word [cursor_pos] - pop bp - push word [es:bp] - pop word [x_save] - push word [es:bp+2] - pop word [y_save] - push word [es:bp+6] - pop word [number_vm] - mov word [preboot_graph],bp ;save choose - - jmp .d - -.change_b: - _setcursor 15,0 -; mov si, ask_dma -; call print -; mov bx, '13' -; call getkey -; mov [preboot_dma], al - mov si, ask_bd - call print - mov bx, '12' - call getkey - mov [preboot_biosdisk], al - _setcursor 11,0 - jmp .d -;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.say_on_off: - pushf - call print - mov si, on_msg - popf - jz @f - mov si, off_msg -@@: jmp printplain -; novesa and vervesa strings are not used at the moment of executing this code -virtual at novesa -.oldtimer dd ? -.starttime dd ? -.bSettingsChanged db ? -.timer dd ? -end virtual -.loader_block dd -1 -.gettime: - mov ah, 0 - int 1Ah - xchg ax, cx - shl eax, 10h - xchg ax, dx - ret -.newtimer: - push ds - push cs - pop ds - pushf - call [.oldtimer] - pushad - call .gettime - sub eax, [.starttime] - sub ax, 18*5 - jae .timergo - neg ax - add ax, 18-1 - mov bx, 18 - xor dx, dx - div bx -if lang eq ru -; Ї®¤®¦¤ЁвҐ 5 ᥪ㭤, 4/3/2 ᥪ㭤л, 1 ᥪ㭤г - cmp al, 5 - mov cl, ' ' - jae @f - cmp al, 1 - mov cl, 'г' - jz @f - mov cl, 'л' -@@: mov [time_str+9], cl -else if lang eq et - cmp al, 1 - ja @f - mov [time_str+9], ' ' - mov [time_str+10],' ' -@@: -else -; wait 5/4/3/2 seconds, 1 second - cmp al, 1 - mov cl, 's' - ja @f - mov cl, ' ' -@@: mov [time_str+9], cl -end if - add al, '0' - mov [time_str+1], al - mov si, time_msg - _setcursor 7,0 - call print - _setcursor 25,0 - popad - pop ds - iret -.timergo: - push 0 - pop es - mov eax, [.oldtimer] - mov [es:8*4], eax - mov sp, 0EC00h -.continue: - sti - _setcursor 6,0 - mov si, space_msg - call printplain - call printplain - _setcursor 6,0 - mov si, loading_msg - call print - _setcursor 15,0 - cmp [.bSettingsChanged], 0 - jz .load - cmp [.loader_block], -1 - jz .load - les bx, [.loader_block] - mov eax, [es:bx+3] - push ds - pop es - test eax, eax - jz .load - push eax - mov si, save_quest - call print -.waityn: - mov ah, 0 - int 16h - or al, 20h - cmp al, 'n' - jz .loadc - cmp al, 'y' - jnz .waityn - call putchar - mov byte [space_msg+80], 186 - pop eax - push cs - push .cont - push eax - retf -.loadc: - pop eax -.cont: - push cs - pop ds - mov si, space_msg - mov byte [si+80], 0 - _setcursor 15,0 - call printplain - _setcursor 15,0 -.load: -; \end{diamond}[02.12.2005] - -; ASK GRAPHICS MODE - - call set_vmode - -; GRAPHICS ACCELERATION -; force yes - mov [es:0x901C], byte 1 - -; DMA ACCESS TO HD - - mov al, [preboot_dma] - mov [es:0x901F], al - -; VRR_M USE - - mov al,[preboot_vrrm] - mov [es:0x9030], al - mov [es:0x901E], byte 1 - -; BOOT DEVICE - - mov al, [preboot_device] - dec al - mov [boot_dev], al - - - - - - -;;;;;;;;;;; set videomode - xor ax, ax - mov es, ax - - mov ax, [es:0x9008] ; vga & 320x200 - mov bx, ax - cmp ax, 0x13 - je setgr - cmp ax, 0x12 - je setgr - mov ax, 0x4f02 ; Vesa -setgr: - int 0x10 - test ah, ah - mov si, fatalsel - jnz v_mode_error -; set mode 0x12 graphics registers: - cmp bx, 0x12 - jne gmok2 - - mov al, 0x05 - mov dx, 0x03ce - push dx - out dx, al ; select GDC mode register - mov al, 0x02 - inc dx - out dx, al ; set write mode 2 - - mov al, 0x02 - mov dx, 0x03c4 - out dx, al ; select VGA sequencer map mask register - mov al, 0x0f - inc dx - out dx, al ; set mask for all planes 0-3 - - mov al, 0x08 - pop dx - out dx, al ; select GDC bit mask register - ; for writes to 0x03cf -gmok2: - push ds - pop es - - jmp $ - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;data -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -include "lang.inc" -include "bootstr.inc" ; language-independent boot messages -;if lang eq en -;include "booteng.inc" ; english system boot messages -;else if lang eq ru -include "bootru.inc" ; russian system boot messages -include "ru.inc" ; Russian font -;else if lang eq et -;include "bootet.inc" ; estonian system boot messages -;include "et.inc" ; Estonian font -;else -;include "bootge.inc" ; german system boot messages -;end if - -include 'macros.inc' -include 'bootvesa.inc' - -include "preboot.inc" - - -setcursor: -; in: dl=column, dh=row - mov ah, 2 - mov bh, 0 - int 10h - ret - -putchar: -; in: al=character - mov ah, 0Eh - mov bh, 0 - int 10h - ret - -print: -; in: si->string - mov al, 186 - call putchar - mov al, ' ' - call putchar - -printplain: -; in: si->string - pusha - lodsb -@@: - call putchar - lodsb - cmp al, 0 - jnz @b - popa - ret - -getkey: -; get number in range [bl,bh] (bl,bh in ['0'..'9']) -; in: bx=range -; out: ax=digit (1..9, 10 for 0) - mov ah, 0 - int 16h - cmp al, bl - jb getkey - cmp al, bh - ja getkey - push ax - call putchar - pop ax - and ax, 0Fh - jnz @f - mov al, 10 -@@: - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Last modify Alexey Teplov 2008. All rights reserved. ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Copyright (C) MenuetOS 2000-2004 Ville Mikael Turjanmaa ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; kolibri_ldm.asm the module for Secondary Loader ;; +;; ;; +;; KolibriOS 16-bit loader module, ;; +;; based on bootcode for KolibriOS ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +include "lang.inc" + +macro _setcursor row,column +{ + mov dx, row*256 + column + call setcursor +} +long_v_table equ 9 ;long of visible video table +size_of_step equ 10 +d80x25_bottom_num equ 3 +d80x25_top_num equ 4 +;It's a module for Secondary Loader to load kolibri OS +; +start_of_code: + cld +; \begin{diamond}[02.12.2005] +; if bootloader sets ax = 'KL', then ds:si points to loader block +; cmp ax, 'KL' +; jnz @f +; mov word [cs:cfgmanager.loader_block], si +; mov word [cs:cfgmanager.loader_block+2], ds +;@@: +; \end{diamond}[02.12.2005] + +; if bootloader sets cx = 'HA' and dx = 'RD', then bx contains identifier of source hard disk +; (see comment to bx_from_load) +; cmp cx, 'HA' +; jnz no_hd_load +; cmp dx,'RD' +; jnz no_hd_load +; mov word [cs:bx_from_load], bx ; {SPraid}[13.03.2007] +;no_hd_load: + +; set up stack + push cs + pop ss + xor ax, ax + mov sp, ax +; mov ax, 3000h +; mov ss, ax +; mov sp, 0EC00h +; set up segment registers + push cs + pop ds + push cs + pop es + +; set videomode + mov ax, 3 + int 0x10 + +;if lang eq ru + ; Load & set russian VGA font (RU.INC) + mov bp, RU_FNT1 ; RU_FNT1 - First part + mov bx, 1000h ; 768 bytes + mov cx, 30h ; 48 symbols + mov dx, 80h ; 128 - position of first symbol + mov ax, 1100h + int 10h + + mov bp, RU_FNT2 ; RU_FNT2 -Second part + mov bx, 1000h ; 512 bytes + mov cx, 20h ; 32 symbols + mov dx, 0E0h ; 224 - position of first symbol + mov ax, 1100h + int 10h + ; End set VGA russian font +;else if lang eq et +; mov bp, ET_FNT ; ET_FNT1 +; mov bx, 1000h ; +; mov cx, 255 ; 256 symbols +; xor dx, dx ; 0 - position of first symbol +; mov ax, 1100h +; int 10h +;end if + +; draw frames + push 0xb800 + pop es + xor di, di + mov ah, 1*16+15 + +; draw top + mov si, d80x25_top + mov cx, d80x25_top_num * 80 +@@: + lodsb + stosw + loop @b +; draw spaces + mov si, space_msg + mov dx, 25 - d80x25_top_num - d80x25_bottom_num +dfl1: + push si + mov cx, 80 +@@: + lodsb + stosw + loop @b + pop si + dec dx + jnz dfl1 +; draw bottom + mov si, d80x25_bottom + mov cx, d80x25_bottom_num * 80 +@@: + lodsb + stosw + loop @b + + mov byte [space_msg+80], 0 ; now space_msg is null terminated + + _setcursor d80x25_top_num,0 + + +; TEST FOR 386+ + + mov bx, 0x4000 + pushf + pop ax + mov dx, ax + xor ax, bx + push ax + popf + pushf + pop ax + and ax, bx + and dx, bx + cmp ax, dx + jnz cpugood + mov si, not386 +sayerr: + call print + jmp $ + cpugood: + + push 0 + popf + sti + +; set up esp + movzx esp, sp + + push 0 + pop es + and word [es:0x9031], 0 +; \begin{Mario79} +; find HDD IDE DMA PCI device +; check for PCI BIOS + mov ax, 0xB101 + int 0x1A + jc .nopci + cmp edx, 'PCI ' + jnz .nopci +; find PCI class code +; class 1 = mass storage +; subclass 1 = IDE controller +; a) class 1, subclass 1, programming interface 0x80 + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x80 + xor si, si ; device index = 0 + int 0x1A + jnc .found +; b) class 1, subclass 1, programming interface 0x8A + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x8A + xor si, si ; device index = 0 + int 0x1A + jnc .found +; c) class 1, subclass 1, programming interface 0x85 + mov ax, 0xB103 + mov ecx, 1*10000h + 1*100h + 0x85 + xor si, si + int 0x1A + jc .nopci +.found: +; get memory base + mov ax, 0xB10A + mov di, 0x20 ; memory base is config register at 0x20 + int 0x1A + jc .nopci + and cx, 0xFFF0 ; clear address decode type + mov [es:0x9031], cx +.nopci: +; \end{Mario79} + + mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование + out 0x60, al + xor cx, cx +wait_loop: ; variant 2 +; reading state of port of 8042 controller + in al, 64h + and al, 00000010b ; ready flag +; wait until 8042 controller is ready + loopnz wait_loop + +;;;/diamond today 5.02.2008 +; set keyboard typematic rate & delay + mov al, 0xf3 + out 0x60, al + xor cx, cx +@@: + in al, 64h + test al, 2 + loopnz @b + mov al, 0 + out 0x60, al + xor cx, cx +@@: + in al, 64h + test al, 2 + loopnz @b +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; --------------- APM --------------------- + and word [es:0x9044], 0 ; ver = 0.0 (APM not found) + mov ax, 0x5300 + xor bx, bx + int 0x15 + jc apm_end ; APM not found + test cx, 2 + jz apm_end ; APM 32-bit protected-mode interface not supported + mov [es:0x9044], ax ; Save APM Version + mov [es:0x9046], cx ; Save APM flags + + ; Write APM ver ---- + and ax, 0xf0f + add ax, '00' + mov si, msg_apm + mov [si + 5], ah + mov [si + 7], al + _setcursor 0, 3 + call printplain + ; ------------------ + + mov ax, 0x5304 ; Disconnect interface + xor bx, bx + int 0x15 + mov ax, 0x5303 ; Connect 32 bit mode interface + xor bx, bx + int 0x15 + + mov [es:0x9040], ebx + mov [es:0x9050], ax + mov [es:0x9052], cx + mov [es:0x9054], dx + +apm_end: + _setcursor d80x25_top_num, 0 + +;CHECK current of code + cmp [cfgmanager.loader_block], -1 + jz noloaderblock + les bx, [cfgmanager.loader_block] + cmp byte [es:bx], 1 + mov si, loader_block_error + jnz sayerr + push 0 + pop es + +noloaderblock: +; DISPLAY VESA INFORMATION + call print_vesa_info + call calc_vmodes_table + call check_first_parm ;check and enable cursor_pos + + +; \begin{diamond}[30.11.2005] +cfgmanager: +; settings: +; a) preboot_graph = graphical mode +; preboot_gprobe = probe this mode? +; b) preboot_dma = use DMA access? +; c) preboot_vrrm = use VRR? + +; determine default settings + mov [.bSettingsChanged], 0 + +;.preboot_gr_end: + mov di, preboot_device +; if image in memory is present and [preboot_device] is uninitialized, +; set it to use this preloaded image + cmp byte [di], 0 + jnz .preboot_device_inited + cmp [.loader_block], -1 + jz @f + les bx, [.loader_block] + test byte [es:bx+1], 1 + jz @f + mov byte [di], 3 + jmp .preboot_device_inited +@@: +; otherwise, set [preboot_device] to 1 (default value - boot from floppy) + mov byte [di], 1 +.preboot_device_inited: +; following 6 lines set variables to 1 if its current value is 0 + cmp byte [di+preboot_dma-preboot_device], 1 + adc byte [di+preboot_dma-preboot_device], 0 + cmp byte [di+preboot_biosdisk-preboot_device], 1 + adc byte [di+preboot_biosdisk-preboot_device], 0 + cmp byte [di+preboot_vrrm-preboot_device], 1 + adc byte [di+preboot_vrrm-preboot_device], 0 +; notify user + _setcursor 5,2 + + mov si, linef + call printplain + mov si, start_msg + call print + mov si, time_msg + call print +; get start time + call .gettime + mov [.starttime], eax + mov word [.timer], .newtimer + mov word [.timer+2], cs +.printcfg: + _setcursor 9,0 + mov si, current_cfg_msg + call print + mov si, curvideo_msg + call print + + call draw_current_vmode + + mov si, usebd_msg + cmp [preboot_biosdisk], 1 + call .say_on_off + mov si, vrrm_msg + cmp [preboot_vrrm], 1 + call .say_on_off +; mov si, preboot_device_msg +; call print +; mov al, [preboot_device] +; and eax, 7 +; mov si, [preboot_device_msgs+eax*2] +; call printplain +.show_remarks: +; show remarks in gray color + mov di, ((21-num_remarks)*80 + 2)*2 + push 0xB800 + pop es + mov cx, num_remarks + mov si, remarks +.write_remarks: + lodsw + push si + xchg ax, si + mov ah, 1*16+7 ; background: blue (1), foreground: gray (7) + push di +.write_remark: + lodsb + test al, al + jz @f + stosw + jmp .write_remark +@@: + pop di + pop si + add di, 80*2 + loop .write_remarks +.wait: + _setcursor 25,0 ; out of screen +; set timer interrupt handler + cli + push 0 + pop es + push dword [es:8*4] + pop dword [.oldtimer] + push dword [.timer] + pop dword [es:8*4] +; mov eax, [es:8*4] +; mov [.oldtimer], eax +; mov eax, [.timer] +; mov [es:8*4], eax + sti +; wait for keypressed + xor ax, ax + int 16h + push ax +; restore timer interrupt +; push 0 +; pop es + mov eax, [.oldtimer] + mov [es:8*4], eax + mov [.timer], eax + _setcursor 7,0 + mov si, space_msg + call printplain +; clear remarks and restore normal attributes + push es + mov di, ((21-num_remarks)*80 + 2)*2 + push 0xB800 + pop es + mov cx, num_remarks + mov ax, ' ' + (1*16 + 15)*100h +@@: + push cx + mov cx, 76 + rep stosw + pop cx + add di, 4*2 + loop @b + pop es + pop ax +; switch on key + cmp al, 13 + jz .continue + or al, 20h + cmp al, 'a' + jz .change_a + cmp al, 'b' + jz .change_b + cmp al, 'c' + jnz .show_remarks + + _setcursor 15,0 + mov si, vrrmprint + call print + mov bx, '12' + call getkey + mov [preboot_vrrm], al + _setcursor 12,0 +.d: + mov [.bSettingsChanged], 1 + call clear_vmodes_table ;clear vmodes_table + jmp .printcfg +.change_a: +.loops: + call draw_vmodes_table + _setcursor 25,0 ; out of screen + xor ax, ax + int 0x16 +; call clear_table_cursor ;clear current position of cursor + + mov si, word [cursor_pos] + + cmp ah, 0x48;x,0x48E0 ; up + jne .down + cmp si, modes_table + jbe .loops + sub word [cursor_pos], size_of_step + jmp .loops + +.down: + cmp ah, 0x50;x,0x50E0 ; down + jne .pgup + cmp word[es:si+10], -1 + je .loops + add word [cursor_pos], size_of_step + jmp .loops + +.pgup: + cmp ah, 0x49 ; page up + jne .pgdn + sub si, size_of_step*long_v_table + cmp si, modes_table + jae @f + mov si, modes_table +@@: + mov word [cursor_pos], si + mov si, word [home_cursor] + sub si, size_of_step*long_v_table + cmp si, modes_table + jae @f + mov si, modes_table +@@: + mov word [home_cursor], si + jmp .loops + +.pgdn: + cmp ah, 0x51 ; page down + jne .enter + mov ax, [end_cursor] + add si, size_of_step*long_v_table + cmp si, ax + jb @f + mov si, ax + sub si, size_of_step +@@: + mov word [cursor_pos], si + mov si, word [home_cursor] + sub ax, size_of_step*long_v_table + add si, size_of_step*long_v_table + cmp si, ax + jb @f + mov si, ax +@@: + mov word [home_cursor], si + jmp .loops + +.enter: + cmp al, 0x0D;x,0x1C0D ; enter + jne .loops + push word [cursor_pos] + pop bp + push word [es:bp] + pop word [x_save] + push word [es:bp+2] + pop word [y_save] + push word [es:bp+6] + pop word [number_vm] + mov word [preboot_graph], bp ;save choose + + jmp .d + +.change_b: + _setcursor 15,0 +; mov si, ask_dma +; call print +; mov bx, '13' +; call getkey +; mov [preboot_dma], al + mov si, ask_bd + call print + mov bx, '12' + call getkey + mov [preboot_biosdisk], al + _setcursor 11,0 + jmp .d +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.say_on_off: + pushf + call print + mov si, on_msg + popf + jz @f + mov si, off_msg +@@: + jmp printplain +; novesa and vervesa strings are not used at the moment of executing this code +virtual at novesa +.oldtimer dd ? +.starttime dd ? +.bSettingsChanged db ? +.timer dd ? +end virtual +.loader_block dd -1 +.gettime: + mov ah, 0 + int 1Ah + xchg ax, cx + shl eax, 10h + xchg ax, dx + ret +.newtimer: + push ds + push cs + pop ds + pushf + call [.oldtimer] + pushad + call .gettime + sub eax, [.starttime] + sub ax, 18*5 + jae .timergo + neg ax + add ax, 18-1 + mov bx, 18 + xor dx, dx + div bx +if lang eq ru +; Ї®¤®¦¤ЁвҐ 5 ᥪ㭤, 4/3/2 ᥪ㭤л, 1 ᥪ㭤г + cmp al, 5 + mov cl, ' ' + jae @f + cmp al, 1 + mov cl, 'г' + jz @f + mov cl, 'л' +@@: + mov [time_str+9], cl +else if lang eq et + cmp al, 1 + ja @f + mov [time_str+9], ' ' + mov [time_str+10], ' ' +@@: +else +; wait 5/4/3/2 seconds, 1 second + cmp al, 1 + mov cl, 's' + ja @f + mov cl, ' ' +@@: + mov [time_str+9], cl +end if + add al, '0' + mov [time_str+1], al + mov si, time_msg + _setcursor 7,0 + call print + _setcursor 25,0 + popad + pop ds + iret +.timergo: + push 0 + pop es + mov eax, [.oldtimer] + mov [es:8*4], eax + mov sp, 0EC00h +.continue: + sti + _setcursor 6,0 + mov si, space_msg + call printplain + call printplain + _setcursor 6,0 + mov si, loading_msg + call print + _setcursor 15,0 + cmp [.bSettingsChanged], 0 + jz .load + cmp [.loader_block], -1 + jz .load + les bx, [.loader_block] + mov eax, [es:bx+3] + push ds + pop es + test eax, eax + jz .load + push eax + mov si, save_quest + call print +.waityn: + mov ah, 0 + int 16h + or al, 20h + cmp al, 'n' + jz .loadc + cmp al, 'y' + jnz .waityn + call putchar + mov byte [space_msg+80], 186 + pop eax + push cs + push .cont + push eax + retf +.loadc: + pop eax +.cont: + push cs + pop ds + mov si, space_msg + mov byte [si+80], 0 + _setcursor 15,0 + call printplain + _setcursor 15,0 +.load: +; \end{diamond}[02.12.2005] + +; ASK GRAPHICS MODE + + call set_vmode + +; GRAPHICS ACCELERATION +; force yes + mov [es:0x901C], byte 1 + +; DMA ACCESS TO HD + + mov al, [preboot_dma] + mov [es:0x901F], al + +; VRR_M USE + + mov al, [preboot_vrrm] + mov [es:0x9030], al + mov [es:0x901E], byte 1 + +; BOOT DEVICE + + mov al, [preboot_device] + dec al + mov [boot_dev], al + + + + + + +;;;;;;;;;;; set videomode + xor ax, ax + mov es, ax + + mov ax, [es:0x9008] ; vga & 320x200 + mov bx, ax + cmp ax, 0x13 + je setgr + cmp ax, 0x12 + je setgr + mov ax, 0x4f02 ; Vesa +setgr: + int 0x10 + test ah, ah + mov si, fatalsel + jnz v_mode_error +; set mode 0x12 graphics registers: + cmp bx, 0x12 + jne gmok2 + + mov al, 0x05 + mov dx, 0x03ce + push dx + out dx, al ; select GDC mode register + mov al, 0x02 + inc dx + out dx, al ; set write mode 2 + + mov al, 0x02 + mov dx, 0x03c4 + out dx, al ; select VGA sequencer map mask register + mov al, 0x0f + inc dx + out dx, al ; set mask for all planes 0-3 + + mov al, 0x08 + pop dx + out dx, al ; select GDC bit mask register + ; for writes to 0x03cf +gmok2: + push ds + pop es + + jmp $ + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;data +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +include "lang.inc" +include "bootstr.inc" ; language-independent boot messages +;if lang eq en +;include "booteng.inc" ; english system boot messages +;else if lang eq ru +include "bootru.inc" ; russian system boot messages +include "ru.inc" ; Russian font +;else if lang eq et +;include "bootet.inc" ; estonian system boot messages +;include "et.inc" ; Estonian font +;else +;include "bootge.inc" ; german system boot messages +;end if + +include 'macros.inc' +include 'bootvesa.inc' + +include "preboot.inc" + + +setcursor: +; in: dl=column, dh=row + mov ah, 2 + mov bh, 0 + int 10h + ret + +putchar: +; in: al=character + mov ah, 0Eh + mov bh, 0 + int 10h + ret + +print: +; in: si->string + mov al, 186 + call putchar + mov al, ' ' + call putchar + +printplain: +; in: si->string + pusha + lodsb +@@: + call putchar + lodsb + cmp al, 0 + jnz @b + popa + ret + +getkey: +; get number in range [bl,bh] (bl,bh in ['0'..'9']) +; in: bx=range +; out: ax=digit (1..9, 10 for 0) + mov ah, 0 + int 16h + cmp al, bl + jb getkey + cmp al, bh + ja getkey + push ax + call putchar + pop ax + and ax, 0Fh + jnz @f + mov al, 10 +@@: + ret diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/macros.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/macros.inc index 01c180f3a..4558bbc6a 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/macros.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/macros.inc @@ -1,86 +1,86 @@ - - -; structure definition helper -macro struct name, [arg] - { - common - name@struct equ name - struc name arg { - } - -macro struct_helper name - { - match xname,name - \{ - virtual at 0 - xname xname - sizeof.#xname = $ - xname - name equ sizeof.#xname - end virtual - \} - } - -ends fix } struct_helper name@struct - -;// mike.dld, 2006-29-01 [ - -; macros definition -macro diff16 title,l1,l2 -{ - local s,d - s = l2-l1 - display title,': 0x' - repeat 16 - d = 48 + s shr ((16-%) shl 2) and $0F - if d > 57 - d = d + 65-57-1 - end if - display d - end repeat - display 13,10 -} -macro diff10 title,l1,l2 - { - local s,d,z,m - s = l2-l1 - z = 0 - m = 1000000000 - display title,': ' - repeat 10 - d = '0' + s / m - s = s - (s/m)*m - m = m / 10 - if d <> '0' - z = 1 - end if - if z <> 0 - display d - end if - end repeat - display 13,10 - } - -; \begin{diamond}[29.09.2006] -; may be useful for kernel debugging -; example 1: -; dbgstr 'Hello, World!' -; example 2: -; dbgstr 'Hello, World!', save_flags -macro dbgstr string*, f -{ -local a -iglobal_nested -a db 'K : ',string,13,10,0 -endg_nested -if ~ f eq - pushfd -end if - push esi - mov esi, a - call sys_msg_board_str - pop esi -if ~ f eq - popfd -end if -} -; \end{diamond}[29.09.2006] + + +; structure definition helper +macro struct name, [arg] + { + common + name@struct equ name + struc name arg { + } + +macro struct_helper name + { + match xname,name + \{ + virtual at 0 + xname xname + sizeof.#xname = $ - xname + name equ sizeof.#xname + end virtual + \} + } + +ends fix } struct_helper name@struct + +;// mike.dld, 2006-29-01 [ + +; macros definition +macro diff16 title,l1,l2 +{ + local s,d + s = l2-l1 + display title,': 0x' + repeat 16 + d = 48 + s shr ((16-%) shl 2) and $0F + if d > 57 + d = d + 65-57-1 + end if + display d + end repeat + display 13,10 +} +macro diff10 title,l1,l2 + { + local s,d,z,m + s = l2-l1 + z = 0 + m = 1000000000 + display title,': ' + repeat 10 + d = '0' + s / m + s = s - (s/m)*m + m = m / 10 + if d <> '0' + z = 1 + end if + if z <> 0 + display d + end if + end repeat + display 13,10 + } + +; \begin{diamond}[29.09.2006] +; may be useful for kernel debugging +; example 1: +; dbgstr 'Hello, World!' +; example 2: +; dbgstr 'Hello, World!', save_flags +macro dbgstr string*, f +{ +local a +iglobal_nested +a db 'K : ',string,13,10,0 +endg_nested +if ~ f eq + pushfd +end if + push esi + mov esi, a + call sys_msg_board_str + pop esi +if ~ f eq + popfd +end if +} +; \end{diamond}[29.09.2006] diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/preboot.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/preboot.inc index b3fdb3831..b1ee5be20 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/preboot.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/preboot.inc @@ -1,36 +1,36 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -display_modechg db 0 ; display mode change for text, yes/no (0 or 2) - ; - ; !! Important note !! - ; - ; Must be set to 2, to avoid two screenmode - ; changes within a very short period of time. - -display_atboot db 0 ; show boot screen messages ( 2-no ) - -preboot_graph dw 0 ; graph mode -x_save dw 0 ; x -y_save dw 0 ; y -number_vm dw 0 ; -;pixel_save dw 0 ; per to pixel -preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) -preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) -preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) -preboot_device db 0 ; boot device - ; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) - ;!!!! 0 - autodetect !!!! -preboot_blogesc = 0 ; start immediately after bootlog -preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) - -; if $>0x200 -;ERROR: prebooting parameters must fit in first sector!!! -; end if -;hdsysimage db 'KOLIBRI IMG' ; load from -;image_save db 'KOLIBRI IMG' ; save to +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +display_modechg db 0 ; display mode change for text, yes/no (0 or 2) + ; + ; !! Important note !! + ; + ; Must be set to 2, to avoid two screenmode + ; changes within a very short period of time. + +display_atboot db 0 ; show boot screen messages ( 2-no ) + +preboot_graph dw 0 ; graph mode +x_save dw 0 ; x +y_save dw 0 ; y +number_vm dw 0 ; +;pixel_save dw 0 ; per to pixel +preboot_gprobe db 0 ; probe vesa3 videomodes (1-no, 2-yes) +preboot_vrrm db 0 ; use VRR_M (1-yes, 2- no) +preboot_dma db 0 ; use DMA for access to HDD (1-always, 2-only for read, 3-never) +preboot_device db 0 ; boot device + ; (1-floppy 2-harddisk 3-kernel restart 4-format ram disk) + ;!!!! 0 - autodetect !!!! +preboot_blogesc = 0 ; start immediately after bootlog +preboot_biosdisk db 0 ; use V86 to access disks through BIOS (1-yes, 2-no) + +; if $>0x200 +;ERROR: prebooting parameters must fit in first sector!!! +; end if +;hdsysimage db 'KOLIBRI IMG' ; load from +;image_save db 'KOLIBRI IMG' ; save to diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/rdload.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/rdload.inc index af70d34e3..23fe19e3e 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/rdload.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/rdload.inc @@ -1,123 +1,123 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -; READ RAMDISK IMAGE FROM HD - - cmp [boot_dev+OS_BASE+0x10000],1 - jne no_sys_on_hd - - test [DRIVE_DATA+1],byte 0x40 - jz position_2 - mov [hdbase],0x1f0 - mov [hdid],0x0 - mov [hdpos],1 - mov [fat32part],0 - position_1_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+2] - cmp [fat32part],eax - jle position_1_1 - position_2: - test [DRIVE_DATA+1],byte 0x10 - jz position_3 - mov [hdbase],0x1f0 - mov [hdid],0x10 - mov [hdpos],2 - mov [fat32part],0 - position_2_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+3] - cmp eax,[fat32part] - jle position_2_1 - position_3: - test [DRIVE_DATA+1],byte 0x4 - jz position_4 - mov [hdbase],0x170 - mov [hdid],0x0 - mov [hdpos],3 - mov [fat32part],0 - position_3_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+4] - cmp eax,[fat32part] - jle position_3_1 - position_4: - test [DRIVE_DATA+1],byte 0x1 - jz no_sys_on_hd - mov [hdbase],0x170 - mov [hdid],0x10 - mov [hdpos],4 - mov [fat32part],0 - position_4_1: - inc [fat32part] - call search_and_read_image - cmp [image_retrieved],1 - je yes_sys_on_hd - movzx eax,byte [DRIVE_DATA+5] - cmp eax,[fat32part] - jle position_4_1 - jmp yes_sys_on_hd - - search_and_read_image: - call set_FAT32_variables - mov edx, bootpath - call read_image - test eax, eax - jz image_present - mov edx, bootpath2 - call read_image - test eax, eax - jz image_present - ret - image_present: - mov [image_retrieved],1 - ret - -read_image: - mov eax, hdsysimage+OS_BASE+0x10000 - mov ebx, 1474560/512 - mov ecx, RAMDISK - mov esi, 0 - mov edi, 12 - call file_read - ret - -image_retrieved db 0 -counter_of_partitions db 0 -no_sys_on_hd: - ; test_to_format_ram_disk (need if not using ram disk) - cmp [boot_dev+OS_BASE+0x10000],3 - jne not_format_ram_disk - ; format_ram_disk - mov edi, RAMDISK - mov ecx, 0x1080 - xor eax,eax -@@: - stosd - loop @b - - mov ecx, 0x58F7F - mov eax,0xF6F6F6F6 -@@: - stosd - loop @b - - mov [RAMDISK+0x200],dword 0xFFFFF0 ; fat table - mov [RAMDISK+0x4200],dword 0xFFFFF0 - -not_format_ram_disk: -yes_sys_on_hd: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; READ RAMDISK IMAGE FROM HD + + cmp [boot_dev+OS_BASE+0x10000], 1 + jne no_sys_on_hd + + test [DRIVE_DATA+1], byte 0x40 + jz position_2 + mov [hdbase], 0x1f0 + mov [hdid], 0x0 + mov [hdpos], 1 + mov [fat32part], 0 + position_1_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+2] + cmp [fat32part], eax + jle position_1_1 + position_2: + test [DRIVE_DATA+1], byte 0x10 + jz position_3 + mov [hdbase], 0x1f0 + mov [hdid], 0x10 + mov [hdpos], 2 + mov [fat32part], 0 + position_2_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+3] + cmp eax, [fat32part] + jle position_2_1 + position_3: + test [DRIVE_DATA+1], byte 0x4 + jz position_4 + mov [hdbase], 0x170 + mov [hdid], 0x0 + mov [hdpos], 3 + mov [fat32part], 0 + position_3_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+4] + cmp eax, [fat32part] + jle position_3_1 + position_4: + test [DRIVE_DATA+1], byte 0x1 + jz no_sys_on_hd + mov [hdbase], 0x170 + mov [hdid], 0x10 + mov [hdpos], 4 + mov [fat32part], 0 + position_4_1: + inc [fat32part] + call search_and_read_image + cmp [image_retrieved], 1 + je yes_sys_on_hd + movzx eax, byte [DRIVE_DATA+5] + cmp eax, [fat32part] + jle position_4_1 + jmp yes_sys_on_hd + + search_and_read_image: + call set_FAT32_variables + mov edx, bootpath + call read_image + test eax, eax + jz image_present + mov edx, bootpath2 + call read_image + test eax, eax + jz image_present + ret + image_present: + mov [image_retrieved], 1 + ret + +read_image: + mov eax, hdsysimage+OS_BASE+0x10000 + mov ebx, 1474560/512 + mov ecx, RAMDISK + mov esi, 0 + mov edi, 12 + call file_read + ret + +image_retrieved db 0 +counter_of_partitions db 0 +no_sys_on_hd: + ; test_to_format_ram_disk (need if not using ram disk) + cmp [boot_dev+OS_BASE+0x10000], 3 + jne not_format_ram_disk + ; format_ram_disk + mov edi, RAMDISK + mov ecx, 0x1080 + xor eax, eax +@@: + stosd + loop @b + + mov ecx, 0x58F7F + mov eax, 0xF6F6F6F6 +@@: + stosd + loop @b + + mov [RAMDISK+0x200], dword 0xFFFFF0 ; fat table + mov [RAMDISK+0x4200], dword 0xFFFFF0 + +not_format_ram_disk: +yes_sys_on_hd: diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/ru.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/ru.inc index 606c698e3..a454e92c2 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/ru.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/ru.inc @@ -1,100 +1,100 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -; Generated by RUFNT.EXE -; By BadBugsKiller (C) -; Modifyed by BadBugsKiller 12.01.2004 17:45 -; Шрифт уменьшен в размере и теперь состоит из 2-ух частей, -; содержащих только символы русского алфавита. -; символы в кодировке ASCII (ДОС'овская), кодовая страница 866. -RU_FNT1: - db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - - db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 - - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 - -RU_FNT2: - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 - db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 - - db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 - db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 - db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 - db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +; Generated by RUFNT.EXE +; By BadBugsKiller (C) +; Modifyed by BadBugsKiller 12.01.2004 17:45 +; Шрифт уменьшен в размере и теперь состоит из 2-ух частей, +; содержащих только символы русского алфавита. +; символы в кодировке ASCII (ДОС'овская), кодовая страница 866. +RU_FNT1: + db 0x00, 0x00, 0x1E, 0x36, 0x66, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x62, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0x81, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xDB, 0xDB, 0x5A, 0x5A, 0x7E, 0x7E, 0x5A, 0xDB, 0xDB, 0xDB, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x1F, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xCF, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + + db 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xFF, 0xDB, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0xF8, 0xF0, 0xB0, 0x30, 0x3E, 0x33, 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xDB, 0xDB, 0xDB, 0xDB, 0xF3, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x26, 0x3E, 0x26, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x3F, 0x66, 0x66, 0x66, 0x3E, 0x3E, 0x66, 0x66, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 + + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x02, 0x06, 0x7C, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x62, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xFF, 0xC3, 0xC3, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xFE, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0x54, 0x7C, 0x54, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3C, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xCE, 0xD6, 0xE6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x36, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00 + +RU_FNT2: + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 + db 0x00, 0x00, 0x00, 0x3C, 0x18, 0x7E, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0x7E, 0x18, 0x18, 0x3C, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xFF, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xFE, 0x03, 0x03, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xB0, 0xB0, 0x3E, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xF6, 0xDE, 0xDE, 0xF6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x3E, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xDB, 0xDB, 0xFB, 0xDB, 0xDB, 0xCE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC6, 0xC6, 0x7E, 0x36, 0x66, 0xE7, 0x00, 0x00, 0x00, 0x00 + + db 0x6C, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xFC, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC8, 0xF8, 0xC8, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xF8, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x66, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00 + db 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x6C, 0x38, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0xC6, 0x7C, 0x00 + db 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0xCF, 0xCD, 0xEF, 0xEC, 0xFF, 0xDC, 0xDC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00 + db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 diff --git a/kernel/trunk/sec_loader/trunk/kolibri_ldm/shutdown.inc b/kernel/trunk/sec_loader/trunk/kolibri_ldm/shutdown.inc index 07ba5355f..25c28704c 100644 --- a/kernel/trunk/sec_loader/trunk/kolibri_ldm/shutdown.inc +++ b/kernel/trunk/sec_loader/trunk/kolibri_ldm/shutdown.inc @@ -1,207 +1,207 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; Shutdown for Menuet ;; -;; ;; -;; Distributed under General Public License ;; -;; See file COPYING for details. ;; -;; Copyright 2003 Ville Turjanmaa ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - -align 4 -pr_mode_exit: - -; setup stack - mov ax, 0x3000 - mov ss, ax - mov esp, 0x0EC00 -; setup ds - push cs - pop ds - - lidt [old_ints_h] -;remap IRQs - mov al,0x11 - out 0x20,al - call rdelay - out 0xA0,al - call rdelay - - mov al,0x08 - out 0x21,al - call rdelay - mov al,0x70 - out 0xA1,al - call rdelay - - mov al,0x04 - out 0x21,al - call rdelay - mov al,0x02 - out 0xA1,al - call rdelay - - mov al,0x01 - out 0x21,al - call rdelay - out 0xA1,al - call rdelay - - mov al,0xB8 - out 0x21,al - call rdelay - mov al,0xBD - out 0xA1,al - sti - -temp_3456: - xor ax,ax - mov es,ax - mov al,byte [es:0x9030] - cmp al,1 - jl nbw - cmp al,4 - jle nbw32 - -nbw: - in al,0x60 - cmp al,6 - jae nbw - mov bl,al -nbw2: - in al,0x60 - cmp al,bl - je nbw2 - cmp al,240 ;ax,240 - jne nbw31 - mov al,bl - dec ax - jmp nbw32 -nbw31: - add bl,128 - cmp al,bl - jne nbw - sub al,129 - -nbw32: - - dec ax - dec ax ; 2 = power off - jnz no_apm_off - call APM_PowerOff - jmp $ -no_apm_off: - - dec ax ; 3 = reboot - jnz restart_kernel ; 4 = restart kernel - push 0x40 - pop ds - mov word[0x0072],0x1234 - jmp 0xF000:0xFFF0 - - -rdelay: - ret - -APM_PowerOff: - mov ax, 5304h - xor bx, bx - int 15h -;!!!!!!!!!!!!!!!!!!!!!!!! - mov ax,0x5300 - xor bx,bx - int 0x15 - push ax - - mov ax,0x5301 - xor bx,bx - int 0x15 - - mov ax,0x5308 - mov bx,1 - mov cx,bx - int 0x15 - - mov ax,0x530E - xor bx,bx - pop cx - int 0x15 - - mov ax,0x530D - mov bx,1 - mov cx,bx - int 0x15 - - mov ax,0x530F - mov bx,1 - mov cx,bx - int 0x15 - - mov ax,0x5307 - mov bx,1 - mov cx,3 - int 0x15 -;!!!!!!!!!!!!!!!!!!!!!!!! - ret - -restart_kernel: - - mov ax,0x0003 ; set text mode for screen - int 0x10 - jmp 0x4000:0000 - -restart_kernel_4000: - cli - - push ds - pop es - mov cx, 0x8000 - push cx - push 0x7000 - pop ds - xor si, si - xor di, di - rep movsw - pop cx - mov ds, cx - push 0x2000 - pop es - rep movsw - push 0x9000 - pop ds - push 0x3000 - pop es - mov cx, 0xE000/2 - rep movsw - - wbinvd ; write and invalidate cache - - mov al, 00110100b - out 43h, al - jcxz $+2 - mov al, 0xFF - out 40h, al - jcxz $+2 - out 40h, al - jcxz $+2 - sti - -; (hint by Black_mirror) -; We must read data from keyboard port, -; because there may be situation when previous keyboard interrupt is lost -; (due to return to real mode and IRQ reprogramming) -; and next interrupt will not be generated (as keyboard waits for handling) - in al, 0x60 - -; bootloader interface - push 0x1000 - pop ds - mov si, kernel_restart_bootblock - mov ax, 'KL' - jmp 0x1000:0000 - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; Shutdown for Menuet ;; +;; ;; +;; Distributed under General Public License ;; +;; See file COPYING for details. ;; +;; Copyright 2003 Ville Turjanmaa ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + +align 4 +pr_mode_exit: + +; setup stack + mov ax, 0x3000 + mov ss, ax + mov esp, 0x0EC00 +; setup ds + push cs + pop ds + + lidt [old_ints_h] +;remap IRQs + mov al, 0x11 + out 0x20, al + call rdelay + out 0xA0, al + call rdelay + + mov al, 0x08 + out 0x21, al + call rdelay + mov al, 0x70 + out 0xA1, al + call rdelay + + mov al, 0x04 + out 0x21, al + call rdelay + mov al, 0x02 + out 0xA1, al + call rdelay + + mov al, 0x01 + out 0x21, al + call rdelay + out 0xA1, al + call rdelay + + mov al, 0xB8 + out 0x21, al + call rdelay + mov al, 0xBD + out 0xA1, al + sti + +temp_3456: + xor ax, ax + mov es, ax + mov al, byte [es:0x9030] + cmp al, 1 + jl nbw + cmp al, 4 + jle nbw32 + +nbw: + in al, 0x60 + cmp al, 6 + jae nbw + mov bl, al +nbw2: + in al, 0x60 + cmp al, bl + je nbw2 + cmp al, 240;ax,240 + jne nbw31 + mov al, bl + dec ax + jmp nbw32 +nbw31: + add bl, 128 + cmp al, bl + jne nbw + sub al, 129 + +nbw32: + + dec ax + dec ax ; 2 = power off + jnz no_apm_off + call APM_PowerOff + jmp $ +no_apm_off: + + dec ax ; 3 = reboot + jnz restart_kernel ; 4 = restart kernel + push 0x40 + pop ds + mov word[0x0072], 0x1234 + jmp 0xF000:0xFFF0 + + +rdelay: + ret + +APM_PowerOff: + mov ax, 5304h + xor bx, bx + int 15h +;!!!!!!!!!!!!!!!!!!!!!!!! + mov ax, 0x5300 + xor bx, bx + int 0x15 + push ax + + mov ax, 0x5301 + xor bx, bx + int 0x15 + + mov ax, 0x5308 + mov bx, 1 + mov cx, bx + int 0x15 + + mov ax, 0x530E + xor bx, bx + pop cx + int 0x15 + + mov ax, 0x530D + mov bx, 1 + mov cx, bx + int 0x15 + + mov ax, 0x530F + mov bx, 1 + mov cx, bx + int 0x15 + + mov ax, 0x5307 + mov bx, 1 + mov cx, 3 + int 0x15 +;!!!!!!!!!!!!!!!!!!!!!!!! + ret + +restart_kernel: + + mov ax, 0x0003 ; set text mode for screen + int 0x10 + jmp 0x4000:0000 + +restart_kernel_4000: + cli + + push ds + pop es + mov cx, 0x8000 + push cx + push 0x7000 + pop ds + xor si, si + xor di, di + rep movsw + pop cx + mov ds, cx + push 0x2000 + pop es + rep movsw + push 0x9000 + pop ds + push 0x3000 + pop es + mov cx, 0xE000/2 + rep movsw + + wbinvd ; write and invalidate cache + + mov al, 00110100b + out 43h, al + jcxz $+2 + mov al, 0xFF + out 40h, al + jcxz $+2 + out 40h, al + jcxz $+2 + sti + +; (hint by Black_mirror) +; We must read data from keyboard port, +; because there may be situation when previous keyboard interrupt is lost +; (due to return to real mode and IRQ reprogramming) +; and next interrupt will not be generated (as keyboard waits for handling) + in al, 0x60 + +; bootloader interface + push 0x1000 + pop ds + mov si, kernel_restart_bootblock + mov ax, 'KL' + jmp 0x1000:0000 + + diff --git a/kernel/trunk/sec_loader/trunk/listing.inc b/kernel/trunk/sec_loader/trunk/listing.inc index 4ef5f8eeb..e14b2fe65 100644 --- a/kernel/trunk/sec_loader/trunk/listing.inc +++ b/kernel/trunk/sec_loader/trunk/listing.inc @@ -1,635 +1,635 @@ -; Listing generator -; LocoDelAssembly 2007.06.01 - -INSTRUCTIONS equ bt in ja jb jc je jg jl jo jp js jz or \ - aaa aad aam aas adc add and bsf bsr btc btr bts cbw cdq clc \ - cld cli cmc cmp cqo cwd daa das dec div fld fst hlt inc ins \ - int jae jbe jge jle jmp jna jnb jnc jne jng jnl jno jnp jns \ - jnz jpe jpo lar lds lea les lfs lgs lsl lss ltr mov mul neg \ - nop not out pop por rcl rcr ret rol ror rsm sal sar sbb shl \ - shr stc std sti str sub ud2 xor \ - arpl call cdqe clgi clts cmps cwde emms fabs fadd fbld fchs \ - fcom fcos fdiv feni fild fist fld1 fldz fmul fnop fsin fstp \ - fsub ftst fxam fxch idiv imul insb insd insw int1 int3 into \ - invd iret jcxz jnae jnbe jnge jnle lahf lgdt lidt lldt lmsw \ - lods loop movd movq movs orpd orps outs pand popa popd popf \ - popq popw push pxor retd retf retn retq retw sahf salc scas \ - seta setb setc sete setg setl seto setp sets setz sgdt shld \ - shrd sidt sldt smsw stgi stos test verr verw wait xadd xchg \ - xlat \ - addpd addps addsd addss andpd andps bound bswap cmova cmovb \ - cmovc cmove cmovg cmovl cmovo cmovp cmovs cmovz cmppd cmpps \ - cmpsb cmpsd cmpsq cmpss cmpsw cpuid divpd divps divsd divss \ - enter f2xm1 faddp fbstp fclex fcomi fcomp fdisi fdivp fdivr \ - femms ffree fiadd ficom fidiv fimul finit fistp fisub fldcw \ - fldpi fmulp fneni fprem fptan fsave fsqrt fstcw fstsw fsubp \ - fsubr fucom fwait fyl2x icebp iretd iretq iretw jecxz jrcxz \ - lddqu leave lodsb lodsd lodsq lodsw loopd loope loopq loopw \ - loopz maxpd maxps maxsd maxss minpd minps minsd minss movsb \ - movsd movsq movss movsw movsx movzx mulpd mulps mulsd mulss \ - mwait outsb outsd outsw pabsb pabsd pabsw paddb paddd paddq \ - paddw pandn pause pavgb pavgw pf2id pf2iw pfacc pfadd pfmax \ - pfmin pfmul pfrcp pfsub pi2fd pi2fw popad popaw popfd popfq \ - popfw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb \ - psubd psubq psubw pusha pushd pushf pushq pushw rcpps rcpss \ - rdmsr rdpmc rdtsc retfd retfq retfw retnd retnq retnw scasb \ - scasd scasq scasw setae setbe setge setle setna setnb setnc \ - setne setng setnl setno setnp setns setnz setpe setpo stosb \ - stosd stosq stosw subpd subps subsd subss vmrun vmxon wrmsr \ - xlatb xorpd xorps \ - andnpd andnps cmovae cmovbe cmovge cmovle cmovna cmovnb cmovnc\ - cmovne cmovng cmovnl cmovno cmovnp cmovns cmovnz cmovpe cmovpo\ - comisd comiss fcmovb fcmove fcmovu fcomip fcompp fdivrp ffreep\ - ficomp fidivr fisttp fisubr fldenv fldl2e fldl2t fldlg2 fldln2\ - fnclex fndisi fninit fnsave fnstcw fnstsw fpatan fprem1 frstor\ - frstpm fscale fsetpm fstenv fsubrp fucomi fucomp fxsave haddpd\ - haddps hsubpd hsubps invlpg lfence looped loopeq loopew loopne\ - loopnz loopzd loopzq loopzw mfence movapd movaps movdqa movdqu\ - movhpd movhps movlpd movlps movnti movntq movsxd movupd movups\ - paddsb paddsw pextrw pfnacc pfsubr phaddd phaddw phsubd phsubw\ - pinsrw pmaxsw pmaxub pminsw pminub pmulhw pmullw psadbw pshufb\ - pshufd pshufw psignb psignd psignw pslldq psrldq psubsb psubsw\ - pswapd pushad pushaw pushfd pushfq pushfw rdmsrq rdtscp setalc\ - setnae setnbe setnge setnle sfence shufpd shufps skinit sqrtpd\ - sqrtps sqrtsd sqrtss swapgs sysret vmcall vmload vmread vmsave\ - vmxoff wbinvd wrmsrq \ - clflush cmovnae cmovnbe cmovnge cmovnle cmpeqpd cmpeqps \ - cmpeqsd cmpeqss cmplepd cmpleps cmplesd cmpless cmpltpd \ - cmpltps cmpltsd cmpltss cmpxchg fcmovbe fcmovnb fcmovne \ - fcmovnu fdecstp fincstp fnstenv frndint fsincos fucomip \ - fucompp fxrstor fxtract fyl2xp1 invlpga ldmxcsr loopned \ - loopneq loopnew loopnzd loopnzq loopnzw monitor movddup \ - movdq2q movhlps movlhps movntdq movntpd movntps movq2dq \ - paddusb paddusw palignr pavgusb pcmpeqb pcmpeqd pcmpeqw \ - pcmpgtb pcmpgtd pcmpgtw pfcmpeq pfcmpge pfcmpgt pfpnacc \ - pfrsqrt phaddsw phsubsw pmaddwd pmulhrw pmulhuw pmuludq \ - pshufhw pshuflw psubusb psubusw rsqrtps rsqrtss stmxcsr \ - syscall sysexit sysretq ucomisd ucomiss vmclear vmmcall \ - vmptrld vmptrst vmwrite \ - addsubpd addsubps cmpneqpd cmpneqps cmpneqsd cmpneqss cmpnlepd\ - cmpnleps cmpnlesd cmpnless cmpnltpd cmpnltps cmpnltsd cmpnltss\ - cmpordpd cmpordps cmpordsd cmpordss cvtdq2pd cvtdq2ps cvtpd2dq\ - cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd cvtps2pi\ - cvtsd2si cvtsd2ss cvtsi2sd cvtsi2ss cvtss2sd cvtss2si fcmovnbe\ - maskmovq movmskpd movmskps movshdup movsldup packssdw packsswb\ - packuswb pfrcpit1 pfrcpit2 pfrsqit1 pmovmskb pmulhrsw prefetch\ - sysenter sysexitq unpckhpd unpckhps unpcklpd unpcklps vmlaunch\ - vmresume \ - cmpxchg8b cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi cvttsd2si \ - cvttss2si pmaddubsw prefetchw punpckhbw punpckhdq punpckhwd \ - punpcklbw punpckldq punpcklwd \ - cmpunordpd cmpunordps cmpunordsd cmpunordss cmpxchg16b \ - loadall286 loadall386 maskmovdqu prefetcht0 prefetcht1 \ - prefetcht2 punpckhqdq punpcklqdq prefetchnta - -PREFIXES equ rep lock repe repz repne repnz - -DATA_DEFINITORS equ db dw du dd dp df dq dt file -DATA_RESERVERS equ rb rw rd rp rf rq rt - -CRLF equ 13, 10 ; Remove 13 for Linux -MAX_BYTES equ 13 - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MODE MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -macro use16 -{ -use16 - _USE = 16 -} - -macro use32 -{ -use32 - _USE = 32 -} - -macro use64 -{ -use64 - _USE = 64 -} - -macro detect_mode -{ -local aux - - _USE = 32 - - virtual at 0 - xchg eax, eax - load aux byte from 0 - - if aux = $66 - _USE = 16 - else if aux = $87 - _USE = 64 - end if - end virtual -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISPLAYING MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -macro display_address address* -{ -local aux, digit - - aux = address - - repeat _USE / 4 - digit = aux shr (_USE - 4 * %) and $F - - display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F - end repeat - - display ': ' -} - -macro display_bytes pointer -{ -local aux, size, digit - - size = $ - pointer - - if size > MAX_BYTES - size = MAX_BYTES - end if - - repeat size - load aux byte from pointer+%-1 - - digit = aux shr 4 - display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F - - digit = aux and $F - display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F - - - display ' ' - end repeat - - repeat MAX_BYTES - size - display ' ' - end repeat -} - -; The macro below in some situations doesn't adds a space to separate things unfortunatelly, so for readability ensurance -; another one will be used instead... -;macro display_args [args] -;{ -;common -; aux = 1 -; -;forward -; if ~args eq -; if aux -; display ' ' -; else -; display ', ' -; end if -; -; aux = 0 -; -; match =ON, _RESOLVE_EQUATES -; \{ -; match args, args -; \\{ -; irps arg, args -; \\\{ -; display \\\`arg -; \\\} -; \\} -; \} -; match =OFF, _RESOLVE_EQUATES -; \{ -; irps arg, args -; \\{ -; display \\`arg -; \\} -; -; \} -; end if -;} - -; This one separates everything with one space. A very ugly listing but at least you will not see things -; like "push ebxesiedi" nor "ret word0" - -macro display_args [args] -{ -common - aux = 1 - -forward - if ~args eq - if ~aux - display ',' - end if - - aux = 0 - - match =ON, _RESOLVE_EQUATES - \{ - match args, args - \\{ - if ~args eqtype "" - irps arg, args - \\\{ - display ' ', \\\`arg - \\\} - else - display " '", args, "'" - end if - \\} - \} - match =OFF, _RESOLVE_EQUATES - \{ - if ~args eqtype "" - irps arg, args - \\{ - display ' ', \\`arg - \\} - else - display " '", args, "'" - end if - \} - end if -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;; INSTRUCTIONS & PREFIXES MACROSES ;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -macro prefix mnemonic -{ -local aux - - macro mnemonic [args] - \{ - \common - match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} - match =equ, args\\{_LISTING equ 0\\} - match =equ any, args\\{_LISTING equ 0\\} - - match =1, _LISTING - \\{ - display_address $ - aux = $ - \\} - - mnemonic - - match =1, _LISTING - \\{ - display_bytes aux - - display \`mnemonic - display CRLF - \\} - - match =1, _ON_VIRTUAL\\{restore _LISTING\\} - match =equ, args\\{restore _LISTING\\} - match =equ any, args\\{restore _LISTING\\} - - def_prefix mnemonic - args - purge mnemonic - \} -} - -macro def_prefix mnemonic -{ - macro def_prefix mnemonic - \{ - prefix mnemonic - \} - def_prefix mnemonic -} - -macro instruction mnemonic -{ -local aux - - macro mnemonic [args] - \{ - \common - match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} - match =equ, args\\{_LISTING equ 0\\} - match =equ any, args\\{_LISTING equ 0\\} - - match =1, _LISTING - \\{ - display_address $ - aux = $ - \\} - - mnemonic args - - match =1, _LISTING - \\{ - display_bytes aux - - display \`mnemonic - - virtual at 0 - db \`mnemonic - repeat 11 - $ - display ' ' - end repeat - end virtual - - display_args args - display CRLF - \\} - - match =1, _ON_VIRTUAL\\{restore _LISTING\\} - match =equ, args\\{restore _LISTING\\} - match =equ any, args\\{restore _LISTING\\} - \} -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -macro data_define mnemonic -{ -local aux - macro mnemonic [args] - \{ - \common - match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} - match =equ, args\\{_LISTING equ 0\\} - match =equ any, args\\{_LISTING equ 0\\} - - match =1, _LISTING - \\{ - display_address $ - aux = $ - \\} - - mnemonic args - - match =1, _LISTING - \\{ - display_bytes aux - - display \`mnemonic - - display_args args - display CRLF - - aux = aux + MAX_BYTES - - repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES - display_address aux - display_bytes aux - display CRLF - - aux = aux + MAX_BYTES - end repeat - \\} - - match =1, _ON_VIRTUAL\\{restore _LISTING\\} - match =equ, args\\{restore _LISTING\\} - match =equ any, args\\{restore _LISTING\\} - \} - - struc mnemonic [args] - \{ - \common - match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} - match =equ, args\\{_LISTING equ 0\\} - match =equ any, args\\{_LISTING equ 0\\} - - match =1, _LISTING - \\{ - display_address $ - aux = $ - \\} - - . mnemonic args - - match =1, _LISTING - \\{ - display_bytes aux - - display \`., ' ', \`mnemonic - - display_args args - display CRLF - - aux = aux + MAX_BYTES - - repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES - display_address aux - display_bytes aux - display CRLF - - aux = aux + MAX_BYTES - end repeat - \\} - - match =1, _ON_VIRTUAL\\{restore _LISTING\\} - match =equ, args\\{restore _LISTING\\} - match =equ any, args\\{restore _LISTING\\} - \} -} - -macro data_reserve mnemonic -{ -local aux - macro mnemonic [args] - \{ - \common - match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} - match =equ, args\\{_LISTING equ 0\\} - match =equ any, args\\{_LISTING equ 0\\} - - match =1, _LISTING - \\{ - display_address $ - aux = $ - \\} - - mnemonic args - - match =1, _LISTING - \\{ - times MAX_BYTES display ' ' - - display \`mnemonic - - display_args args - display CRLF - \\} - - match =1, _ON_VIRTUAL\\{restore _LISTING\\} - match =equ, args\\{restore _LISTING\\} - match =equ any, args\\{restore _LISTING\\} - \} - - struc mnemonic [args] - \{ - \common - match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} - match =equ, args\\{_LISTING equ 0\\} - match =equ any, args\\{_LISTING equ 0\\} - - match =1, _LISTING - \\{ - display_address $ - aux = $ - \\} - - . mnemonic args - - match =1, _LISTING - \\{ - times MAX_BYTES display ' ' - - display \`., ' ', \`mnemonic - - display_args args - display CRLF - \\} - - match =1, _ON_VIRTUAL\\{restore _LISTING\\} - match =equ, args\\{restore _LISTING\\} - match =equ any, args\\{restore _LISTING\\} - \} -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;; LISTING CONTROL MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -macro virtual [args] -{ -common - _ON_VIRTUAL equ 1 - - virtual args -} - -macro end [args] -{ -common - match =virtual, args\{restore _ON_VIRTUAL\} - - end args -} - -macro enable_listing -{ - detect_mode - - match =0, _MACROSES_INSTALLED - \{ - match instructions, INSTRUCTIONS - \\{ - irps ins, instructions - \\\{ - instruction ins - \\\} - \\} - - match prefixes, PREFIXES - \\{ - irps prefix, prefixes - \\\{ - def_prefix prefix - \\\} - \\} - - match data_definitors, DATA_DEFINITORS - \\{ - irps def, data_definitors - \\\{ - data_define def - \\\} - \\} - - match data_reservers, DATA_RESERVERS - \\{ - irps def, data_reservers - \\\{ - data_reserve def - \\\} - \\} - \} - - _MACROSES_INSTALLED equ 1 - _LISTING equ 1 -} - -macro disable_listing -{ - _LISTING equ 0 -} - -macro enable [feature*] -{ -forward - UNKNOWN equ 1 - - match =resolve_equates, feature - \{ - restore _RESOLVE_EQUATES - _RESOLVE_EQUATES equ ON - UNKNOWN equ 0 - \} - - match =listing, feature - \{ - enable_listing - UNKNOWN equ 0 - \} - - match =1, UNKNOWN - \{ - display 'ERROR: Unknown "',`feature, '" feature', 13, 10 - err - \} - - restore UNKNOWN - restore UNKNOWN -} - -macro disable [feature*] -{ - UNKNOWN equ 1 - - match =resolve_equates, feature - \{ - restore _RESOLVE_EQUATES - _RESOLVE_EQUATES equ OFF - UNKNOWN equ 0 - \} - - match =listing, feature - \{ - disable_listing - UNKNOWN equ 0 - \} - - match =1, UNKNOWN - \{ - display 'ERROR: Unknown "',`feature, '" feature', 13, 10 - err - \} - - restore UNKNOWN - restore UNKNOWN -} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INITIALIZATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -_MACROSES_INSTALLED equ 0 -_ON_VIRTUAL equ 0 - -disable resolve_equates +; Listing generator +; LocoDelAssembly 2007.06.01 + +INSTRUCTIONS equ bt in ja jb jc je jg jl jo jp js jz or \ + aaa aad aam aas adc add and bsf bsr btc btr bts cbw cdq clc \ + cld cli cmc cmp cqo cwd daa das dec div fld fst hlt inc ins \ + int jae jbe jge jle jmp jna jnb jnc jne jng jnl jno jnp jns \ + jnz jpe jpo lar lds lea les lfs lgs lsl lss ltr mov mul neg \ + nop not out pop por rcl rcr ret rol ror rsm sal sar sbb shl \ + shr stc std sti str sub ud2 xor \ + arpl call cdqe clgi clts cmps cwde emms fabs fadd fbld fchs \ + fcom fcos fdiv feni fild fist fld1 fldz fmul fnop fsin fstp \ + fsub ftst fxam fxch idiv imul insb insd insw int1 int3 into \ + invd iret jcxz jnae jnbe jnge jnle lahf lgdt lidt lldt lmsw \ + lods loop movd movq movs orpd orps outs pand popa popd popf \ + popq popw push pxor retd retf retn retq retw sahf salc scas \ + seta setb setc sete setg setl seto setp sets setz sgdt shld \ + shrd sidt sldt smsw stgi stos test verr verw wait xadd xchg \ + xlat \ + addpd addps addsd addss andpd andps bound bswap cmova cmovb \ + cmovc cmove cmovg cmovl cmovo cmovp cmovs cmovz cmppd cmpps \ + cmpsb cmpsd cmpsq cmpss cmpsw cpuid divpd divps divsd divss \ + enter f2xm1 faddp fbstp fclex fcomi fcomp fdisi fdivp fdivr \ + femms ffree fiadd ficom fidiv fimul finit fistp fisub fldcw \ + fldpi fmulp fneni fprem fptan fsave fsqrt fstcw fstsw fsubp \ + fsubr fucom fwait fyl2x icebp iretd iretq iretw jecxz jrcxz \ + lddqu leave lodsb lodsd lodsq lodsw loopd loope loopq loopw \ + loopz maxpd maxps maxsd maxss minpd minps minsd minss movsb \ + movsd movsq movss movsw movsx movzx mulpd mulps mulsd mulss \ + mwait outsb outsd outsw pabsb pabsd pabsw paddb paddd paddq \ + paddw pandn pause pavgb pavgw pf2id pf2iw pfacc pfadd pfmax \ + pfmin pfmul pfrcp pfsub pi2fd pi2fw popad popaw popfd popfq \ + popfw pslld psllq psllw psrad psraw psrld psrlq psrlw psubb \ + psubd psubq psubw pusha pushd pushf pushq pushw rcpps rcpss \ + rdmsr rdpmc rdtsc retfd retfq retfw retnd retnq retnw scasb \ + scasd scasq scasw setae setbe setge setle setna setnb setnc \ + setne setng setnl setno setnp setns setnz setpe setpo stosb \ + stosd stosq stosw subpd subps subsd subss vmrun vmxon wrmsr \ + xlatb xorpd xorps \ + andnpd andnps cmovae cmovbe cmovge cmovle cmovna cmovnb cmovnc\ + cmovne cmovng cmovnl cmovno cmovnp cmovns cmovnz cmovpe cmovpo\ + comisd comiss fcmovb fcmove fcmovu fcomip fcompp fdivrp ffreep\ + ficomp fidivr fisttp fisubr fldenv fldl2e fldl2t fldlg2 fldln2\ + fnclex fndisi fninit fnsave fnstcw fnstsw fpatan fprem1 frstor\ + frstpm fscale fsetpm fstenv fsubrp fucomi fucomp fxsave haddpd\ + haddps hsubpd hsubps invlpg lfence looped loopeq loopew loopne\ + loopnz loopzd loopzq loopzw mfence movapd movaps movdqa movdqu\ + movhpd movhps movlpd movlps movnti movntq movsxd movupd movups\ + paddsb paddsw pextrw pfnacc pfsubr phaddd phaddw phsubd phsubw\ + pinsrw pmaxsw pmaxub pminsw pminub pmulhw pmullw psadbw pshufb\ + pshufd pshufw psignb psignd psignw pslldq psrldq psubsb psubsw\ + pswapd pushad pushaw pushfd pushfq pushfw rdmsrq rdtscp setalc\ + setnae setnbe setnge setnle sfence shufpd shufps skinit sqrtpd\ + sqrtps sqrtsd sqrtss swapgs sysret vmcall vmload vmread vmsave\ + vmxoff wbinvd wrmsrq \ + clflush cmovnae cmovnbe cmovnge cmovnle cmpeqpd cmpeqps \ + cmpeqsd cmpeqss cmplepd cmpleps cmplesd cmpless cmpltpd \ + cmpltps cmpltsd cmpltss cmpxchg fcmovbe fcmovnb fcmovne \ + fcmovnu fdecstp fincstp fnstenv frndint fsincos fucomip \ + fucompp fxrstor fxtract fyl2xp1 invlpga ldmxcsr loopned \ + loopneq loopnew loopnzd loopnzq loopnzw monitor movddup \ + movdq2q movhlps movlhps movntdq movntpd movntps movq2dq \ + paddusb paddusw palignr pavgusb pcmpeqb pcmpeqd pcmpeqw \ + pcmpgtb pcmpgtd pcmpgtw pfcmpeq pfcmpge pfcmpgt pfpnacc \ + pfrsqrt phaddsw phsubsw pmaddwd pmulhrw pmulhuw pmuludq \ + pshufhw pshuflw psubusb psubusw rsqrtps rsqrtss stmxcsr \ + syscall sysexit sysretq ucomisd ucomiss vmclear vmmcall \ + vmptrld vmptrst vmwrite \ + addsubpd addsubps cmpneqpd cmpneqps cmpneqsd cmpneqss cmpnlepd\ + cmpnleps cmpnlesd cmpnless cmpnltpd cmpnltps cmpnltsd cmpnltss\ + cmpordpd cmpordps cmpordsd cmpordss cvtdq2pd cvtdq2ps cvtpd2dq\ + cvtpd2pi cvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq cvtps2pd cvtps2pi\ + cvtsd2si cvtsd2ss cvtsi2sd cvtsi2ss cvtss2sd cvtss2si fcmovnbe\ + maskmovq movmskpd movmskps movshdup movsldup packssdw packsswb\ + packuswb pfrcpit1 pfrcpit2 pfrsqit1 pmovmskb pmulhrsw prefetch\ + sysenter sysexitq unpckhpd unpckhps unpcklpd unpcklps vmlaunch\ + vmresume \ + cmpxchg8b cvttpd2dq cvttpd2pi cvttps2dq cvttps2pi cvttsd2si \ + cvttss2si pmaddubsw prefetchw punpckhbw punpckhdq punpckhwd \ + punpcklbw punpckldq punpcklwd \ + cmpunordpd cmpunordps cmpunordsd cmpunordss cmpxchg16b \ + loadall286 loadall386 maskmovdqu prefetcht0 prefetcht1 \ + prefetcht2 punpckhqdq punpcklqdq prefetchnta + +PREFIXES equ rep lock repe repz repne repnz + +DATA_DEFINITORS equ db dw du dd dp df dq dt file +DATA_RESERVERS equ rb rw rd rp rf rq rt + +CRLF equ 13, 10 ; Remove 13 for Linux +MAX_BYTES equ 13 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MODE MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +macro use16 +{ +use16 + _USE = 16 +} + +macro use32 +{ +use32 + _USE = 32 +} + +macro use64 +{ +use64 + _USE = 64 +} + +macro detect_mode +{ +local aux + + _USE = 32 + + virtual at 0 + xchg eax, eax + load aux byte from 0 + + if aux = $66 + _USE = 16 + else if aux = $87 + _USE = 64 + end if + end virtual +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISPLAYING MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +macro display_address address* +{ +local aux, digit + + aux = address + + repeat _USE / 4 + digit = aux shr (_USE - 4 * %) and $F + + display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F + end repeat + + display ': ' +} + +macro display_bytes pointer +{ +local aux, size, digit + + size = $ - pointer + + if size > MAX_BYTES + size = MAX_BYTES + end if + + repeat size + load aux byte from pointer+%-1 + + digit = aux shr 4 + display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F + + digit = aux and $F + display digit + '0' + ('9' - 'B') and (9 - digit) shr 4 and $F + + + display ' ' + end repeat + + repeat MAX_BYTES - size + display ' ' + end repeat +} + +; The macro below in some situations doesn't adds a space to separate things unfortunatelly, so for readability ensurance +; another one will be used instead... +;macro display_args [args] +;{ +;common +; aux = 1 +; +;forward +; if ~args eq +; if aux +; display ' ' +; else +; display ', ' +; end if +; +; aux = 0 +; +; match =ON, _RESOLVE_EQUATES +; \{ +; match args, args +; \\{ +; irps arg, args +; \\\{ +; display \\\`arg +; \\\} +; \\} +; \} +; match =OFF, _RESOLVE_EQUATES +; \{ +; irps arg, args +; \\{ +; display \\`arg +; \\} +; +; \} +; end if +;} + +; This one separates everything with one space. A very ugly listing but at least you will not see things +; like "push ebxesiedi" nor "ret word0" + +macro display_args [args] +{ +common + aux = 1 + +forward + if ~args eq + if ~aux + display ',' + end if + + aux = 0 + + match =ON, _RESOLVE_EQUATES + \{ + match args, args + \\{ + if ~args eqtype "" + irps arg, args + \\\{ + display ' ', \\\`arg + \\\} + else + display " '", args, "'" + end if + \\} + \} + match =OFF, _RESOLVE_EQUATES + \{ + if ~args eqtype "" + irps arg, args + \\{ + display ' ', \\`arg + \\} + else + display " '", args, "'" + end if + \} + end if +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;; INSTRUCTIONS & PREFIXES MACROSES ;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +macro prefix mnemonic +{ +local aux + + macro mnemonic [args] + \{ + \common + match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} + match =equ, args\\{_LISTING equ 0\\} + match =equ any, args\\{_LISTING equ 0\\} + + match =1, _LISTING + \\{ + display_address $ + aux = $ + \\} + + mnemonic + + match =1, _LISTING + \\{ + display_bytes aux + + display \`mnemonic + display CRLF + \\} + + match =1, _ON_VIRTUAL\\{restore _LISTING\\} + match =equ, args\\{restore _LISTING\\} + match =equ any, args\\{restore _LISTING\\} + + def_prefix mnemonic + args + purge mnemonic + \} +} + +macro def_prefix mnemonic +{ + macro def_prefix mnemonic + \{ + prefix mnemonic + \} + def_prefix mnemonic +} + +macro instruction mnemonic +{ +local aux + + macro mnemonic [args] + \{ + \common + match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} + match =equ, args\\{_LISTING equ 0\\} + match =equ any, args\\{_LISTING equ 0\\} + + match =1, _LISTING + \\{ + display_address $ + aux = $ + \\} + + mnemonic args + + match =1, _LISTING + \\{ + display_bytes aux + + display \`mnemonic + + virtual at 0 + db \`mnemonic + repeat 11 - $ + display ' ' + end repeat + end virtual + + display_args args + display CRLF + \\} + + match =1, _ON_VIRTUAL\\{restore _LISTING\\} + match =equ, args\\{restore _LISTING\\} + match =equ any, args\\{restore _LISTING\\} + \} +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +macro data_define mnemonic +{ +local aux + macro mnemonic [args] + \{ + \common + match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} + match =equ, args\\{_LISTING equ 0\\} + match =equ any, args\\{_LISTING equ 0\\} + + match =1, _LISTING + \\{ + display_address $ + aux = $ + \\} + + mnemonic args + + match =1, _LISTING + \\{ + display_bytes aux + + display \`mnemonic + + display_args args + display CRLF + + aux = aux + MAX_BYTES + + repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES + display_address aux + display_bytes aux + display CRLF + + aux = aux + MAX_BYTES + end repeat + \\} + + match =1, _ON_VIRTUAL\\{restore _LISTING\\} + match =equ, args\\{restore _LISTING\\} + match =equ any, args\\{restore _LISTING\\} + \} + + struc mnemonic [args] + \{ + \common + match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} + match =equ, args\\{_LISTING equ 0\\} + match =equ any, args\\{_LISTING equ 0\\} + + match =1, _LISTING + \\{ + display_address $ + aux = $ + \\} + + . mnemonic args + + match =1, _LISTING + \\{ + display_bytes aux + + display \`., ' ', \`mnemonic + + display_args args + display CRLF + + aux = aux + MAX_BYTES + + repeat ($ - aux + MAX_BYTES - 1) / MAX_BYTES + display_address aux + display_bytes aux + display CRLF + + aux = aux + MAX_BYTES + end repeat + \\} + + match =1, _ON_VIRTUAL\\{restore _LISTING\\} + match =equ, args\\{restore _LISTING\\} + match =equ any, args\\{restore _LISTING\\} + \} +} + +macro data_reserve mnemonic +{ +local aux + macro mnemonic [args] + \{ + \common + match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} + match =equ, args\\{_LISTING equ 0\\} + match =equ any, args\\{_LISTING equ 0\\} + + match =1, _LISTING + \\{ + display_address $ + aux = $ + \\} + + mnemonic args + + match =1, _LISTING + \\{ + times MAX_BYTES display ' ' + + display \`mnemonic + + display_args args + display CRLF + \\} + + match =1, _ON_VIRTUAL\\{restore _LISTING\\} + match =equ, args\\{restore _LISTING\\} + match =equ any, args\\{restore _LISTING\\} + \} + + struc mnemonic [args] + \{ + \common + match =1, _ON_VIRTUAL\\{_LISTING equ 0\\} + match =equ, args\\{_LISTING equ 0\\} + match =equ any, args\\{_LISTING equ 0\\} + + match =1, _LISTING + \\{ + display_address $ + aux = $ + \\} + + . mnemonic args + + match =1, _LISTING + \\{ + times MAX_BYTES display ' ' + + display \`., ' ', \`mnemonic + + display_args args + display CRLF + \\} + + match =1, _ON_VIRTUAL\\{restore _LISTING\\} + match =equ, args\\{restore _LISTING\\} + match =equ any, args\\{restore _LISTING\\} + \} +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;; LISTING CONTROL MACROSES ;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +macro virtual [args] +{ +common + _ON_VIRTUAL equ 1 + + virtual args +} + +macro end [args] +{ +common + match =virtual, args\{restore _ON_VIRTUAL\} + + end args +} + +macro enable_listing +{ + detect_mode + + match =0, _MACROSES_INSTALLED + \{ + match instructions, INSTRUCTIONS + \\{ + irps ins, instructions + \\\{ + instruction ins + \\\} + \\} + + match prefixes, PREFIXES + \\{ + irps prefix, prefixes + \\\{ + def_prefix prefix + \\\} + \\} + + match data_definitors, DATA_DEFINITORS + \\{ + irps def, data_definitors + \\\{ + data_define def + \\\} + \\} + + match data_reservers, DATA_RESERVERS + \\{ + irps def, data_reservers + \\\{ + data_reserve def + \\\} + \\} + \} + + _MACROSES_INSTALLED equ 1 + _LISTING equ 1 +} + +macro disable_listing +{ + _LISTING equ 0 +} + +macro enable [feature*] +{ +forward + UNKNOWN equ 1 + + match =resolve_equates, feature + \{ + restore _RESOLVE_EQUATES + _RESOLVE_EQUATES equ ON + UNKNOWN equ 0 + \} + + match =listing, feature + \{ + enable_listing + UNKNOWN equ 0 + \} + + match =1, UNKNOWN + \{ + display 'ERROR: Unknown "',`feature, '" feature', 13, 10 + err + \} + + restore UNKNOWN + restore UNKNOWN +} + +macro disable [feature*] +{ + UNKNOWN equ 1 + + match =resolve_equates, feature + \{ + restore _RESOLVE_EQUATES + _RESOLVE_EQUATES equ OFF + UNKNOWN equ 0 + \} + + match =listing, feature + \{ + disable_listing + UNKNOWN equ 0 + \} + + match =1, UNKNOWN + \{ + display 'ERROR: Unknown "',`feature, '" feature', 13, 10 + err + \} + + restore UNKNOWN + restore UNKNOWN +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INITIALIZATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +_MACROSES_INSTALLED equ 0 +_ON_VIRTUAL equ 0 + +disable resolve_equates diff --git a/kernel/trunk/sec_loader/trunk/loader.asm b/kernel/trunk/sec_loader/trunk/loader.asm index 3ea008ab7..81e554438 100644 --- a/kernel/trunk/sec_loader/trunk/loader.asm +++ b/kernel/trunk/sec_loader/trunk/loader.asm @@ -1,317 +1,317 @@ -; Copyright (c) 2008-2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -;start of the project 13.02.2008 year. -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;Secondary Loader copyright Alexey Teplov nickname -;if you need log preproc -;///////////// -;include 'listing.inc' -;enable listing -;//////////// -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;start of code: ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -use16 - org 0x0 - jmp start -include 'sl_equ.inc' ; в файле размещены все equ предопределения -include 'boot_st.inc' -include 'debug_msg.inc' ;here is message from debug -include 'parse_dat.inc' -include 'sl_proc.inc' -include 'parse.inc' -include 'parse_loader.inc' -include 'parse_any.inc' -include 'parse_def_sect.inc' -include 'parse_err.inc' - -file_data dw 0x0,ini_data_ ;формат: смещение: сегмент т.к. используется les -size_data dw 16 ;16 блоков по 4 кб т.е предел до 64 кб -name_ini_f db 'kord/startos.ini',0 - -;//////////// -loader_callback dd ? -load_drive dw ? -load_ft dw ? -;Start code - -start: -; Save far pointer to callback procedure, ds:si is point - mov word [cs:loader_callback], si - mov word [cs:loader_callback+2], ds -; Save type of drive - mov word [cs:load_drive],ax -; Save type of FT - mov word [cs:load_ft],bx -; set up stack - mov ax, cs - mov ss, ax - xor sp, sp -; set up segment registers - mov ds,ax - mov es,ax -; just to be sure: force DF=0, IF=1 - cld - sti - -; set videomode - mov ax,3 - int 0x10 - - mov si,version - call printplain - mov al,'#' - mov cx,80 -;input cx=size al=char будет вывден символ сколько раз указано в cx -@@: - call putchar - loop @b - - if DEBUG - pushad - mov ax,cs - shl eax,4 ; в десятичной системе адрес сегмента - mov cx,0xa - mov di,cseg_msg - call decode -;*************** - mov si,cseg_msg - call printplain - popad - end if - - - if DEBUG - mov si,stack_msg - call printplain - end if - -; Require 586 or higher processor (cpuid and rdtsc,rdmsr/wrmsr commands) -; install int 6 (#UD) handler - xor bx, bx - mov ds, bx - push word [bx+6*4+2] - push word [bx+6*4] - mov word [bx+6*4], ud16 - mov word [bx+6*4+2], cs -; issue CPUID command - xor eax, eax ; N.B.: will cause #UD before 386 - cpuid ; N.B.: will cause #UD before later 486s - test eax, eax - jz cpubad -; get processor features - xor eax, eax - inc ax - cpuid - test dl, 10h ; CPUID[1].edx[4] - TSC support - jz cpubad - test dl, 20h ; CPUID[1].edx[5] - MSR support - jnz cpugood - -ud16: ; #UD handler, called if processor did not recognize some commands -cpubad: -; restore int 6 (#UD) handler - pop word [6*4] - pop word [6*4+2] -; say error - push cs - pop ds - mov si, badprocessor -sayerr: - call printplain - jmp $ - -cpugood: -; restore int 6 (#UD) handler - pop dword [6*4] - push cs - pop ds - -; set up esp - movzx esp, sp - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; init memory -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - - - -; Load startos.ini - mov cx,loop_read_startos_file ;кол-во попыток чтения файла конфигурации startos.ini -align 4 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Load startos.ini ; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -load_startos_file: - - xor ax,ax - mov di,file_data - inc ax ;function 1 - read file - push cx - call far dword [loader_callback] - pop cx - push cs - push cs - pop ds - pop es - - test bx,bx - jz check_conf_file - dec cx - jnz load_startos_file - -;SET DEFAULT Not use ini file -error_ini: - mov si, error_ini_f1 ;Error: cannot load ini file, buffer is full - dec bx - jz err_show_ini - mov si, error_ini_f2 ;Error: ini file not found - dec bx - jz err_show_ini - mov si, error_ini_f3 ;Error: cannot read ini file - dec bx - jz err_show_ini - - mov si, error_ini_nf ;Error: unrecognized error when loading ini file -err_show_ini: - call printplain - mov si, error_ini_common - call printplain -; wait for keypress - xor ax,ax - int 16h - -ini_loaded: - - jmp $ - -align 4 -check_conf_file: -;Check config file in current dir - push ax ;save size file - if DEBUG - mov cx,0x0a - mov di,show_decode - call decode -;Show size - mov si,show_string - call printplain - end if - - -;Show message - mov si,load_ini - call printplain - - pop cx ;restore size file -use_parse ;parsing startos.ini -; - jmp ini_loaded - -;;;;;;;;;;;;;;;;;;;;;;;;;;; -;DATA -;;;;;;;;;;;;;;;;;;;;;;;;;;; -; table for move to extended memory (int 15h, ah=87h) -align 4 -table_15_87: - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - - db 0xff,0xff - db 0x0,0x10 - db 0x00,0x93,0x0,0x0 - - db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 - - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 - -fat12_buffer: -.BS_jmpBoot db 0x90,0x90,0x90 ;3 байта NOP инструкция - ничего не делать -.BS_OEMName db 'K SyS 64' ;8 байт -.BPB_BytsPerSec dw 512 ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта -.BPB_SecPerClus db 0x1 ;кол-во секторов в кластере -.BPB_RsvdSecCnt dw 0x1 ;для FAt12/16 только 1, для FAT32 обычно 32 -.BPB_NumFATs db 0x1 ;кол-во фат таблиц, на тот случай если будет сброс на дискету образа рам диска -.BPB_RootEntCnt dw 512 ;для мак совместимости с fat16 -.BPB_TotSec16 dw 0x0 ;кл-во секторов -.BPB_Media db 0xF0 -.BPB_FATSz16 dw 0x0 -.BPB_SecPerTrk dw 0x0 ;содержит геометрию диска для RAMFS на как бы без разницы, пока пустое поле, позже внести реальные значения. -.BPB_NumHeads dw 0x0 -.BPB_HiddSec dd 0x0 ;кол-во скрытых секторов -.BPB_TotSec32 dd 0x0 -.BS_DrvNum db 'R' ;от слова RAM -.BS_Reserved1 db 0x0 -.BS_BootSig db 0x29 -.BS_VolID db 'RFKS' -.BS_VolLab db 'RAM DISK FS' ;11 символов -.BS_FilSysType db 'FAT12 ' ;8 символов -;62 байта структура fat12. -db (512-($-fat12_buffer))dup(0x90) - - - -;структура для дирректории fat -struc FAT_32_entry ;Byte Directory Entry Structure -{ -.DIR_Name rb 11 -.DIR_Attr db ? -.DIR_NTRes db ? -.DIR_CrtTimeTenth db ? -.DIR_CrtTime dw ? -.DIR_CrtDate dw ? -.DIR_LstAccDate dw ? -.DIR_FstClusHI dw ? -.DIR_WrtTime dw ? -.DIR_WrtDate dw ? -.DIR_FstClusLO dw ? -.DIR_FileSize dd ? - - -} -;Тут будут распологатсья данные, которые затруднительно распологать в стековой области.... -;;; -;timer -shot_name_fat rb 11 ;временный буфер для fat12, в нем храняться имена файлов приведенные к правилам FAT /* вдальнейшем перенести в стэк - -if DEBUG - rb 1 ;нужен для отладки и вывода имени файла после преобразования -dest_name_fat db 24 dup('_');12 -db 0x0 -end if - -value_timeout rw 1 ;value to timeout -old_timer rd 1 ;старое значение вектора таймера -start_timer rd 1 ;значение таймера -timer_ rd 1 ;новое значение вектора таймера т.е. SL -start_stack rw 1 ;save stack -save_bp_from_timer rw 1 ;save bp from timer - +; Copyright (c) 2008-2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +;start of the project 13.02.2008 year. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;Secondary Loader copyright Alexey Teplov nickname +;if you need log preproc +;///////////// +;include 'listing.inc' +;enable listing +;//////////// +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;start of code: ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +use16 + org 0x0 + jmp start +include 'sl_equ.inc' ; в файле размещены все equ предопределения +include 'boot_st.inc' +include 'debug_msg.inc' ;here is message from debug +include 'parse_dat.inc' +include 'sl_proc.inc' +include 'parse.inc' +include 'parse_loader.inc' +include 'parse_any.inc' +include 'parse_def_sect.inc' +include 'parse_err.inc' + +file_data dw 0x0,ini_data_ ;формат: смещение: сегмент т.к. используется les +size_data dw 16 ;16 блоков по 4 кб т.е предел до 64 кб +name_ini_f db 'kord/startos.ini',0 + +;//////////// +loader_callback dd ? +load_drive dw ? +load_ft dw ? +;Start code + +start: +; Save far pointer to callback procedure, ds:si is point + mov word [cs:loader_callback], si + mov word [cs:loader_callback+2], ds +; Save type of drive + mov word [cs:load_drive], ax +; Save type of FT + mov word [cs:load_ft], bx +; set up stack + mov ax, cs + mov ss, ax + xor sp, sp +; set up segment registers + mov ds, ax + mov es, ax +; just to be sure: force DF=0, IF=1 + cld + sti + +; set videomode + mov ax, 3 + int 0x10 + + mov si, version + call printplain + mov al, '#' + mov cx, 80 +;input cx=size al=char будет вывден символ сколько раз указано в cx +@@: + call putchar + loop @b + + if DEBUG + pushad + mov ax, cs + shl eax, 4 ; в десятичной системе адрес сегмента + mov cx, 0xa + mov di, cseg_msg + call decode +;*************** + mov si, cseg_msg + call printplain + popad + end if + + + if DEBUG + mov si, stack_msg + call printplain + end if + +; Require 586 or higher processor (cpuid and rdtsc,rdmsr/wrmsr commands) +; install int 6 (#UD) handler + xor bx, bx + mov ds, bx + push word [bx+6*4+2] + push word [bx+6*4] + mov word [bx+6*4], ud16 + mov word [bx+6*4+2], cs +; issue CPUID command + xor eax, eax ; N.B.: will cause #UD before 386 + cpuid ; N.B.: will cause #UD before later 486s + test eax, eax + jz cpubad +; get processor features + xor eax, eax + inc ax + cpuid + test dl, 10h ; CPUID[1].edx[4] - TSC support + jz cpubad + test dl, 20h ; CPUID[1].edx[5] - MSR support + jnz cpugood + +ud16: ; #UD handler, called if processor did not recognize some commands +cpubad: +; restore int 6 (#UD) handler + pop word [6*4] + pop word [6*4+2] +; say error + push cs + pop ds + mov si, badprocessor +sayerr: + call printplain + jmp $ + +cpugood: +; restore int 6 (#UD) handler + pop dword [6*4] + push cs + pop ds + +; set up esp + movzx esp, sp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; init memory +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + + +; Load startos.ini + mov cx, loop_read_startos_file ;кол-во попыток чтения файла конфигурации startos.ini +align 4 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Load startos.ini ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +load_startos_file: + + xor ax, ax + mov di, file_data + inc ax ;function 1 - read file + push cx + call far dword [loader_callback] + pop cx + push cs + push cs + pop ds + pop es + + test bx, bx + jz check_conf_file + dec cx + jnz load_startos_file + +;SET DEFAULT Not use ini file +error_ini: + mov si, error_ini_f1 ;Error: cannot load ini file, buffer is full + dec bx + jz err_show_ini + mov si, error_ini_f2 ;Error: ini file not found + dec bx + jz err_show_ini + mov si, error_ini_f3 ;Error: cannot read ini file + dec bx + jz err_show_ini + + mov si, error_ini_nf ;Error: unrecognized error when loading ini file +err_show_ini: + call printplain + mov si, error_ini_common + call printplain +; wait for keypress + xor ax, ax + int 16h + +ini_loaded: + + jmp $ + +align 4 +check_conf_file: +;Check config file in current dir + push ax ;save size file + if DEBUG + mov cx, 0x0a + mov di, show_decode + call decode +;Show size + mov si, show_string + call printplain + end if + + +;Show message + mov si, load_ini + call printplain + + pop cx ;restore size file +use_parse ;parsing startos.ini +; + jmp ini_loaded + +;;;;;;;;;;;;;;;;;;;;;;;;;;; +;DATA +;;;;;;;;;;;;;;;;;;;;;;;;;;; +; table for move to extended memory (int 15h, ah=87h) +align 4 +table_15_87: + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + + db 0xff,0xff + db 0x0,0x10 + db 0x00,0x93,0x0,0x0 + + db 0xff,0xff,0x0,0x00,0x10,0x93,0x0,0x0 + + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + db 0x00,0x00,0x0,0x00,0x00,0x00,0x0,0x0 + +fat12_buffer: +.BS_jmpBoot db 0x90,0x90,0x90 ;3 байта NOP инструкция - ничего не делать +.BS_OEMName db 'K SyS 64' ;8 байт +.BPB_BytsPerSec dw 512 ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта +.BPB_SecPerClus db 0x1 ;кол-во секторов в кластере +.BPB_RsvdSecCnt dw 0x1 ;для FAt12/16 только 1, для FAT32 обычно 32 +.BPB_NumFATs db 0x1 ;кол-во фат таблиц, на тот случай если будет сброс на дискету образа рам диска +.BPB_RootEntCnt dw 512 ;для мак совместимости с fat16 +.BPB_TotSec16 dw 0x0 ;кл-во секторов +.BPB_Media db 0xF0 +.BPB_FATSz16 dw 0x0 +.BPB_SecPerTrk dw 0x0 ;содержит геометрию диска для RAMFS на как бы без разницы, пока пустое поле, позже внести реальные значения. +.BPB_NumHeads dw 0x0 +.BPB_HiddSec dd 0x0 ;кол-во скрытых секторов +.BPB_TotSec32 dd 0x0 +.BS_DrvNum db 'R' ;от слова RAM +.BS_Reserved1 db 0x0 +.BS_BootSig db 0x29 +.BS_VolID db 'RFKS' +.BS_VolLab db 'RAM DISK FS' ;11 символов +.BS_FilSysType db 'FAT12 ' ;8 символов +;62 байта структура fat12. +db (512-($-fat12_buffer))dup(0x90) + + + +;структура для дирректории fat +struc FAT_32_entry ;Byte Directory Entry Structure +{ +.DIR_Name rb 11 +.DIR_Attr db ? +.DIR_NTRes db ? +.DIR_CrtTimeTenth db ? +.DIR_CrtTime dw ? +.DIR_CrtDate dw ? +.DIR_LstAccDate dw ? +.DIR_FstClusHI dw ? +.DIR_WrtTime dw ? +.DIR_WrtDate dw ? +.DIR_FstClusLO dw ? +.DIR_FileSize dd ? + + +} +;Тут будут распологатсья данные, которые затруднительно распологать в стековой области.... +;;; +;timer +shot_name_fat rb 11 ;временный буфер для fat12, в нем храняться имена файлов приведенные к правилам FAT /* вдальнейшем перенести в стэк + +if DEBUG + rb 1 ;нужен для отладки и вывода имени файла после преобразования +dest_name_fat db 24 dup('_');12 +db 0x0 +end if + +value_timeout rw 1 ;value to timeout +old_timer rd 1 ;старое значение вектора таймера +start_timer rd 1 ;значение таймера +timer_ rd 1 ;новое значение вектора таймера т.е. SL +start_stack rw 1 ;save stack +save_bp_from_timer rw 1 ;save bp from timer + diff --git a/kernel/trunk/sec_loader/trunk/parse.inc b/kernel/trunk/sec_loader/trunk/parse.inc index 595c1f3e7..d23784b8e 100644 --- a/kernel/trunk/sec_loader/trunk/parse.inc +++ b/kernel/trunk/sec_loader/trunk/parse.inc @@ -1,118 +1,118 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -; Модуль парсинга - это стандартный компонент, встраиваемый во вторичный загрузчик. -; Данный модуль позволяет стандартно произвести разбор ini файла -; (и с использованием полученных данных ОС будет загружаться дальше). -; В начале найдем открывающий "[" - это будет указывать на начало -; секции. Поддерживается 1 секция это [loader], остальные секции могут иметь -; любые имена, но они должны быть заключены в в скобки [] -macro use_parse -{ -;input cx=size of ini file -parse_start: -;es:di as 2000:0000 new segment -;установим указатель на загруженный блок - enter 256,0 ;set 16 byte for current task in stack -;we are is not use bp because bp is pointer on array 16 byte - mov word [save_bp_from_timer],bp ;save point to own data array - mov save_cx,cx ;it's placed size of ini file - les di,dword [file_data] -;обнулим все переменные выделенные из стека -;init flag - xor ax,ax - mov status_flag,ax -;set data size - mov info_real_mode_size,ini_data_ +0x1000 ;изменим значение занятости памяти - -;поиск начала блока. -;///////////check [loader] - cld - - mov ret_on_ch,.start ;set return - mov al,byte [es:di] - push word .first_ret - cmp al,' ' - jz .first_sp_1 - jmp get_firs_sym.not_space -.first_sp_1: - jmp get_firs_sym.first_sp - -.start: - call get_firs_sym ;get first symbol on new line -.first_ret: ;первый возврат -; jcxz .end_file ;.end_loader ;found or not found parametrs in section exit in section - test cx,cx - jz error.not_loader - cmp al,'[' - jz .parse_loader - jmp .start -;////// проверка на наличее секции loader -use_parse_loader -;pause -if DEBUG - xor ax,ax - int 16h -end if -;////// вывод графического экрана, выбор, секции под дефолту -use_any_sec -;парсинг выбраной или дефолтной секции т.е. разбор параметров выполнение сценария -use_parse_def_sect - -;////////////////// -;/end parse block -;////////////////// -;.end_bl: -; mov cx,bx -; -; jmp .start - -.exit: - -; mov si,parse_ini_end -; call printplain -; -;if DEBUG -; pusha -; mov ax,cx -; mov cx,0x0a -; mov di,show_db1_dec -; mov dword[ds:di],' ' -; call decode -;Show size -; mov si,show_db1 -; call printplain -; -; popa -;end if - jmp $ - -;///////////////////procedure ////////// -;input es:di - is pointer to date -;cx - counter -;return: cx - status if =0 - end of date else es:di point to first symbol on new line - -} \ No newline at end of file +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +; Модуль парсинга - это стандартный компонент, встраиваемый во вторичный загрузчик. +; Данный модуль позволяет стандартно произвести разбор ini файла +; (и с использованием полученных данных ОС будет загружаться дальше). +; В начале найдем открывающий "[" - это будет указывать на начало +; секции. Поддерживается 1 секция это [loader], остальные секции могут иметь +; любые имена, но они должны быть заключены в в скобки [] +macro use_parse +{ +;input cx=size of ini file +parse_start: +;es:di as 2000:0000 new segment +;установим указатель на загруженный блок + enter 256, 0 ;set 16 byte for current task in stack +;we are is not use bp because bp is pointer on array 16 byte + mov word [save_bp_from_timer], bp ;save point to own data array + mov save_cx, cx ;it's placed size of ini file + les di, dword [file_data] +;обнулим все переменные выделенные из стека +;init flag + xor ax, ax + mov status_flag, ax +;set data size + mov info_real_mode_size, ini_data_ +0x1000 ;изменим значение занятости памяти + +;поиск начала блока. +;///////////check [loader] + cld + + mov ret_on_ch, .start ;set return + mov al, byte [es:di] + push word .first_ret + cmp al, ' ' + jz .first_sp_1 + jmp get_firs_sym.not_space +.first_sp_1: + jmp get_firs_sym.first_sp + +.start: + call get_firs_sym ;get first symbol on new line +.first_ret: ;первый возврат +; jcxz .end_file ;.end_loader ;found or not found parametrs in section exit in section + test cx, cx + jz error.not_loader + cmp al, '[' + jz .parse_loader + jmp .start +;////// проверка на наличее секции loader +use_parse_loader +;pause +if DEBUG + xor ax, ax + int 16h +end if +;////// вывод графического экрана, выбор, секции под дефолту +use_any_sec +;парсинг выбраной или дефолтной секции т.е. разбор параметров выполнение сценария +use_parse_def_sect + +;////////////////// +;/end parse block +;////////////////// +;.end_bl: +; mov cx,bx +; +; jmp .start + +.exit: + +; mov si,parse_ini_end +; call printplain +; +;if DEBUG +; pusha +; mov ax,cx +; mov cx,0x0a +; mov di,show_db1_dec +; mov dword[ds:di],' ' +; call decode +;Show size +; mov si,show_db1 +; call printplain +; +; popa +;end if + jmp $ + +;///////////////////procedure ////////// +;input es:di - is pointer to date +;cx - counter +;return: cx - status if =0 - end of date else es:di point to first symbol on new line + +} diff --git a/kernel/trunk/sec_loader/trunk/parse_any.inc b/kernel/trunk/sec_loader/trunk/parse_any.inc index 1ae93fb83..d51a60c9d 100644 --- a/kernel/trunk/sec_loader/trunk/parse_any.inc +++ b/kernel/trunk/sec_loader/trunk/parse_any.inc @@ -1,683 +1,686 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -;тут распологается модуль с помощью которого будут парситься все остальные секции -color_sym_black equ 0 -color_sym_blue equ 1 -color_sym_green equ 2 -color_sym_turquoise equ 3 -color_sym_red equ 4 - -color_sym_lightgray equ 7 - -color_sym_lightblue equ 9 -color_sym_lettuce equ 10 -color_sym_pink equ 12 -color_sym_yellow equ 14 - -macro use_any_sec -{ -;узнаем работу предыдущего шага т.е. чему = timeout, если он 0, то визуальная часть не будет отображена на дисплее с выбором загрузочных секций. -;иначе мы ее должны отобразить и ждать заявленое время для выбора и конигурирования пукнктов секции от пользователя. - -if DEBUG - pusha - mov ax,word [value_timeout] ;идет проверка на наличее значения timeout, для более быстрой работы, этот параметр должен быть уже обработан,т.е. в этом случае при его =0 будет сформирован указатель только на дефолтную секцию, иначе информация будет собрана по всем секциям и составлены указатели в блоке памяти -; mov ax,cx - mov cx,0x0a - mov di,show_db1 - mov dword[ds:di],' ' - mov word [ds:di+4],' ' - call decode -;Show size - mov si,show_db1 - call printplain -; - popa -end if - - test ax,ax - jz .parse_run_only - -;отобразим полный список всех найденых секций. -if DEBUG - pusha - mov si,show_all_sect - call printplain - popa -end if -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование - out 0x60, al - xor cx, cx -.wait_loop: ; variant 2 -; reading state of port of 8042 controller - in al, 64h - and al, 00000010b ; ready flag -; wait until 8042 controller is ready - loopnz .wait_loop - - -; set keyboard typematic rate & delay - mov al, 0xf3 - out 0x60, al - xor cx, cx -@@: - in al, 64h - test al, 2 - loopnz @b - mov al, 0 - out 0x60, al - xor cx, cx -@@: - in al, 64h - test al, 2 - loopnz @b -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; get start time - call gettime - mov dword [start_timer],eax - mov word [timer_],newtimer - mov word [timer_+2],cs -;установить свое прерывание на таймер т.е. код будет перрываться ~18 раз в сек и переходить на обработчик - cli - push 0 - pop es - push dword [es:8*4] - pop dword [old_timer] - push dword [timer_] - pop dword [es:8*4] - sti - -;процедура формирования буфера для скролинга секций -;if DEBUG -; pusha -; mov ax,point_default -; mov ax,cx -; mov cx,0x0a -; mov di,show_db1 -; mov dword[ds:di],' ' -; mov word [ds:di+4],' ' -; call decode -;Show size -; mov si,show_db1 -; call printplain -; -; xor ax,ax -; int 0x16 -; popa -;end if -;;;;;;;;;;;;;размер предыдущей сеции установим =0 - mov save_descript_size,18 -;отобразить black screen -show_bl_sc ;es=0xb800 -.show_all_scr: -get_frame_buffer ;es=0x2000 -;отображение секций - call show_bl_sc_sect ;es=0xb800 -;отобразить активный курсор -.show_active_cursor: -show_act_cursor -show_descript ;макрос по отображению описания секции - -;отобразить Press any key .... - mov eax,dword [old_timer] - cmp eax,dword [timer_] - jz .interrupt_16 - -show_timer_message - mov word [start_stack],sp -.interrupt_16: - xor ax,ax ;получим информацию о том что нажато - int 0x16 -;check on change - mov ebx,dword [old_timer] - cmp ebx,dword [timer_] - jz @f -;restore timer interrupt - cli - push 0 - pop es -; mov eax,dword [old_timer] ; восстановим прежднее прерывание - mov [es:8*4],ebx - mov dword [timer_],ebx - sti - - push ax -clear_timer_msg - pop ax -@@: - call clean_active_cursor ;clean old cursor ;es=0xb800 - - cmp ah,0x48 ;реакция системы на события - jz .up - cmp ah,0x50 - jz .down - cmp ah,0x49 - jz .pgup - cmp ah,0x51 - jz .pgdown - cmp ah,0x47 - jz .home - cmp ah,0x4f - jz .end - - cmp al,0xD - jnz .show_active_cursor - - jmp .end_show_all ;парсинг секции которая указана в point_default -.up: - mov si,point_to_point_def ;значение указателя - add si,2 - lea ax,point_to_hframe - - cmp si,ax - ja @f - - mov point_to_point_def,si - mov ax,[si] - mov point_default,ax - jmp .show_active_cursor -@@: - call find_before_sect - jmp .show_all_scr - - - -.down: - mov si,point_to_point_def ;значение указателя - mov ax,point_to_eframe ;указатель на последний элемент - sub si,2 - cmp si,ax - jb @f - - mov point_to_point_def,si - mov ax,[si] - mov point_default,ax - jmp .show_active_cursor - -@@: call find_next_sect - jmp .show_all_scr - -.pgup: - mov cx,size_show_section -@@: - push cx - call find_before_sect - pop cx - loop @b - jmp .show_all_scr - - -.pgdown: - mov cx,size_show_section -@@: - push cx - call find_next_sect - pop cx - loop @b - jmp .show_all_scr - -.home: - xor di,di - call find_next_sect.h - jmp .show_all_scr - -.end: - mov di,save_cx - call find_before_sect.e - jmp .show_all_scr - - - - -; тут мы будем парсить только дефолтную секцию и выполнять ее ничего не предлагая пользователю из диалогов. -.parse_run_only: -if DEBUG - pusha - mov si,no_show_only_w - call printplain - popa -end if - - -.end_show_all: -} - - - - - - - - - - - - - - - -;show black screen SL -macro show_bl_sc -{ -;;;;;;;;;;;;;;; -;очистим экран и выведем меню -; draw frames - xor ax,ax -if DEBUG - mov ax,0x0720 -end if - push 0xb800 - pop es - xor di, di -; draw top - mov cx, 25 * 80 - rep stosw -;;;;;;;;;;;;;;;;;;;;;;; show 'Secondary Loader v0.xxx' - mov di,164 - mov si,version - mov cx,version_end-version - mov ah,color_sym_yellow -@@: - lodsb - stosw - loop @b -;;;;;;;;;;;;;;;;;;;;;;; show firm )) - mov di,(2*160-(2*(soft_mes_end-soft_mes+4))) ;286 - mov ah,color_sym_pink;color_sym_red - mov al,'K' - stosw - mov al,' ' - stosw - mov ah,color_sym_lightgray;color_sym_lightblue;color_sym_pink - mov si,soft_mes - mov cx,soft_mes_end- soft_mes -@@: - lodsb - stosw - loop @b -;;;;;;;;;;;;;;;;;;;;;;; show '__________________________' - mov di,480 - mov ah,color_sym_yellow - mov al,'Д' - mov cx,61 - rep stosw -;;;;;;;;;;;;;;;;;;;;;;; show 'Select section' - mov di,804 - mov si,select_section - mov cx,select_section_end - select_section - mov ah,color_sym_lightgray -@@: - lodsb - stosw - loop @b -;;;;;;;;;;;;;;;;;;;;;;; show 'Section description' - mov di,880 - mov si,section_description - mov cx,section_description_end - section_description -; mov ah,color_sym_lightgray -@@: - lodsb - stosw - loop @b - -} - -macro show_timer_message -{ -;;;;;;;;;;;;;;;;;;;;; show Press any key -;;;;;;;;;;;;;;;;;;;;; show ramk - - xor ax,ax - mov di,3360 - mov cx,80*4 - rep stosw - - mov di,3362 - mov ah,color_sym_pink - mov al,0xDA - stosw - mov al,0xc4 - mov cx,76 - rep stosw - mov al,0xBF - stosw - add di,4 - mov al,0xb3 - stosw - add di,152 - stosw - add di,4 - stosw - add di,152 - stosw - add di,4 - mov al,0xc0 - stosw - mov al,0xc4 - mov cx,76 - rep stosw - mov al,0xd9 - stosw -;;;;;;;;;;;;;;;;;;;;;;;;ramk is complete show -;show first message - mov si,start_msg - mov cx,start_msg_e-start_msg - mov di,3526 -@@: - lodsb - stosw - loop @b -;;;;;;;;;;;;;;;;;;;; show press Enter to.... - add di,44 - mov si,time_msg - mov cx,time_msg_e-time_msg -@@: - lodsb - stosw - loop @b -} - - - - - - - - -macro get_frame_buffer -{ - mov cx,save_cx ;it's placed size of ini file - les di,dword [file_data] - - mov si,di ;point frame - mov bx,cx - mov dx,size_show_section -; mov point_to_hframe,di ; внесем значение, так подстраховка не более - - mov al,byte [es:di] - push word .first_ret_bl_sc - cmp al,' ' - jz .first_bl_sc - jmp get_firs_sym.not_space -.first_bl_sc: - jmp get_firs_sym.first_sp - -.start_hbl: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before - cmp al,'[' - jnz .start_hbl - - mov si,di ;point frame - mov bx,cx - mov dx,size_show_section - jmp .analisist_al - - -.start_bl: - call get_firs_sym ;get first symbol on new line -.first_ret_bl_sc: ;первый возврат - test cx,cx - jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before -.analisist_al: - cmp al,'[' - jnz .start_bl -;просматриваем ini файл с начала в поисках секции указаной как default -;поиск фрейма в котором содержиться значение default -.found_sect_bl: - cmp di,point_loader - jz .start_bl - cmp di,point_default - jz .save_point_def - - dec dx - jnz .start_bl - - jmp .start_hbl - - -.save_point_def: -;итак далее мы должны заполнить frame буфер адресов секций, что бы потом по нему быстро перемещаться не вычисляя снова адреса - mov di,si ;указатель на начало - mov cx,bx - lea si,point_to_hframe - mov dx,size_show_section+1 ;т.к. у нас структура содержит размер между первым и вторым указателем, то нам нужно на 1 адрес больше обсчитать секций. -;переходим на обработку значения указателя - mov al,byte [es:di] - push word .first_ret_mfb - cmp al,' ' - jz .first_bl_mbf - jmp get_firs_sym.not_space -.first_bl_mbf: - jmp get_firs_sym.first_sp - -.start_mfb: - call get_firs_sym ;get first symbol on new line -.first_ret_mfb: ;первый возврат - jcxz .val_buff_comp ;.end_loader ;found or not found parametrs in section exit in section - cmp al,'[' - jnz .start_mfb - -.found_sect_mfb: - cmp di,point_loader ;if we have section loader - jz .start_mfb - - mov [si],di - - sub si,2 - dec dx - jnz .start_mfb -;bufer is full - jmp @f -.val_buff_comp: - push save_cx - pop word [si] - sub si,2 -@@: - - add si,4 - mov point_to_eframe,si - -} - -macro show_act_cursor -{ -;отображение курсора по умолчанию - lea si,point_to_hframe - mov di,962-160 - mov ax,point_default - mov cx,size_show_section -.home_show_cur: - mov bx,[si] - add di,160 - cmp bx,ax - jz .show_cursor_activ - sub si,2 - loop .home_show_cur - -.show_cursor_activ: -; push 0xb800 -; pop es - mov point_to_point_def,si - mov ax,(color_sym_red*0x100+0x10) - stosw - add di,68 - inc ax - stosw -} - -macro clear_timer_msg -{ - push 0xb800 - pop es - xor ax,ax -if DEBUG - mov ax,0x0720 -end if -;;;;;;;;;;;;;;;;;;;;; show Press any key - mov di,3360 - mov cx,80*4 - rep stosw - -;show sect - push ini_data_ - pop es - call show_bl_sc_sect ;es=0xb800 - -} - -macro show_descript -;Этот макрос показывает краткое описание, если оно есть у секции в пункте -;Section description -{ -local .start_p_sh_d -local .exit -local .rest_value_loop_sh_d -local .end_sh_desc_sec -local .loop_message -local .show_mess_prev_eq - mov di,point_default - push ini_data_ - mov si,point_to_point_def - pop es - sub si,2 - mov cx,[si] ;загрузим указатель наследующию секцию - sub cx,di ;вот теперь имеем истиный размер -;di - указатель на дефолтную секцию т.е. выбранную cx - размер области. для просмотра - -.start_p_sh_d: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz .exit ;нету? ну ладно - следующее значение тогда ) - cmp al,'d' - jnz .start_p_sh_d -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - mov bx,cx - mov ax,di - - mov si,parse_descript - mov cx,parse_descript_e - parse_descript - repe cmpsb - jnz .rest_value_loop_sh_d ;is not compare - - sub bx,parse_descript_e - parse_descript ;correct cx - add bx,cx - mov cx,bx -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; разбор аля ' = ' - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - jcxz .rest_value_loop_sh_d ;not found param timeout - - cmp ah,byte [es:di-1] ;find '=' - jnz .rest_value_loop_sh_d - - repe scasb ;cut ' ' - inc cx - dec di -;;;;;;;;;;;;;;;;;;;;di указывает на строчку, которую нам нужно выводить. -;строчка будет выводиться блоками по 37 символов. -;настроим куда будем выводить т.е. начало -;es:di - указывают на строчку из которой мы берем символ, ds:si куда будем выводить - push di - pop si - - push es - pop ds - - push 0xb800 - pop es - - mov di,1040 - mov bx,18 - mov find_sec_di,di - mov save_cx_d,bx -;;;;;;;;;;;;;;;;;;;;;;;;;; -;clean string - - push di - xor ax,ax - -@@: mov cx,38 - push di - rep stosw - pop di - - cmp save_descript_size,bx - jz @f - - - add di,160 - dec bx - jnz @b - -@@: pop di -;enter in mess -.show_mess_prev_eq: - lodsb - mov ah,color_sym_lettuce;color_sym_turquoise -; sub di,2 - cmp al,'"' - jz .loop_message - cmp al,"'" - jnz .end_sh_desc_sec - -.loop_message: - mov cx,38 -@@: - lodsb - cmp al,'"' - jz .end_sh_desc_sec - cmp al,"'" - jz .end_sh_desc_sec - stosw - loop @b - - add find_sec_di,160 - mov di,find_sec_di - dec save_cx_d - cmp save_cx_d,0 - jnz .loop_message - -.end_sh_desc_sec: - push save_cx_d - pop save_descript_size - - push cs - pop ds - jmp .exit - - -.rest_value_loop_sh_d: - mov di,ax - mov cx,bx - jmp .start_p_sh_d - -.exit: -} \ No newline at end of file +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +;тут распологается модуль с помощью которого будут парситься все остальные секции +color_sym_black equ 0 +color_sym_blue equ 1 +color_sym_green equ 2 +color_sym_turquoise equ 3 +color_sym_red equ 4 + +color_sym_lightgray equ 7 + +color_sym_lightblue equ 9 +color_sym_lettuce equ 10 +color_sym_pink equ 12 +color_sym_yellow equ 14 + +macro use_any_sec +{ +;узнаем работу предыдущего шага т.е. чему = timeout, если он 0, то визуальная часть не будет отображена на дисплее с выбором загрузочных секций. +;иначе мы ее должны отобразить и ждать заявленое время для выбора и конигурирования пукнктов секции от пользователя. + +if DEBUG + pusha + mov ax, word [value_timeout];идет проверка на наличее значения timeout, для более быстрой работы, этот параметр должен быть уже обработан,т.е. в этом случае при его =0 будет сформирован указатель только на дефолтную секцию, иначе информация будет собрана по всем секциям и составлены указатели в блоке памяти +; mov ax,cx + mov cx, 0x0a + mov di, show_db1 + mov dword[ds:di], ' ' + mov word [ds:di+4], ' ' + call decode +;Show size + mov si, show_db1 + call printplain +; + popa +end if + + test ax, ax + jz .parse_run_only + +;отобразим полный список всех найденых секций. +if DEBUG + pusha + mov si, show_all_sect + call printplain + popa +end if +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + mov al, 0xf6 ; Сброс клавиатуры, разрешить сканирование + out 0x60, al + xor cx, cx +.wait_loop: ; variant 2 +; reading state of port of 8042 controller + in al, 64h + and al, 00000010b ; ready flag +; wait until 8042 controller is ready + loopnz .wait_loop + + +; set keyboard typematic rate & delay + mov al, 0xf3 + out 0x60, al + xor cx, cx +@@: + in al, 64h + test al, 2 + loopnz @b + mov al, 0 + out 0x60, al + xor cx, cx +@@: + in al, 64h + test al, 2 + loopnz @b +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; get start time + call gettime + mov dword [start_timer], eax + mov word [timer_], newtimer + mov word [timer_+2], cs +;установить свое прерывание на таймер т.е. код будет перрываться ~18 раз в сек и переходить на обработчик + cli + push 0 + pop es + push dword [es:8*4] + pop dword [old_timer] + push dword [timer_] + pop dword [es:8*4] + sti + +;процедура формирования буфера для скролинга секций +;if DEBUG +; pusha +; mov ax,point_default +; mov ax,cx +; mov cx,0x0a +; mov di,show_db1 +; mov dword[ds:di],' ' +; mov word [ds:di+4],' ' +; call decode +;Show size +; mov si,show_db1 +; call printplain +; +; xor ax,ax +; int 0x16 +; popa +;end if +;;;;;;;;;;;;;размер предыдущей сеции установим =0 + mov save_descript_size, 18 +;отобразить black screen +show_bl_sc ;es=0xb800 +.show_all_scr: +get_frame_buffer ;es=0x2000 +;отображение секций + call show_bl_sc_sect ;es=0xb800 +;отобразить активный курсор +.show_active_cursor: +show_act_cursor +show_descript ;макрос по отображению описания секции + +;отобразить Press any key .... + mov eax, dword [old_timer] + cmp eax, dword [timer_] + jz .interrupt_16 + +show_timer_message + mov word [start_stack], sp +.interrupt_16: + xor ax, ax ;получим информацию о том что нажато + int 0x16 +;check on change + mov ebx, dword [old_timer] + cmp ebx, dword [timer_] + jz @f +;restore timer interrupt + cli + push 0 + pop es +; mov eax,dword [old_timer] ; восстановим прежднее прерывание + mov [es:8*4], ebx + mov dword [timer_], ebx + sti + + push ax +clear_timer_msg + pop ax +@@: + call clean_active_cursor ;clean old cursor ;es=0xb800 + + cmp ah, 0x48 ;реакция системы на события + jz .up + cmp ah, 0x50 + jz .down + cmp ah, 0x49 + jz .pgup + cmp ah, 0x51 + jz .pgdown + cmp ah, 0x47 + jz .home + cmp ah, 0x4f + jz .end + + cmp al, 0xD + jnz .show_active_cursor + + jmp .end_show_all ;парсинг секции которая указана в point_default +.up: + mov si, point_to_point_def ;значение указателя + add si, 2 + lea ax, point_to_hframe + + cmp si, ax + ja @f + + mov point_to_point_def, si + mov ax, [si] + mov point_default, ax + jmp .show_active_cursor +@@: + call find_before_sect + jmp .show_all_scr + + + +.down: + mov si, point_to_point_def ;значение указателя + mov ax, point_to_eframe ;указатель на последний элемент + sub si, 2 + cmp si, ax + jb @f + + mov point_to_point_def, si + mov ax, [si] + mov point_default, ax + jmp .show_active_cursor + +@@: + call find_next_sect + jmp .show_all_scr + +.pgup: + mov cx, size_show_section +@@: + push cx + call find_before_sect + pop cx + loop @b + jmp .show_all_scr + + +.pgdown: + mov cx, size_show_section +@@: + push cx + call find_next_sect + pop cx + loop @b + jmp .show_all_scr + +.home: + xor di, di + call find_next_sect.h + jmp .show_all_scr + +.end: + mov di, save_cx + call find_before_sect.e + jmp .show_all_scr + + + + +; тут мы будем парсить только дефолтную секцию и выполнять ее ничего не предлагая пользователю из диалогов. +.parse_run_only: +if DEBUG + pusha + mov si, no_show_only_w + call printplain + popa +end if + + +.end_show_all: +} + + + + + + + + + + + + + + + +;show black screen SL +macro show_bl_sc +{ +;;;;;;;;;;;;;;; +;очистим экран и выведем меню +; draw frames + xor ax, ax +if DEBUG + mov ax, 0x0720 +end if + push 0xb800 + pop es + xor di, di +; draw top + mov cx, 25 * 80 + rep stosw +;;;;;;;;;;;;;;;;;;;;;;; show 'Secondary Loader v0.xxx' + mov di, 164 + mov si, version + mov cx, version_end-version + mov ah, color_sym_yellow +@@: + lodsb + stosw + loop @b +;;;;;;;;;;;;;;;;;;;;;;; show firm )) + mov di, (2*160-(2*(soft_mes_end-soft_mes+4))) ;286 + mov ah, color_sym_pink;color_sym_red + mov al, 'K' + stosw + mov al, ' ' + stosw + mov ah, color_sym_lightgray;color_sym_lightblue;color_sym_pink + mov si, soft_mes + mov cx, soft_mes_end- soft_mes +@@: + lodsb + stosw + loop @b +;;;;;;;;;;;;;;;;;;;;;;; show '__________________________' + mov di, 480 + mov ah, color_sym_yellow + mov al, 'Д' + mov cx, 61 + rep stosw +;;;;;;;;;;;;;;;;;;;;;;; show 'Select section' + mov di, 804 + mov si, select_section + mov cx, select_section_end - select_section + mov ah, color_sym_lightgray +@@: + lodsb + stosw + loop @b +;;;;;;;;;;;;;;;;;;;;;;; show 'Section description' + mov di, 880 + mov si, section_description + mov cx, section_description_end - section_description +; mov ah,color_sym_lightgray +@@: + lodsb + stosw + loop @b + +} + +macro show_timer_message +{ +;;;;;;;;;;;;;;;;;;;;; show Press any key +;;;;;;;;;;;;;;;;;;;;; show ramk + + xor ax, ax + mov di, 3360 + mov cx, 80*4 + rep stosw + + mov di, 3362 + mov ah, color_sym_pink + mov al, 0xDA + stosw + mov al, 0xc4 + mov cx, 76 + rep stosw + mov al, 0xBF + stosw + add di, 4 + mov al, 0xb3 + stosw + add di, 152 + stosw + add di, 4 + stosw + add di, 152 + stosw + add di, 4 + mov al, 0xc0 + stosw + mov al, 0xc4 + mov cx, 76 + rep stosw + mov al, 0xd9 + stosw +;;;;;;;;;;;;;;;;;;;;;;;;ramk is complete show +;show first message + mov si, start_msg + mov cx, start_msg_e-start_msg + mov di, 3526 +@@: + lodsb + stosw + loop @b +;;;;;;;;;;;;;;;;;;;; show press Enter to.... + add di, 44 + mov si, time_msg + mov cx, time_msg_e-time_msg +@@: + lodsb + stosw + loop @b +} + + + + + + + + +macro get_frame_buffer +{ + mov cx, save_cx ;it's placed size of ini file + les di, dword [file_data] + + mov si, di ;point frame + mov bx, cx + mov dx, size_show_section +; mov point_to_hframe,di ; внесем значение, так подстраховка не более + + mov al, byte [es:di] + push word .first_ret_bl_sc + cmp al, ' ' + jz .first_bl_sc + jmp get_firs_sym.not_space +.first_bl_sc: + jmp get_firs_sym.first_sp + +.start_hbl: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before + cmp al, '[' + jnz .start_hbl + + mov si, di ;point frame + mov bx, cx + mov dx, size_show_section + jmp .analisist_al + + +.start_bl: + call get_firs_sym ;get first symbol on new line +.first_ret_bl_sc: ;первый возврат + test cx, cx + jz error.correct_exit_bl ;critical error not found default point it's not possible because it's param chacking before +.analisist_al: + cmp al, '[' + jnz .start_bl +;просматриваем ini файл с начала в поисках секции указаной как default +;поиск фрейма в котором содержиться значение default +.found_sect_bl: + cmp di, point_loader + jz .start_bl + cmp di, point_default + jz .save_point_def + + dec dx + jnz .start_bl + + jmp .start_hbl + + +.save_point_def: +;итак далее мы должны заполнить frame буфер адресов секций, что бы потом по нему быстро перемещаться не вычисляя снова адреса + mov di, si ;указатель на начало + mov cx, bx + lea si, point_to_hframe + mov dx, size_show_section+1 ;т.к. у нас структура содержит размер между первым и вторым указателем, то нам нужно на 1 адрес больше обсчитать секций. +;переходим на обработку значения указателя + mov al, byte [es:di] + push word .first_ret_mfb + cmp al, ' ' + jz .first_bl_mbf + jmp get_firs_sym.not_space +.first_bl_mbf: + jmp get_firs_sym.first_sp + +.start_mfb: + call get_firs_sym ;get first symbol on new line +.first_ret_mfb: ;первый возврат + jcxz .val_buff_comp ;.end_loader ;found or not found parametrs in section exit in section + cmp al, '[' + jnz .start_mfb + +.found_sect_mfb: + cmp di, point_loader ;if we have section loader + jz .start_mfb + + mov [si], di + + sub si, 2 + dec dx + jnz .start_mfb +;bufer is full + jmp @f +.val_buff_comp: + push save_cx + pop word [si] + sub si, 2 +@@: + + add si, 4 + mov point_to_eframe, si + +} + +macro show_act_cursor +{ +;отображение курсора по умолчанию + lea si, point_to_hframe + mov di, 962-160 + mov ax, point_default + mov cx, size_show_section +.home_show_cur: + mov bx, [si] + add di, 160 + cmp bx, ax + jz .show_cursor_activ + sub si, 2 + loop .home_show_cur + +.show_cursor_activ: +; push 0xb800 +; pop es + mov point_to_point_def, si + mov ax, (color_sym_red*0x100+0x10) + stosw + add di, 68 + inc ax + stosw +} + +macro clear_timer_msg +{ + push 0xb800 + pop es + xor ax, ax +if DEBUG + mov ax, 0x0720 +end if +;;;;;;;;;;;;;;;;;;;;; show Press any key + mov di, 3360 + mov cx, 80*4 + rep stosw + +;show sect + push ini_data_ + pop es + call show_bl_sc_sect ;es=0xb800 + +} + +macro show_descript +;Этот макрос показывает краткое описание, если оно есть у секции в пункте +;Section description +{ +local .start_p_sh_d +local .exit +local .rest_value_loop_sh_d +local .end_sh_desc_sec +local .loop_message +local .show_mess_prev_eq + mov di, point_default + push ini_data_ + mov si, point_to_point_def + pop es + sub si, 2 + mov cx, [si] ;загрузим указатель наследующию секцию + sub cx, di ;вот теперь имеем истиный размер +;di - указатель на дефолтную секцию т.е. выбранную cx - размер области. для просмотра + +.start_p_sh_d: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz .exit ;нету? ну ладно - следующее значение тогда ) + cmp al, 'd' + jnz .start_p_sh_d +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + mov bx, cx + mov ax, di + + mov si, parse_descript + mov cx, parse_descript_e - parse_descript + repe cmpsb + jnz .rest_value_loop_sh_d ;is not compare + + sub bx, parse_descript_e - parse_descript;correct cx + add bx, cx + mov cx, bx +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; разбор аля ' = ' + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + jcxz .rest_value_loop_sh_d ;not found param timeout + + cmp ah, byte [es:di-1] ;find '=' + jnz .rest_value_loop_sh_d + + repe scasb ;cut ' ' + inc cx + dec di +;;;;;;;;;;;;;;;;;;;;di указывает на строчку, которую нам нужно выводить. +;строчка будет выводиться блоками по 37 символов. +;настроим куда будем выводить т.е. начало +;es:di - указывают на строчку из которой мы берем символ, ds:si куда будем выводить + push di + pop si + + push es + pop ds + + push 0xb800 + pop es + + mov di, 1040 + mov bx, 18 + mov find_sec_di, di + mov save_cx_d, bx +;;;;;;;;;;;;;;;;;;;;;;;;;; +;clean string + + push di + xor ax, ax + +@@: + mov cx, 38 + push di + rep stosw + pop di + + cmp save_descript_size, bx + jz @f + + + add di, 160 + dec bx + jnz @b + +@@: + pop di +;enter in mess +.show_mess_prev_eq: + lodsb + mov ah, color_sym_lettuce;color_sym_turquoise +; sub di,2 + cmp al, '"' + jz .loop_message + cmp al, "'" + jnz .end_sh_desc_sec + +.loop_message: + mov cx, 38 +@@: + lodsb + cmp al, '"' + jz .end_sh_desc_sec + cmp al, "'" + jz .end_sh_desc_sec + stosw + loop @b + + add find_sec_di, 160 + mov di, find_sec_di + dec save_cx_d + cmp save_cx_d, 0 + jnz .loop_message + +.end_sh_desc_sec: + push save_cx_d + pop save_descript_size + + push cs + pop ds + jmp .exit + + +.rest_value_loop_sh_d: + mov di, ax + mov cx, bx + jmp .start_p_sh_d + +.exit: +} diff --git a/kernel/trunk/sec_loader/trunk/parse_dat.inc b/kernel/trunk/sec_loader/trunk/parse_dat.inc index 8279f2517..51ff9eca9 100644 --- a/kernel/trunk/sec_loader/trunk/parse_dat.inc +++ b/kernel/trunk/sec_loader/trunk/parse_dat.inc @@ -1,56 +1,56 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -;Тут представленны теги, для сравнения -parse_loader db '[loader]' -parse_loader_e: -parse_l_timeout db 'timeout' -parse_l_timeout_e: -parse_l_default db 'default' -parse_l_default_e: -parse_name db 'ame' -parse_name_e: -parse_descript db 'descript' -parse_descript_e: - -parse_LoaderModule db 'LoaderModule' -parse_LoaderModule_e: -parse_RamdiskSize db 'RamdiskSize' -parse_RamdiskSize_e: -parse_RamdiskFS db 'RamdiskFS' -parse_RamdiskFS_e: -parse_RamdiskSector db 'RamdiskSector' -parse_RamdiskSector_e: -parse_RamdiskCluster db 'RamdiskCluster' -parse_RamdiskCluster_e: -parse_RFS_FAT db 'FAT' -parse_RFS_FAT_e: -parse_RFS_KRFS db 'KRFS' -parse_RFS_KRFS_e: -parse_Loader_Image db 'LoaderImage' -parse_Loader_Image_e: -parse_RamdiskFile db 'RamdiskFile' -parse_RamdiskFile_e: +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +;Тут представленны теги, для сравнения +parse_loader db '[loader]' +parse_loader_e: +parse_l_timeout db 'timeout' +parse_l_timeout_e: +parse_l_default db 'default' +parse_l_default_e: +parse_name db 'ame' +parse_name_e: +parse_descript db 'descript' +parse_descript_e: + +parse_LoaderModule db 'LoaderModule' +parse_LoaderModule_e: +parse_RamdiskSize db 'RamdiskSize' +parse_RamdiskSize_e: +parse_RamdiskFS db 'RamdiskFS' +parse_RamdiskFS_e: +parse_RamdiskSector db 'RamdiskSector' +parse_RamdiskSector_e: +parse_RamdiskCluster db 'RamdiskCluster' +parse_RamdiskCluster_e: +parse_RFS_FAT db 'FAT' +parse_RFS_FAT_e: +parse_RFS_KRFS db 'KRFS' +parse_RFS_KRFS_e: +parse_Loader_Image db 'LoaderImage' +parse_Loader_Image_e: +parse_RamdiskFile db 'RamdiskFile' +parse_RamdiskFile_e: diff --git a/kernel/trunk/sec_loader/trunk/parse_def_sect.inc b/kernel/trunk/sec_loader/trunk/parse_def_sect.inc index c36665208..6bdb69209 100644 --- a/kernel/trunk/sec_loader/trunk/parse_def_sect.inc +++ b/kernel/trunk/sec_loader/trunk/parse_def_sect.inc @@ -1,2094 +1,2121 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -; в этой секции идет разбор параметров указатель на секцию храниться в point_default -;типы ошибок при обработке макроса -;Макрос RamdiskFS -;/определение флагов в записи корневой директории -ATTR_READ_ONLY equ 0x01 -ATTR_HIDDEN equ 0x02 -ATTR_SYSTEM equ 0x04 -ATTR_VOLUME_ID equ 0x08 -ATTR_DIRECTORY equ 0x10 -ATTR_ARCHIVE equ 0x20 - - - -show_error_1 equ 0x1 ;кончились данные - не запланированный конец секции -show_error_2 equ 0x2 ;нет завершающего символа в размере рам диска. -show_error_3 equ 0x4 ; рам диск будет иметь размер =64 кб. -show_error_4 equ 0x8 ; - -macro use_parse_def_sect -{ - mov di,point_default - push ini_data_ - pop es - mov si,point_to_point_def - sub si,2 - mov cx,[si] ;загрузим указатель наследующию секцию - - xor ax,ax ;обнулим аx для очистки флагов - - sub cx,di ;вот теперь имеем истиный размер - mov save_cx_d,cx ;сохраним значение cx своей переменной -;обнулим переменную флагов, это необходимо, для того, что бы избежать обработку повторяющихся значений - - mov status_flag,ax -;;;; -;ВХод в обработку парсинга значений секций. es:di - указатель на начало секции cx размер секции доступной для парсинга -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;соглашение не разрушаем bp, es, cs, sp -;use_Loader_Image ;загрузить образ выше 1 мб -use_RamdiskFS -;проверяется самый последний. -use_LoaderModule ;особенность - передает управление на загруженный модуль. -} - -macro use_LoaderModule -;как вариант сейчас используется модель, при загрузке модуля на него передается управление, решение временое -;управление будет передаваться только после обработки всей секции -{ -local .found_end_str - - mov di,point_default ;restore value - mov cx,save_cx_d -;обработка конструкции типа LoaderModule=kord/kolibri.ldm -.start_p_LM: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz ._afterLoaderModule ;нету? ну ладно - следующее значение тогда ) - cmp al,'L' - jnz .start_p_LM -;проверка на значение LoaderModule -; parse_LoaderModule - mov bx,cx - mov ax,di - - mov si,parse_LoaderModule - mov cx,parse_LoaderModule_e - parse_LoaderModule - repe cmpsb - jnz .rest_value_loop_LM ;is not compare - - sub bx,parse_LoaderModule_e - parse_LoaderModule ;correct cx - add bx,cx - mov cx,bx - - test status_flag,flag_found_LM ;оценка флагов - jz .correct_is_not_set_LM - -; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем -; call printplain -; jmp .get_next_str - -.correct_is_not_set_LM: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - jcxz .rest_value_loop_LM ;not found param timeout - - cmp ah,byte [es:di-1] ;find '=' - jnz .rest_value_loop_LM - - repe scasb ;cut ' ' - inc cx - dec di -;di указывает на начало блока информации, в cx длинна до конца секции. -;после загрузки заноситься значение занятой памяти. -;для того что бы загрузить модуль, воспользуемся callback сервисом -;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0 -;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader -;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем -;сохранили певые 2 word - push dword [es:di-6] - lea si,[di-6] - - push word [es:di-2] - xor ax,ax - mov word [es:di-6],ax ;вносим нужные значения -;info_real_mode_size размер и указатель на область в которую можно загрузиться - mov ax,info_real_mode_size ;0x3000 ;следующий сегмент за данными - - - mov word [es:di-4],ax - mov word [es:di-2],16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем -;;;;;; поиск конца строчки -@@: mov al,byte [es:di] - cmp al,' ' - jz .found_end_str - cmp al,0xa - jz .found_end_str - cmp al,0xd - jz .found_end_str - inc di - dec cx - jnz @b -;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки -.found_end_str: - - push word [es:di] - xor ax,ax - mov word [es:di],ax -; xor ax,ax ; function 1 - read file - mov di,si ;file_data - inc ax - push si - push es - - push es - pop ds - push cs - pop es - - call far dword [es:loader_callback] - - push cs - pop ds - - pop es - pop si - - test bx,bx - jnz .error_LM - - - jmp far dword [es:si] - - -.error_LM: - call error.LoaderModule -.rest_value_loop_LM: - mov di,ax - mov cx,bx - jmp .start_p_LM - -._afterLoaderModule: -} - -macro use_RamdiskFS -; формирование рам диска, + обработка всего связанного. -{ -if DEBUG -local ._not_memory_in_sys -;//////// clear window - mov ax,3 - int 0x10 -;\\\\\\\\\ clear window is end - mov si,ramdiskFS_st - call printplain -end if -; обнулим регистр состояния ошибок - xor ax,ax - mov show_errors_sect,ax -use_free_memory ; узнаем какого объема у нас доступна память. значение возаращается в ax -;узнаем сколько у нас есть памяти и сможем ли мы сформировать нужного размера рам диск. -use_RamdiskSize ;значение возвращается в bx - cmp free_ad_memory,bx ; размерность в кб. - jbe ._not_memory_in_sys - movzx eax,bx - shl eax,10 ;*1024 = get size in byte - mov save_ramdisksize,eax ; сорханим размер в byte - -get_type_FS ;получим тип файловой системы + создадим ее - - -._not_memory_in_sys: - -if DEBUG -;pause - xor ax,ax - int 0x16 -end if -} -macro use_RamdiskSize -{ -local .start_p_RS -local .correct_is_not_set_RS -local .CS -local .correct_val_RS -local .correct_size_RS -local .rest_value_loop_RS -local .end_get_RS_ERROR_1 -local .end_get_RS_ERROR_2 -local ._end_parse_RS -;обрабатывается размер формируемого рам диска -;загрузим начало секции, т.к. будем просматривать с начала и всю секцию - mov di,point_default ;restore value - mov cx,save_cx_d -.start_p_RS: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz ._end_parse_RS ;нету? ну ладно - следующее значение тогда ) - cmp al,'R' - jnz .start_p_RS -;проверка на значения RamdiskSize -; parse_RamdiskSize - mov bx,cx - mov ax,di - - mov si,parse_RamdiskSize - mov cx,parse_RamdiskSize_e - parse_RamdiskSize - repe cmpsb - jnz .rest_value_loop_RS ;is not compare - - sub bx,parse_RamdiskSize_e - parse_RamdiskSize ;correct cx - add bx,cx - mov cx,bx - - test status_flag,flag_found_RS ;оценка флагов - jz .correct_is_not_set_RS - -; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем -; call printplain -; jmp .get_next_str - -.correct_is_not_set_RS: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - jcxz .end_get_RS_ERROR_1 ;not found param - - cmp ah,byte [es:di-1] ;find '=' - jnz .start_p_RS ; перейдем на начало и попробуем найти еще секцию - - repe scasb ;cut ' ' - inc cx - dec di -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;Тут нужно преобразовывать строчку в цифровое значение. -;;;;;;;;;;;;;;;;;;;;;;;;;; - xor bx,bx - mov cx,5 -@@: mov al,byte [es:di] - cmp al,'0' - jb .CS - cmp al,'9' - jbe .correct_val_RS -.CS: - cmp al,'K' - jz .correct_size_RS - jmp .end_get_RS_ERROR_2 -.correct_val_RS: - imul bx,10 - xor al,0x30 - add bl,al - inc di - loop @b - -.correct_size_RS: -;возможен 1 вариант, когда размер задан в K киллобайтах -;внутренный формат данных это кол-во запрощеной памяти в кб. - test bx,bx - jnz @f ;если значение отлично от 0 -;;;;;сообщение об ошибке, размер "найденого" блока =0 минимально мы должны -;установить 64 кб размер рам диска. - or show_errors_sect,show_error_3 - mov bx,64 -@@: - jmp ._end_parse_RS - - -.rest_value_loop_RS: - mov di,ax - mov cx,bx - jmp .start_p_RS - - - -.end_get_RS_ERROR_1: -;сообщение об ошибке - данный участок кода не был корректно обработан :( - or show_errors_sect,show_error_1 - jmp ._end_parse_RS -.end_get_RS_ERROR_2: - or show_errors_sect,show_error_2 - -._end_parse_RS: -if DEBUG - pusha - movzx eax,bx - mov cx,0x0a - mov di,RamdiskSize_msg - mov dword[ds:di],' ' - mov word [ds:di+4],' ' - call decode -;Show size - mov si,RamdiskSize_msg - call printplain - - popa -end if - -} - -macro use_free_memory -{ -local _support_function_use_free_memory -;макрос для получения общего числа доступной памяти в кб, для формирования рам диска за пределами 1 мб. -;используется 0х88 функция 0х15 прерывания -; если поддерживается функция, то в ax значение в кб, если нет, то в ax=0 - mov ah,0x88 ;ah,0x88 - int 0x15 - jnc ._support_function_use_free_memory - xor ax,ax -;возвращает в ax число в кб -._support_function_use_free_memory: - mov free_ad_memory,ax ; если не поддерживается биосом, то в ax=0 -if DEBUG - pushad - movzx eax,ax - mov cx,0x0a - mov di,free_memory_msg - mov dword[ds:di],' ' - mov word [ds:di+4],' ' - call decode -;Show size - mov si,free_memory_msg - call printplain - - popad -end if - - - - -} -macro show_ERRORS -{ - -} - -macro get_type_FS ;получить и создать образ для заданной RFS. -{ - mov di,point_default ;restore value - mov cx,save_cx_d -.start_g_tpe_RFS: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz ._end_parse_FRS ;._end_get_type_RFS ;нету? ну ладно - следующее значение тогда ) - cmp al,'R' - jnz .start_g_tpe_RFS -;проверка на значения RamdiskSize -; parse_RamdiskSize - mov bx,cx - mov ax,di - - mov si,parse_RamdiskFS - mov cx,parse_RamdiskFS_e - parse_RamdiskFS - repe cmpsb - jnz .start_g_tpe_RFS_rest_v ;is not compare - - sub bx,parse_RamdiskFS_e - parse_RamdiskFS ;correct cx - add bx,cx - mov cx,bx - - test status_flag,flag_found_GTRFMS ;оценка флагов - jz .correct_is_not_set_FRS - -; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем -; call printplain -; jmp .get_next_str - -.correct_is_not_set_FRS: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - test cx,cx - jz .end_get_FRS_ERROR_1 ;not found param - - cmp ah,byte [es:di-1] ;find '=' - jnz .start_g_tpe_RFS ; перейдем на начало и попробуем найти еще секцию - - repe scasb ;cut ' ' - inc cx - dec di -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;Тут нужно преобразовывать строчку в цифровое значение. -;;;;;;;;;;;;;;;;;;;;;;;;;; - mov bx,cx - mov ax,di - - mov si,parse_RFS_FAT - mov cx,parse_RFS_FAT_e - parse_RFS_FAT - repe cmpsb - jnz .krfs_cmp ;is not compare - -make_FAT_RamFS ;сделать - -if DEBUG - pusha - mov si,make_fat12_RFS_msg - call printplain - popa -end if - jmp ._end_parse_FRS - -.krfs_cmp: - mov cx,bx - mov di,ax - - mov si,parse_RFS_KRFS - mov cx,parse_RFS_KRFS_e - parse_RFS_KRFS - repe cmpsb -; jnz @f ;is not compare - - jmp ._end_parse_FRS - - -.start_g_tpe_RFS_rest_v: - mov cx,bx - mov di,ax - jmp .start_g_tpe_RFS - - - -.end_get_FRS_ERROR_1: -;сообщение об ошибке - данный участок кода не был корректно обработан :( - or show_errors_sect,show_error_1 - jmp ._end_parse_FRS -.end_get_FRS_ERROR_2: - or show_errors_sect,show_error_2 - -._end_parse_FRS: -if DEBUG - pusha - mov si,get_type_FS_msg - call printplain - popa -end if - - - -} -macro make_FAT_RamFS -{ -local .RS1 -local .fat12 -local .fat16 -; мы должны сформировать в начальный образ Ram FS, а потом записать его за область выше 1 мб.. -;для случая с FAT12 -; mov di,fat12_buffer ;ds должен быть = cs -;es:di - указывают на начало блока для формирования рам фс. -use_RamdiskSector ;возращаемое значение в ax размер сектора в байтах - cmp ax,4096 ;по спецификации значение должно быть в пределах от 1 до 4096 - ja .RS1 - test ax,ax - jnz @f ;ошибка если сюда прыгнули все таки ... - -.RS1: mov word [fat12_buffer.BPB_BytsPerSec],512 -;;;;;;;;;;скажем что по дефолту будем юзать значение... -@@: mov word [fat12_buffer.BPB_BytsPerSec],ax ;тут все ок - -;BPB_SecPerClus кол-во секторов в кластере -use_RamdiskCluster ;возращаемое значение в al - cmp al,128 - ja @f -; test al,0x1 ;проверка на кратность ) -; jnz @f - - mov byte [fat12_buffer.BPB_SecPerClus],al - - ;incorrect value will be set dafault - -;ниже некорректное значение в т.к. размер кратен 2 и в диапазоне от 1 до 128 включительно -; мы должны ругнуться на это -;@@: ;mov byte [fat12_buffer.BPB_SecPerClus],1 - -;;;;; определеим какая у нас будет использоваться FAT -;по условию, fat12<4085<=fat16<65525<=fat32 -; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = кол-во секторов - movzx eax,word [fat12_buffer.BPB_BytsPerSec] - movzx ebx,byte [fat12_buffer.BPB_SecPerClus] - - imul ebx,eax ;тут размерность сектора - mov eax,save_ramdisksize ;размер запрошенного рам диска в байтах - cdq - idiv ebx -;;;;;;;; сейчас частное в eax, а остаток в edx -;получим кол-во секторов, и можем уже определить тип FAT которую нужно делать. - cmp eax,4085 - jb .fat12 - cmp eax,65525 - jb .fat16 -;;;;;;;;;;;;;;;;;;;;;;;; тут fat32 - mov set_ramfs,32 ;установим тип файловой системы - mov word [fat12_buffer.BPB_RsvdSecCnt],32 - xor eax,eax - mov word [fat12_buffer.BPB_RootEntCnt],ax - mov word [fat12_buffer.BPB_TotSec16],ax - mov dword [fat12_buffer.BPB_TotSec32],eax - - -.fat16: ;fat16 -;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000). - jmp $ - mov set_ramfs,16 ;установим тип файловой системы - movzx ebx,byte [fat12_buffer.BPB_SecPerClus] - imul eax,ebx - - cmp eax,0x10000 - jae @f - mov word [fat12_buffer.BPB_TotSec16],ax - mov dword [fat12_buffer.BPB_TotSec32],0 -@@: -;количество секторов занимаемое одной копией фат -; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ?? -;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число -;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно -;быть 0. Пока константа, нужно будет позже доделать. - mov eax,root_dir_entry_count - mov word [fat12_buffer.BPB_RootEntCnt],ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) -;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб -;;;;;;; -;Для FAT16 это количество секторов одной FAT. Для FAT32 это значение -;равно 0, а количество секторов одной FAT содержится в BPB_FATSz32. -;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec; - -;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors); -;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs; -;If(FATType == FAT32) -; TmpVal2 = TmpVal2 / 2; -;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2; -;If(FATType == FAT32) { -; BPB_FATSz16 = 0; -; BPB_FATSz32 = FATSz; -;} else { -; BPB_FATSz16 = LOWORD(FATSz); -; /* there is no BPB_FATSz32 in a FAT16 BPB */ -;} -;===================================== -;RootDirSectors - movzx ebx, word [fat12_buffer.BPB_BytsPerSec] - imul eax,32 - add eax,ebx - dec eax - - cdq - idiv ebx -;;;;;;;; сейчас частное в eax, а остаток в edx для дискеты 1.44 у нас должно быть значение =14 -;BPB_ResvdSecCnt + RootDirSectors - movzx ebx, word [fat12_buffer.BPB_RsvdSecCnt] - add ebx,eax - -;DskSize у нас это значение уже получено и доступно - movzx eax,word [fat12_buffer.BPB_TotSec16] ;должен быть в секторах - sub eax,ebx - - -;TmpVal1=eax - shl edi,8 ;=edi*256 - movzx ecx,byte [fat12_buffer.BPB_NumFATs] - add edi,ecx -;TmpVal2=edi - add eax,edi - dec eax - cdq - idiv edi -;FATSz = сейчас частное в eax, а остаток в edx - mov word [fat12_buffer.BPB_FATSz16],ax - - - - - - - - -.fat12: ;fat12 -if DEBUG -; выведем в отладке, что собираемся делать образ диска c FS=fat12 - pushad - mov si,start_making_FAT12_msg - call printplain - popad -end if - - - -;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000). - mov set_ramfs,12 ;установим тип файловой системы - movzx ebx,byte [fat12_buffer.BPB_SecPerClus] - imul eax,ebx - - cmp eax,0x10000 - jae @f - mov word [fat12_buffer.BPB_TotSec16],ax - mov dword [fat12_buffer.BPB_TotSec32],0 -@@: -;количество секторов занимаемое одной копией фат -; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ?? -;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число -;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно -;быть 0. Пока константа, нужно будет позже доделать. - mov eax,root_dir_entry_count - mov word [fat12_buffer.BPB_RootEntCnt],ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) -;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб -;;;;;;; -;DskSize(в секторах)*12 (размерность файловой системы, т.е предположим сколько битов потребуется для адресации этого объема) /8 (что получить размер в байтах) -;полученное число округляем в большую сторону кратное сектору т.е. 512 байт Такой подход не универсален, но пока пойдет -;вообще у мелкософт это все считается ручками, но мы будем юзать только под коос рам диск с фат12 - movzx eax, word [fat12_buffer.BPB_TotSec16] - imul eax,12 - shr eax,3 ;делим на 8 но т.е. нам нужно делить еще и на 512 или более в зависимости от размеров кластера - movzx ebx,word [fat12_buffer.BPB_BytsPerSec] ;размер сектора - cdq - idiv ebx ;разделим на размер кластера -;сейчас у нас в eax значение его нужно округлить в большую сторону кратному 512 байтам -;применим следующее очистим and и добавим 512 байт. таким образом выравним на 512 байт -;но т.к. все равно делить нижний код нам не нужен -; and eax,0xfff200 -; add eax,0x200 ;добавим 512 байт для 1.44 дискеты идеально подходит )) - - inc ax -;по идее должно на каждую фат таблицу -;резервироваться 9 секторов т.е. получается 2*9=18+1 =19 секторов т.е. рут дир находиться на с 20 сетора т.е. с адреса 0х2600 -;сейчас нужно вычислить сколько будет секторов занимать фат ) нужно разделить на 512 -;FATSz = сейчас частное в eax - mov word [fat12_buffer.BPB_FATSz16],ax -;;;;;;;;;;;;;;;;;;;;;;;;;;;; -get_firstDataSector ;получить смещение до данных -;создадим певую запись в фат по определенному адресу. -first_create_fat_table -;закиним BPB файловой системы за 1 мб. -use_BPB_RAM -; -;копирование файла. -use_RamdiskFile - -;;;; вычисляем указатель на корневую дир FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16); -; movzx ebx, [fat12_buffer.BPB_NumFATs] -; movzx eax,ax -; imul eax,ebx -;eax=(BPB_NumFATs * BPB_FATSz16) -; inc eax -; BPB_ResvdSecCnt значение только 1 для fat12/16 -;в eax указатель на root dir. для дискеты fat12 должно получиться при кол-во копий fat 1 = 1+ (1*1) =2 или 3 - -if DEBUG - pusha -; mov ax,point_default -; mov ax,cx - mov cx,0x0a - mov di,show_db1 -; mov dword[ds:di],' ' -; mov word [ds:di+4],' ' - call decode -;Show size - mov si,show_db1 - call printplain -; -; xor ax,ax -; int 0x16 - popa -end if - - - - - - - -} - -macro use_RamdiskSector -{ -;для некоторых FS будет игнорироваться - mov di,point_default ;restore value - mov cx,save_cx_d - -.start_RamdiskSector: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz .end_RamdiskSector ;нету? ну ладно - следующее значение тогда ) - - cmp al,'R' - jnz .start_RamdiskSector -;проверка на значения RamdiskSize -; parse_RamdiskSize - - mov bx,cx - mov ax,di - - mov si,parse_RamdiskSector - mov cx,parse_RamdiskSector_e - parse_RamdiskSector - repe cmpsb - jnz .RamdiskSector_rest_val ;is not compare - - sub bx,parse_RamdiskSector_e - parse_RamdiskSector ;correct cx - add bx,cx - mov cx,bx - - test status_flag,flag_found_RamdiskSector ;оценка флагов - jz .correct_is_not_set_RamdiskSector - -; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем -; call printplain -; jmp .get_next_str - -.correct_is_not_set_RamdiskSector: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - jcxz .end_get_RamS_ERROR_1 ;not found param - - cmp ah,byte [es:di-1] ;find '=' - jnz .start_RamdiskSector ; перейдем на начало и попробуем найти еще секцию - - repe scasb ;cut ' ' - inc cx - dec di -;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - xor bx,bx - mov cx,4 -@@: movzx ax,byte [es:di] - cmp al,'0' - jb .end_RamdiskSector - cmp al,'9' - ja .end_RamdiskSector -;;;;;;;;;;;;;;;;;;; - - imul bx,10 - xor al,0x30 - add bx,ax - - inc di - - loop @b - jmp .end_RamdiskSector - - -.RamdiskSector_rest_val: - mov cx,bx - mov di,ax - jmp .start_RamdiskSector -.end_get_RamS_ERROR_1: - -.end_RamdiskSector: - mov ax,bx - -if DEBUG - pusha - movzx eax,bx;save_cx_d;point_default - mov cx,0x0a - mov di,RamdiskSector_msg - mov dword[ds:di],' ' - mov dword [ds:di+4],' ' - call decode -;Show size - mov si,RamdiskSector_msg - call printplain - - popa -end if - -; pop di -; pop es -} - -macro use_RamdiskCluster -{ -;для некоторых FS будет игнорироваться -; push es -; push di - mov di,point_default ;restore value - mov cx,save_cx_d -; push ini_data_ -; pop es -.start_RamdiskCluster: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz .end_RamdiskCluster ;нету? ну ладно - следующее значение тогда ) - cmp al,'R' - jnz .start_RamdiskCluster -;проверка на значения RamdiskSize -; parse_RamdiskSize - - mov bx,cx - mov ax,di - - mov si,parse_RamdiskCluster - mov cx,parse_RamdiskCluster_e - parse_RamdiskCluster - repe cmpsb - jnz .RamdiskCluster_rest_val ;is not compare - - sub bx,parse_RamdiskCluster_e - parse_RamdiskCluster ;correct cx - add bx,cx - mov cx,bx - - test status_flag,flag_found_RamdiskCluster ;оценка флагов - jz .correct_is_not_set_RamdiskCluster - -; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем -; call printplain -; jmp .get_next_str - -.correct_is_not_set_RamdiskCluster: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - jcxz .end_get_RamSC_ERROR_1 ;not found param - - cmp ah,byte [es:di-1] ;find '=' - jnz .start_RamdiskCluster ; перейдем на начало и попробуем найти еще секцию - - repe scasb ;cut ' ' - inc cx - dec di -;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -@@: movzx ax,byte [es:di] - cmp al,'0' - jb .end_RamdiskCluster - cmp al,'9' - ja .end_RamdiskCluster -;;;;;;;;;;;;;;;;;;; - xor al,0x30 - - jmp .end_RamdiskCluster - - -.RamdiskCluster_rest_val: - mov cx,bx - mov di,ax - jmp .start_RamdiskCluster -.end_get_RamSC_ERROR_1: - -.end_RamdiskCluster: -if DEBUG - pusha - mov cx,0x0a - mov di,RamdiskCluster_msg -; mov word[ds:di],' ' - call decode -;Show size - mov si,RamdiskCluster_msg - call printplain - - popa -end if - -} - -macro use_Loader_Image -;предназначен для загрузки образов выше 1 Мб. -;первоначальная версия загружает образ дискеты 1.44 мб -{ -local .start_p_LI -local .exit -local .error_LI -local .rest_value_loop -local .found_end_str - mov di,point_default ;restore value - mov cx,save_cx_d -;обработка конструкции типа LoaderModule=kord/kolibri.ldm -.start_p_LI: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz .exit ;нету? ну ладно - следующее значение тогда ) - cmp al,'L' - jnz .start_p_LI -;проверка на значение LoaderModule -; parse_LoaderModule - mov bx,cx - mov ax,di - - mov si,parse_LoaderImage - mov cx,parse_LoaderImage_e - parse_LoaderImage - repe cmpsb - jnz .rest_value_loop ;is not compare - - sub bx,parse_LoaderImage_e - parse_LoaderImage ;correct cx - add bx,cx - mov cx,bx - -; test status_flag,flag_found_LM ;оценка флагов -; jz .correct_is_not_set_LI - -; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем -; call printplain -; jmp .get_next_str - -;.correct_is_not_set_LI: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - jcxz .rest_value_loop_LI ;not found param timeout - - cmp ah,byte [es:di-1] ;find '=' - jnz .rest_value_loop_LI - - repe scasb ;cut ' ' - inc cx - dec di -;di указывает на начало блока информации, в cx длинна до конца секции. -;после загрузки заноситься значение занятой памяти. -;для того что бы загрузить модуль, воспользуемся callback сервисом -;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0 -;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader -;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем -;сохранили певые 2 word - push dword [es:di-6] - lea si,[di-6] - - push word [es:di-2] - xor ax,ax - mov word [es:di-6],ax ;вносим нужные значения -;info_real_mode_size размер и указатель на область в которую можно загрузиться - mov ax,info_real_mode_size ;0x3000 ;следующий сегмент за данными - - - mov word [es:di-4],ax - mov word [es:di-2],16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем -;;;;;; поиск конца строчки -@@: mov al,byte [es:di] - cmp al,' ' - jz .found_end_str - cmp al,0xa - jz .found_end_str - cmp al,0xd - jz .found_end_str - inc di - dec cx - jnz @b -;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки -.found_end_str: -; чтение блока по 64 кб в сегмент и забрасывание его выше 1 мб. - push word [es:di] - xor ax,ax - mov word [es:di],ax -; xor ax,ax ; function 1 - read file - mov di,si ;file_data - inc ax - push si - push es - call far dword [loader_callback] - push cs - pop ds - - pop es - pop si - - test bx,bx - jnz .error_LM - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; забрасывание блока в 64 кб выше 1 мб. - mov si,table_15_87 - push es - push ds - pop es - mov cx, 256*18 - mov ah, 0x87 - int 0x15 - pop es - pop dx cx - test ah, ah - - - - jmp far dword [es:si] - - - - -.rest_value_loop: - mov di,ax - mov cx,bx - jmp .start_p_LI - -.exit: - - - -} - - - -macro name_in_root_fat -;макрос, который записывает информацию о загруженном файле в корневую фат таблицу -{ - -} - - - -macro use_RamdiskFile -{ -;загрузка файлов с использование callback сервиса первичного загрузчика -;используется только для загрузки необходимых и небольших файлов, т.к. достаточно медленно работает -;для загрузки использует 0х87 функцию int 0x15 прерывания - загрузка блоков данных до 64 кб выше 1 мб -local .start_loop -local ._end -local .rest_value_loop -local .error - mov di,point_default ;restore value - mov cx,save_cx_d - mov data_offset,0 ;clean offset -;обработка конструкции типа LoaderModule=kord/kolibri.ldm -.start_loop: - call get_firs_sym ;get first symbol on new line - test cx,cx - jz ._end ;нету? ну ладно - следующее значение тогда ) - cmp al,'R' - jnz .start_loop -;проверка на значение RamdiskFile - mov bx,cx - mov ax,di - - mov si,parse_RamdiskFile - mov cx,parse_RamdiskFile_e - parse_RamdiskFile - repe cmpsb - jnz .rest_value_loop ;is not compare - - sub bx,parse_RamdiskFile_e - parse_RamdiskFile ;correct cx - add bx,cx - mov cx,bx -; test status_flag,flag_found_LM ;оценка флагов -; jz .correct_is_not_set_LM - -; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем -; call printplain -; jmp .get_next_str - -;.correct_is_not_set_LM: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - test ecx,ecx - jz .rest_value_loop ;not found param timeout - - cmp ah,byte [es:di-1] ;find '=' - jnz .rest_value_loop - - repe scasb ;cut ' ' - inc cx - dec di - - mov save_di_RAMDISK,di - mov save_cx_RAMDISK,cx -;di указывает на начало блока информации, в cx длинна до конца секции. -;после загрузки заноситься значение занятой памяти. -;для того что бы загрузить модуль, воспользуемся callback сервисом -;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0 -;это выглядит так: в ini файле существует строчка RamdiskFile = @menu,@menu -;мы ее модифицируем до такого состояния dw,dw,db'@menu',0 конечно сохранив те значения которые мы заменяем -;сохранили певые 2 word - -; -@@: mov al,byte [es:di] - cmp al,',' ; т.е. ищем разделитель - jz .found_end_str - inc di - dec cx - jnz @b -;;;not found допустим,что это конец файла и он не имеет привычного завершения строки -.found_end_str: -; mov al,byte [es:di] -; cmp al,' ' ; убираем пробелы, если они есть -; jnz @f -; inc di -; dec cx -; jnz .found_end_str - -;@@: - mov point_to_dest_file_name,di - inc di -;проверка индивидуальности имени файла -check_name_file -;/restore di - point and cx -size section - mov di,save_di_RAMDISK - mov cx,save_cx_RAMDISK - - test al,al - jnz .start_loop ;если в al значение не =0, то такое имя уже существует в системе. - - - - push dword [es:di-6] - lea si,[di-6] - - push word [es:di-2] - push di - xor ax,ax - mov word [es:di-6],ax ;вносим нужные значения -;info_real_mode_size размер и указатель на область в которую можно загрузиться - mov ax,info_real_mode_size ;0x3000 ;следующий сегмент за данными - - - mov word [es:di-4],ax - mov word [es:di-2],16 ;кол-во блоков по 4 кб =64 кб т.е. больше не читаем - - mov di,point_to_dest_file_name - -if DEBUG - pushad -; mov ax,di - mov cx,0x0a - mov di,name_of_seg_get_64 - mov dword[ds:di],' ' - mov word[ds:di+4],' ' - call decode -;Show size - mov si,name_of_seg_get_64 - call printplain - - popad -end if - - push word [es:di] - push cx - xor ax,ax - mov word [es:di],ax -; xor ax,ax ; function 1 - read file - push di - mov di,si ;file_data - inc ax - push si - push es - push bp - - push es - pop ds - push cs - pop es - - call far dword [es:loader_callback] - - - push cs - pop ds - - pop bp - pop es - pop si - - cmp bx,2 - ja .error -; сейчас у нас в dx:ax размер файла, который мы загрузили. -; возможна ситуация, когда в bx=1 т.е. есть еще данные на диске - mov status_flag_loader_f,bx - - shl edx,16 - mov dx,ax -; shr edx,10 ;размер файла в кб. -;;в edx размер в байтах. - mov save_file_size,edx - mov eax,edx -;восстановим полностью файл сценария - pop di - pop cx ;длинна остатка с 2-ой частью имени т.е. с именем назначением. - pop word [es:di] - pop di - pop word [es:di-2] - pop dword [es:di-6] - - -if DEBUG - pushad - mov cx,0x0a - mov di,RamdiskFile_msg - mov dword[ds:di],' ' - call decode -;Show size - mov si,RamdiskFile_msg - call printplain - - popad -end if - - - - - - - - - - -; загрузим чему у нас равен кластер -; mov ax,word [fat12_buffer.BPB_BytsPerSec] ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта -; movzx bx,byte [fat12_buffer.BPB_SecPerClus] ;кол-во секторов в кластере -; imul ax,bx -;сейчас в eax размер кластера (512) байт -;в edx длина файла в байтах до 64 кб -;закиним файл за 1 мб -;1 нам нужно составить фат таблицу т.е. произвести разметку рамдиска, затем перенесем по адресу файл - -;записать инфорамацию о файле в корневую директорию -register_file_in_fat -;перенести за 1 мб содержимое файла -move_file_up - -;проверим, загружен ли до конца файл? т.е. если размер файла больше чем 64 кб, то будет подгружать оставшиеся блоки - cmp status_flag_loader_f,0x1 - jnz @f -;нужно дозагузить данные файла и перенести их за 1-ый мб согласно фат структуре - - - - - - - - - -@@: -;тут организован цикл по загрузке файлов в корневую директорию - mov di,save_di_RAMDISK - mov cx,save_cx_RAMDISK -if DEBUG - pusha - xor ax,ax - int 0x16 - popa -end if - - - jmp .start_loop - - -.error: - ;call error.LoaderModule -;fixme! -.rest_value_loop: - mov di,ax - mov cx,bx - jmp .start_loop - -._end: -;перенесем за 1-ый мб фат и рут дир -move_up_fat_and_root_d - - - - - - -;загрузка блока -; mov ah,0x87 -; mov cx, ;size in byte - - -;es:si point to descripts - - -} - -macro use_BPB_RAM ;закинуть самые первые 512 байт за 1-й мб -;данный макрос закидывает BPB структуру т.е. первые 512 байт, пока только фат12 за 1 мб -{ - mov ax,fat12_buffer - mov si,table_15_87 - add word [si+8*2+2],ax - push es - push ds - pop es - mov cx,256 ;бут сектор укладывается в 512 байт 512/2=256 - mov ah, 0x87 - int 0x15 - pop es -;add 512 byte for destination adress -; add dword [si+8*3+2], 512 -; test ah, ah -; jz -if DEBUG - pusha - mov ax,word [si+8*2+2] - mov cx,0x0a - mov di,BPB_msg - call decode -;Show size - mov si,BPB_msg - call printplain - popa -end if -} -macro first_create_fat_table -;данный макрос создает оформляет 3 первых байта fat таблицы, и устанавливает указатель на следующий блок, и вносит 0 значение -;для смещения в корневой таблице. -{ - mov al,byte [fat12_buffer.BPB_Media] - - - push ds - - - mov di,info_real_mode_size - add di,0x1000 - -if DEBUG - pushad - - mov ax,info_real_mode_size - add ax,0x1000 -; mov ax,ds - mov cx,0xa - - mov di,first_entry_in_fat - mov dword [di],' ' - mov word [di+4],' ' - call decode -;Show size - mov si,first_entry_in_fat - call printplain - - xor ax,ax - int 0x16 - - popad -end if - - - push di ; push word info_real_mode_size+0x1000 ;cледующий сегмент за загруженным участком - - xor di,di - mov point_to_free_root,di ;значение смещения =0 в корневой фат таблице описания - - pop ds ; загружен следующий сегмент т.е. пустой сегмент - - mov byte [di],al - or ax,-1 - inc di - mov word [di],ax - - pop ds - mov point_next_fat_str,3 - -if DEBUG - pushad - mov ax,point_next_fat_str - mov cx,0x0a - mov di,fat_create_msg - call decode -;Show size - mov si,fat_create_msg - call printplain - popad -end if - -} -macro register_file_in_fat -;макрос регистрации файла в файловой структуре Fat -;пока поддерживается только фат12, пока )) -;вычисление смежных кластеров и занесение инфы в fat/ -{ -local .step2 -local .step3 -local .end -local .eof_file - -;di point on root dir на фри секцию. - push es - - mov ax,info_real_mode_size - add ax,0x1000 - mov es,ax ; push word info_real_mode_size+0x1000 ;сегмент следующий за загруженным блоком в 64 кб - -; определяем тип фат пока не определяем, пока только фат 12 -; 12 бит, для вычесления соседних каластеров. - mov di,firstDataSect ;в секторах - sub di,size_root_dir -;теперь в ax размер в секторах начала рут дир - shl di,9 ;imul 512 - add di,point_to_free_root ;смещение в уже записанных 32-х структурах. -;необходимо внести значение в рут дир т.е. 32 байта -if DEBUG - pushad -; mov ax,point_default -; mov ax, - mov cx,0x0a - mov di,show_db2 - mov dword[ds:di],' ' - mov word [ds:di+4],' ' - call decode -;Show size - mov si,show_db2 - call printplain -; -; xor ax,ax -; int 0x16 - popad -end if - - - -;gs:di - указатель для внесения инфорации в рут область фат таблицы инормации о файле. - mov si,shot_name_fat - mov cx,11 -;запишем в структуру имя -@@: lodsb - stosb - loop @b - -;запишем атрибуты файла и DIR_NTRes - зарезеврированный байт =0 - xor ax,ax - mov ah,ATTR_VOLUME_ID - mov word [es:di],ax - add di,2 -;DIR_CrtTimeTenth - mov byte [es:di],100 - inc di -;DIR_CrtTime - mov word [es:di],0x032b ;дата - add di,2 -;DIR_CrtDate - mov word [es:di],0x0 ;время >< - add di,2 -;DIR_LstAccDate - mov word [es:di],0x032b ;дата моего - add di,2 -;DIR_FstClusHI - mov word [es:di],0x0 ;время для фат12 /16 всегда 0 - add di,2 -;DIR_WrtTime - mov word [es:di],0x0 ;время >< - add di,2 -;DIR_WrtDate - mov word [es:di],0x032b - add di,2 - - mov ax,point_next_fat_str - mov word [es:di],ax - add di,2 - - push di -;DIR_FstClusLO Младшее слово номера первого кластера. - ; mov ax,point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи -;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат - mov bx,ax - shr bx,1 - add ax,bx -;в ах сейчас FATOffset -;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec); - mov bx, word [fat12_buffer.BPB_BytsPerSec] - cwd - idiv bx -;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) четный или нечетный указатель. - mov si,ax -;нам нужно в цикле записать все кластеры которые будут использованы для размещения файла. -;узнаем размер кластера. - movzx eax,word [fat12_buffer.BPB_BytsPerSec] - movzx ebx,byte [fat12_buffer.BPB_SecPerClus] - imul eax,ebx -;ax - размер кластера. -;сейчас будем записывать во временный буфер фат таблицу для выбранного файла. Поскольку мы его загрузили возможно не полностью -;мы обработаем запись для фат полностью, в не зависимости от предела буфера где возможна часть файла. - mov ebx,save_file_size ;размер файла в байтах - -@@: sub ebx,eax - cmp ebx,eax - jbe .eof_file - - inc point_next_fat_str - mov cx,point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи -;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат - mov dx,ax - shr dx,1 - add cx,dx - - - - test si,0x1 - jz .step2 - shl cx,4 - mov word[es:si],cx - inc si - add cx,ax - jmp @b - -.step2: and cx,0x0FFF - mov word[es:si],cx - inc si - add cx,ax - jmp @b - -.eof_file: - mov cx,0x0fff - test si,0x1 - jz .step3 - shl cx,4 - mov word[es:si],cx - jmp .end - -.step3: and cx,0x0FFF - mov word[es:si],cx - -.end: inc point_next_fat_str - - pop di -;DIR_FileSize 32-битный DWORD содержит размер файла в байтах. - mov eax,save_file_size - mov dword [es:di],eax - -if DEBUG - pushad - - mov di,firstDataSect ;в секторах - sub di,size_root_dir -;теперь в ax размер в секторах начала рут дир - shl di,9 ;imul 512 - add di,point_to_free_root ;смещение в уже записанных 32-х структурах. - - push di - - mov si,dest_name_fat - mov cx,11 - -;запишем в структуру имя -@@: mov al,byte [es:di] - inc di - mov byte [ds:si],al - inc si - loop @b - - mov di,si - inc di - pop ax - mov cx,0xa - call decode - - mov si,dest_name_fat - call printplain - popad - -END IF - - - - - - add point_to_free_root,32 ;увелицим смещение до следующего значения. - pop es - -} - - - - - -macro get_firstDataSector -;макрос для вычисления певого сектора данных т.е. данных файлов в фате -;вычислим FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors; -{ - mov ax,word [fat12_buffer.BPB_FATSz16] - movzx bx,byte [fat12_buffer.BPB_NumFATs] - imul ax,bx ;9x1=9 -;ax=BPB_NumFATs * FATSz - mov bx,word [fat12_buffer.BPB_RootEntCnt] ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) - shr bx,4 ;imul bx,32 and then div 512 -> in bx size in sectors - add ax,bx ;9+14=23 - mov size_root_dir,bx - movzx bx,byte [fat12_buffer.BPB_RsvdSecCnt] ;add 1 for fat 16/12 - add ax,bx -;ax=firstDataSector - где начинается первый секторо от 0 сектора в секторах. - фактически = 24 сектор - mov firstDataSect,ax ;сохраним для вычисления -; получимзначение кластеров, это объем в который мы можем записать данные - mov bx,word [fat12_buffer.BPB_TotSec16] - sub bx,ax - mov ax,bx - movzx bx,byte [fat12_buffer.BPB_SecPerClus] - cwd - idiv bx - mov DataClasters,ax - -if DEBUG - pushad - mov ax,firstDataSect ;первый сектор данных - mov cx,0x0a - mov di,firstDataSect_msg - call decode -;Show size - mov si,firstDataSect_msg - call printplain -;;;;;;;;;;;;;;;;;;;;;;;;;; - mov ax,size_root_dir ;размер рут дир в сетокторах - mov cx,0x0a - mov di,size_root_dir_msg - call decode -;Show size - mov si,size_root_dir_msg - call printplain -;;;;;;;;;;;;;;;;;;;;;;;;;; - mov ax,DataClasters ;кластеры - mov cx,0x0a - mov di,DataClasters_msg - call decode -;Show size - mov si,DataClasters_msg - call printplain - popad - -end if - -} - -macro use_RamdiskPATHS -;парсинг пути источника файлов. -{ - -} - -macro use_RamdiskPATHD -;парсинг пути назначения файлов. -{ - -} -macro check_name_file -;макрос проверки имени на повтор, имя должно быть уникальным. -;входные данные: es- сегмент где лежит файл для парсинга т.е. startos.ini -;di - указатель на имя файла т.е. es:di указывает на имя файла назначения -;выходные данные eax =-1 имя совпало, eax=0 имя не совпало. -{ -local .no_equal -local .exit -local .loop_size_root_dir -;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными. -;преобразуем в аналог фат записи сточку с именем назначения - convertion_file_name ; преобразовали имя по нужным правилам - test ax,ax - jnz .exit - - lea si,[shot_name_fat] ; desination name of file - -;вычислим указатель на корневую директорию - mov di,firstDataSect - sub di,size_root_dir -;теперь в ax размер в секторах начала рут дир - shl di,9 ;imul 512 -;di= Это смещение от начала буфера до рут директории. в пределах 64 кб. -;загрузим значение - т.е. кол-во элементов, которые мы можем просматривать. - mov dx,root_dir_entry_count - - mov ax,info_real_mode_size - add ax,0x1000 - - - mov gs,ax -.loop_size_root_dir: -DEBUG1 equ 0 -if DEBUG1 - pushad - push di - mov eax,dword[gs:di] - lea si,[check_root_fat_+14] - mov dword [ds:si],'----' - mov dword [ds:si+4],'----' - mov dword [ds:si+8],'----' - mov dword[ds:si],eax - mov eax,dword[gs:di+4] - mov dword[ds:si+4],eax - mov eax,dword[gs:di+8] - mov dword[ds:si+8],eax - -; - xor eax,eax - mov ax,gs;point_next_fat_str - mov cx,0x0a - mov di,check_root_fat_ - mov dword [di],' ' - mov word [di+4],' ' - call decode - xor eax,eax - pop ax - mov di,(check_root_fat_+7) - mov dword [di],' ' - mov word [di+4],' ' - call decode - -;Show size - lea si,[check_root_fat_] - call printplain - - lea si,[shot_name_fat] - call printplain - - xor ax,ax - int 0x16 - popad -end if - - xor bx,bx - mov cx,11 ;size of name in struct FAT - -@@: - mov al,byte [ds:si+bx] ;ds:si - point to name of convertion variable. - mov ah,byte [gs:di+bx] ;gs:di - point to name in fat struct - inc bx - -if DEBUG -; pushad -; lea si,[check_root_fat_+14] -; mov dword [ds:si],'----' -; mov word [ds:si],ax -; call printplain - -; xor ax,ax -; int 0x16 - -; popad -end if - - - - cmp ah,al - jnz .no_equal - -; dec cx -; jnz @b - loop @b - -;.succesfuly: -;печально, такое имя уже имеется :( - or ax,-1 - jmp .exit - - -.no_equal: - add di,32 ;fat struct =32 byte - dec dx - jnz .loop_size_root_dir - -;.exit_check_name: - and ax,0 - -.exit: - -if DEBUG - pushad -;Show size - lea si,[check_name_fat_msg_n] - test ax,ax - jz @f - lea si,[check_name_fat_msg_y] - call printplain - lea si,[alarm_msg] -@@: call printplain - popad -end if - -} - - -macro convertion_file_name -;макрос конвертации имени, это нужно поскольку формат представленный не соответсвует фат и напрямую редко можно когда использовать -;преобразование имени типа hello.asm в 'HELLO ASM', в соответствии с правилами fat. -;входные параметры es:di указатель на имя файла которое нужно преобразовать, конечный буфер shot_name_fat -{ -local .next_step -local .error -local .st1 -local .st2 -local .st2_l -local .st3 -local .st4_s -local .st4 -local .st5 - -;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными. -; mov di,point_to_dest_file_name входной параметр - mov si,shot_name_fat - or first_input,-1 ;при первом входе устанавливаем флаг - mov cx,11 ;длинна имени в стуктуре фат таблицы - -@@: - mov al,byte [es:di] - cmp al,0xa - jz .st4_s - cmp al,0xd - jz .st4_s - cmp al,0x20 - jz .st4_s - - cmp al,0x20 - jb .error - cmp al,0x22 - jz .error - cmp al,0x2a - jz .error - cmp al,0x2b - jz .error - cmp al,0x2c - jz .error - cmp al,0x2F - jz .error - - cmp al,0x3a - jz .error - cmp al,0x3b - jz .error - cmp al,0x3c - jz .error - cmp al,0x3d - jz .error - cmp al,0x3E - jz .error - cmp al,0x3F - jz .error - - cmp al,0x5b - jz .error - cmp al,0x5c - jz .error - cmp al,0x5d - jz .error - - cmp al,0x7c - jz .error - - - cmp first_input,-1 - jnz .next_step - and first_input,0 ;сборосим флаг. - cmp al,'.' - jz .error ;обработка точки, файл не может начинаться с точки - -.next_step: - cmp al,0x2e - jnz .st2 ;обработка точки, в середине файла -;тут у нас установлен разделитель -;все остальнео место займут пробелы - mov al,' ' - -;!fixme обработаны не все исключения :( - cmp cl,3 ;формат файла такой GIDGIDIIASM т.е. gidgidii.asm - jbe .st2 - - -.st3: - mov byte [si],al - inc si - dec cx - cmp cx,3 - ja .st3 -; inc cx - inc di - jmp @b - -.st2: - cmp al,0x60 - jbe .st2_l - - xor al,0x20 ;сделаем заглавные буквы -.st2_l: mov byte [si],al - inc di - inc si -; dec cx -; jnz @b - loop @b -.st5: xor ax,ax - jmp @f - -;;;;;;;;файл закончился, и нужно внести в конец пробелы -.st4_s: mov al,' ' -.st4: mov byte [si],al - inc si - loop .st4 - jmp .st5 - -.error: or ax,-1 -@@: - -if DEBUG - pushad - - mov si,convertion_file_name_msg_y - test ax,ax - jz @f - mov si,convertion_file_name_msg_n -@@: call printplain - - mov si,shot_name_fat - mov byte [si+12],0 - call printplain - popad - -end if -} - -macro move_file_up -;макрос который перемещает за 1 мб с правилами фат данные файла. -{ -local .st1 -local .correct_on_byte -;сейчас имеет быть ситуация, когда BPB уже перемещен за 1 мб, фат, и рут дир будут позже перемещены, -;а нам нужно вычислить место, и перенести туда содержимое файла -;полученое значение указывает в байтах на начало данных - - mov ax,info_real_mode_size ; сегмент где расположены данные - mov si,table_15_87 - mov word [si+8*2+2],ax -;смещение до данных уже за 1-м мб - movzx eax,firstDataSect - movzx edx,data_offset - add eax,edx - - movzx ebx,word [fat12_buffer.BPB_BytsPerSec] - movzx edx,byte [fat12_buffer.BPB_SecPerClus] - imul bx,dx ;получим размер кластера - - - - push ebx ;save bx - - imul eax,ebx -; shl eax,9 ;умножим на 512 - -if DEBUG - pushad - xor eax,eax - mov ax,info_real_mode_size - mov cx,0x0a - mov di,seg_where_get_data - mov dword [di],' ' - mov word [di+4],' ' - call decode -;Show size - mov si,seg_where_get_data - call printplain - popad - -end if - -; mov bx,word [fat12_buffer.BPB_BytsPerSec] -; movzx dx,byte [fat12_buffer.BPB_SecPerClus] -; imul bx,dx -; cwd -; idiv bx - - mov dl,0x10 - -@@: cmp eax,0x00010000 - jb @f - - sub eax,0x00010000 - inc dl - jmp @b - - -@@: mov byte [si+8*3+3],dl ;куда писать - mov word [si+8*3+2],ax - - mov ecx,save_file_size ;размер файла в байтах. - cmp ecx,0x0000ffff ;размер блока т.е. 64 кб - jbe .correct_on_byte ;корректировка на байт значения - - - - mov ecx,0x00010000 ;65536 - sub save_file_size,ecx ;отнимим -; jmp .st1 ;получим 0х8000 - - - - -;корректировка значения должна быть выполенена на размер кластера -.correct_on_byte: -;/узнаем размер кластера - pop eax ;restore size of claster - push ecx -@@: inc data_offset - - cmp eax,ecx - jae @f - sub ecx,eax - jmp @b -@@: pop ecx - - - - - test ecx,0x1 - jz .st1 - inc ecx -.st1: shr ecx,1 ; преобразовать значение для 0x87 function - -;перенесем блок за 1 мб - push es - push ds - pop es - - mov ah, 0x87 - int 0x15 - pop es - -if DEBUG - pusha -; mov ax,point_next_fat_str - mov cx,0x0a - mov di,return_code_af_move - call decode -;Show size - mov si,return_code_af_move - call printplain - popa - -end if - -} - - -macro move_up_fat_and_root_d -;макрос, который позволяет перенести выше 1 мб в структуру образа фат таблицу и рут директорию -{ -local .st1 - - mov ax,info_real_mode_size - add ax,0x1000 - - mov si,table_15_87 - mov word [si+8*2+2],ax -;смещение до данных - mov ax,512 - mov word [si+8*3+2],ax -;fixme! тут необходимо сделать подержку т.е. формировать смещение файла в уже записанных данных. - - movzx ecx,word [fat12_buffer.BPB_FATSz16] - movzx bx,byte [fat12_buffer.BPB_NumFATs] - imul cx,bx ;9x1=9 - - add cx,size_root_dir ;размер корневой дирректории - shl ecx,9 ;imul 512 - - -;корректировка значения - test ecx,0x1 - jz .st1 - inc ecx -.st1: shr ecx,1 - - push es - push ds - pop es - - mov ah, 0x87 - int 0x15 - pop es - -if DEBUG - pusha -; mov ax,point_next_fat_str - mov cx,0x0a - mov di,return_code_af_fat_m - call decode -;Show size - mov si,return_code_af_fat_m - call printplain - popa - -end if - -} \ No newline at end of file +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +; в этой секции идет разбор параметров указатель на секцию храниться в point_default +;типы ошибок при обработке макроса +;Макрос RamdiskFS +;/определение флагов в записи корневой директории +ATTR_READ_ONLY equ 0x01 +ATTR_HIDDEN equ 0x02 +ATTR_SYSTEM equ 0x04 +ATTR_VOLUME_ID equ 0x08 +ATTR_DIRECTORY equ 0x10 +ATTR_ARCHIVE equ 0x20 + + + +show_error_1 equ 0x1 ;кончились данные - не запланированный конец секции +show_error_2 equ 0x2 ;нет завершающего символа в размере рам диска. +show_error_3 equ 0x4 ; рам диск будет иметь размер =64 кб. +show_error_4 equ 0x8 ; + +macro use_parse_def_sect +{ + mov di, point_default + push ini_data_ + pop es + mov si, point_to_point_def + sub si, 2 + mov cx, [si] ;загрузим указатель наследующию секцию + + xor ax, ax ;обнулим аx для очистки флагов + + sub cx, di ;вот теперь имеем истиный размер + mov save_cx_d, cx ;сохраним значение cx своей переменной +;обнулим переменную флагов, это необходимо, для того, что бы избежать обработку повторяющихся значений + + mov status_flag, ax +;;;; +;ВХод в обработку парсинга значений секций. es:di - указатель на начало секции cx размер секции доступной для парсинга +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;соглашение не разрушаем bp, es, cs, sp +;use_Loader_Image ;загрузить образ выше 1 мб +use_RamdiskFS +;проверяется самый последний. +use_LoaderModule ;особенность - передает управление на загруженный модуль. +} + +macro use_LoaderModule +;как вариант сейчас используется модель, при загрузке модуля на него передается управление, решение временое +;управление будет передаваться только после обработки всей секции +{ +local .found_end_str + + mov di, point_default ;restore value + mov cx, save_cx_d +;обработка конструкции типа LoaderModule=kord/kolibri.ldm +.start_p_LM: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz ._afterLoaderModule ;нету? ну ладно - следующее значение тогда ) + cmp al, 'L' + jnz .start_p_LM +;проверка на значение LoaderModule +; parse_LoaderModule + mov bx, cx + mov ax, di + + mov si, parse_LoaderModule + mov cx, parse_LoaderModule_e - parse_LoaderModule + repe cmpsb + jnz .rest_value_loop_LM ;is not compare + + sub bx, parse_LoaderModule_e - parse_LoaderModule;correct cx + add bx, cx + mov cx, bx + + test status_flag, flag_found_LM ;оценка флагов + jz .correct_is_not_set_LM + +; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем +; call printplain +; jmp .get_next_str + +.correct_is_not_set_LM: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + jcxz .rest_value_loop_LM ;not found param timeout + + cmp ah, byte [es:di-1] ;find '=' + jnz .rest_value_loop_LM + + repe scasb ;cut ' ' + inc cx + dec di +;di указывает на начало блока информации, в cx длинна до конца секции. +;после загрузки заноситься значение занятой памяти. +;для того что бы загрузить модуль, воспользуемся callback сервисом +;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0 +;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader +;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем +;сохранили певые 2 word + push dword [es:di-6] + lea si, [di-6] + + push word [es:di-2] + xor ax, ax + mov word [es:di-6], ax ;вносим нужные значения +;info_real_mode_size размер и указатель на область в которую можно загрузиться + mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными + + + mov word [es:di-4], ax + mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем +;;;;;; поиск конца строчки +@@: + mov al, byte [es:di] + cmp al, ' ' + jz .found_end_str + cmp al, 0xa + jz .found_end_str + cmp al, 0xd + jz .found_end_str + inc di + dec cx + jnz @b +;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки +.found_end_str: + + push word [es:di] + xor ax, ax + mov word [es:di], ax +; xor ax,ax ; function 1 - read file + mov di, si ;file_data + inc ax + push si + push es + + push es + pop ds + push cs + pop es + + call far dword [es:loader_callback] + + push cs + pop ds + + pop es + pop si + + test bx, bx + jnz .error_LM + + + jmp far dword [es:si] + + +.error_LM: + call error.LoaderModule +.rest_value_loop_LM: + mov di, ax + mov cx, bx + jmp .start_p_LM + +._afterLoaderModule: +} + +macro use_RamdiskFS +; формирование рам диска, + обработка всего связанного. +{ +if DEBUG +local ._not_memory_in_sys +;//////// clear window + mov ax, 3 + int 0x10 +;\\\\\\\\\ clear window is end + mov si, ramdiskFS_st + call printplain +end if +; обнулим регистр состояния ошибок + xor ax, ax + mov show_errors_sect, ax +use_free_memory ; узнаем какого объема у нас доступна память. значение возаращается в ax +;узнаем сколько у нас есть памяти и сможем ли мы сформировать нужного размера рам диск. +use_RamdiskSize ;значение возвращается в bx + cmp free_ad_memory, bx ; размерность в кб. + jbe ._not_memory_in_sys + movzx eax, bx + shl eax, 10 ;*1024 = get size in byte + mov save_ramdisksize, eax ; сорханим размер в byte + +get_type_FS ;получим тип файловой системы + создадим ее + + +._not_memory_in_sys: + +if DEBUG +;pause + xor ax, ax + int 0x16 +end if +} +macro use_RamdiskSize +{ +local .start_p_RS +local .correct_is_not_set_RS +local .CS +local .correct_val_RS +local .correct_size_RS +local .rest_value_loop_RS +local .end_get_RS_ERROR_1 +local .end_get_RS_ERROR_2 +local ._end_parse_RS +;обрабатывается размер формируемого рам диска +;загрузим начало секции, т.к. будем просматривать с начала и всю секцию + mov di, point_default ;restore value + mov cx, save_cx_d +.start_p_RS: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz ._end_parse_RS ;нету? ну ладно - следующее значение тогда ) + cmp al, 'R' + jnz .start_p_RS +;проверка на значения RamdiskSize +; parse_RamdiskSize + mov bx, cx + mov ax, di + + mov si, parse_RamdiskSize + mov cx, parse_RamdiskSize_e - parse_RamdiskSize + repe cmpsb + jnz .rest_value_loop_RS ;is not compare + + sub bx, parse_RamdiskSize_e - parse_RamdiskSize;correct cx + add bx, cx + mov cx, bx + + test status_flag, flag_found_RS ;оценка флагов + jz .correct_is_not_set_RS + +; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем +; call printplain +; jmp .get_next_str + +.correct_is_not_set_RS: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + jcxz .end_get_RS_ERROR_1 ;not found param + + cmp ah, byte [es:di-1] ;find '=' + jnz .start_p_RS ; перейдем на начало и попробуем найти еще секцию + + repe scasb ;cut ' ' + inc cx + dec di +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;Тут нужно преобразовывать строчку в цифровое значение. +;;;;;;;;;;;;;;;;;;;;;;;;;; + xor bx, bx + mov cx, 5 +@@: + mov al, byte [es:di] + cmp al, '0' + jb .CS + cmp al, '9' + jbe .correct_val_RS +.CS: + cmp al, 'K' + jz .correct_size_RS + jmp .end_get_RS_ERROR_2 +.correct_val_RS: + imul bx, 10 + xor al, 0x30 + add bl, al + inc di + loop @b + +.correct_size_RS: +;возможен 1 вариант, когда размер задан в K киллобайтах +;внутренный формат данных это кол-во запрощеной памяти в кб. + test bx, bx + jnz @f ;если значение отлично от 0 +;;;;;сообщение об ошибке, размер "найденого" блока =0 минимально мы должны +;установить 64 кб размер рам диска. + or show_errors_sect, show_error_3 + mov bx, 64 +@@: + jmp ._end_parse_RS + + +.rest_value_loop_RS: + mov di, ax + mov cx, bx + jmp .start_p_RS + + + +.end_get_RS_ERROR_1: +;сообщение об ошибке - данный участок кода не был корректно обработан :( + or show_errors_sect, show_error_1 + jmp ._end_parse_RS +.end_get_RS_ERROR_2: + or show_errors_sect, show_error_2 + +._end_parse_RS: +if DEBUG + pusha + movzx eax, bx + mov cx, 0x0a + mov di, RamdiskSize_msg + mov dword[ds:di], ' ' + mov word [ds:di+4], ' ' + call decode +;Show size + mov si, RamdiskSize_msg + call printplain + + popa +end if + +} + +macro use_free_memory +{ +local _support_function_use_free_memory +;макрос для получения общего числа доступной памяти в кб, для формирования рам диска за пределами 1 мб. +;используется 0х88 функция 0х15 прерывания +; если поддерживается функция, то в ax значение в кб, если нет, то в ax=0 + mov ah, 0x88 ;ah,0x88 + int 0x15 + jnc ._support_function_use_free_memory + xor ax, ax +;возвращает в ax число в кб +._support_function_use_free_memory: + mov free_ad_memory, ax ; если не поддерживается биосом, то в ax=0 +if DEBUG + pushad + movzx eax, ax + mov cx, 0x0a + mov di, free_memory_msg + mov dword[ds:di], ' ' + mov word [ds:di+4], ' ' + call decode +;Show size + mov si, free_memory_msg + call printplain + + popad +end if + + + + +} +macro show_ERRORS +{ + +} + +macro get_type_FS ;получить и создать образ для заданной RFS. +{ + mov di, point_default ;restore value + mov cx, save_cx_d +.start_g_tpe_RFS: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz ._end_parse_FRS ;._end_get_type_RFS ;нету? ну ладно - следующее значение тогда ) + cmp al, 'R' + jnz .start_g_tpe_RFS +;проверка на значения RamdiskSize +; parse_RamdiskSize + mov bx, cx + mov ax, di + + mov si, parse_RamdiskFS + mov cx, parse_RamdiskFS_e - parse_RamdiskFS + repe cmpsb + jnz .start_g_tpe_RFS_rest_v ;is not compare + + sub bx, parse_RamdiskFS_e - parse_RamdiskFS;correct cx + add bx, cx + mov cx, bx + + test status_flag, flag_found_GTRFMS ;оценка флагов + jz .correct_is_not_set_FRS + +; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем +; call printplain +; jmp .get_next_str + +.correct_is_not_set_FRS: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + test cx, cx + jz .end_get_FRS_ERROR_1 ;not found param + + cmp ah, byte [es:di-1] ;find '=' + jnz .start_g_tpe_RFS ; перейдем на начало и попробуем найти еще секцию + + repe scasb ;cut ' ' + inc cx + dec di +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;Тут нужно преобразовывать строчку в цифровое значение. +;;;;;;;;;;;;;;;;;;;;;;;;;; + mov bx, cx + mov ax, di + + mov si, parse_RFS_FAT + mov cx, parse_RFS_FAT_e - parse_RFS_FAT + repe cmpsb + jnz .krfs_cmp ;is not compare + +make_FAT_RamFS ;сделать + +if DEBUG + pusha + mov si, make_fat12_RFS_msg + call printplain + popa +end if + jmp ._end_parse_FRS + +.krfs_cmp: + mov cx, bx + mov di, ax + + mov si, parse_RFS_KRFS + mov cx, parse_RFS_KRFS_e - parse_RFS_KRFS + repe cmpsb +; jnz @f ;is not compare + + jmp ._end_parse_FRS + + +.start_g_tpe_RFS_rest_v: + mov cx, bx + mov di, ax + jmp .start_g_tpe_RFS + + + +.end_get_FRS_ERROR_1: +;сообщение об ошибке - данный участок кода не был корректно обработан :( + or show_errors_sect, show_error_1 + jmp ._end_parse_FRS +.end_get_FRS_ERROR_2: + or show_errors_sect, show_error_2 + +._end_parse_FRS: +if DEBUG + pusha + mov si, get_type_FS_msg + call printplain + popa +end if + + + +} +macro make_FAT_RamFS +{ +local .RS1 +local .fat12 +local .fat16 +; мы должны сформировать в начальный образ Ram FS, а потом записать его за область выше 1 мб.. +;для случая с FAT12 +; mov di,fat12_buffer ;ds должен быть = cs +;es:di - указывают на начало блока для формирования рам фс. +use_RamdiskSector ;возращаемое значение в ax размер сектора в байтах + cmp ax, 4096;по спецификации значение должно быть в пределах от 1 до 4096 + ja .RS1 + test ax, ax + jnz @f ;ошибка если сюда прыгнули все таки ... + +.RS1: + mov word [fat12_buffer.BPB_BytsPerSec], 512 +;;;;;;;;;;скажем что по дефолту будем юзать значение... +@@: + mov word [fat12_buffer.BPB_BytsPerSec], ax;тут все ок + +;BPB_SecPerClus кол-во секторов в кластере +use_RamdiskCluster ;возращаемое значение в al + cmp al, 128 + ja @f +; test al,0x1 ;проверка на кратность ) +; jnz @f + + mov byte [fat12_buffer.BPB_SecPerClus], al + + ;incorrect value will be set dafault + +;ниже некорректное значение в т.к. размер кратен 2 и в диапазоне от 1 до 128 включительно +; мы должны ругнуться на это +;@@: ;mov byte [fat12_buffer.BPB_SecPerClus],1 + +;;;;; определеим какая у нас будет использоваться FAT +;по условию, fat12<4085<=fat16<65525<=fat32 +; fat12_buffer.BPB_BytsPerSec*fat12_buffer.BPB_SecPerClus = кол-во секторов + movzx eax, word [fat12_buffer.BPB_BytsPerSec] + movzx ebx, byte [fat12_buffer.BPB_SecPerClus] + + imul ebx, eax;тут размерность сектора + mov eax, save_ramdisksize ;размер запрошенного рам диска в байтах + cdq + idiv ebx +;;;;;;;; сейчас частное в eax, а остаток в edx +;получим кол-во секторов, и можем уже определить тип FAT которую нужно делать. + cmp eax, 4085 + jb .fat12 + cmp eax, 65525 + jb .fat16 +;;;;;;;;;;;;;;;;;;;;;;;; тут fat32 + mov set_ramfs, 32 ;установим тип файловой системы + mov word [fat12_buffer.BPB_RsvdSecCnt], 32 + xor eax, eax + mov word [fat12_buffer.BPB_RootEntCnt], ax + mov word [fat12_buffer.BPB_TotSec16], ax + mov dword [fat12_buffer.BPB_TotSec32], eax + + +.fat16: ;fat16 +;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000). + jmp $ + mov set_ramfs, 16 ;установим тип файловой системы + movzx ebx, byte [fat12_buffer.BPB_SecPerClus] + imul eax, ebx + + cmp eax, 0x10000 + jae @f + mov word [fat12_buffer.BPB_TotSec16], ax + mov dword [fat12_buffer.BPB_TotSec32], 0 +@@: +;количество секторов занимаемое одной копией фат +; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ?? +;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число +;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно +;быть 0. Пока константа, нужно будет позже доделать. + mov eax, root_dir_entry_count + mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) +;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб +;;;;;;; +;Для FAT16 это количество секторов одной FAT. Для FAT32 это значение +;равно 0, а количество секторов одной FAT содержится в BPB_FATSz32. +;RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec; + +;TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors); +;TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs; +;If(FATType == FAT32) +; TmpVal2 = TmpVal2 / 2; +;FATSz = (TMPVal1 + (TmpVal2 - 1)) / TmpVal2; +;If(FATType == FAT32) { +; BPB_FATSz16 = 0; +; BPB_FATSz32 = FATSz; +;} else { +; BPB_FATSz16 = LOWORD(FATSz); +; /* there is no BPB_FATSz32 in a FAT16 BPB */ +;} +;===================================== +;RootDirSectors + movzx ebx, word [fat12_buffer.BPB_BytsPerSec] + imul eax, 32 + add eax, ebx + dec eax + + cdq + idiv ebx +;;;;;;;; сейчас частное в eax, а остаток в edx для дискеты 1.44 у нас должно быть значение =14 +;BPB_ResvdSecCnt + RootDirSectors + movzx ebx, word [fat12_buffer.BPB_RsvdSecCnt] + add ebx, eax + +;DskSize у нас это значение уже получено и доступно + movzx eax, word [fat12_buffer.BPB_TotSec16] ;должен быть в секторах + sub eax, ebx + + +;TmpVal1=eax + shl edi, 8 ;=edi*256 + movzx ecx, byte [fat12_buffer.BPB_NumFATs] + add edi, ecx +;TmpVal2=edi + add eax, edi + dec eax + cdq + idiv edi +;FATSz = сейчас частное в eax, а остаток в edx + mov word [fat12_buffer.BPB_FATSz16], ax + + + + + + + + +.fat12: ;fat12 +if DEBUG +; выведем в отладке, что собираемся делать образ диска c FS=fat12 + pushad + mov si, start_making_FAT12_msg + call printplain + popad +end if + + + +;Для FAT12 и FAT16 дисков это поле содержит количество секторов, а BPB_TotSec32 равно 0, если значение <умещается> (меньше 0x10000). + mov set_ramfs, 12 ;установим тип файловой системы + movzx ebx, byte [fat12_buffer.BPB_SecPerClus] + imul eax, ebx + + cmp eax, 0x10000 + jae @f + mov word [fat12_buffer.BPB_TotSec16], ax + mov dword [fat12_buffer.BPB_TotSec32], 0 +@@: +;количество секторов занимаемое одной копией фат +; mov word [fat12_buffer.BPB_FATSz16],0x9 ;Для FAT12/FAT16 это количество секторов одной FAT. ?? +;;;; заполним BPB_RootEntCnt Для FAT12 и FAT16 дисков, это поле содержит число +;32-байтных элементов корневой директории. Для FAT32 дисков, это поле должно +;быть 0. Пока константа, нужно будет позже доделать. + mov eax, root_dir_entry_count + mov word [fat12_buffer.BPB_RootEntCnt], ax ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) +;по документации рекомендуют отрезать 16 кб для рут дир но это оч много, даже для коос. имхо для начала хватит и 7 кб +;;;;;;; +;DskSize(в секторах)*12 (размерность файловой системы, т.е предположим сколько битов потребуется для адресации этого объема) /8 (что получить размер в байтах) +;полученное число округляем в большую сторону кратное сектору т.е. 512 байт Такой подход не универсален, но пока пойдет +;вообще у мелкософт это все считается ручками, но мы будем юзать только под коос рам диск с фат12 + movzx eax, word [fat12_buffer.BPB_TotSec16] + imul eax, 12 + shr eax, 3 ;делим на 8 но т.е. нам нужно делить еще и на 512 или более в зависимости от размеров кластера + movzx ebx, word [fat12_buffer.BPB_BytsPerSec] ;размер сектора + cdq + idiv ebx ;разделим на размер кластера +;сейчас у нас в eax значение его нужно округлить в большую сторону кратному 512 байтам +;применим следующее очистим and и добавим 512 байт. таким образом выравним на 512 байт +;но т.к. все равно делить нижний код нам не нужен +; and eax,0xfff200 +; add eax,0x200 ;добавим 512 байт для 1.44 дискеты идеально подходит )) + + inc ax +;по идее должно на каждую фат таблицу +;резервироваться 9 секторов т.е. получается 2*9=18+1 =19 секторов т.е. рут дир находиться на с 20 сетора т.е. с адреса 0х2600 +;сейчас нужно вычислить сколько будет секторов занимать фат ) нужно разделить на 512 +;FATSz = сейчас частное в eax + mov word [fat12_buffer.BPB_FATSz16], ax +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get_firstDataSector ;получить смещение до данных +;создадим певую запись в фат по определенному адресу. +first_create_fat_table +;закиним BPB файловой системы за 1 мб. +use_BPB_RAM +; +;копирование файла. +use_RamdiskFile + +;;;; вычисляем указатель на корневую дир FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16); +; movzx ebx, [fat12_buffer.BPB_NumFATs] +; movzx eax,ax +; imul eax,ebx +;eax=(BPB_NumFATs * BPB_FATSz16) +; inc eax +; BPB_ResvdSecCnt значение только 1 для fat12/16 +;в eax указатель на root dir. для дискеты fat12 должно получиться при кол-во копий fat 1 = 1+ (1*1) =2 или 3 + +if DEBUG + pusha +; mov ax,point_default +; mov ax,cx + mov cx, 0x0a + mov di, show_db1 +; mov dword[ds:di],' ' +; mov word [ds:di+4],' ' + call decode +;Show size + mov si, show_db1 + call printplain +; +; xor ax,ax +; int 0x16 + popa +end if + + + + + + + +} + +macro use_RamdiskSector +{ +;для некоторых FS будет игнорироваться + mov di, point_default ;restore value + mov cx, save_cx_d + +.start_RamdiskSector: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz .end_RamdiskSector ;нету? ну ладно - следующее значение тогда ) + + cmp al, 'R' + jnz .start_RamdiskSector +;проверка на значения RamdiskSize +; parse_RamdiskSize + + mov bx, cx + mov ax, di + + mov si, parse_RamdiskSector + mov cx, parse_RamdiskSector_e - parse_RamdiskSector + repe cmpsb + jnz .RamdiskSector_rest_val ;is not compare + + sub bx, parse_RamdiskSector_e - parse_RamdiskSector;correct cx + add bx, cx + mov cx, bx + + test status_flag, flag_found_RamdiskSector ;оценка флагов + jz .correct_is_not_set_RamdiskSector + +; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем +; call printplain +; jmp .get_next_str + +.correct_is_not_set_RamdiskSector: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + jcxz .end_get_RamS_ERROR_1 ;not found param + + cmp ah, byte [es:di-1] ;find '=' + jnz .start_RamdiskSector ; перейдем на начало и попробуем найти еще секцию + + repe scasb ;cut ' ' + inc cx + dec di +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + xor bx, bx + mov cx, 4 +@@: + movzx ax, byte [es:di] + cmp al, '0' + jb .end_RamdiskSector + cmp al, '9' + ja .end_RamdiskSector +;;;;;;;;;;;;;;;;;;; + + imul bx, 10 + xor al, 0x30 + add bx, ax + + inc di + + loop @b + jmp .end_RamdiskSector + + +.RamdiskSector_rest_val: + mov cx, bx + mov di, ax + jmp .start_RamdiskSector +.end_get_RamS_ERROR_1: + +.end_RamdiskSector: + mov ax, bx + +if DEBUG + pusha + movzx eax, bx;save_cx_d;point_default + mov cx, 0x0a + mov di, RamdiskSector_msg + mov dword[ds:di], ' ' + mov dword [ds:di+4], ' ' + call decode +;Show size + mov si, RamdiskSector_msg + call printplain + + popa +end if + +; pop di +; pop es +} + +macro use_RamdiskCluster +{ +;для некоторых FS будет игнорироваться +; push es +; push di + mov di, point_default ;restore value + mov cx, save_cx_d +; push ini_data_ +; pop es +.start_RamdiskCluster: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz .end_RamdiskCluster ;нету? ну ладно - следующее значение тогда ) + cmp al, 'R' + jnz .start_RamdiskCluster +;проверка на значения RamdiskSize +; parse_RamdiskSize + + mov bx, cx + mov ax, di + + mov si, parse_RamdiskCluster + mov cx, parse_RamdiskCluster_e - parse_RamdiskCluster + repe cmpsb + jnz .RamdiskCluster_rest_val ;is not compare + + sub bx, parse_RamdiskCluster_e - parse_RamdiskCluster;correct cx + add bx, cx + mov cx, bx + + test status_flag, flag_found_RamdiskCluster ;оценка флагов + jz .correct_is_not_set_RamdiskCluster + +; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем +; call printplain +; jmp .get_next_str + +.correct_is_not_set_RamdiskCluster: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + jcxz .end_get_RamSC_ERROR_1 ;not found param + + cmp ah, byte [es:di-1] ;find '=' + jnz .start_RamdiskCluster ; перейдем на начало и попробуем найти еще секцию + + repe scasb ;cut ' ' + inc cx + dec di +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +@@: + movzx ax, byte [es:di] + cmp al, '0' + jb .end_RamdiskCluster + cmp al, '9' + ja .end_RamdiskCluster +;;;;;;;;;;;;;;;;;;; + xor al, 0x30 + + jmp .end_RamdiskCluster + + +.RamdiskCluster_rest_val: + mov cx, bx + mov di, ax + jmp .start_RamdiskCluster +.end_get_RamSC_ERROR_1: + +.end_RamdiskCluster: +if DEBUG + pusha + mov cx, 0x0a + mov di, RamdiskCluster_msg +; mov word[ds:di],' ' + call decode +;Show size + mov si, RamdiskCluster_msg + call printplain + + popa +end if + +} + +macro use_Loader_Image +;предназначен для загрузки образов выше 1 Мб. +;первоначальная версия загружает образ дискеты 1.44 мб +{ +local .start_p_LI +local .exit +local .error_LI +local .rest_value_loop +local .found_end_str + mov di, point_default ;restore value + mov cx, save_cx_d +;обработка конструкции типа LoaderModule=kord/kolibri.ldm +.start_p_LI: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz .exit ;нету? ну ладно - следующее значение тогда ) + cmp al, 'L' + jnz .start_p_LI +;проверка на значение LoaderModule +; parse_LoaderModule + mov bx, cx + mov ax, di + + mov si, parse_LoaderImage + mov cx, parse_LoaderImage_e - parse_LoaderImage + repe cmpsb + jnz .rest_value_loop ;is not compare + + sub bx, parse_LoaderImage_e - parse_LoaderImage;correct cx + add bx, cx + mov cx, bx + +; test status_flag,flag_found_LM ;оценка флагов +; jz .correct_is_not_set_LI + +; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем +; call printplain +; jmp .get_next_str + +;.correct_is_not_set_LI: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + jcxz .rest_value_loop_LI ;not found param timeout + + cmp ah, byte [es:di-1] ;find '=' + jnz .rest_value_loop_LI + + repe scasb ;cut ' ' + inc cx + dec di +;di указывает на начало блока информации, в cx длинна до конца секции. +;после загрузки заноситься значение занятой памяти. +;для того что бы загрузить модуль, воспользуемся callback сервисом +;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0 +;это выглядит так: в ini файле существует строчка LoaderModule = kord/kernel.loader +;мы ее модифицируем до такого состояния dw,dw,db'kord/kernel.loader',0 конечно сохранив те значения которые мы заменяем +;сохранили певые 2 word + push dword [es:di-6] + lea si, [di-6] + + push word [es:di-2] + xor ax, ax + mov word [es:di-6], ax ;вносим нужные значения +;info_real_mode_size размер и указатель на область в которую можно загрузиться + mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными + + + mov word [es:di-4], ax + mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не считаем +;;;;;; поиск конца строчки +@@: + mov al, byte [es:di] + cmp al, ' ' + jz .found_end_str + cmp al, 0xa + jz .found_end_str + cmp al, 0xd + jz .found_end_str + inc di + dec cx + jnz @b +;;;not found допустим,что это конец файла и он не имеет привычного заверешния строки +.found_end_str: +; чтение блока по 64 кб в сегмент и забрасывание его выше 1 мб. + push word [es:di] + xor ax, ax + mov word [es:di], ax +; xor ax,ax ; function 1 - read file + mov di, si ;file_data + inc ax + push si + push es + call far dword [loader_callback] + push cs + pop ds + + pop es + pop si + + test bx, bx + jnz .error_LM + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; забрасывание блока в 64 кб выше 1 мб. + mov si, table_15_87 + push es + push ds + pop es + mov cx, 256*18 + mov ah, 0x87 + int 0x15 + pop es + pop dx cx + test ah, ah + + + + jmp far dword [es:si] + + + + +.rest_value_loop: + mov di, ax + mov cx, bx + jmp .start_p_LI + +.exit: + + + +} + + + +macro name_in_root_fat +;макрос, который записывает информацию о загруженном файле в корневую фат таблицу +{ + +} + + + +macro use_RamdiskFile +{ +;загрузка файлов с использование callback сервиса первичного загрузчика +;используется только для загрузки необходимых и небольших файлов, т.к. достаточно медленно работает +;для загрузки использует 0х87 функцию int 0x15 прерывания - загрузка блоков данных до 64 кб выше 1 мб +local .start_loop +local ._end +local .rest_value_loop +local .error + mov di, point_default ;restore value + mov cx, save_cx_d + mov data_offset, 0 ;clean offset +;обработка конструкции типа LoaderModule=kord/kolibri.ldm +.start_loop: + call get_firs_sym ;get first symbol on new line + test cx, cx + jz ._end ;нету? ну ладно - следующее значение тогда ) + cmp al, 'R' + jnz .start_loop +;проверка на значение RamdiskFile + mov bx, cx + mov ax, di + + mov si, parse_RamdiskFile + mov cx, parse_RamdiskFile_e - parse_RamdiskFile + repe cmpsb + jnz .rest_value_loop ;is not compare + + sub bx, parse_RamdiskFile_e - parse_RamdiskFile;correct cx + add bx, cx + mov cx, bx +; test status_flag,flag_found_LM ;оценка флагов +; jz .correct_is_not_set_LM + +; mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем +; call printplain +; jmp .get_next_str + +;.correct_is_not_set_LM: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + test ecx, ecx + jz .rest_value_loop ;not found param timeout + + cmp ah, byte [es:di-1] ;find '=' + jnz .rest_value_loop + + repe scasb ;cut ' ' + inc cx + dec di + + mov save_di_RAMDISK, di + mov save_cx_RAMDISK, cx +;di указывает на начало блока информации, в cx длинна до конца секции. +;после загрузки заноситься значение занятой памяти. +;для того что бы загрузить модуль, воспользуемся callback сервисом +;оригинальное решение - разместим dd перед строчкой и после строчки разместим byte =0 +;это выглядит так: в ini файле существует строчка RamdiskFile = @menu,@menu +;мы ее модифицируем до такого состояния dw,dw,db'@menu',0 конечно сохранив те значения которые мы заменяем +;сохранили певые 2 word + +; +@@: + mov al, byte [es:di] + cmp al, ',' ; т.е. ищем разделитель + jz .found_end_str + inc di + dec cx + jnz @b +;;;not found допустим,что это конец файла и он не имеет привычного завершения строки +.found_end_str: +; mov al,byte [es:di] +; cmp al,' ' ; убираем пробелы, если они есть +; jnz @f +; inc di +; dec cx +; jnz .found_end_str + +;@@: + mov point_to_dest_file_name, di + inc di +;проверка индивидуальности имени файла +check_name_file +;/restore di - point and cx -size section + mov di, save_di_RAMDISK + mov cx, save_cx_RAMDISK + + test al, al + jnz .start_loop ;если в al значение не =0, то такое имя уже существует в системе. + + + + push dword [es:di-6] + lea si, [di-6] + + push word [es:di-2] + push di + xor ax, ax + mov word [es:di-6], ax ;вносим нужные значения +;info_real_mode_size размер и указатель на область в которую можно загрузиться + mov ax, info_real_mode_size ;0x3000 ;следующий сегмент за данными + + + mov word [es:di-4], ax + mov word [es:di-2], 16 ;кол-во блоков по 4 кб =64 кб т.е. больше не читаем + + mov di, point_to_dest_file_name + +if DEBUG + pushad +; mov ax,di + mov cx, 0x0a + mov di, name_of_seg_get_64 + mov dword[ds:di], ' ' + mov word[ds:di+4], ' ' + call decode +;Show size + mov si, name_of_seg_get_64 + call printplain + + popad +end if + + push word [es:di] + push cx + xor ax, ax + mov word [es:di], ax +; xor ax,ax ; function 1 - read file + push di + mov di, si ;file_data + inc ax + push si + push es + push bp + + push es + pop ds + push cs + pop es + + call far dword [es:loader_callback] + + + push cs + pop ds + + pop bp + pop es + pop si + + cmp bx, 2 + ja .error +; сейчас у нас в dx:ax размер файла, который мы загрузили. +; возможна ситуация, когда в bx=1 т.е. есть еще данные на диске + mov status_flag_loader_f, bx + + shl edx, 16 + mov dx, ax +; shr edx,10 ;размер файла в кб. +;;в edx размер в байтах. + mov save_file_size, edx + mov eax, edx +;восстановим полностью файл сценария + pop di + pop cx ;длинна остатка с 2-ой частью имени т.е. с именем назначением. + pop word [es:di] + pop di + pop word [es:di-2] + pop dword [es:di-6] + + +if DEBUG + pushad + mov cx, 0x0a + mov di, RamdiskFile_msg + mov dword[ds:di], ' ' + call decode +;Show size + mov si, RamdiskFile_msg + call printplain + + popad +end if + + + + + + + + + + +; загрузим чему у нас равен кластер +; mov ax,word [fat12_buffer.BPB_BytsPerSec] ;кол-во байтов в секторе может быть любое 512 1024 2048 4096 2 байта +; movzx bx,byte [fat12_buffer.BPB_SecPerClus] ;кол-во секторов в кластере +; imul ax,bx +;сейчас в eax размер кластера (512) байт +;в edx длина файла в байтах до 64 кб +;закиним файл за 1 мб +;1 нам нужно составить фат таблицу т.е. произвести разметку рамдиска, затем перенесем по адресу файл + +;записать инфорамацию о файле в корневую директорию +register_file_in_fat +;перенести за 1 мб содержимое файла +move_file_up + +;проверим, загружен ли до конца файл? т.е. если размер файла больше чем 64 кб, то будет подгружать оставшиеся блоки + cmp status_flag_loader_f, 0x1 + jnz @f +;нужно дозагузить данные файла и перенести их за 1-ый мб согласно фат структуре + + + + + + + + + +@@: +;тут организован цикл по загрузке файлов в корневую директорию + mov di, save_di_RAMDISK + mov cx, save_cx_RAMDISK +if DEBUG + pusha + xor ax, ax + int 0x16 + popa +end if + + + jmp .start_loop + + +.error: + ;call error.LoaderModule +;fixme! +.rest_value_loop: + mov di, ax + mov cx, bx + jmp .start_loop + +._end: +;перенесем за 1-ый мб фат и рут дир +move_up_fat_and_root_d + + + + + + +;загрузка блока +; mov ah,0x87 +; mov cx, ;size in byte + + +;es:si point to descripts + + +} + +macro use_BPB_RAM ;закинуть самые первые 512 байт за 1-й мб +;данный макрос закидывает BPB структуру т.е. первые 512 байт, пока только фат12 за 1 мб +{ + mov ax, fat12_buffer + mov si, table_15_87 + add word [si+8*2+2], ax + push es + push ds + pop es + mov cx, 256 ;бут сектор укладывается в 512 байт 512/2=256 + mov ah, 0x87 + int 0x15 + pop es +;add 512 byte for destination adress +; add dword [si+8*3+2], 512 +; test ah, ah +; jz +if DEBUG + pusha + mov ax, word [si+8*2+2] + mov cx, 0x0a + mov di, BPB_msg + call decode +;Show size + mov si, BPB_msg + call printplain + popa +end if +} +macro first_create_fat_table +;данный макрос создает оформляет 3 первых байта fat таблицы, и устанавливает указатель на следующий блок, и вносит 0 значение +;для смещения в корневой таблице. +{ + mov al, byte [fat12_buffer.BPB_Media] + + + push ds + + + mov di, info_real_mode_size + add di, 0x1000 + +if DEBUG + pushad + + mov ax, info_real_mode_size + add ax, 0x1000 +; mov ax,ds + mov cx, 0xa + + mov di, first_entry_in_fat + mov dword [di], ' ' + mov word [di+4], ' ' + call decode +;Show size + mov si, first_entry_in_fat + call printplain + + xor ax, ax + int 0x16 + + popad +end if + + + push di ; push word info_real_mode_size+0x1000 ;cледующий сегмент за загруженным участком + + xor di, di + mov point_to_free_root, di ;значение смещения =0 в корневой фат таблице описания + + pop ds ; загружен следующий сегмент т.е. пустой сегмент + + mov byte [di], al + or ax, -1 + inc di + mov word [di], ax + + pop ds + mov point_next_fat_str, 3 + +if DEBUG + pushad + mov ax, point_next_fat_str + mov cx, 0x0a + mov di, fat_create_msg + call decode +;Show size + mov si, fat_create_msg + call printplain + popad +end if + +} +macro register_file_in_fat +;макрос регистрации файла в файловой структуре Fat +;пока поддерживается только фат12, пока )) +;вычисление смежных кластеров и занесение инфы в fat/ +{ +local .step2 +local .step3 +local .end +local .eof_file + +;di point on root dir на фри секцию. + push es + + mov ax, info_real_mode_size + add ax, 0x1000 + mov es, ax ; push word info_real_mode_size+0x1000 ;сегмент следующий за загруженным блоком в 64 кб + +; определяем тип фат пока не определяем, пока только фат 12 +; 12 бит, для вычесления соседних каластеров. + mov di, firstDataSect ;в секторах + sub di, size_root_dir +;теперь в ax размер в секторах начала рут дир + shl di, 9;imul 512 + add di, point_to_free_root ;смещение в уже записанных 32-х структурах. +;необходимо внести значение в рут дир т.е. 32 байта +if DEBUG + pushad +; mov ax,point_default +; mov ax, + mov cx, 0x0a + mov di, show_db2 + mov dword[ds:di], ' ' + mov word [ds:di+4], ' ' + call decode +;Show size + mov si, show_db2 + call printplain +; +; xor ax,ax +; int 0x16 + popad +end if + + + +;gs:di - указатель для внесения инфорации в рут область фат таблицы инормации о файле. + mov si, shot_name_fat + mov cx, 11 +;запишем в структуру имя +@@: + lodsb + stosb + loop @b + +;запишем атрибуты файла и DIR_NTRes - зарезеврированный байт =0 + xor ax, ax + mov ah, ATTR_VOLUME_ID + mov word [es:di], ax + add di, 2 +;DIR_CrtTimeTenth + mov byte [es:di], 100 + inc di +;DIR_CrtTime + mov word [es:di], 0x032b ;дата + add di, 2 +;DIR_CrtDate + mov word [es:di], 0x0 ;время >< + add di, 2 +;DIR_LstAccDate + mov word [es:di], 0x032b ;дата моего + add di, 2 +;DIR_FstClusHI + mov word [es:di], 0x0 ;время для фат12 /16 всегда 0 + add di, 2 +;DIR_WrtTime + mov word [es:di], 0x0 ;время >< + add di, 2 +;DIR_WrtDate + mov word [es:di], 0x032b + add di, 2 + + mov ax, point_next_fat_str + mov word [es:di], ax + add di, 2 + + push di +;DIR_FstClusLO Младшее слово номера первого кластера. + ; mov ax,point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи +;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат + mov bx, ax + shr bx, 1 + add ax, bx +;в ах сейчас FATOffset +;ThisFATEntOffset = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec); + mov bx, word [fat12_buffer.BPB_BytsPerSec] + cwd + idiv bx +;ax=ThisFATEntOffset= rem (FATOffset / BPB_BytsPerSec) четный или нечетный указатель. + mov si, ax +;нам нужно в цикле записать все кластеры которые будут использованы для размещения файла. +;узнаем размер кластера. + movzx eax, word [fat12_buffer.BPB_BytsPerSec] + movzx ebx, byte [fat12_buffer.BPB_SecPerClus] + imul eax, ebx +;ax - размер кластера. +;сейчас будем записывать во временный буфер фат таблицу для выбранного файла. Поскольку мы его загрузили возможно не полностью +;мы обработаем запись для фат полностью, в не зависимости от предела буфера где возможна часть файла. + mov ebx, save_file_size ;размер файла в байтах + +@@: + sub ebx, eax + cmp ebx, eax + jbe .eof_file + + inc point_next_fat_str + mov cx, point_next_fat_str ;загрузим указатель на элемент фат таблицы т.е. это номер фат записи +;FATOffset = N + (N / 2) т.е. это уже у нас смещение мы знаем что -начинается все с 3-го элемента записи фат + mov dx, ax + shr dx, 1 + add cx, dx + + + + test si, 0x1 + jz .step2 + shl cx, 4 + mov word[es:si], cx + inc si + add cx, ax + jmp @b + +.step2: + and cx, 0x0FFF + mov word[es:si], cx + inc si + add cx, ax + jmp @b + +.eof_file: + mov cx, 0x0fff + test si, 0x1 + jz .step3 + shl cx, 4 + mov word[es:si], cx + jmp .end + +.step3: + and cx, 0x0FFF + mov word[es:si], cx + +.end: + inc point_next_fat_str + + pop di +;DIR_FileSize 32-битный DWORD содержит размер файла в байтах. + mov eax, save_file_size + mov dword [es:di], eax + +if DEBUG + pushad + + mov di, firstDataSect ;в секторах + sub di, size_root_dir +;теперь в ax размер в секторах начала рут дир + shl di, 9;imul 512 + add di, point_to_free_root ;смещение в уже записанных 32-х структурах. + + push di + + mov si, dest_name_fat + mov cx, 11 + +;запишем в структуру имя +@@: + mov al, byte [es:di] + inc di + mov byte [ds:si], al + inc si + loop @b + + mov di, si + inc di + pop ax + mov cx, 0xa + call decode + + mov si, dest_name_fat + call printplain + popad + +END IF + + + + + + add point_to_free_root, 32 ;увелицим смещение до следующего значения. + pop es + +} + + + + + +macro get_firstDataSector +;макрос для вычисления певого сектора данных т.е. данных файлов в фате +;вычислим FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors; +{ + mov ax, word [fat12_buffer.BPB_FATSz16] + movzx bx, byte [fat12_buffer.BPB_NumFATs] + imul ax, bx ;9x1=9 +;ax=BPB_NumFATs * FATSz + mov bx, word [fat12_buffer.BPB_RootEntCnt] ; count of 32-byte dir. entries (224*32 = 14 sectors= 7 kb) + shr bx, 4 ;imul bx,32 and then div 512 -> in bx size in sectors + add ax, bx ;9+14=23 + mov size_root_dir, bx + movzx bx, byte [fat12_buffer.BPB_RsvdSecCnt] ;add 1 for fat 16/12 + add ax, bx +;ax=firstDataSector - где начинается первый секторо от 0 сектора в секторах. - фактически = 24 сектор + mov firstDataSect, ax ;сохраним для вычисления +; получимзначение кластеров, это объем в который мы можем записать данные + mov bx, word [fat12_buffer.BPB_TotSec16] + sub bx, ax + mov ax, bx + movzx bx, byte [fat12_buffer.BPB_SecPerClus] + cwd + idiv bx + mov DataClasters, ax + +if DEBUG + pushad + mov ax, firstDataSect ;первый сектор данных + mov cx, 0x0a + mov di, firstDataSect_msg + call decode +;Show size + mov si, firstDataSect_msg + call printplain +;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, size_root_dir ;размер рут дир в сетокторах + mov cx, 0x0a + mov di, size_root_dir_msg + call decode +;Show size + mov si, size_root_dir_msg + call printplain +;;;;;;;;;;;;;;;;;;;;;;;;;; + mov ax, DataClasters;кластеры + mov cx, 0x0a + mov di, DataClasters_msg + call decode +;Show size + mov si, DataClasters_msg + call printplain + popad + +end if + +} + +macro use_RamdiskPATHS +;парсинг пути источника файлов. +{ + +} + +macro use_RamdiskPATHD +;парсинг пути назначения файлов. +{ + +} +macro check_name_file +;макрос проверки имени на повтор, имя должно быть уникальным. +;входные данные: es- сегмент где лежит файл для парсинга т.е. startos.ini +;di - указатель на имя файла т.е. es:di указывает на имя файла назначения +;выходные данные eax =-1 имя совпало, eax=0 имя не совпало. +{ +local .no_equal +local .exit +local .loop_size_root_dir +;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными. +;преобразуем в аналог фат записи сточку с именем назначения + convertion_file_name ; преобразовали имя по нужным правилам + test ax, ax + jnz .exit + + lea si, [shot_name_fat] ; desination name of file + +;вычислим указатель на корневую директорию + mov di, firstDataSect + sub di, size_root_dir +;теперь в ax размер в секторах начала рут дир + shl di, 9;imul 512 +;di= Это смещение от начала буфера до рут директории. в пределах 64 кб. +;загрузим значение - т.е. кол-во элементов, которые мы можем просматривать. + mov dx, root_dir_entry_count + + mov ax, info_real_mode_size + add ax, 0x1000 + + + mov gs, ax +.loop_size_root_dir: +DEBUG1 equ 0 +if DEBUG1 + pushad + push di + mov eax, dword[gs:di] + lea si, [check_root_fat_+14] + mov dword [ds:si], '----' + mov dword [ds:si+4], '----' + mov dword [ds:si+8], '----' + mov dword[ds:si], eax + mov eax, dword[gs:di+4] + mov dword[ds:si+4], eax + mov eax, dword[gs:di+8] + mov dword[ds:si+8], eax + +; + xor eax, eax + mov ax, gs;point_next_fat_str + mov cx, 0x0a + mov di, check_root_fat_ + mov dword [di], ' ' + mov word [di+4], ' ' + call decode + xor eax, eax + pop ax + mov di, (check_root_fat_+7) + mov dword [di], ' ' + mov word [di+4], ' ' + call decode + +;Show size + lea si, [check_root_fat_] + call printplain + + lea si, [shot_name_fat] + call printplain + + xor ax, ax + int 0x16 + popad +end if + + xor bx, bx + mov cx, 11 ;size of name in struct FAT + +@@: + mov al, byte [ds:si+bx] ;ds:si - point to name of convertion variable. + mov ah, byte [gs:di+bx] ;gs:di - point to name in fat struct + inc bx + +if DEBUG +; pushad +; lea si,[check_root_fat_+14] +; mov dword [ds:si],'----' +; mov word [ds:si],ax +; call printplain + +; xor ax,ax +; int 0x16 + +; popad +end if + + + + cmp ah, al + jnz .no_equal + +; dec cx +; jnz @b + loop @b + +;.succesfuly: +;печально, такое имя уже имеется :( + or ax, -1 + jmp .exit + + +.no_equal: + add di, 32 ;fat struct =32 byte + dec dx + jnz .loop_size_root_dir + +;.exit_check_name: + and ax, 0 + +.exit: + +if DEBUG + pushad +;Show size + lea si, [check_name_fat_msg_n] + test ax, ax + jz @f + lea si, [check_name_fat_msg_y] + call printplain + lea si, [alarm_msg] +@@: + call printplain + popad +end if + +} + + +macro convertion_file_name +;макрос конвертации имени, это нужно поскольку формат представленный не соответсвует фат и напрямую редко можно когда использовать +;преобразование имени типа hello.asm в 'HELLO ASM', в соответствии с правилами fat. +;входные параметры es:di указатель на имя файла которое нужно преобразовать, конечный буфер shot_name_fat +{ +local .next_step +local .error +local .st1 +local .st2 +local .st2_l +local .st3 +local .st4_s +local .st4 +local .st5 + +;вычислим длинну строчки имени назначения, которую будем сравнивать с уже записанными данными. +; mov di,point_to_dest_file_name входной параметр + mov si, shot_name_fat + or first_input, -1 ;при первом входе устанавливаем флаг + mov cx, 11 ;длинна имени в стуктуре фат таблицы + +@@: + mov al, byte [es:di] + cmp al, 0xa + jz .st4_s + cmp al, 0xd + jz .st4_s + cmp al, 0x20 + jz .st4_s + + cmp al, 0x20 + jb .error + cmp al, 0x22 + jz .error + cmp al, 0x2a + jz .error + cmp al, 0x2b + jz .error + cmp al, 0x2c + jz .error + cmp al, 0x2F + jz .error + + cmp al, 0x3a + jz .error + cmp al, 0x3b + jz .error + cmp al, 0x3c + jz .error + cmp al, 0x3d + jz .error + cmp al, 0x3E + jz .error + cmp al, 0x3F + jz .error + + cmp al, 0x5b + jz .error + cmp al, 0x5c + jz .error + cmp al, 0x5d + jz .error + + cmp al, 0x7c + jz .error + + + cmp first_input, -1 + jnz .next_step + and first_input, 0 ;сборосим флаг. + cmp al, '.' + jz .error ;обработка точки, файл не может начинаться с точки + +.next_step: + cmp al, 0x2e + jnz .st2 ;обработка точки, в середине файла +;тут у нас установлен разделитель +;все остальнео место займут пробелы + mov al, ' ' + +;!fixme обработаны не все исключения :( + cmp cl, 3 ;формат файла такой GIDGIDIIASM т.е. gidgidii.asm + jbe .st2 + + +.st3: + mov byte [si], al + inc si + dec cx + cmp cx, 3 + ja .st3 +; inc cx + inc di + jmp @b + +.st2: + cmp al, 0x60 + jbe .st2_l + + xor al, 0x20;сделаем заглавные буквы +.st2_l: + mov byte [si], al + inc di + inc si +; dec cx +; jnz @b + loop @b +.st5: + xor ax, ax + jmp @f + +;;;;;;;;файл закончился, и нужно внести в конец пробелы +.st4_s: + mov al, ' ' +.st4: + mov byte [si], al + inc si + loop .st4 + jmp .st5 + +.error: + or ax, -1 +@@: + +if DEBUG + pushad + + mov si, convertion_file_name_msg_y + test ax, ax + jz @f + mov si, convertion_file_name_msg_n +@@: + call printplain + + mov si, shot_name_fat + mov byte [si+12], 0 + call printplain + popad + +end if +} + +macro move_file_up +;макрос который перемещает за 1 мб с правилами фат данные файла. +{ +local .st1 +local .correct_on_byte +;сейчас имеет быть ситуация, когда BPB уже перемещен за 1 мб, фат, и рут дир будут позже перемещены, +;а нам нужно вычислить место, и перенести туда содержимое файла +;полученое значение указывает в байтах на начало данных + + mov ax, info_real_mode_size ; сегмент где расположены данные + mov si, table_15_87 + mov word [si+8*2+2], ax +;смещение до данных уже за 1-м мб + movzx eax, firstDataSect + movzx edx, data_offset + add eax, edx + + movzx ebx, word [fat12_buffer.BPB_BytsPerSec] + movzx edx, byte [fat12_buffer.BPB_SecPerClus] + imul bx, dx ;получим размер кластера + + + + push ebx ;save bx + + imul eax, ebx +; shl eax,9 ;умножим на 512 + +if DEBUG + pushad + xor eax, eax + mov ax, info_real_mode_size + mov cx, 0x0a + mov di, seg_where_get_data + mov dword [di], ' ' + mov word [di+4], ' ' + call decode +;Show size + mov si, seg_where_get_data + call printplain + popad + +end if + +; mov bx,word [fat12_buffer.BPB_BytsPerSec] +; movzx dx,byte [fat12_buffer.BPB_SecPerClus] +; imul bx,dx +; cwd +; idiv bx + + mov dl, 0x10 + +@@: + cmp eax, 0x00010000 + jb @f + + sub eax, 0x00010000 + inc dl + jmp @b + + +@@: + mov byte [si+8*3+3], dl ;куда писать + mov word [si+8*3+2], ax + + mov ecx, save_file_size ;размер файла в байтах. + cmp ecx, 0x0000ffff ;размер блока т.е. 64 кб + jbe .correct_on_byte ;корректировка на байт значения + + + + mov ecx, 0x00010000 ;65536 + sub save_file_size, ecx ;отнимим +; jmp .st1 ;получим 0х8000 + + + + +;корректировка значения должна быть выполенена на размер кластера +.correct_on_byte: +;/узнаем размер кластера + pop eax ;restore size of claster + push ecx +@@: + inc data_offset + + cmp eax, ecx + jae @f + sub ecx, eax + jmp @b +@@: + pop ecx + + + + + test ecx, 0x1 + jz .st1 + inc ecx +.st1: + shr ecx, 1 ; преобразовать значение для 0x87 function + +;перенесем блок за 1 мб + push es + push ds + pop es + + mov ah, 0x87 + int 0x15 + pop es + +if DEBUG + pusha +; mov ax,point_next_fat_str + mov cx, 0x0a + mov di, return_code_af_move + call decode +;Show size + mov si, return_code_af_move + call printplain + popa + +end if + +} + + +macro move_up_fat_and_root_d +;макрос, который позволяет перенести выше 1 мб в структуру образа фат таблицу и рут директорию +{ +local .st1 + + mov ax, info_real_mode_size + add ax, 0x1000 + + mov si, table_15_87 + mov word [si+8*2+2], ax +;смещение до данных + mov ax, 512 + mov word [si+8*3+2], ax +;fixme! тут необходимо сделать подержку т.е. формировать смещение файла в уже записанных данных. + + movzx ecx, word [fat12_buffer.BPB_FATSz16] + movzx bx, byte [fat12_buffer.BPB_NumFATs] + imul cx, bx ;9x1=9 + + add cx, size_root_dir ;размер корневой дирректории + shl ecx, 9 ;imul 512 + + +;корректировка значения + test ecx, 0x1 + jz .st1 + inc ecx +.st1: + shr ecx, 1 + + push es + push ds + pop es + + mov ah, 0x87 + int 0x15 + pop es + +if DEBUG + pusha +; mov ax,point_next_fat_str + mov cx, 0x0a + mov di, return_code_af_fat_m + call decode +;Show size + mov si, return_code_af_fat_m + call printplain + popa + +end if + +} diff --git a/kernel/trunk/sec_loader/trunk/parse_err.inc b/kernel/trunk/sec_loader/trunk/parse_err.inc index 380c90afc..d1c9a8436 100644 --- a/kernel/trunk/sec_loader/trunk/parse_err.inc +++ b/kernel/trunk/sec_loader/trunk/parse_err.inc @@ -1,66 +1,66 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -error: -.rest_value: - mov di,ax ;restore value after repe cmpsb - mov cx,bx - jmp ret_on_ch ;return - -;///// ошибка при находжении длинны секции в параметре default -.error_get_size_d_sect: - leave ;clear array in stack - mov si,not_found_def_sect - jmp err_show_ini - -;/////ERROR -.not_loader: - leave ;clear array in stack - mov si,not_found_sec_loader - jmp err_show_ini - -.default_eq_loader: ;критическая ошибка default секция = loader - leave - mov si,default_eq_loader - jmp err_show_ini -.correct_exit_bl: - leave - mov si,point_to_default_sec_not_found - jmp err_show_ini -.incorect_section_def: - leave - mov si,incorect_section_define - jmp err_show_ini -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;show message error -.LoaderModule: - push word 0xb800 - pop es - - - - - ret \ No newline at end of file +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +error: +.rest_value: + mov di, ax;restore value after repe cmpsb + mov cx, bx + jmp ret_on_ch ;return + +;///// ошибка при находжении длинны секции в параметре default +.error_get_size_d_sect: + leave ;clear array in stack + mov si, not_found_def_sect + jmp err_show_ini + +;/////ERROR +.not_loader: + leave ;clear array in stack + mov si, not_found_sec_loader + jmp err_show_ini + +.default_eq_loader: ;критическая ошибка default секция = loader + leave + mov si, default_eq_loader + jmp err_show_ini +.correct_exit_bl: + leave + mov si, point_to_default_sec_not_found + jmp err_show_ini +.incorect_section_def: + leave + mov si, incorect_section_define + jmp err_show_ini +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;show message error +.LoaderModule: + push word 0xb800 + pop es + + + + + ret diff --git a/kernel/trunk/sec_loader/trunk/parse_loader.inc b/kernel/trunk/sec_loader/trunk/parse_loader.inc index ed229d9d9..540b4ab8d 100644 --- a/kernel/trunk/sec_loader/trunk/parse_loader.inc +++ b/kernel/trunk/sec_loader/trunk/parse_loader.inc @@ -1,332 +1,335 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -;блок макросов по обработке секции [loader] -;входные данные: -;es:di - указатель на секцию начинающиюся с '[' встечающиюся после 0хa -;cx - счетчик кол-во байт для проверке в кадре -; -macro use_parse_loader -{ -.parse_loader: -;////////////////// -;/ parse [loader] -;////////////////// - mov bx,cx ;cохраним в регистры значения счетчика и указателя - mov ax,di - -; mov word [bp-4],.start ;is alredy set, see up - mov si,parse_loader - mov cx,parse_loader_e - parse_loader - repe cmpsb - jnz error.rest_value ;цепочка не совпала :( перейдем далее т.е. будем снова искать)) - - ;сохраним указательна loader, что бы потом больше его не искать - mov point_loader,ax - sub bx,parse_loader_e - parse_loader ;correct cx - add bx,cx - mov cx,bx - -if DEBUG - pusha - mov si,lm_l_found - call printplain - popa -end if -;/////////////////end check [loader]. [loader] is found -;parsing section [loader] -;first found end section,let's found '[' -it's start next section -;in previosly steep bx =cx we are not need save cx, save only di - point - mov dx,di -@@: - call get_firs_sym - jcxz .loader_f_end ;.end_loader ; end даже если мы не нашли секцию предположим что секция [loader] стоит в конце - cmp al,'[' - jnz @b - -.loader_f_end: - sub bx,cx ;bx = n byte presend in section [loader] - mov di,dx ;restore di -;////////////////parse parametrs in section [loader] -;//timeout=5 -;//default=main -; mov di,dx ;set pointer on section [loader] i think it's not need - mov cx,bx ;set counter for parsing section [loader] cx= кол-ву символов в секции [loader] - mov ret_on_ch,.get_next_str ; return point -;;;;;;; parse timeout & default -.get_next_str: - call get_firs_sym ;get first symbol on new line - - test cx,cx - jz .end_loader -; jcxz .end_loader ;завершение парсинга значений timeout & default - cmp al,'t' - jz .loader_timeout - cmp al,'d' - jnz .get_next_str -;//////[loader].default -;input di point to data cx=size [loader] - mov bx,cx - mov ax,di - - mov si,parse_l_default - mov cx,parse_l_default_e - parse_l_default - repe cmpsb - - jnz error.rest_value ;is not compare цепочка не совпала - - sub bx,parse_l_default_e - parse_l_default ;correct cx - add bx,cx - mov cx,bx - - test status_flag,flag_found_default - jz .correct_is_not_set - - mov si,found_equal_default ;мы нашли что флаг уже установлен, информируем - call printplain - jmp .get_next_str - -.correct_is_not_set: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - test cx,cx - jz .end_loader - - cmp ah,byte [es:di-1] ;find '=' - jnz .get_next_str - - repe scasb ;cut ' ' - inc cx - dec di -;сейчас es:di указывают на название секции, имя секции по дефолту не должно быть loader т.е. иначе возможно зацикливание -;установим указатель si на это значение и сначала проверим - -;получение длинны секции -; cx=bx содержит длинну остатка секции -; di=ax указатель на текущию секцию - mov bx,cx - mov dx,di - -@@: mov al,byte [es:di] - inc di - dec cx - test cx,cx - jz error.error_get_size_d_sect ;переход на обработку ошибки по нахождению длины дефолтной секции - cmp al,' ' - jz @b - cmp al,0xd - jz .found_size_d_sect - cmp al,0xa - jnz @b -.found_size_d_sect: -; - inc cx ;correct cx - mov ax,bx - sub bx,cx ; в bx длина секции которая определена по дефолту - mov save_cx_d,bx - mov di,dx - - mov cx,bx ;set size default section -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;проверка на =loader -;save in reg point and счетчик -;check on loader - mov bx,ax - mov ax,dx - - mov si,parse_loader - inc si ;set only loader and 6 char in counter - repe cmpsb - jnz .check_section ;цепочка не совпала :( перейдем далее )) значит не исключение - - jmp error.default_eq_loader ;error критическая ошибка т.е. в дефолте присутствует имя [loader] - -.check_section: ;поиск соответствующей секции нам нужно будет узнать адрес этой секции - mov cx,bx - mov di,ax - -;///////////////////////////// -; mov ret_on_ch,.start_d ;set return - mov si,di ;установим указатель на нашу секцию, которая по дефолту - - push di ;save point di - - push cx ;save cx -;установим указатель es:di на начало ini файла - mov cx,save_cx ;it's placed size of ini file - les di,dword [file_data] - - - mov al,byte [es:di] - push word .first_ret_d - cmp al,' ' - jz .first_sp_1_d - jmp get_firs_sym.not_space -.first_sp_1_d: - jmp get_firs_sym.first_sp - -.start_d: - call get_firs_sym ;get first symbol on new line -.first_ret_d: ;первый возврат - jcxz .correct_exit ;.end_loader ;found or not found parametrs in section exit in section - cmp al,'[' - jz .found_sect_d - jmp .start_d -;просматриваем ini файл с начала в поисках секции указаной как default -;идет проверка на наличее значения timeout, для более быстрой работы, этот параметр должен быть уже обработан,т.е. в этом случае при его =0 будет сформирован указатель только на дефолтную секцию, иначе информация будет собрана по всем секциям и составлены указатели в блоке памяти -.found_sect_d: - -;check on name section - mov bx,cx - mov ax,di - push si ;save point - -; mov si,parse_loader - mov cx,save_cx_d ;load size section - push es - pop ds - - inc di - repe cmpsb - push cs - pop ds - pop si - - jnz .not_compare_d_s ;цепочка не совпала :( перейдем далее )) значит не исключение - cmp byte[es:di],']' - jnz .not_compare_d_s ;нет в конце нашей секции завершающего символа :( - - - -;set flag -we have found default -not enter again in this prosedure - or status_flag,flag_found_default - pop cx - pop di - mov point_default,ax ;point to [ - -if DEBUG - pusha - mov si,lm_lf_default_f - call printplain - popa -end if - - jmp .get_next_str - -.not_compare_d_s: - - mov cx,bx - mov di,ax - jmp .start_d - -.correct_exit: - pop cx ;восстановим значение счетчика - pop di - - -if DEBUG - pusha - mov si,lm_lf_default - call printplain - popa -end if - jmp .get_next_str - -;//////////[loader].timeout -.loader_timeout: - mov bx,cx - mov ax,di - - mov si,parse_l_timeout - mov cx,parse_l_timeout_e - parse_l_timeout - repe cmpsb - jnz error.rest_value ;is not compare - - sub bx,parse_l_timeout_e - parse_l_timeout ;correct cx - add bx,cx - mov cx,bx - - test status_flag,flag_found_timeout - jz .correct_is_not_set_t - - mov si,found_equal_timeout ;мы нашли что флаг уже установлен, информируем - call printplain - jmp .get_next_str - -.correct_is_not_set_t: - mov ax,0x3d20 ;cut al=' ' ah='=' - repe scasb - jcxz .timeout_sec_end_d ;not found param timeout - - cmp ah,byte [es:di-1] ;find '=' - jnz .get_next_str - - repe scasb ;cut ' ' - inc cx - dec di -;get timeout value -;2 знакa может быть обработано т.е. значение от 0 до 99 секунд - push cx - xor bx,bx - mov cx,2 -@@: mov al,byte [es:di] - cmp al,'0' - jb .end_get_val_t - cmp al,'9' - ja .end_get_val_t - imul bx,10 - xor al,0x30 - add bl,al -.end_get_val_t: - inc di - loop @b - mov word [value_timeout],bx -; pop cx - -if DEBUG - pusha - mov si,lm_lf_timeout - call printplain - popa -end if - - jmp @f -.timeout_sec_end_d: - mov word [value_timeout],default_timeout_value - mov si,set_default_timeout_val - call printplain -@@: pop cx - jmp .get_next_str - -;///////here end block loader -.end_loader: -if DEBUG - pusha - mov si,lm_l_end - call printplain - popa -end if - -} \ No newline at end of file +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov nickname ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +;блок макросов по обработке секции [loader] +;входные данные: +;es:di - указатель на секцию начинающиюся с '[' встечающиюся после 0хa +;cx - счетчик кол-во байт для проверке в кадре +; +macro use_parse_loader +{ +.parse_loader: +;////////////////// +;/ parse [loader] +;////////////////// + mov bx, cx ;cохраним в регистры значения счетчика и указателя + mov ax, di + +; mov word [bp-4],.start ;is alredy set, see up + mov si, parse_loader + mov cx, parse_loader_e - parse_loader + repe cmpsb + jnz error.rest_value ;цепочка не совпала :( перейдем далее т.е. будем снова искать)) + + ;сохраним указательна loader, что бы потом больше его не искать + mov point_loader, ax + sub bx, parse_loader_e - parse_loader;correct cx + add bx, cx + mov cx, bx + +if DEBUG + pusha + mov si, lm_l_found + call printplain + popa +end if +;/////////////////end check [loader]. [loader] is found +;parsing section [loader] +;first found end section,let's found '[' -it's start next section +;in previosly steep bx =cx we are not need save cx, save only di - point + mov dx, di +@@: + call get_firs_sym + jcxz .loader_f_end ;.end_loader ; end даже если мы не нашли секцию предположим что секция [loader] стоит в конце + cmp al, '[' + jnz @b + +.loader_f_end: + sub bx, cx ;bx = n byte presend in section [loader] + mov di, dx ;restore di +;////////////////parse parametrs in section [loader] +;//timeout=5 +;//default=main +; mov di,dx ;set pointer on section [loader] i think it's not need + mov cx, bx ;set counter for parsing section [loader] cx= кол-ву символов в секции [loader] + mov ret_on_ch, .get_next_str; return point +;;;;;;; parse timeout & default +.get_next_str: + call get_firs_sym ;get first symbol on new line + + test cx, cx + jz .end_loader +; jcxz .end_loader ;завершение парсинга значений timeout & default + cmp al, 't' + jz .loader_timeout + cmp al, 'd' + jnz .get_next_str +;//////[loader].default +;input di point to data cx=size [loader] + mov bx, cx + mov ax, di + + mov si, parse_l_default + mov cx, parse_l_default_e - parse_l_default + repe cmpsb + + jnz error.rest_value ;is not compare цепочка не совпала + + sub bx, parse_l_default_e - parse_l_default;correct cx + add bx, cx + mov cx, bx + + test status_flag, flag_found_default + jz .correct_is_not_set + + mov si, found_equal_default ;мы нашли что флаг уже установлен, информируем + call printplain + jmp .get_next_str + +.correct_is_not_set: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + test cx, cx + jz .end_loader + + cmp ah, byte [es:di-1] ;find '=' + jnz .get_next_str + + repe scasb ;cut ' ' + inc cx + dec di +;сейчас es:di указывают на название секции, имя секции по дефолту не должно быть loader т.е. иначе возможно зацикливание +;установим указатель si на это значение и сначала проверим + +;получение длинны секции +; cx=bx содержит длинну остатка секции +; di=ax указатель на текущию секцию + mov bx, cx + mov dx, di + +@@: + mov al, byte [es:di] + inc di + dec cx + test cx, cx + jz error.error_get_size_d_sect ;переход на обработку ошибки по нахождению длины дефолтной секции + cmp al, ' ' + jz @b + cmp al, 0xd + jz .found_size_d_sect + cmp al, 0xa + jnz @b +.found_size_d_sect: +; + inc cx ;correct cx + mov ax, bx + sub bx, cx ; в bx длина секции которая определена по дефолту + mov save_cx_d, bx + mov di, dx + + mov cx, bx ;set size default section +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;проверка на =loader +;save in reg point and счетчик +;check on loader + mov bx, ax + mov ax, dx + + mov si, parse_loader + inc si ;set only loader and 6 char in counter + repe cmpsb + jnz .check_section ;цепочка не совпала :( перейдем далее )) значит не исключение + + jmp error.default_eq_loader ;error критическая ошибка т.е. в дефолте присутствует имя [loader] + +.check_section: ;поиск соответствующей секции нам нужно будет узнать адрес этой секции + mov cx, bx + mov di, ax + +;///////////////////////////// +; mov ret_on_ch,.start_d ;set return + mov si, di ;установим указатель на нашу секцию, которая по дефолту + + push di ;save point di + + push cx ;save cx +;установим указатель es:di на начало ini файла + mov cx, save_cx ;it's placed size of ini file + les di, dword [file_data] + + + mov al, byte [es:di] + push word .first_ret_d + cmp al, ' ' + jz .first_sp_1_d + jmp get_firs_sym.not_space +.first_sp_1_d: + jmp get_firs_sym.first_sp + +.start_d: + call get_firs_sym ;get first symbol on new line +.first_ret_d: ;первый возврат + jcxz .correct_exit ;.end_loader ;found or not found parametrs in section exit in section + cmp al, '[' + jz .found_sect_d + jmp .start_d +;просматриваем ini файл с начала в поисках секции указаной как default +;идет проверка на наличее значения timeout, для более быстрой работы, этот параметр должен быть уже обработан,т.е. в этом случае при его =0 будет сформирован указатель только на дефолтную секцию, иначе информация будет собрана по всем секциям и составлены указатели в блоке памяти +.found_sect_d: + +;check on name section + mov bx, cx + mov ax, di + push si ;save point + +; mov si,parse_loader + mov cx, save_cx_d;load size section + push es + pop ds + + inc di + repe cmpsb + push cs + pop ds + pop si + + jnz .not_compare_d_s ;цепочка не совпала :( перейдем далее )) значит не исключение + cmp byte[es:di], ']' + jnz .not_compare_d_s ;нет в конце нашей секции завершающего символа :( + + + +;set flag -we have found default -not enter again in this prosedure + or status_flag, flag_found_default + pop cx + pop di + mov point_default, ax ;point to [ + +if DEBUG + pusha + mov si, lm_lf_default_f + call printplain + popa +end if + + jmp .get_next_str + +.not_compare_d_s: + + mov cx, bx + mov di, ax + jmp .start_d + +.correct_exit: + pop cx ;восстановим значение счетчика + pop di + + +if DEBUG + pusha + mov si, lm_lf_default + call printplain + popa +end if + jmp .get_next_str + +;//////////[loader].timeout +.loader_timeout: + mov bx, cx + mov ax, di + + mov si, parse_l_timeout + mov cx, parse_l_timeout_e - parse_l_timeout + repe cmpsb + jnz error.rest_value ;is not compare + + sub bx, parse_l_timeout_e - parse_l_timeout;correct cx + add bx, cx + mov cx, bx + + test status_flag, flag_found_timeout + jz .correct_is_not_set_t + + mov si, found_equal_timeout ;мы нашли что флаг уже установлен, информируем + call printplain + jmp .get_next_str + +.correct_is_not_set_t: + mov ax, 0x3d20 ;cut al=' ' ah='=' + repe scasb + jcxz .timeout_sec_end_d ;not found param timeout + + cmp ah, byte [es:di-1] ;find '=' + jnz .get_next_str + + repe scasb ;cut ' ' + inc cx + dec di +;get timeout value +;2 знакa может быть обработано т.е. значение от 0 до 99 секунд + push cx + xor bx, bx + mov cx, 2 +@@: + mov al, byte [es:di] + cmp al, '0' + jb .end_get_val_t + cmp al, '9' + ja .end_get_val_t + imul bx, 10 + xor al, 0x30 + add bl, al +.end_get_val_t: + inc di + loop @b + mov word [value_timeout], bx +; pop cx + +if DEBUG + pusha + mov si, lm_lf_timeout + call printplain + popa +end if + + jmp @f +.timeout_sec_end_d: + mov word [value_timeout], default_timeout_value + mov si, set_default_timeout_val + call printplain +@@: + pop cx + jmp .get_next_str + +;///////here end block loader +.end_loader: +if DEBUG + pusha + mov si, lm_l_end + call printplain + popa +end if + +} diff --git a/kernel/trunk/sec_loader/trunk/sl_equ.inc b/kernel/trunk/sec_loader/trunk/sl_equ.inc index c19d2393a..a8e42bfa2 100644 --- a/kernel/trunk/sec_loader/trunk/sl_equ.inc +++ b/kernel/trunk/sec_loader/trunk/sl_equ.inc @@ -1,98 +1,98 @@ -; Copyright (c) 2008-2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** -; Предопределения -DEBUG equ 1 ;компиляция с отладочной информацией =1 без отладочной инфорации =0 -loop_read_startos_file equ 3 ;кол-во попыток считать через callback сервис файл конфигурации блок2 -root_dir_entry_count equ 224 ;кол-во элементов в корневой дирректории -;point_to_fat_struc equ 0xA000 ;временный буфер, куда будет размещена Fat таблица, и затем перенесена за 1 мб -ini_data_ equ 0x2000 ;файл где размещен файл сценария загрузки, там происходит синтаксический разбор -size_show_section equ 18 -default_timeout_value equ 5 ;default value to timeout is will was some errors -flag_found_default equ 0x1 ;default value is found -flag_found_timeout equ 0x2 ;timeout value is found -flag_found_LM equ 0x1 ;found LM value -flag_found_RS equ 0x2 ;found RS value -flag_found_GTRFMS equ 0x4 ;found type RamFS -flag_found_RamdiskSector equ 0x8 ;found RamdiskSector -flag_found_RamdiskCluster equ 0x16 ;found RamdiskCluster -;statick data эти данные не предопределяются в течении выполнения всей программы. -save_cx equ word [bp-2] ;save cx size ini file -ret_on_ch equ word [bp-4] ;point to return разрушаемое значение -save_cx_d equ word [bp-6] ;save cx - size default section and working section -status_flag equ word [bp-8] ;status flag -point_loader equ word [bp-10] -point_default equ word [bp-12] ;point to default - -;данные которые зависимы от ветки выполнения и которые могут быть переопределены в процессе выполнения программы. -point_to_hframe equ word [bp-14] ;point on start frame (for change section) -point_to_1 equ word [bp-16] -point_to_2 equ word [bp-18] -point_to_3 equ word [bp-20] -point_to_4 equ word [bp-22] -point_to_5 equ word [bp-24] -point_to_6 equ word [bp-26] -point_to_7 equ word [bp-28] -point_to_8 equ word [bp-30] -point_to_9 equ word [bp-32] -point_to_10 equ word [bp-34] -point_to_11 equ word [bp-36] -point_to_12 equ word [bp-38] -point_to_13 equ word [bp-40] -point_to_14 equ word [bp-42] -point_to_15 equ word [bp-44] -point_to_16 equ word [bp-46] -point_to_16 equ word [bp-48] -point_to_17 equ word [bp-50] -point_to_18 equ word [bp-52] -;here array for fast scroling 16 word - poin to start section -point_to_point_def equ word [bp-54] -point_to_eframe equ word [bp-56] ;point on point frame - - - -; тут расположено временное хранилище для cx и di при переходе на следующий буфер при поиске секций -find_sec_di equ word [bp-58] ;тут будет храниться di -info_real_mode_size equ word [bp-60];тут храниться информация о занятой области т.е. размер, можно узнать сколько осталось места вычислив -free_ad_memory equ word [bp-62] ;сколько у нас расширенной памяти для формирования рам диска и загрузки модулей -show_errors_sect equ word [bp-64] ;переменая которая хранит биты ошибок для каждой логической секции. -save_descript_size equ word [bp-66] ;save descript size previos section сохраним размер предыдущей секции которую выводили -save_ramdisksize equ dword [bp-70] ;save size of ramdisk in byte -save_file_size equ dword [bp-74] ;save size of reading file -set_ramfs equ word [bp-76] ;определенный тип файловой системы,нужно для формирования рам диска -point_next_fat_str equ word [bp-78] ;указатель на следующий элемент fat таблицы -size_root_dir equ word [bp-80] ;кол-во элементов в секторах по 512 байт корневой директории -firstDataSect equ word [bp-82] ;первый сектор данных в сеторах от 0 -DataClasters equ word [bp-84] ;размер массива доступной для записи данных в кластерах. -point_to_free_root equ word [bp-86] ;указатель на следующий пустую запись в рут дир -point_to_dest_file_name equ word [bp-88] ;указывает на начало имени файла назначения. в формате es:point_to_dest_file_name, где es =0x2000 -data_offset equ word [bp-90] ;смещение в кластерах для записанных данных т.е перекинутых за 1-й мб -first_input equ word [bp-92] ;поле для флагов в преобразовании имени. -save_di_RAMDISK equ word [bp-94] ;сохраним di -указателя при обработке секции -save_cx_RAMDISK equ word [bp-96] ;сохраним размер остатка секции -status_flag_loader_f equ word [bp-98] ;сохраним результат выполенения загрузки файла -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;данные которые используются при обработке секции, т.е. после нажатия Enter, уже не возможно вернуться в первоначальный экран -;для возврата, необходимо перезапустить полностью код т.е. стартовать с 0х1000:0000 +; Copyright (c) 2008-2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** +; Предопределения +DEBUG equ 1 ;компиляция с отладочной информацией =1 без отладочной инфорации =0 +loop_read_startos_file equ 3 ;кол-во попыток считать через callback сервис файл конфигурации блок2 +root_dir_entry_count equ 224 ;кол-во элементов в корневой дирректории +;point_to_fat_struc equ 0xA000 ;временный буфер, куда будет размещена Fat таблица, и затем перенесена за 1 мб +ini_data_ equ 0x2000 ;файл где размещен файл сценария загрузки, там происходит синтаксический разбор +size_show_section equ 18 +default_timeout_value equ 5 ;default value to timeout is will was some errors +flag_found_default equ 0x1 ;default value is found +flag_found_timeout equ 0x2 ;timeout value is found +flag_found_LM equ 0x1 ;found LM value +flag_found_RS equ 0x2 ;found RS value +flag_found_GTRFMS equ 0x4 ;found type RamFS +flag_found_RamdiskSector equ 0x8 ;found RamdiskSector +flag_found_RamdiskCluster equ 0x16 ;found RamdiskCluster +;statick data эти данные не предопределяются в течении выполнения всей программы. +save_cx equ word [bp-2] ;save cx size ini file +ret_on_ch equ word [bp-4] ;point to return разрушаемое значение +save_cx_d equ word [bp-6] ;save cx - size default section and working section +status_flag equ word [bp-8] ;status flag +point_loader equ word [bp-10] +point_default equ word [bp-12] ;point to default + +;данные которые зависимы от ветки выполнения и которые могут быть переопределены в процессе выполнения программы. +point_to_hframe equ word [bp-14] ;point on start frame (for change section) +point_to_1 equ word [bp-16] +point_to_2 equ word [bp-18] +point_to_3 equ word [bp-20] +point_to_4 equ word [bp-22] +point_to_5 equ word [bp-24] +point_to_6 equ word [bp-26] +point_to_7 equ word [bp-28] +point_to_8 equ word [bp-30] +point_to_9 equ word [bp-32] +point_to_10 equ word [bp-34] +point_to_11 equ word [bp-36] +point_to_12 equ word [bp-38] +point_to_13 equ word [bp-40] +point_to_14 equ word [bp-42] +point_to_15 equ word [bp-44] +point_to_16 equ word [bp-46] +point_to_16 equ word [bp-48] +point_to_17 equ word [bp-50] +point_to_18 equ word [bp-52] +;here array for fast scroling 16 word - poin to start section +point_to_point_def equ word [bp-54] +point_to_eframe equ word [bp-56] ;point on point frame + + + +; тут расположено временное хранилище для cx и di при переходе на следующий буфер при поиске секций +find_sec_di equ word [bp-58] ;тут будет храниться di +info_real_mode_size equ word [bp-60];тут храниться информация о занятой области т.е. размер, можно узнать сколько осталось места вычислив +free_ad_memory equ word [bp-62] ;сколько у нас расширенной памяти для формирования рам диска и загрузки модулей +show_errors_sect equ word [bp-64] ;переменая которая хранит биты ошибок для каждой логической секции. +save_descript_size equ word [bp-66] ;save descript size previos section сохраним размер предыдущей секции которую выводили +save_ramdisksize equ dword [bp-70] ;save size of ramdisk in byte +save_file_size equ dword [bp-74] ;save size of reading file +set_ramfs equ word [bp-76] ;определенный тип файловой системы,нужно для формирования рам диска +point_next_fat_str equ word [bp-78] ;указатель на следующий элемент fat таблицы +size_root_dir equ word [bp-80] ;кол-во элементов в секторах по 512 байт корневой директории +firstDataSect equ word [bp-82] ;первый сектор данных в сеторах от 0 +DataClasters equ word [bp-84] ;размер массива доступной для записи данных в кластерах. +point_to_free_root equ word [bp-86] ;указатель на следующий пустую запись в рут дир +point_to_dest_file_name equ word [bp-88] ;указывает на начало имени файла назначения. в формате es:point_to_dest_file_name, где es =0x2000 +data_offset equ word [bp-90] ;смещение в кластерах для записанных данных т.е перекинутых за 1-й мб +first_input equ word [bp-92] ;поле для флагов в преобразовании имени. +save_di_RAMDISK equ word [bp-94] ;сохраним di -указателя при обработке секции +save_cx_RAMDISK equ word [bp-96] ;сохраним размер остатка секции +status_flag_loader_f equ word [bp-98] ;сохраним результат выполенения загрузки файла +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;данные которые используются при обработке секции, т.е. после нажатия Enter, уже не возможно вернуться в первоначальный экран +;для возврата, необходимо перезапустить полностью код т.е. стартовать с 0х1000:0000 diff --git a/kernel/trunk/sec_loader/trunk/sl_proc.inc b/kernel/trunk/sec_loader/trunk/sl_proc.inc index d480e4399..7e718a572 100644 --- a/kernel/trunk/sec_loader/trunk/sl_proc.inc +++ b/kernel/trunk/sec_loader/trunk/sl_proc.inc @@ -1,524 +1,528 @@ -; Copyright (c) 2009, -; All rights reserved. -; -; Redistribution and use in source and binary forms, with or without -; modification, are permitted provided that the following conditions are met: -; * Redistributions of source code must retain the above copyright -; notice, this list of conditions and the following disclaimer. -; * Redistributions in binary form must reproduce the above copyright -; notice, this list of conditions and the following disclaimer in the -; documentation and/or other materials provided with the distribution. -; * Neither the name of the nor the -; names of its contributors may be used to endorse or promote products -; derived from this software without specific prior written permission. -; -; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY -; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;***************************************************************************** - -; тут описываются процедуры которые используются в secondary loader -color_sym_black equ 0 -color_sym_blue equ 1 -color_sym_green equ 2 -color_sym_turquoise equ 3 -color_sym_red equ 4 - -color_sym_lightgray equ 7 - -color_sym_lightblue equ 9 -color_sym_lettuce equ 10 -color_sym_pink equ 12 -color_sym_yellow equ 14 -color_sym_white equ 15 -if DEBUG -decode: -;input eax - число, es:di куда писать, cx=10 - cmp eax,ecx - jb @f - xor edx,edx - div ecx - push edx - call decode - pop eax - @@: or al,0x30 - mov [ds:di],al - inc di - ret - -end if - - -putchar: -; in: al=character - mov ah, 0Eh - mov bh, 0 - int 10h - ret - -printplain: -; in: si->string - pushad - lodsb -@@: - call putchar - lodsb - test al,al - jnz @b - mov al,13 - call putchar - - mov al,10 - call putchar - popad - ret -getkey: -; get number in range [bl,bh] (bl,bh in ['0'..'9']) -; in: bx=range -; out: ax=digit (1..9, 10 for 0) - mov ah, 0 - int 16h - cmp al, bl - jb getkey - cmp al, bh - ja getkey - push ax - call putchar - pop ax - and ax, 0Fh - jnz @f - mov al, 10 -@@: - ret - -;setcursor: -; in: dl=column, dh=row -; mov ah, 2 -; mov bh, 0 -; int 10h -; ret - -;macro _setcursor row,column -;{ -; mov dx, row*256 + column -; call setcursor -;} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -get_firs_sym: -.start: - mov al,byte [es:di] - inc di - dec cx - jcxz .exit - - cmp al,0xa ;cmp al,0xa - jz ._entry - - cmp al,';' - jnz .start - -.first_com: - - mov al,0xa - repnz scasb - jcxz .exit -._entry: - mov al,byte [es:di] -.first_sp: - cmp al,' ' - jnz .not_space - -; mov al,' ' ;cut ' ' - repe scasb - dec di - inc cx - mov al,byte [es:di] -.not_space: - cmp al,';' - jz .first_com -.exit: ret -;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -show_name_section: - push si - push ini_data_ - pop es - - - mov al,']' - repnz scasb - test cx,cx - jz error.incorect_section_def -.find_val_name_fb1: - mov al,'n' -.find_val_name_fb: - repnz scasb - jcxz .not_name_sec_fb - - mov si,parse_name - - push cx - push di - - mov cx,parse_name_e -parse_name - repe cmpsb - pop di - pop cx - jz .yaaa_find_value - - - jmp .find_val_name_fb - -.yaaa_find_value: - sub cx,parse_name_e -parse_name - add di,parse_name_e -parse_name - - mov ax,0x3d20 ; ah='=' - repe scasb - test cx,cx - jz .not_name_sec_fb - - cmp ah,byte [es:di-1] ;find '=' - jnz .find_val_name_fb1 - - repe scasb ;cut ' ' - inc cx - dec di - - -;все вырезали и все готово для вывода имени секции )) - push es - pop ds - -.def_sect_name: - push 0xb800 - pop es -;clear array for message - xor ax,ax -if DEBUG - mov ax,0x0720 -end if - - mov cx,39 - mov si,di - mov di,dx - sub di,2 - rep stosw -;////////////////////// - - - mov di,dx - mov ah,color_sym_white;color_sym_lightblue - mov cx,36 - lodsb - sub di,2 - cmp al,'"' - jz @f - cmp al,"'" - jnz .end_sh_name_sec -@@: lodsb -@@: - stosw - lodsb - cmp al,'"' - jz .end_sh_name_sec - cmp al,"'" - jz .end_sh_name_sec - loop @b - - mov al,'}' - mov ah,color_sym_yellow - stosw -.end_sh_name_sec: - push cs - pop ds - - pop si - ret - -.not_name_sec_fb: ;нет имени в названии секции - значит так и скажем об этом - push cs - pop ds - mov di,default_section_name - jmp .def_sect_name - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;процедура поиска вверх следующей секции -;в point_default содержиться указатель на дефаулт секцию, и в пределах врейма мы бегаем по заранее пропарсеными значениям указателей -;для того что бы отобразить и пропарсить следующий фрейм, нам нужно получить за пердыдущий или следующий указатель -find_before_sect: - mov di,point_default -.e: - push ini_data_ - pop es - mov cx,di ;предположим будем просматривать к началу, текущая позиция di = сколько символов от начала документа имеется - mov bx,cx ;копия - -;настроили указатель на дефаулт секцию -;будем искать вверх -.find_start_section: - std ;установка флага направления - будем просматирвать к началу нашего ини файла -;будем искать начало секции т.е. '[' этот символ - mov al,0xa - repnz scasb ;просканируем на наличее символа начала секции - jcxz .go_ ;мы просмотрели до начала файла, но так и ничего не нашли ;(( по тихому выйдем ) - - mov find_sec_di,di ;сохраним данные - mov cx,di ; - - sub bx,cx - mov cx,bx ;в сx значение - кол-во символов - cld - call get_firs_sym -.ret_go: - jcxz ._not_section ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее - - cmp di,point_loader ; секцию loader мы не заносим иначе крах - jz ._not_section -;все удачно мы нашли вхождение секции предыдущей - cmp al,'[' - jnz ._not_section - mov point_default,di -.exit_scan_sect: - ret -;;;;;;;; восстановим значения и продолжим поиски начала секции которая нас устроит )) -._not_section: - mov di,find_sec_di - mov cx,di - mov bx,cx - jmp .find_start_section -.go_: - cld - mov cx,bx ;в сx значение - кол-во символов - - mov al,byte [es:di] - push word .f_go - cmp al,' ' - jz @f - jmp get_firs_sym.not_space -@@: - jmp get_firs_sym.first_sp - -.f_go: - jcxz .exit_scan_sect ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее - - cmp di,point_loader ; секцию loader мы не заносим иначе крах - jz .exit_scan_sect -;все удачно мы нашли вхождение секции предыдущей - cmp al,'[' - jnz .exit_scan_sect - mov point_default,di - ret - - - - - - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -find_next_sect: - mov di,point_default - push ini_data_ - pop es - mov cx,save_cx;di ;предположим будем просматривать к концу, текущая позиция di = сколько символов от начала документа имеется - sub cx,di ;сейчас в cx остаток т.е. сколько можно крутить до конца и не вылазить на начало - jmp .let_s_go -.h: - push ini_data_ - pop es - mov cx,save_cx;di ;предположим будем просматривать к концу, текущая позиция di = сколько символов от начала документа имеется -; sub cx,di ;сейчас в cx остаток т.е. сколько можно крутить до конца и не вылазить на начало - - mov al,byte [es:di] - push word .let_s_go_ret - cmp al,' ' - jz @f - jmp get_firs_sym.not_space -@@: - jmp get_firs_sym.first_sp - - - - -;настроили указатель на дефаулт секцию -;будем искать вниз -.let_s_go: - call get_firs_sym -.let_s_go_ret: - jcxz .exit_scan_sect ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее - cmp al,'[' - jnz .let_s_go - cmp di,point_loader - jz .let_s_go -;все удачно мы нашли вхождение секции предыдущей - mov point_default,di -.exit_scan_sect: - ret - -;;;;;;;;;;;;;;;;;;;;;;;;;; -;clean old cursor -clean_active_cursor: -;не изменяет значение ax -;отображение курсора по умолчанию - lea si,point_to_hframe - mov di,962-160 - mov dx,point_default - mov cx,18 -.clean_show_cur: - mov bx,[si] - add di,160 - cmp bx,dx - jz .clean_cursor_ - sub si,2 - loop .clean_show_cur - -; jmp $ - -.clean_cursor_: - push 0xb800 - pop es - push ax - mov point_to_point_def,si - xor ax,ax -if DEBUG - mov ax,0x0720 -end if - stosw - add di,68 - stosw - pop ax - ret -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;установка таймера и отображение счетчика времени -gettime: - mov ah,0 - int 1Ah - xchg ax, cx - shl eax, 10h - xchg ax, dx - ret -newtimer: - push ds - - push cs - pop ds - - pushf - call far dword [old_timer] - - pushad - call gettime - - sub eax, dword[start_timer] - mov bx, word [value_timeout] - imul bx,18 - sub bx, ax - jbe .timergo - - push es - - push 0xb800 - pop es - mov ax,bx - - mov bx, 18 - xor dx, dx - div bx - - mov bx,10 - mov di,3734 - call .decode - - xor ax,ax - stosw - -; wait 5/4/3/2 seconds, 1 second - pop es - popad - pop ds - - iret -.timergo: - push 0 - pop es - mov eax,dword [old_timer] - mov [es:8*4], eax - mov dword [timer_],eax - mov sp, word [start_stack] - mov bp,word [save_bp_from_timer] -;;не восстановленый стек :( - sti - jmp parse_start.parse_run_only - - -.decode: -;input ax - число, es:di куда писать, bx=10 - cmp ax,bx - jb @f - xor dx,dx - div bx - push dx - call .decode - pop ax - @@: or al,0x30 - push ax - mov ah,9 - stosw - pop ax - ret - -show_bl_sc_sect: -;1) отображение списка секций. Если секция не имет имя - ошибка - вывод Section unname -;проверка на наличее имени. -;входные данные es:di -указатель на секцию - cx размер секции -; push bp - mov bx,point_to_eframe - lea si,point_to_hframe - mov dx,966 - -.home_show_fb: - cmp si,bx - jb ._show_space_fb - mov di,[si] - sub si,2 - mov cx,[si] - sub cx,di ;home first section it's end before section - call show_name_section - add dx,160 - jmp .home_show_fb -._show_space_fb: - sub dx,4 - push 0xb800 - pop es -@@: - cmp dx,0xE64 - ja .exit_show_fb - mov di,dx -;clear array for message - xor ax,ax -if DEBUG - mov ax,0x0720 -end if - mov cx,39 - rep stosw -;////////////////////// - - add dx,160 - jmp @b -.exit_show_fb: -; pop bp - ret - +; Copyright (c) 2009, +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; * Neither the name of the nor the +; names of its contributors may be used to endorse or promote products +; derived from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka ''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 BE LIABLE FOR ANY +; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;***************************************************************************** + +; тут описываются процедуры которые используются в secondary loader +color_sym_black equ 0 +color_sym_blue equ 1 +color_sym_green equ 2 +color_sym_turquoise equ 3 +color_sym_red equ 4 + +color_sym_lightgray equ 7 + +color_sym_lightblue equ 9 +color_sym_lettuce equ 10 +color_sym_pink equ 12 +color_sym_yellow equ 14 +color_sym_white equ 15 +if DEBUG +decode: +;input eax - число, es:di куда писать, cx=10 + cmp eax, ecx + jb @f + xor edx, edx + div ecx + push edx + call decode + pop eax + @@: + or al, 0x30 + mov [ds:di], al + inc di + ret + +end if + + +putchar: +; in: al=character + mov ah, 0Eh + mov bh, 0 + int 10h + ret + +printplain: +; in: si->string + pushad + lodsb +@@: + call putchar + lodsb + test al, al + jnz @b + mov al, 13 + call putchar + + mov al, 10 + call putchar + popad + ret +getkey: +; get number in range [bl,bh] (bl,bh in ['0'..'9']) +; in: bx=range +; out: ax=digit (1..9, 10 for 0) + mov ah, 0 + int 16h + cmp al, bl + jb getkey + cmp al, bh + ja getkey + push ax + call putchar + pop ax + and ax, 0Fh + jnz @f + mov al, 10 +@@: + ret + +;setcursor: +; in: dl=column, dh=row +; mov ah, 2 +; mov bh, 0 +; int 10h +; ret + +;macro _setcursor row,column +;{ +; mov dx, row*256 + column +; call setcursor +;} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +get_firs_sym: +.start: + mov al, byte [es:di] + inc di + dec cx + jcxz .exit + + cmp al, 0xa ;cmp al,0xa + jz ._entry + + cmp al, ';' + jnz .start + +.first_com: + + mov al, 0xa + repnz scasb + jcxz .exit +._entry: + mov al, byte [es:di] +.first_sp: + cmp al, ' ' + jnz .not_space + +; mov al,' ' ;cut ' ' + repe scasb + dec di + inc cx + mov al, byte [es:di] +.not_space: + cmp al, ';' + jz .first_com +.exit: + ret +;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +show_name_section: + push si + push ini_data_ + pop es + + + mov al, ']' + repnz scasb + test cx, cx + jz error.incorect_section_def +.find_val_name_fb1: + mov al, 'n' +.find_val_name_fb: + repnz scasb + jcxz .not_name_sec_fb + + mov si, parse_name + + push cx + push di + + mov cx, parse_name_e -parse_name + repe cmpsb + pop di + pop cx + jz .yaaa_find_value + + + jmp .find_val_name_fb + +.yaaa_find_value: + sub cx, parse_name_e -parse_name + add di, parse_name_e -parse_name + + mov ax, 0x3d20 ; ah='=' + repe scasb + test cx, cx + jz .not_name_sec_fb + + cmp ah, byte [es:di-1] ;find '=' + jnz .find_val_name_fb1 + + repe scasb ;cut ' ' + inc cx + dec di + + +;все вырезали и все готово для вывода имени секции )) + push es + pop ds + +.def_sect_name: + push 0xb800 + pop es +;clear array for message + xor ax, ax +if DEBUG + mov ax, 0x0720 +end if + + mov cx, 39 + mov si, di + mov di, dx + sub di, 2 + rep stosw +;////////////////////// + + + mov di, dx + mov ah, color_sym_white;color_sym_lightblue + mov cx, 36 + lodsb + sub di, 2 + cmp al, '"' + jz @f + cmp al, "'" + jnz .end_sh_name_sec +@@: + lodsb +@@: + stosw + lodsb + cmp al, '"' + jz .end_sh_name_sec + cmp al, "'" + jz .end_sh_name_sec + loop @b + + mov al, '}' + mov ah, color_sym_yellow + stosw +.end_sh_name_sec: + push cs + pop ds + + pop si + ret + +.not_name_sec_fb: ;нет имени в названии секции - значит так и скажем об этом + push cs + pop ds + mov di, default_section_name + jmp .def_sect_name + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;процедура поиска вверх следующей секции +;в point_default содержиться указатель на дефаулт секцию, и в пределах врейма мы бегаем по заранее пропарсеными значениям указателей +;для того что бы отобразить и пропарсить следующий фрейм, нам нужно получить за пердыдущий или следующий указатель +find_before_sect: + mov di, point_default +.e: + push ini_data_ + pop es + mov cx, di ;предположим будем просматривать к началу, текущая позиция di = сколько символов от начала документа имеется + mov bx, cx ;копия + +;настроили указатель на дефаулт секцию +;будем искать вверх +.find_start_section: + std ;установка флага направления - будем просматирвать к началу нашего ини файла +;будем искать начало секции т.е. '[' этот символ + mov al, 0xa + repnz scasb ;просканируем на наличее символа начала секции + jcxz .go_ ;мы просмотрели до начала файла, но так и ничего не нашли ;(( по тихому выйдем ) + + mov find_sec_di, di ;сохраним данные + mov cx, di ; + + sub bx, cx + mov cx, bx ;в сx значение - кол-во символов + cld + call get_firs_sym +.ret_go: + jcxz ._not_section ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее + + cmp di, point_loader; секцию loader мы не заносим иначе крах + jz ._not_section +;все удачно мы нашли вхождение секции предыдущей + cmp al, '[' + jnz ._not_section + mov point_default, di +.exit_scan_sect: + ret +;;;;;;;; восстановим значения и продолжим поиски начала секции которая нас устроит )) +._not_section: + mov di, find_sec_di + mov cx, di + mov bx, cx + jmp .find_start_section +.go_: + cld + mov cx, bx ;в сx значение - кол-во символов + + mov al, byte [es:di] + push word .f_go + cmp al, ' ' + jz @f + jmp get_firs_sym.not_space +@@: + jmp get_firs_sym.first_sp + +.f_go: + jcxz .exit_scan_sect ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее + + cmp di, point_loader; секцию loader мы не заносим иначе крах + jz .exit_scan_sect +;все удачно мы нашли вхождение секции предыдущей + cmp al, '[' + jnz .exit_scan_sect + mov point_default, di + ret + + + + + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +find_next_sect: + mov di, point_default + push ini_data_ + pop es + mov cx, save_cx;di ;предположим будем просматривать к концу, текущая позиция di = сколько символов от начала документа имеется + sub cx, di ;сейчас в cx остаток т.е. сколько можно крутить до конца и не вылазить на начало + jmp .let_s_go +.h: + push ini_data_ + pop es + mov cx, save_cx;di ;предположим будем просматривать к концу, текущая позиция di = сколько символов от начала документа имеется +; sub cx,di ;сейчас в cx остаток т.е. сколько можно крутить до конца и не вылазить на начало + + mov al, byte [es:di] + push word .let_s_go_ret + cmp al, ' ' + jz @f + jmp get_firs_sym.not_space +@@: + jmp get_firs_sym.first_sp + + + + +;настроили указатель на дефаулт секцию +;будем искать вниз +.let_s_go: + call get_firs_sym +.let_s_go_ret: + jcxz .exit_scan_sect ; в данном случае имеем конструкцию 0xa ... ; hello [секция] обломс ищем далее + cmp al, '[' + jnz .let_s_go + cmp di, point_loader + jz .let_s_go +;все удачно мы нашли вхождение секции предыдущей + mov point_default, di +.exit_scan_sect: + ret + +;;;;;;;;;;;;;;;;;;;;;;;;;; +;clean old cursor +clean_active_cursor: +;не изменяет значение ax +;отображение курсора по умолчанию + lea si, point_to_hframe + mov di, 962-160 + mov dx, point_default + mov cx, 18 +.clean_show_cur: + mov bx, [si] + add di, 160 + cmp bx, dx + jz .clean_cursor_ + sub si, 2 + loop .clean_show_cur + +; jmp $ + +.clean_cursor_: + push 0xb800 + pop es + push ax + mov point_to_point_def, si + xor ax, ax +if DEBUG + mov ax, 0x0720 +end if + stosw + add di, 68 + stosw + pop ax + ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;установка таймера и отображение счетчика времени +gettime: + mov ah, 0 + int 1Ah + xchg ax, cx + shl eax, 10h + xchg ax, dx + ret +newtimer: + push ds + + push cs + pop ds + + pushf + call far dword [old_timer] + + pushad + call gettime + + sub eax, dword[start_timer] + mov bx, word [value_timeout] + imul bx, 18 + sub bx, ax + jbe .timergo + + push es + + push 0xb800 + pop es + mov ax, bx + + mov bx, 18 + xor dx, dx + div bx + + mov bx, 10 + mov di, 3734 + call .decode + + xor ax, ax + stosw + +; wait 5/4/3/2 seconds, 1 second + pop es + popad + pop ds + + iret +.timergo: + push 0 + pop es + mov eax, dword [old_timer] + mov [es:8*4], eax + mov dword [timer_], eax + mov sp, word [start_stack] + mov bp, word [save_bp_from_timer] +;;не восстановленый стек :( + sti + jmp parse_start.parse_run_only + + +.decode: +;input ax - число, es:di куда писать, bx=10 + cmp ax, bx + jb @f + xor dx, dx + div bx + push dx + call .decode + pop ax + @@: + or al, 0x30 + push ax + mov ah, 9 + stosw + pop ax + ret + +show_bl_sc_sect: +;1) отображение списка секций. Если секция не имет имя - ошибка - вывод Section unname +;проверка на наличее имени. +;входные данные es:di -указатель на секцию - cx размер секции +; push bp + mov bx, point_to_eframe + lea si, point_to_hframe + mov dx, 966 + +.home_show_fb: + cmp si, bx + jb ._show_space_fb + mov di, [si] + sub si, 2 + mov cx, [si] + sub cx, di ;home first section it's end before section + call show_name_section + add dx, 160 + jmp .home_show_fb +._show_space_fb: + sub dx, 4 + push 0xb800 + pop es +@@: + cmp dx, 0xE64 + ja .exit_show_fb + mov di, dx +;clear array for message + xor ax, ax +if DEBUG + mov ax, 0x0720 +end if + mov cx, 39 + rep stosw +;////////////////////// + + add dx, 160 + jmp @b +.exit_show_fb: +; pop bp + ret + diff --git a/kernel/trunk/skin/default.asm b/kernel/trunk/skin/default.asm index 88c6f15f1..c5d9870fc 100644 --- a/kernel/trunk/skin/default.asm +++ b/kernel/trunk/skin/default.asm @@ -1,38 +1,38 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -include 'me_skin.inc' - -SKIN_PARAMS \ - height = bmp_base.height,\ ; skin height - margins = [5:1:43:1],\ ; margins [left:top:right:bottom] - colors active = [binner=0x00081d:\ ; border inner color - bouter=0x00081d:\ ; border outer color - bframe=0x0054e7],\ ; border frame color - colors inactive = [binner=0x00081d:\ ; border inner color - bouter=0x00081d:\ ; border outer color - bframe=0x1a8acc],\ ; border frame color - dtp = 'myblue.dtp' ; dtp colors - -SKIN_BUTTONS \ - close = [-21:3][16:16],\ ; buttons coordinates - minimize = [-39:3][16:16] ; [left:top][width:height] - -SKIN_BITMAPS \ - left active = bmp_left,\ ; skin bitmaps pointers - left inactive = bmp_left1,\ - oper active = bmp_oper,\ - oper inactive = bmp_oper1,\ - base active = bmp_base,\ - base inactive = bmp_base1 - -BITMAP bmp_left ,'left.bmp' ; skin bitmaps -BITMAP bmp_oper ,'oper.bmp' -BITMAP bmp_base ,'base.bmp' -BITMAP bmp_left1,'left_1.bmp' -BITMAP bmp_oper1,'oper_1.bmp' -BITMAP bmp_base1,'base_1.bmp' +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +include 'me_skin.inc' + +SKIN_PARAMS \ + height = bmp_base.height,\ ; skin height + margins = [5:1:43:1],\ ; margins [left:top:right:bottom] + colors active = [binner=0x00081d:\ ; border inner color + bouter=0x00081d:\ ; border outer color + bframe=0x0054e7],\ ; border frame color + colors inactive = [binner=0x00081d:\ ; border inner color + bouter=0x00081d:\ ; border outer color + bframe=0x1a8acc],\ ; border frame color + dtp = 'myblue.dtp' ; dtp colors + +SKIN_BUTTONS \ + close = [-21:3][16:16],\ ; buttons coordinates + minimize = [-39:3][16:16] ; [left:top][width:height] + +SKIN_BITMAPS \ + left active = bmp_left,\ ; skin bitmaps pointers + left inactive = bmp_left1,\ + oper active = bmp_oper,\ + oper inactive = bmp_oper1,\ + base active = bmp_base,\ + base inactive = bmp_base1 + +BITMAP bmp_left ,'left.bmp' ; skin bitmaps +BITMAP bmp_oper ,'oper.bmp' +BITMAP bmp_base ,'base.bmp' +BITMAP bmp_left1,'left_1.bmp' +BITMAP bmp_oper1,'oper_1.bmp' +BITMAP bmp_base1,'base_1.bmp' diff --git a/kernel/trunk/skin/me_skin.inc b/kernel/trunk/skin/me_skin.inc index 365964eb3..3ab605995 100644 --- a/kernel/trunk/skin/me_skin.inc +++ b/kernel/trunk/skin/me_skin.inc @@ -1,242 +1,242 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;============================================================================ -; This file should be used to generate skins of new standard -;============================================================================ -; skin file structure: -;---------------------------------------------------------------------------- -; header: -; dd 'SKIN' -; dd = version (1 for now) -; dd @ params -; dd @ buttons -; dd @ bitmaps -; ... -;---------------------------------------------------------------------------- -; NOTE: order of sections listed below is insignificant -; since they're identified by pointer in above header -;---------------------------------------------------------------------------- -; ... -; params: -; dd = skin height -; dw = right margin -; dw = left margin -; dw = bottom margin -; dw = top margin -; dd = inner line color -; dd = outer line color -; dd = frame color -; dd = dtp file size -; ?? = dtp file itself -; ... -;---------------------------------------------------------------------------- -; ... -; buttons: -; dd = button type (1 = close, 2 = minimize) -; dw = left button coord (could be negative) -; dw = top button coord (could be negative) -; dw = button width -; dw = button height -; ... etc for all buttons -; dd = 0 (end of buttons list) -; ... -;---------------------------------------------------------------------------- -; ... -; bitmaps: -; dw = bitmap kind (1 = left, 2 = oper, 3 = base) -; dw = bitmap type (1 = active, 0 = inactive) -; dd @ bitmap -; ... etc for all bitmaps -; dd 0 (end of bitmaps list) -; ... -;---------------------------------------------------------------------------- -; ... -; bitmap: -; dd = bitmap width -; dd = bitmap height -; ?? = raw bitmap data -; ... etc for all bitmaps -; ... -;============================================================================ - -dd 'SKIN',1,__params__,__buttons__,__bitmaps__ - -struc BITMAPFILEHEADER { - .bfType dw ? ; WORD - .bfSize dd ? ; DWORD - .bfReserved1 dw ? ; WORD - .bfReserved2 dw ? ; WORD - .bfOffBits dd ? ; DWORD -} - -struc BITMAPINFOHEADER { - .biSize dd ? ; DWORD - .biWidth dd ? ; LONG - .biHeight dd ? ; LONG - .biPlanes dw ? ; WORD - .biBitCount dw ? ; WORD - .biCompression dd ? ; DWORD - .biSizeImage dd ? ; DWORD - .biXPelsPerMeter dd ? ; LONG - .biYPelsPerMeter dd ? ; LONG - .biClrUsed dd ? ; DWORD - .biClrImportant dd ? ; DWORD -} - -struc _bmp { - .h BITMAPFILEHEADER - .i BITMAPINFOHEADER -} -virtual at 0 - _bmp _bmp -end virtual - -macro BITMAP _name*,_fname* -{ - local w,h,a,r,g,b - virtual at 0 - file _fname - load w dword from _bmp.i.biWidth - load h dword from _bmp.i.biHeight - end virtual - align 4 - label _name - .width = w - .height = h - dd w,h - a=54+(w*3+(w mod 4))*(h-1) - size = $ - repeat h - repeat w - virtual at 0 - file _fname - load r from a+0 - load g from a+1 - load b from a+2 - end virtual - db r,g,b - a=a+3 - end repeat - a=a-w*3*2-(w mod 4) - end repeat -} - -macro define_colors name,[col,val] -{ - common - local a,b,c - forward - match =binner,col \{ a = val \} - match =bouter,col \{ b = val \} - match =bframe,col \{ c = val \} - common - name equ a,b,c -} - -macro SKIN_PARAMS [a] -{ - common - local _height,_margins,_colors,_colors_1,_dtp,_dtp_sz - __params__: - forward - match qq == ww,a - \{ - match =height,qq \\{ _height = ww \\} - match =margins,qq \\{ - match [q1:q2:q3:q4],ww - \\\{ - _margins equ q3,q1,q4,q2 - \\\} - \\} - match =colors =active,qq - \\{ - match [q10==q11:q20==q21:q30==q31],ww - \\\{ - define_colors _colors,q10,q11,q20,q21,q30,q31 - \\\} - \\} - match =colors =inactive,qq - \\{ - match [q10==q11:q20==q21:q30==q31],ww - \\\{ - define_colors _colors_1,q10,q11,q20,q21,q30,q31 - \\\} - \\} - match =dtp,qq \\{ _dtp equ ww \\} - \} - common - dd _height - dw _margins - dd _colors,_colors_1 - virtual at 0 - file _dtp - _dtp_sz = $ - end virtual - dd _dtp_sz - file _dtp -} - -macro SKIN_BUTTONS [a] -{ - common - local btn - __buttons__: - forward - match qq == ww,a - \{ - btn = 0 - match =close,qq \\{ btn = 1 \\} - match =minimize,qq \\{ btn = 2 \\} - match [q1:q2][q3:q4],ww - \\{ - if btn <> 0 - dd btn - dw q1,q2,q3,q4 - end if - \\} - \} - common - dd 0 -} - -macro SKIN_BITMAPS [a] -{ - common - local bmp - __bitmaps__: - forward - match qq == ww,a - \{ - bmp=-1 - match qqq =active,qq \\{ bmp = 1 \\} - match qqq =inactive,qq \\{ bmp = 0 \\} - match =left qqq,qq - \\{ - if bmp >= 0 - dw 1,bmp - dd ww - end if - \\} - match =oper qqq,qq - \\{ - if bmp >= 0 - dw 2,bmp - dd ww - end if - \\} - match =base qqq,qq - \\{ - if bmp >= 0 - dw 3,bmp - dd ww - end if - \\} - \} - common - dd 0 -} \ No newline at end of file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;============================================================================ +; This file should be used to generate skins of new standard +;============================================================================ +; skin file structure: +;---------------------------------------------------------------------------- +; header: +; dd 'SKIN' +; dd = version (1 for now) +; dd @ params +; dd @ buttons +; dd @ bitmaps +; ... +;---------------------------------------------------------------------------- +; NOTE: order of sections listed below is insignificant +; since they're identified by pointer in above header +;---------------------------------------------------------------------------- +; ... +; params: +; dd = skin height +; dw = right margin +; dw = left margin +; dw = bottom margin +; dw = top margin +; dd = inner line color +; dd = outer line color +; dd = frame color +; dd = dtp file size +; ?? = dtp file itself +; ... +;---------------------------------------------------------------------------- +; ... +; buttons: +; dd = button type (1 = close, 2 = minimize) +; dw = left button coord (could be negative) +; dw = top button coord (could be negative) +; dw = button width +; dw = button height +; ... etc for all buttons +; dd = 0 (end of buttons list) +; ... +;---------------------------------------------------------------------------- +; ... +; bitmaps: +; dw = bitmap kind (1 = left, 2 = oper, 3 = base) +; dw = bitmap type (1 = active, 0 = inactive) +; dd @ bitmap +; ... etc for all bitmaps +; dd 0 (end of bitmaps list) +; ... +;---------------------------------------------------------------------------- +; ... +; bitmap: +; dd = bitmap width +; dd = bitmap height +; ?? = raw bitmap data +; ... etc for all bitmaps +; ... +;============================================================================ + +dd 'SKIN',1,__params__,__buttons__,__bitmaps__ + +struc BITMAPFILEHEADER { + .bfType dw ? ; WORD + .bfSize dd ? ; DWORD + .bfReserved1 dw ? ; WORD + .bfReserved2 dw ? ; WORD + .bfOffBits dd ? ; DWORD +} + +struc BITMAPINFOHEADER { + .biSize dd ? ; DWORD + .biWidth dd ? ; LONG + .biHeight dd ? ; LONG + .biPlanes dw ? ; WORD + .biBitCount dw ? ; WORD + .biCompression dd ? ; DWORD + .biSizeImage dd ? ; DWORD + .biXPelsPerMeter dd ? ; LONG + .biYPelsPerMeter dd ? ; LONG + .biClrUsed dd ? ; DWORD + .biClrImportant dd ? ; DWORD +} + +struc _bmp { + .h BITMAPFILEHEADER + .i BITMAPINFOHEADER +} +virtual at 0 + _bmp _bmp +end virtual + +macro BITMAP _name*,_fname* +{ + local w,h,a,r,g,b + virtual at 0 + file _fname + load w dword from _bmp.i.biWidth + load h dword from _bmp.i.biHeight + end virtual + align 4 + label _name + .width = w + .height = h + dd w,h + a=54+(w*3+(w mod 4))*(h-1) + size = $ + repeat h + repeat w + virtual at 0 + file _fname + load r from a+0 + load g from a+1 + load b from a+2 + end virtual + db r,g,b + a=a+3 + end repeat + a=a-w*3*2-(w mod 4) + end repeat +} + +macro define_colors name,[col,val] +{ + common + local a,b,c + forward + match =binner,col \{ a = val \} + match =bouter,col \{ b = val \} + match =bframe,col \{ c = val \} + common + name equ a,b,c +} + +macro SKIN_PARAMS [a] +{ + common + local _height,_margins,_colors,_colors_1,_dtp,_dtp_sz + __params__: + forward + match qq == ww,a + \{ + match =height,qq \\{ _height = ww \\} + match =margins,qq \\{ + match [q1:q2:q3:q4],ww + \\\{ + _margins equ q3,q1,q4,q2 + \\\} + \\} + match =colors =active,qq + \\{ + match [q10==q11:q20==q21:q30==q31],ww + \\\{ + define_colors _colors,q10,q11,q20,q21,q30,q31 + \\\} + \\} + match =colors =inactive,qq + \\{ + match [q10==q11:q20==q21:q30==q31],ww + \\\{ + define_colors _colors_1,q10,q11,q20,q21,q30,q31 + \\\} + \\} + match =dtp,qq \\{ _dtp equ ww \\} + \} + common + dd _height + dw _margins + dd _colors,_colors_1 + virtual at 0 + file _dtp + _dtp_sz = $ + end virtual + dd _dtp_sz + file _dtp +} + +macro SKIN_BUTTONS [a] +{ + common + local btn + __buttons__: + forward + match qq == ww,a + \{ + btn = 0 + match =close,qq \\{ btn = 1 \\} + match =minimize,qq \\{ btn = 2 \\} + match [q1:q2][q3:q4],ww + \\{ + if btn <> 0 + dd btn + dw q1,q2,q3,q4 + end if + \\} + \} + common + dd 0 +} + +macro SKIN_BITMAPS [a] +{ + common + local bmp + __bitmaps__: + forward + match qq == ww,a + \{ + bmp=-1 + match qqq =active,qq \\{ bmp = 1 \\} + match qqq =inactive,qq \\{ bmp = 0 \\} + match =left qqq,qq + \\{ + if bmp >= 0 + dw 1,bmp + dd ww + end if + \\} + match =oper qqq,qq + \\{ + if bmp >= 0 + dw 2,bmp + dd ww + end if + \\} + match =base qqq,qq + \\{ + if bmp >= 0 + dw 3,bmp + dd ww + end if + \\} + \} + common + dd 0 +} diff --git a/kernel/trunk/sound/playnote.inc b/kernel/trunk/sound/playnote.inc index 065bbc809..f3f8fd4aa 100644 --- a/kernel/trunk/sound/playnote.inc +++ b/kernel/trunk/sound/playnote.inc @@ -1,166 +1,166 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; PLAYNOTE.INC version 1.1 22 November 2003 ;; -;; ;; -;; Player Notes for Speaker PC ;; -;; subfunction #55 from function #55 Menuet OS ;; -;; ;; -;; Copyright 2003 VaStaNi ;; -;; vastani@ukr.net ;; -;; >>>- SIMPLY - QUICKLY - SHORTLY -<<< ;; -;; ;; -;; Note: playnote.txt ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - -align 4 -sound_interface: - - cmp eax,ebx ; this is subfunction #55 ? - jne retFunc55 ; if no then return. - - cmp byte [sound_flag],0 - jne retFunc55 - - movzx eax, byte [countDelayNote] - or al, al ; player is busy ? - jnz retFunc55 ; return counter delay Note - - mov [memAdrNote],esi;edx - call get_pid - mov [pidProcessNote],eax - xor eax, eax ; Ok! EAX = 0 - retFunc55: - mov [esp+32], eax ; return value EAX for application - ret - -iglobal -align 4 - kontrOctave dw 0x4742, 0x4342, 0x3F7C, 0x3BEC, 0x388F, 0x3562 - dw 0x3264, 0x2F8F, 0x2CE4, 0x2A5F, 0x2802, 0x25BF - memAdrNote dd 0 - pidProcessNote dd 0 - slotProcessNote dd 0 - count_timer_Note dd 1 - mem8253r42 dw 0 - countDelayNote db 0 -endg - -playNote: -; jmp NotPlayNotes - mov esi, [memAdrNote] - or esi, esi ; ESI = 0 ? - OFF Notes Play ? - jz NotPlayNotes ; if ESI = 0 -> ignore play pocedure - cmp eax, [count_timer_Note] - jb NotPlayNotes - push eax - inc eax - mov [count_timer_Note], eax - mov al, [countDelayNote] - dec al ; decrement counter Delay for Playing Note - jz NewLoadNote@Delay - cmp al, 0xFF ; this is first Note Play ? - jne NextDelayNote - ;This is FIRST Note, save counter channel 2 chip 8253 - mov al, 0xB6 ; control byte to timer chip 8253 - out 0x43, al ; Send it to the control port chip 8253 - in al, 0x42 ; Read Lower byte counter channel 2 chip 8253 - mov ah, al ; AH = Lower byte counter channel 2 - in al, 0x42 ; Read Upper byte counter channel 2 chip 8253 - mov [mem8253r42], ax ; Save counter channel 2 timer chip 8253 - NewLoadNote@Delay: - cld -; lodsb ; load AL - counter Delay - call ReadNoteByte - or al, al ; THE END ? - jz EndPlayNote - cmp al, 0x81 - jnc NoteforOctave - mov [countDelayNote], al -; lodsw ; load AX - counter for Note! - call ReadNoteByte - mov ah,al - call ReadNoteByte - xchg al,ah - jmp pokeNote - - EndPlayNote: ; THE END Play Notes! - in al, 0x61 ; Get contents of system port B chip 8255 - and al, 0xFC ; Turn OFF timer and speaker - out 0x61, al ; Send out new values to port B chip 8255 - mov ax, [mem8253r42] ; memorize counter channel 2 timer chip 8253 - xchg al, ah ; reverse byte in word - out 0x42, al ; restore Lower byte counter channel 2 - mov al, ah ; AL = Upper byte counter channel 2 - out 0x42, al ; restore Upper byte channel 2 - xor eax, eax ; EAX = 0 - mov [memAdrNote], eax ; clear header control Delay-Note string - NextDelayNote: - mov [countDelayNote], al ; save new counter delay Note - pop eax - NotPlayNotes: - RET - - NoteforOctave: - sub al, 0x81 ; correction value for delay Note - mov [countDelayNote], al ; save counter delay this new Note -; lodsb ; load pack control code - call ReadNoteByte - cmp al, 0xFF ; this is PAUSE ? - jne packCode ; no, this is PACK CODE - in al, 0x61 ; Get contents of system port B chip 8255 - and al, 0xFC ; Turn OFF timer and speaker - out 0x61, al ; Send out new values to port B chip 8255 - jmp saveESI - - packCode: - mov cl, al ; save code - and al, 0xF ; clear upper bits - dec al ; correction - add al, al ; transform number to offset constant - movsx eax, al ; EAX - offset - add eax, dword kontrOctave ; EAX - address from constant - mov ax, [eax] ; read constant - shr cl, 4 ; transform for number Octave - shr ax, cl ; calculate from Note this Octave! - pokeNote: - out 0x42, al ; Lower byte Out to channel 2 timer chip 8253 - mov al, ah - out 0x42, al ; Upper byte Out to channel 2 timer chip 8253 - in al, 0x61 ; Get contents of system port B chip 8255 - or al, 3 ; Turn ON timer and speaker - out 0x61, al ; Send out new values to port B chip 8255 - saveESI: -; mov [memAdrNote], esi ; save new header control Delay-Note string - pop eax - RET -ReadNoteByte: -;result: -; al - note - push eax - push ecx - push edx - push esi - - mov eax,[pidProcessNote] - call pid_to_slot - test eax,eax - jz .failed - lea ecx,[esp+12] - mov edx,1 - mov esi,[memAdrNote] - inc [memAdrNote] - - call read_process_memory -.failed: - pop esi - pop edx - pop ecx - pop eax - ret -;------------------- END CODE ------------------- +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; PLAYNOTE.INC version 1.1 22 November 2003 ;; +;; ;; +;; Player Notes for Speaker PC ;; +;; subfunction #55 from function #55 Menuet OS ;; +;; ;; +;; Copyright 2003 VaStaNi ;; +;; vastani@ukr.net ;; +;; >>>- SIMPLY - QUICKLY - SHORTLY -<<< ;; +;; ;; +;; Note: playnote.txt ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + +align 4 +sound_interface: + + cmp eax, ebx ; this is subfunction #55 ? + jne retFunc55 ; if no then return. + + cmp byte [sound_flag], 0 + jne retFunc55 + + movzx eax, byte [countDelayNote] + or al, al ; player is busy ? + jnz retFunc55 ; return counter delay Note + + mov [memAdrNote], esi;edx + call get_pid + mov [pidProcessNote], eax + xor eax, eax ; Ok! EAX = 0 + retFunc55: + mov [esp+32], eax ; return value EAX for application + ret + +iglobal +align 4 + kontrOctave dw 0x4742, 0x4342, 0x3F7C, 0x3BEC, 0x388F, 0x3562 + dw 0x3264, 0x2F8F, 0x2CE4, 0x2A5F, 0x2802, 0x25BF + memAdrNote dd 0 + pidProcessNote dd 0 + slotProcessNote dd 0 + count_timer_Note dd 1 + mem8253r42 dw 0 + countDelayNote db 0 +endg + +playNote: +; jmp NotPlayNotes + mov esi, [memAdrNote] + or esi, esi ; ESI = 0 ? - OFF Notes Play ? + jz NotPlayNotes ; if ESI = 0 -> ignore play pocedure + cmp eax, [count_timer_Note] + jb NotPlayNotes + push eax + inc eax + mov [count_timer_Note], eax + mov al, [countDelayNote] + dec al ; decrement counter Delay for Playing Note + jz NewLoadNote@Delay + cmp al, 0xFF ; this is first Note Play ? + jne NextDelayNote + ;This is FIRST Note, save counter channel 2 chip 8253 + mov al, 0xB6 ; control byte to timer chip 8253 + out 0x43, al ; Send it to the control port chip 8253 + in al, 0x42 ; Read Lower byte counter channel 2 chip 8253 + mov ah, al ; AH = Lower byte counter channel 2 + in al, 0x42 ; Read Upper byte counter channel 2 chip 8253 + mov [mem8253r42], ax ; Save counter channel 2 timer chip 8253 + NewLoadNote@Delay: + cld +; lodsb ; load AL - counter Delay + call ReadNoteByte + or al, al ; THE END ? + jz EndPlayNote + cmp al, 0x81 + jnc NoteforOctave + mov [countDelayNote], al +; lodsw ; load AX - counter for Note! + call ReadNoteByte + mov ah, al + call ReadNoteByte + xchg al, ah + jmp pokeNote + + EndPlayNote: ; THE END Play Notes! + in al, 0x61 ; Get contents of system port B chip 8255 + and al, 0xFC ; Turn OFF timer and speaker + out 0x61, al ; Send out new values to port B chip 8255 + mov ax, [mem8253r42] ; memorize counter channel 2 timer chip 8253 + xchg al, ah ; reverse byte in word + out 0x42, al ; restore Lower byte counter channel 2 + mov al, ah ; AL = Upper byte counter channel 2 + out 0x42, al ; restore Upper byte channel 2 + xor eax, eax ; EAX = 0 + mov [memAdrNote], eax; clear header control Delay-Note string + NextDelayNote: + mov [countDelayNote], al; save new counter delay Note + pop eax + NotPlayNotes: + RET + + NoteforOctave: + sub al, 0x81 ; correction value for delay Note + mov [countDelayNote], al; save counter delay this new Note +; lodsb ; load pack control code + call ReadNoteByte + cmp al, 0xFF ; this is PAUSE ? + jne packCode ; no, this is PACK CODE + in al, 0x61 ; Get contents of system port B chip 8255 + and al, 0xFC ; Turn OFF timer and speaker + out 0x61, al ; Send out new values to port B chip 8255 + jmp saveESI + + packCode: + mov cl, al ; save code + and al, 0xF ; clear upper bits + dec al ; correction + add al, al ; transform number to offset constant + movsx eax, al ; EAX - offset + add eax, dword kontrOctave; EAX - address from constant + mov ax, [eax] ; read constant + shr cl, 4 ; transform for number Octave + shr ax, cl ; calculate from Note this Octave! + pokeNote: + out 0x42, al ; Lower byte Out to channel 2 timer chip 8253 + mov al, ah + out 0x42, al ; Upper byte Out to channel 2 timer chip 8253 + in al, 0x61 ; Get contents of system port B chip 8255 + or al, 3 ; Turn ON timer and speaker + out 0x61, al ; Send out new values to port B chip 8255 + saveESI: +; mov [memAdrNote], esi ; save new header control Delay-Note string + pop eax + RET +ReadNoteByte: +;result: +; al - note + push eax + push ecx + push edx + push esi + + mov eax, [pidProcessNote] + call pid_to_slot + test eax, eax + jz .failed + lea ecx, [esp+12] + mov edx, 1 + mov esi, [memAdrNote] + inc [memAdrNote] + + call read_process_memory +.failed: + pop esi + pop edx + pop ecx + pop eax + ret +;------------------- END CODE ------------------- diff --git a/kernel/trunk/unpacker.inc b/kernel/trunk/unpacker.inc index e87ebe534..9c30bfc50 100644 --- a/kernel/trunk/unpacker.inc +++ b/kernel/trunk/unpacker.inc @@ -1,527 +1,528 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; void __stdcall unpack(void* packed_data, void* unpacked_data); -unpack: - pushad - mov esi, [esp+32+4] - mov edi, [esp+32+8] - mov eax, [esi+8] - and al, 0xC0 - cmp al, 0xC0 - jz .failed - mov eax, [esi+8] - push eax - add esi, 12 - and al, not 0xC0 - dec al - jz .lzma -.failed: - pop eax - popad - ret 8 -.lzma: - call .lzma_unpack -.common: - pop eax - test al, 0x80 - jnz .ctr1 - test al, 0x40 - jz .ok - lodsd - mov ecx, eax - jecxz .ok - mov dl, [esi] - mov esi, [esp+32+8] -.c1: - lodsb - sub al, 0E8h - cmp al, 1 - ja .c1 - cmp byte [esi], dl - jnz .c1 - lodsd -; "bswap eax" is not supported on i386 - shr ax, 8 - ror eax, 16 - xchg al, ah - sub eax, esi - add eax, [esp+32+8] - mov [esi-4], eax - loop .c1 -.ok: - popad - ret 8 -.ctr1: - lodsd - mov ecx, eax - jecxz .ok - mov dl, [esi] - mov esi, [esp+32+8] -.c2: - lodsb -@@: - cmp al, 0xF - jnz .f - lodsb - cmp al, 80h - jb @b - cmp al, 90h - jb @f -.f: - sub al, 0E8h - cmp al, 1 - ja .c2 -@@: - cmp byte [esi], dl - jnz .c2 - lodsd - shr ax, 8 - ror eax, 16 - xchg al, ah - sub eax, esi - add eax, [esp+32+8] - mov [esi-4], eax - loop .c2 - jmp .ok - -.lzma_unpack: - -.pb = 2 ; pos state bits -.lp = 0 ; literal pos state bits -.lc = 3 ; literal context bits -.posStateMask = ((1 shl .pb)-1) -.literalPosMask = ((1 shl .lp)-1) - -.kNumPosBitsMax = 4 -.kNumPosStatesMax = (1 shl .kNumPosBitsMax) - -.kLenNumLowBits = 3 -.kLenNumLowSymbols = (1 shl .kLenNumLowBits) -.kLenNumMidBits = 3 -.kLenNumMidSymbols = (1 shl .kLenNumMidBits) -.kLenNumHighBits = 8 -.kLenNumHighSymbols = (1 shl .kLenNumHighBits) - -.LenChoice = 0 -.LenChoice2 = 1 -.LenLow = 2 -.LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits)) -.LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits)) -.kNumLenProbs = (.LenHigh + .kLenNumHighSymbols) - -.kNumStates = 12 -.kNumLitStates = 7 -.kStartPosModelIndex = 4 -.kEndPosModelIndex = 14 -.kNumFullDistances = (1 shl (.kEndPosModelIndex/2)) -.kNumPosSlotBits = 6 -.kNumLenToPosStates = 4 -.kNumAlignBits = 4 -.kAlignTableSize = (1 shl .kNumAlignBits) -.kMatchMinLen = 2 - -.IsMatch = 0 -.IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax)) -.IsRepG0 = (.IsRep + .kNumStates) -.IsRepG1 = (.IsRepG0 + .kNumStates) -.IsRepG2 = (.IsRepG1 + .kNumStates) -.IsRep0Long = (.IsRepG2 + .kNumStates) -.PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax)) -.SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits)) -.Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex) -.Lencoder = (.Align_ + .kAlignTableSize) -.RepLencoder = (.Lencoder + .kNumLenProbs) -.Literal = (.RepLencoder + .kNumLenProbs) - -.LZMA_BASE_SIZE = 1846 ; must be ==Literal -.LZMA_LIT_SIZE = 768 - -.kNumTopBits = 24 -.kTopValue = (1 shl .kNumTopBits) - -.kNumBitModelTotalBits = 11 -.kBitModelTotal = (1 shl .kNumBitModelTotalBits) -.kNumMoveBits = 5 - - push edi -; int state=0; - xor ebx, ebx - mov [.previousByte], bl -; unsigned rep0=1,rep1=1,rep2=1,rep3=1; - mov eax, 1 - mov edi, .rep0 - stosd - stosd - stosd - stosd -; int len=0; -; result=0; - mov ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp)) - mov eax, .kBitModelTotal/2 - mov edi, [.p] - rep stosd -; RangeDecoderInit -; rd->ExtraBytes = 0 -; rd->Buffer = stream -; rd->BufferLim = stream+bufferSize -; rd->Range = 0xFFFFFFFF - pop edi - mov ebp, [esi-8] ; dest_length - add ebp, edi ; ebp = destination limit - lodsd -; rd->code_ = eax - mov [.code_], eax - or [.range], -1 -.main_loop: - cmp edi, ebp - jae .main_loop_done - mov edx, edi - and edx, .posStateMask - mov eax, ebx - shl eax, .kNumPosBitsMax+2 - lea eax, [.IsMatch*4 + eax + edx*4] - add eax, [.p] - call .RangeDecoderBitDecode - jc .1 - movzx eax, [.previousByte] -if .literalPosMask - mov ah, dl - and ah, .literalPosMask -end if - shr eax, 8-.lc - imul eax, .LZMA_LIT_SIZE*4 - add eax, .Literal*4 - add eax, [.p] - cmp ebx, .kNumLitStates - jb .literal - xor edx, edx - sub edx, [.rep0] - mov dl, [edi + edx] - call .LzmaLiteralDecodeMatch - jmp @f -.literal: - call .LzmaLiteralDecode -@@: - mov [.previousByte], al - stosb - mov al, bl - cmp bl, 4 - jb @f - mov al, 3 - cmp bl, 10 - jb @f - mov al, 6 -@@: sub bl, al - jmp .main_loop -.1: - lea eax, [.IsRep*4 + ebx*4] - add eax, [.p] - call .RangeDecoderBitDecode - jnc .10 - lea eax, [.IsRepG0*4 + ebx*4] - add eax, [.p] - call .RangeDecoderBitDecode - jc .111 - mov eax, ebx - shl eax, .kNumPosBitsMax+2 - lea eax, [.IsRep0Long*4 + eax + edx*4] - add eax, [.p] - call .RangeDecoderBitDecode - jc .1101 - cmp bl, 7 - setae bl - lea ebx, [9 + ebx + ebx] - xor edx, edx - sub edx, [.rep0] - mov al, [edi + edx] - stosb - mov [.previousByte], al - jmp .main_loop -.111: - lea eax, [.IsRepG1*4 + ebx*4] - add eax, [.p] - call .RangeDecoderBitDecode - mov eax, [.rep1] - jnc .l3 -.l1: - lea eax, [.IsRepG2*4 + ebx*4] - add eax, [.p] - call .RangeDecoderBitDecode - mov eax, [.rep2] - jnc .l2 - xchg [.rep3], eax -.l2: - push [.rep1] - pop [.rep2] -.l3: - xchg eax, [.rep0] - mov [.rep1], eax -.1101: - mov eax, .RepLencoder*4 - add eax, [.p] - call .LzmaLenDecode - cmp bl, 7 - setc bl - adc bl, bl - xor bl, 3 - add bl, 8 - jmp .repmovsb -.10: - mov eax, [.rep0] - xchg eax, [.rep1] - xchg eax, [.rep2] - xchg eax, [.rep3] - cmp bl, 7 - setc bl - adc bl, bl - xor bl, 3 - add bl, 7 - mov eax, .Lencoder*4 - add eax, [.p] - call .LzmaLenDecode - mov eax, .kNumLenToPosStates-1 - cmp eax, ecx - jb @f - mov eax, ecx -@@: - push ecx - mov ecx, .kNumPosSlotBits - shl eax, cl - shl eax, 2 - add eax, .PosSlot*4 - add eax, [.p] - call .RangeDecoderBitTreeDecode - mov [.rep0], ecx - cmp ecx, .kStartPosModelIndex - jb .l6 - push ecx - mov eax, ecx - and eax, 1 - shr ecx, 1 - or eax, 2 - dec ecx - shl eax, cl - mov [.rep0], eax - pop edx - cmp edx, .kEndPosModelIndex - jae .l5 - sub eax, edx - shl eax, 2 - add eax, (.SpecPos - 1)*4 - add eax, [.p] - call .RangeDecoderReverseBitTreeDecode - add [.rep0], ecx - jmp .l6 -.l5: - sub ecx, .kNumAlignBits - call .RangeDecoderDecodeDirectBits - mov ecx, .kNumAlignBits - shl eax, cl - add [.rep0], eax - mov eax, .Align_*4 - add eax, [.p] - call .RangeDecoderReverseBitTreeDecode - add [.rep0], ecx -.l6: - pop ecx - inc [.rep0] - jz .main_loop_done -.repmovsb: - add ecx, .kMatchMinLen - push esi - mov esi, edi - sub esi, [.rep0] - rep movsb - pop esi - mov al, [edi-1] - mov [.previousByte], al - jmp .main_loop -.main_loop_done: - ret - -.RangeDecoderBitDecode: -; in: eax->prob -; out: CF=bit; destroys eax - push edx - mov edx, [.range] - shr edx, .kNumBitModelTotalBits - imul edx, [eax] - cmp [.code_], edx - jae .ae - mov [.range], edx - mov edx, .kBitModelTotal - sub edx, [eax] - shr edx, .kNumMoveBits - add [eax], edx - clc -.n: - lahf - cmp [.range], .kTopValue - jae @f - shl [.range], 8 - shl [.code_], 8 - lodsb - mov byte [.code_], al -@@: - sahf - pop edx - ret -.ae: - sub [.range], edx - sub [.code_], edx - mov edx, [eax] - shr edx, .kNumMoveBits - sub [eax], edx - stc - jmp .n - -.RangeDecoderDecodeDirectBits: -; in: ecx=numTotalBits -; out: eax=result; destroys edx - xor eax, eax -.l: - shr [.range], 1 - shl eax, 1 - mov edx, [.code_] - sub edx, [.range] - jb @f - mov [.code_], edx - or eax, 1 -@@: - cmp [.range], .kTopValue - jae @f - shl [.range], 8 - shl [.code_], 8 - push eax - lodsb - mov byte [.code_], al - pop eax -@@: - loop .l - ret - -.LzmaLiteralDecode: -; in: eax->probs -; out: al=byte; destroys edx - push ecx - mov ecx, 1 -@@: - push eax - lea eax, [eax+ecx*4] - call .RangeDecoderBitDecode - pop eax - adc cl, cl - jnc @b -.LzmaLiteralDecode.ret: - mov al, cl - pop ecx - ret -.LzmaLiteralDecodeMatch: -; in: eax->probs, dl=matchByte -; out: al=byte; destroys edx - push ecx - mov ecx, 1 -.LzmaLiteralDecodeMatch.1: - add dl, dl - setc ch - push eax - lea eax, [eax+ecx*4+0x100*4] - call .RangeDecoderBitDecode - pop eax - adc cl, cl - jc .LzmaLiteralDecode.ret - xor ch, cl - test ch, 1 - mov ch, 0 - jnz @b - jmp .LzmaLiteralDecodeMatch.1 - -.LzmaLenDecode: -; in: eax->prob, edx=posState -; out: ecx=len - push eax - add eax, .LenChoice*4 - call .RangeDecoderBitDecode - pop eax - jnc .0 - push eax - add eax, .LenChoice2*4 - call .RangeDecoderBitDecode - pop eax - jc @f - mov ecx, .kLenNumMidBits - shl edx, cl - lea eax, [eax + .LenMid*4 + edx*4] - call .RangeDecoderBitTreeDecode - add ecx, .kLenNumLowSymbols - ret -@@: - add eax, .LenHigh*4 - mov ecx, .kLenNumHighBits - call .RangeDecoderBitTreeDecode - add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols - ret -.0: - mov ecx, .kLenNumLowBits - shl edx, cl - lea eax, [eax + .LenLow*4 + edx*4] -.RangeDecoderBitTreeDecode: -; in: eax->probs,ecx=numLevels -; out: ecx=length; destroys edx - push ebx - mov edx, 1 - mov ebx, edx -@@: - push eax - lea eax, [eax+edx*4] - call .RangeDecoderBitDecode - pop eax - adc dl, dl - add bl, bl - loop @b - sub dl, bl - pop ebx - mov ecx, edx - ret -.RangeDecoderReverseBitTreeDecode: -; in: eax->probs,ecx=numLevels -; out: ecx=length; destroys edx - push ebx ecx - mov edx, 1 - xor ebx, ebx -@@: - push eax - lea eax, [eax+edx*4] - call .RangeDecoderBitDecode - lahf - adc edx, edx - sahf - rcr ebx, 1 - pop eax - loop @b - pop ecx - rol ebx, cl - mov ecx, ebx - pop ebx - ret - -uglobal -align 4 -;unpack.p rd unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp)) -unpack.p dd ? -unpack.code_ dd ? -unpack.range dd ? -unpack.rep0 dd ? -unpack.rep1 dd ? -unpack.rep2 dd ? -unpack.rep3 dd ? -unpack.previousByte db ? -endg +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; void __stdcall unpack(void* packed_data, void* unpacked_data); +unpack: + pushad + mov esi, [esp+32+4] + mov edi, [esp+32+8] + mov eax, [esi+8] + and al, 0xC0 + cmp al, 0xC0 + jz .failed + mov eax, [esi+8] + push eax + add esi, 12 + and al, not 0xC0 + dec al + jz .lzma +.failed: + pop eax + popad + ret 8 +.lzma: + call .lzma_unpack +.common: + pop eax + test al, 0x80 + jnz .ctr1 + test al, 0x40 + jz .ok + lodsd + mov ecx, eax + jecxz .ok + mov dl, [esi] + mov esi, [esp+32+8] +.c1: + lodsb + sub al, 0E8h + cmp al, 1 + ja .c1 + cmp byte [esi], dl + jnz .c1 + lodsd +; "bswap eax" is not supported on i386 + shr ax, 8 + ror eax, 16 + xchg al, ah + sub eax, esi + add eax, [esp+32+8] + mov [esi-4], eax + loop .c1 +.ok: + popad + ret 8 +.ctr1: + lodsd + mov ecx, eax + jecxz .ok + mov dl, [esi] + mov esi, [esp+32+8] +.c2: + lodsb +@@: + cmp al, 0xF + jnz .f + lodsb + cmp al, 80h + jb @b + cmp al, 90h + jb @f +.f: + sub al, 0E8h + cmp al, 1 + ja .c2 +@@: + cmp byte [esi], dl + jnz .c2 + lodsd + shr ax, 8 + ror eax, 16 + xchg al, ah + sub eax, esi + add eax, [esp+32+8] + mov [esi-4], eax + loop .c2 + jmp .ok + +.lzma_unpack: + +.pb = 2 ; pos state bits +.lp = 0 ; literal pos state bits +.lc = 3 ; literal context bits +.posStateMask = ((1 shl .pb)-1) +.literalPosMask = ((1 shl .lp)-1) + +.kNumPosBitsMax = 4 +.kNumPosStatesMax = (1 shl .kNumPosBitsMax) + +.kLenNumLowBits = 3 +.kLenNumLowSymbols = (1 shl .kLenNumLowBits) +.kLenNumMidBits = 3 +.kLenNumMidSymbols = (1 shl .kLenNumMidBits) +.kLenNumHighBits = 8 +.kLenNumHighSymbols = (1 shl .kLenNumHighBits) + +.LenChoice = 0 +.LenChoice2 = 1 +.LenLow = 2 +.LenMid = (.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits)) +.LenHigh = (.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits)) +.kNumLenProbs = (.LenHigh + .kLenNumHighSymbols) + +.kNumStates = 12 +.kNumLitStates = 7 +.kStartPosModelIndex = 4 +.kEndPosModelIndex = 14 +.kNumFullDistances = (1 shl (.kEndPosModelIndex/2)) +.kNumPosSlotBits = 6 +.kNumLenToPosStates = 4 +.kNumAlignBits = 4 +.kAlignTableSize = (1 shl .kNumAlignBits) +.kMatchMinLen = 2 + +.IsMatch = 0 +.IsRep = (.IsMatch + (.kNumStates shl .kNumPosBitsMax)) +.IsRepG0 = (.IsRep + .kNumStates) +.IsRepG1 = (.IsRepG0 + .kNumStates) +.IsRepG2 = (.IsRepG1 + .kNumStates) +.IsRep0Long = (.IsRepG2 + .kNumStates) +.PosSlot = (.IsRep0Long + (.kNumStates shl .kNumPosBitsMax)) +.SpecPos = (.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits)) +.Align_ = (.SpecPos + .kNumFullDistances - .kEndPosModelIndex) +.Lencoder = (.Align_ + .kAlignTableSize) +.RepLencoder = (.Lencoder + .kNumLenProbs) +.Literal = (.RepLencoder + .kNumLenProbs) + +.LZMA_BASE_SIZE = 1846 ; must be ==Literal +.LZMA_LIT_SIZE = 768 + +.kNumTopBits = 24 +.kTopValue = (1 shl .kNumTopBits) + +.kNumBitModelTotalBits = 11 +.kBitModelTotal = (1 shl .kNumBitModelTotalBits) +.kNumMoveBits = 5 + + push edi +; int state=0; + xor ebx, ebx + mov [.previousByte], bl +; unsigned rep0=1,rep1=1,rep2=1,rep3=1; + mov eax, 1 + mov edi, .rep0 + stosd + stosd + stosd + stosd +; int len=0; +; result=0; + mov ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp)) + mov eax, .kBitModelTotal/2 + mov edi, [.p] + rep stosd +; RangeDecoderInit +; rd->ExtraBytes = 0 +; rd->Buffer = stream +; rd->BufferLim = stream+bufferSize +; rd->Range = 0xFFFFFFFF + pop edi + mov ebp, [esi-8] ; dest_length + add ebp, edi ; ebp = destination limit + lodsd +; rd->code_ = eax + mov [.code_], eax + or [.range], -1 +.main_loop: + cmp edi, ebp + jae .main_loop_done + mov edx, edi + and edx, .posStateMask + mov eax, ebx + shl eax, .kNumPosBitsMax+2 + lea eax, [.IsMatch*4 + eax + edx*4] + add eax, [.p] + call .RangeDecoderBitDecode + jc .1 + movzx eax, [.previousByte] +if .literalPosMask + mov ah, dl + and ah, .literalPosMask +end if + shr eax, 8-.lc + imul eax, .LZMA_LIT_SIZE*4 + add eax, .Literal*4 + add eax, [.p] + cmp ebx, .kNumLitStates + jb .literal + xor edx, edx + sub edx, [.rep0] + mov dl, [edi + edx] + call .LzmaLiteralDecodeMatch + jmp @f +.literal: + call .LzmaLiteralDecode +@@: + mov [.previousByte], al + stosb + mov al, bl + cmp bl, 4 + jb @f + mov al, 3 + cmp bl, 10 + jb @f + mov al, 6 +@@: + sub bl, al + jmp .main_loop +.1: + lea eax, [.IsRep*4 + ebx*4] + add eax, [.p] + call .RangeDecoderBitDecode + jnc .10 + lea eax, [.IsRepG0*4 + ebx*4] + add eax, [.p] + call .RangeDecoderBitDecode + jc .111 + mov eax, ebx + shl eax, .kNumPosBitsMax+2 + lea eax, [.IsRep0Long*4 + eax + edx*4] + add eax, [.p] + call .RangeDecoderBitDecode + jc .1101 + cmp bl, 7 + setae bl + lea ebx, [9 + ebx + ebx] + xor edx, edx + sub edx, [.rep0] + mov al, [edi + edx] + stosb + mov [.previousByte], al + jmp .main_loop +.111: + lea eax, [.IsRepG1*4 + ebx*4] + add eax, [.p] + call .RangeDecoderBitDecode + mov eax, [.rep1] + jnc .l3 +.l1: + lea eax, [.IsRepG2*4 + ebx*4] + add eax, [.p] + call .RangeDecoderBitDecode + mov eax, [.rep2] + jnc .l2 + xchg [.rep3], eax +.l2: + push [.rep1] + pop [.rep2] +.l3: + xchg eax, [.rep0] + mov [.rep1], eax +.1101: + mov eax, .RepLencoder*4 + add eax, [.p] + call .LzmaLenDecode + cmp bl, 7 + setc bl + adc bl, bl + xor bl, 3 + add bl, 8 + jmp .repmovsb +.10: + mov eax, [.rep0] + xchg eax, [.rep1] + xchg eax, [.rep2] + xchg eax, [.rep3] + cmp bl, 7 + setc bl + adc bl, bl + xor bl, 3 + add bl, 7 + mov eax, .Lencoder*4 + add eax, [.p] + call .LzmaLenDecode + mov eax, .kNumLenToPosStates-1 + cmp eax, ecx + jb @f + mov eax, ecx +@@: + push ecx + mov ecx, .kNumPosSlotBits + shl eax, cl + shl eax, 2 + add eax, .PosSlot*4 + add eax, [.p] + call .RangeDecoderBitTreeDecode + mov [.rep0], ecx + cmp ecx, .kStartPosModelIndex + jb .l6 + push ecx + mov eax, ecx + and eax, 1 + shr ecx, 1 + or eax, 2 + dec ecx + shl eax, cl + mov [.rep0], eax + pop edx + cmp edx, .kEndPosModelIndex + jae .l5 + sub eax, edx + shl eax, 2 + add eax, (.SpecPos - 1)*4 + add eax, [.p] + call .RangeDecoderReverseBitTreeDecode + add [.rep0], ecx + jmp .l6 +.l5: + sub ecx, .kNumAlignBits + call .RangeDecoderDecodeDirectBits + mov ecx, .kNumAlignBits + shl eax, cl + add [.rep0], eax + mov eax, .Align_*4 + add eax, [.p] + call .RangeDecoderReverseBitTreeDecode + add [.rep0], ecx +.l6: + pop ecx + inc [.rep0] + jz .main_loop_done +.repmovsb: + add ecx, .kMatchMinLen + push esi + mov esi, edi + sub esi, [.rep0] + rep movsb + pop esi + mov al, [edi-1] + mov [.previousByte], al + jmp .main_loop +.main_loop_done: + ret + +.RangeDecoderBitDecode: +; in: eax->prob +; out: CF=bit; destroys eax + push edx + mov edx, [.range] + shr edx, .kNumBitModelTotalBits + imul edx, [eax] + cmp [.code_], edx + jae .ae + mov [.range], edx + mov edx, .kBitModelTotal + sub edx, [eax] + shr edx, .kNumMoveBits + add [eax], edx + clc +.n: + lahf + cmp [.range], .kTopValue + jae @f + shl [.range], 8 + shl [.code_], 8 + lodsb + mov byte [.code_], al +@@: + sahf + pop edx + ret +.ae: + sub [.range], edx + sub [.code_], edx + mov edx, [eax] + shr edx, .kNumMoveBits + sub [eax], edx + stc + jmp .n + +.RangeDecoderDecodeDirectBits: +; in: ecx=numTotalBits +; out: eax=result; destroys edx + xor eax, eax +.l: + shr [.range], 1 + shl eax, 1 + mov edx, [.code_] + sub edx, [.range] + jb @f + mov [.code_], edx + or eax, 1 +@@: + cmp [.range], .kTopValue + jae @f + shl [.range], 8 + shl [.code_], 8 + push eax + lodsb + mov byte [.code_], al + pop eax +@@: + loop .l + ret + +.LzmaLiteralDecode: +; in: eax->probs +; out: al=byte; destroys edx + push ecx + mov ecx, 1 +@@: + push eax + lea eax, [eax+ecx*4] + call .RangeDecoderBitDecode + pop eax + adc cl, cl + jnc @b +.LzmaLiteralDecode.ret: + mov al, cl + pop ecx + ret +.LzmaLiteralDecodeMatch: +; in: eax->probs, dl=matchByte +; out: al=byte; destroys edx + push ecx + mov ecx, 1 +.LzmaLiteralDecodeMatch.1: + add dl, dl + setc ch + push eax + lea eax, [eax+ecx*4+0x100*4] + call .RangeDecoderBitDecode + pop eax + adc cl, cl + jc .LzmaLiteralDecode.ret + xor ch, cl + test ch, 1 + mov ch, 0 + jnz @b + jmp .LzmaLiteralDecodeMatch.1 + +.LzmaLenDecode: +; in: eax->prob, edx=posState +; out: ecx=len + push eax + add eax, .LenChoice*4 + call .RangeDecoderBitDecode + pop eax + jnc .0 + push eax + add eax, .LenChoice2*4 + call .RangeDecoderBitDecode + pop eax + jc @f + mov ecx, .kLenNumMidBits + shl edx, cl + lea eax, [eax + .LenMid*4 + edx*4] + call .RangeDecoderBitTreeDecode + add ecx, .kLenNumLowSymbols + ret +@@: + add eax, .LenHigh*4 + mov ecx, .kLenNumHighBits + call .RangeDecoderBitTreeDecode + add ecx, .kLenNumLowSymbols + .kLenNumMidSymbols + ret +.0: + mov ecx, .kLenNumLowBits + shl edx, cl + lea eax, [eax + .LenLow*4 + edx*4] +.RangeDecoderBitTreeDecode: +; in: eax->probs,ecx=numLevels +; out: ecx=length; destroys edx + push ebx + mov edx, 1 + mov ebx, edx +@@: + push eax + lea eax, [eax+edx*4] + call .RangeDecoderBitDecode + pop eax + adc dl, dl + add bl, bl + loop @b + sub dl, bl + pop ebx + mov ecx, edx + ret +.RangeDecoderReverseBitTreeDecode: +; in: eax->probs,ecx=numLevels +; out: ecx=length; destroys edx + push ebx ecx + mov edx, 1 + xor ebx, ebx +@@: + push eax + lea eax, [eax+edx*4] + call .RangeDecoderBitDecode + lahf + adc edx, edx + sahf + rcr ebx, 1 + pop eax + loop @b + pop ecx + rol ebx, cl + mov ecx, ebx + pop ebx + ret + +uglobal +align 4 +;unpack.p rd unpack.LZMA_BASE_SIZE + (unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp)) +unpack.p dd ? +unpack.code_ dd ? +unpack.range dd ? +unpack.rep0 dd ? +unpack.rep1 dd ? +unpack.rep2 dd ? +unpack.rep3 dd ? +unpack.previousByte db ? +endg diff --git a/kernel/trunk/video/blitter.inc b/kernel/trunk/video/blitter.inc index 9fed049aa..4fa2a8d08 100644 --- a/kernel/trunk/video/blitter.inc +++ b/kernel/trunk/video/blitter.inc @@ -34,128 +34,128 @@ end virtual align 4 __L1OutCode: - push ebx - mov ebx, 8 - cmp edx, [eax] - jl .L2 - xor ebx, ebx - cmp edx, [eax+8] - setg bl - sal ebx, 2 + push ebx + mov ebx, 8 + cmp edx, [eax] + jl .L2 + xor ebx, ebx + cmp edx, [eax+8] + setg bl + sal ebx, 2 .L2: - cmp ecx, [eax+4] - jge .L3 - or ebx, 1 - jmp .L4 + cmp ecx, [eax+4] + jge .L3 + or ebx, 1 + jmp .L4 .L3: - cmp ecx, [eax+12] - jle .L4 - or ebx, 2 + cmp ecx, [eax+12] + jle .L4 + or ebx, 2 .L4: - mov eax, ebx - pop ebx + mov eax, ebx + pop ebx ret align 4 block_clip: - push ebp - push edi - push esi - push ebx - sub esp, 4 + push ebp + push edi + push esi + push ebx + sub esp, 4 - mov ebx, eax - mov [esp], edx - mov ebp, ecx - mov ecx, [ecx] - mov edx, [edx] - call __L1OutCode + mov ebx, eax + mov [esp], edx + mov ebp, ecx + mov ecx, [ecx] + mov edx, [edx] + call __L1OutCode - mov esi, eax - mov edx, [esp+28] - mov ecx, [edx] + mov esi, eax + mov edx, [esp+28] + mov ecx, [edx] .L21: - mov eax, [esp+24] - mov edx, [eax] - mov eax, ebx - call __L1OutCode + mov eax, [esp+24] + mov edx, [eax] + mov eax, ebx + call __L1OutCode - mov edi, eax + mov edi, eax .L20: - mov eax, edi - and eax, esi - jne .L9 - cmp esi, edi - je .L9 - test esi, esi - jne .L10 - test edi, 1 - je .L11 - mov eax, [ebx+4] - jmp .L25 + mov eax, edi + and eax, esi + jne .L9 + cmp esi, edi + je .L9 + test esi, esi + jne .L10 + test edi, 1 + je .L11 + mov eax, [ebx+4] + jmp .L25 .L11: - test edi, 2 - je .L13 - mov eax, [ebx+12] + test edi, 2 + je .L13 + mov eax, [ebx+12] .L25: - mov edx, [esp+28] - jmp .L22 + mov edx, [esp+28] + jmp .L22 .L13: - test edi, 4 - je .L14 - mov eax, [ebx+8] - jmp .L26 + test edi, 4 + je .L14 + mov eax, [ebx+8] + jmp .L26 .L14: - and edi, 8 - je .L12 - mov eax, [ebx] + and edi, 8 + je .L12 + mov eax, [ebx] .L26: - mov edx, [esp+24] + mov edx, [esp+24] .L22: - mov [edx], eax + mov [edx], eax .L12: - mov eax, [esp+28] - mov ecx, [eax] - jmp .L21 + mov eax, [esp+28] + mov ecx, [eax] + jmp .L21 .L10: - test esi, 1 - je .L16 - mov eax, [ebx+4] - jmp .L23 + test esi, 1 + je .L16 + mov eax, [ebx+4] + jmp .L23 .L16: - test esi, 2 - je .L18 - mov eax, [ebx+12] + test esi, 2 + je .L18 + mov eax, [ebx+12] .L23: - mov [ebp+0], eax - jmp .L17 + mov [ebp+0], eax + jmp .L17 .L18: - test esi, 4 - je .L19 - mov eax, [ebx+8] - jmp .L24 + test esi, 4 + je .L19 + mov eax, [ebx+8] + jmp .L24 .L19: - and esi, 8 - je .L17 - mov eax, [ebx] + and esi, 8 + je .L17 + mov eax, [ebx] .L24: - mov edx, [esp] - mov [edx], eax + mov edx, [esp] + mov [edx], eax .L17: - mov ecx, [ebp+0] - mov eax, [esp] - mov edx, [eax] - mov eax, ebx - call __L1OutCode - mov esi, eax - jmp .L20 + mov ecx, [ebp+0] + mov eax, [esp] + mov edx, [eax] + mov eax, ebx + call __L1OutCode + mov esi, eax + jmp .L20 .L9: - add esp, 4 - pop ebx - pop esi - pop edi - pop ebp + add esp, 4 + pop ebx + pop esi + pop edi + pop ebp ret align 4 @@ -172,97 +172,97 @@ blit_clip: .dy1 equ 8 - push edi - push esi - push ebx - sub esp, 40 + push edi + push esi + push ebx + sub esp, 40 - mov ebx, ecx - mov edx, [ecx+BLITTER.src_x] - mov [esp+.sx0], edx - mov eax, [ecx+BLITTER.src_y] - mov [esp+.sy0], eax - add edx, [ecx+BLITTER.w] - dec edx - mov [esp+.sx1], edx - add eax, [ecx+BLITTER.h] - dec eax - mov [esp+.sy1], eax + mov ebx, ecx + mov edx, [ecx+BLITTER.src_x] + mov [esp+.sx0], edx + mov eax, [ecx+BLITTER.src_y] + mov [esp+.sy0], eax + add edx, [ecx+BLITTER.w] + dec edx + mov [esp+.sx1], edx + add eax, [ecx+BLITTER.h] + dec eax + mov [esp+.sy1], eax - lea ecx, [esp+.sy0] - lea edx, [esp+.sx0] - lea eax, [ebx+BLITTER.sc] - lea esi, [esp+.sy1] + lea ecx, [esp+.sy0] + lea edx, [esp+.sx0] + lea eax, [ebx+BLITTER.sc] + lea esi, [esp+.sy1] - mov [esp+4], esi - lea esi, [esp+.sx1] - mov [esp], esi - call block_clip + mov [esp+4], esi + lea esi, [esp+.sx1] + mov [esp], esi + call block_clip - mov esi, 1 - test eax, eax - jne .L28 + mov esi, 1 + test eax, eax + jne .L28 - mov edi, [esp+.sx0] - mov edx, [ebx+BLITTER.dst_x] - add edx, edi - sub edx, [ebx+BLITTER.src_x] - mov [esp+.dx0], edx + mov edi, [esp+.sx0] + mov edx, [ebx+BLITTER.dst_x] + add edx, edi + sub edx, [ebx+BLITTER.src_x] + mov [esp+.dx0], edx - mov ecx, [esp+.sy0] - mov eax, [ebx+BLITTER.dst_y] - add eax, ecx - sub eax, [ebx+BLITTER.src_y] - mov [esp+.dy0], eax - sub edx, edi - add edx, [esp+.sx1] - mov [esp+.dx1], edx + mov ecx, [esp+.sy0] + mov eax, [ebx+BLITTER.dst_y] + add eax, ecx + sub eax, [ebx+BLITTER.src_y] + mov [esp+.dy0], eax + sub edx, edi + add edx, [esp+.sx1] + mov [esp+.dx1], edx - sub eax, ecx - add eax, [esp+.sy1] - mov [esp+.dy1], eax + sub eax, ecx + add eax, [esp+.sy1] + mov [esp+.dy1], eax - lea ecx, [esp+.dy0] - lea edx, [esp+.dx0] - lea eax, [esp+.dy1] - mov [esp+4], eax - lea eax, [esp+.dx1] - mov [esp], eax - mov eax, ebx - call block_clip - test eax, eax - jne .L28 + lea ecx, [esp+.dy0] + lea edx, [esp+.dx0] + lea eax, [esp+.dy1] + mov [esp+4], eax + lea eax, [esp+.dx1] + mov [esp], eax + mov eax, ebx + call block_clip + test eax, eax + jne .L28 - mov edx, [esp+.dx0] - mov eax, [esp+.dx1] - inc eax - sub eax, edx - mov [ebx+BLITTER.w], eax + mov edx, [esp+.dx0] + mov eax, [esp+.dx1] + inc eax + sub eax, edx + mov [ebx+BLITTER.w], eax - mov eax, [esp+.dy0] - mov ecx, [esp+.dy1] - inc ecx - sub ecx, eax - mov [ebx+BLITTER.h], ecx + mov eax, [esp+.dy0] + mov ecx, [esp+.dy1] + inc ecx + sub ecx, eax + mov [ebx+BLITTER.h], ecx - mov ecx, [ebx+BLITTER.src_x] - add ecx, edx - sub ecx, [ebx+BLITTER.dst_x] - mov [ebx+BLITTER.src_x], ecx + mov ecx, [ebx+BLITTER.src_x] + add ecx, edx + sub ecx, [ebx+BLITTER.dst_x] + mov [ebx+BLITTER.src_x], ecx - mov ecx, [ebx+BLITTER.src_y] - add ecx, eax - sub ecx, [ebx+BLITTER.dst_y] - mov [ebx+BLITTER.src_y], ecx - mov [ebx+BLITTER.dst_x], edx - mov [ebx+BLITTER.dst_y], eax - xor esi, esi + mov ecx, [ebx+BLITTER.src_y] + add ecx, eax + sub ecx, [ebx+BLITTER.dst_y] + mov [ebx+BLITTER.src_y], ecx + mov [ebx+BLITTER.dst_x], edx + mov [ebx+BLITTER.dst_y], eax + xor esi, esi .L28: - mov eax, esi - add esp, 40 - pop ebx - pop esi - pop edi + mov eax, esi + add esp, 40 + pop ebx + pop esi + pop edi purge .sx0 @@ -282,163 +282,163 @@ purge .dy1 align 4 blit_32: - push ebp - push edi - push esi - push ebx - sub esp, 72 + push ebp + push edi + push esi + push ebx + sub esp, 72 - mov eax, [TASK_BASE] - mov ebx, [eax-twdw + WDATA.box.width] - mov edx, [eax-twdw + WDATA.box.height] + mov eax, [TASK_BASE] + mov ebx, [eax-twdw + WDATA.box.width] + mov edx, [eax-twdw + WDATA.box.height] - xor eax, eax + xor eax, eax - mov [esp+BLITTER.dc.xmin], eax - mov [esp+BLITTER.dc.ymin], eax - mov [esp+BLITTER.dc.xmax], ebx - mov [esp+BLITTER.dc.ymax], edx + mov [esp+BLITTER.dc.xmin], eax + mov [esp+BLITTER.dc.ymin], eax + mov [esp+BLITTER.dc.xmax], ebx + mov [esp+BLITTER.dc.ymax], edx - mov [esp+BLITTER.sc.xmin], eax - mov [esp+BLITTER.sc.ymin], eax - mov eax, [ecx+24] - dec eax - mov [esp+BLITTER.sc.xmax], eax - mov eax, [ecx+28] - dec eax - mov [esp+BLITTER.sc.ymax], eax + mov [esp+BLITTER.sc.xmin], eax + mov [esp+BLITTER.sc.ymin], eax + mov eax, [ecx+24] + dec eax + mov [esp+BLITTER.sc.xmax], eax + mov eax, [ecx+28] + dec eax + mov [esp+BLITTER.sc.ymax], eax - mov eax, [ecx] - mov [esp+BLITTER.dst_x], eax - mov eax, [ecx+4] - mov [esp+BLITTER.dst_y], eax + mov eax, [ecx] + mov [esp+BLITTER.dst_x], eax + mov eax, [ecx+4] + mov [esp+BLITTER.dst_y], eax - mov eax, [ecx+16] - mov [esp+BLITTER.src_x], eax - mov eax, [ecx+20] - mov [esp+BLITTER.src_y], eax - mov eax, [ecx+8] - mov [esp+BLITTER.w], eax - mov eax, [ecx+12] - mov [esp+BLITTER.h], eax + mov eax, [ecx+16] + mov [esp+BLITTER.src_x], eax + mov eax, [ecx+20] + mov [esp+BLITTER.src_y], eax + mov eax, [ecx+8] + mov [esp+BLITTER.w], eax + mov eax, [ecx+12] + mov [esp+BLITTER.h], eax - mov eax, [ecx+32] - mov [esp+56], eax - mov eax, [ecx+36] - mov [esp+60], eax + mov eax, [ecx+32] + mov [esp+56], eax + mov eax, [ecx+36] + mov [esp+60], eax - mov ecx, esp - call blit_clip - test eax, eax - jne .L57 + mov ecx, esp + call blit_clip + test eax, eax + jne .L57 - inc [mouse_pause] - call [_display.disable_mouse] + inc [mouse_pause] + call [_display.disable_mouse] - mov eax, [TASK_BASE] + mov eax, [TASK_BASE] - mov ebx, [esp+BLITTER.dst_x] - mov ebp, [esp+BLITTER.dst_y] - add ebx, [eax-twdw + WDATA.box.left] - add ebp, [eax-twdw + WDATA.box.top] - mov edi, ebp + mov ebx, [esp+BLITTER.dst_x] + mov ebp, [esp+BLITTER.dst_y] + add ebx, [eax-twdw + WDATA.box.left] + add ebp, [eax-twdw + WDATA.box.top] + mov edi, ebp - imul edi, [_display.pitch] - imul ebp, [_display.width] - add ebp, ebx - add ebp, [_WinMapAddress] + imul edi, [_display.pitch] + imul ebp, [_display.width] + add ebp, ebx + add ebp, [_WinMapAddress] - mov eax, [esp+BLITTER.src_y] - imul eax, [esp+BLITTER.stride] - mov esi, [esp+BLITTER.src_x] - lea esi, [eax+esi*4] - add esi, [esp+BLITTER.bitmap] + mov eax, [esp+BLITTER.src_y] + imul eax, [esp+BLITTER.stride] + mov esi, [esp+BLITTER.src_x] + lea esi, [eax+esi*4] + add esi, [esp+BLITTER.bitmap] - mov ecx, [esp+BLITTER.h] - mov edx, [esp+BLITTER.w] + mov ecx, [esp+BLITTER.h] + mov edx, [esp+BLITTER.w] - test ecx, ecx ;FIXME check clipping - jz .L57 + test ecx, ecx ;FIXME check clipping + jz .L57 - test edx, edx - jz .L57 + test edx, edx + jz .L57 - cmp [_display.bpp], 32 - jne .core_24 + cmp [_display.bpp], 32 + jne .core_24 - lea edi, [edi+ebx*4] + lea edi, [edi+ebx*4] - mov ebx, [CURRENT_TASK] + mov ebx, [CURRENT_TASK] align 4 .outer32: - xor ecx, ecx + xor ecx, ecx align 4 .inner32: - cmp [ebp+ecx], bl - jne @F + cmp [ebp+ecx], bl + jne @F - mov eax, [esi+ecx*4] - mov [LFB_BASE+edi+ecx*4], eax + mov eax, [esi+ecx*4] + mov [LFB_BASE+edi+ecx*4], eax @@: - inc ecx - dec edx - jnz .inner32 + inc ecx + dec edx + jnz .inner32 - add esi, [esp+BLITTER.stride] - add edi, [_display.pitch] - add ebp, [_display.width] + add esi, [esp+BLITTER.stride] + add edi, [_display.pitch] + add ebp, [_display.width] - mov edx, [esp+BLITTER.w] - dec [esp+BLITTER.h] - jnz .outer32 + mov edx, [esp+BLITTER.w] + dec [esp+BLITTER.h] + jnz .outer32 .done: - dec [mouse_pause] - call [draw_pointer] + dec [mouse_pause] + call [draw_pointer] .L57: - add esp, 72 - pop ebx - pop esi - pop edi - pop ebp + add esp, 72 + pop ebx + pop esi + pop edi + pop ebp ret .core_24: - lea ebx, [ebx+ebx*2] - lea edi, [LFB_BASE+edi+ebx] - mov ebx, [CURRENT_TASK] + lea ebx, [ebx+ebx*2] + lea edi, [LFB_BASE+edi+ebx] + mov ebx, [CURRENT_TASK] align 4 .outer24: - mov [esp+64], edi - xor ecx, ecx + mov [esp+64], edi + xor ecx, ecx align 4 .inner24: - cmp [ebp+ecx], bl - jne @F + cmp [ebp+ecx], bl + jne @F - mov eax, [esi+ecx*4] + mov eax, [esi+ecx*4] - lea edi, [edi+ecx*2] - mov [edi+ecx], ax - shr eax, 16 - mov [edi+ecx+2], al + lea edi, [edi+ecx*2] + mov [edi+ecx], ax + shr eax, 16 + mov [edi+ecx+2], al @@: - mov edi, [esp+64] - inc ecx - dec edx - jnz .inner24 + mov edi, [esp+64] + inc ecx + dec edx + jnz .inner24 - add esi, [esp+BLITTER.stride] - add edi, [_display.pitch] - add ebp, [_display.width] + add esi, [esp+BLITTER.stride] + add edi, [_display.pitch] + add ebp, [_display.width] - mov edx, [esp+BLITTER.w] - dec [esp+BLITTER.h] - jnz .outer24 + mov edx, [esp+BLITTER.w] + dec [esp+BLITTER.h] + jnz .outer24 - jmp .done + jmp .done diff --git a/kernel/trunk/video/cursors.inc b/kernel/trunk/video/cursors.inc index 86298f1f3..630119886 100644 --- a/kernel/trunk/video/cursors.inc +++ b/kernel/trunk/video/cursors.inc @@ -1,806 +1,806 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -LOAD_FROM_FILE equ 0 -LOAD_FROM_MEM equ 1 -LOAD_INDIRECT equ 2 -LOAD_SYSTEM equ 3 - -struc BITMAPINFOHEADER { - .biSize dd ? ; DWORD - .biWidth dd ? ; LONG - .biHeight dd ? ; LONG - .biPlanes dw ? ; WORD - .biBitCount dw ? ; WORD - .biCompression dd ? ; DWORD - .biSizeImage dd ? ; DWORD - .biXPelsPerMeter dd ? ; LONG - .biYPelsPerMeter dd ? ; LONG - .biClrUsed dd ? ; DWORD - .biClrImportant dd ? ; DWORD -} - -virtual at 0 - BI BITMAPINFOHEADER -end virtual - -align 4 -proc init_cursor stdcall, dst:dword, src:dword - locals - rBase dd ? - pQuad dd ? - pBits dd ? - pAnd dd ? - width dd ? - height dd ? - counter dd ? - endl - - mov esi, [src] - add esi,[esi+18] - mov eax,esi - - cmp [esi+BI.biBitCount], 24 - je .img_24 - cmp [esi+BI.biBitCount], 8 - je .img_8 - cmp [esi+BI.biBitCount], 4 - je .img_4 - -.img_2: - add eax, [esi] - mov [pQuad],eax - add eax,8 - mov [pBits],eax - add eax, 128 - mov [pAnd],eax - mov eax,[esi+4] - mov [width],eax - mov ebx,[esi+8] - shr ebx,1 - mov [height],ebx - - mov edi, [dst] - add edi, 32*31*4 - mov [rBase],edi - - mov esi,[pQuad] -.l21: - mov ebx, [pBits] - mov ebx, [ebx] - bswap ebx - mov eax, [pAnd] - mov eax, [eax] - bswap eax - mov [counter], 32 -@@: - xor edx, edx - shl eax,1 - setc dl - dec edx - - xor ecx, ecx - shl ebx,1 - setc cl - mov ecx, [esi+ecx*4] - and ecx, edx - and edx, 0xFF000000 - or edx, ecx - mov [edi], edx - - add edi, 4 - dec [counter] - jnz @B - - add [pBits], 4 - add [pAnd], 4 - mov edi,[rBase] - sub edi,128 - mov [rBase],edi - sub [height],1 - jnz .l21 - ret - -.img_4: - add eax, [esi] - mov [pQuad],eax - add eax,64 - mov [pBits],eax - add eax, 0x200 - mov [pAnd],eax - mov eax,[esi+4] - mov [width],eax - mov ebx,[esi+8] - shr ebx,1 - mov [height],ebx - - mov edi, [dst] - add edi, 32*31*4 - mov [rBase],edi - - mov esi,[pQuad] - mov ebx, [pBits] -.l4: - mov eax, [pAnd] - mov eax, [eax] - bswap eax - mov [counter], 16 -@@: - xor edx, edx - shl eax,1 - setc dl - dec edx - - movzx ecx, byte [ebx] - and cl, 0xF0 - shr ecx, 2 - mov ecx, [esi+ecx] - and ecx, edx - and edx, 0xFF000000 - or edx, ecx - mov [edi], edx - - xor edx, edx - shl eax,1 - setc dl - dec edx - - movzx ecx, byte [ebx] - and cl, 0x0F - mov ecx, [esi+ecx*4] - and ecx, edx - and edx, 0xFF000000 - or edx, ecx - mov [edi+4], edx - - inc ebx - add edi, 8 - dec [counter] - jnz @B - - add [pAnd], 4 - mov edi,[rBase] - sub edi,128 - mov [rBase],edi - sub [height],1 - jnz .l4 - ret -.img_8: - add eax, [esi] - mov [pQuad],eax - add eax,1024 - mov [pBits],eax - add eax, 1024 - mov [pAnd],eax - mov eax,[esi+4] - mov [width],eax - mov ebx,[esi+8] - shr ebx,1 - mov [height],ebx - - mov edi, [dst] - add edi, 32*31*4 - mov [rBase],edi - - mov esi,[pQuad] - mov ebx, [pBits] -.l81: - mov eax, [pAnd] - mov eax, [eax] - bswap eax - mov [counter], 32 -@@: - xor edx, edx - shl eax,1 - setc dl - dec edx - - movzx ecx, byte [ebx] - mov ecx, [esi+ecx*4] - and ecx, edx - and edx, 0xFF000000 - or edx, ecx - mov [edi], edx - - inc ebx - add edi, 4 - dec [counter] - jnz @B - - add [pAnd], 4 - mov edi,[rBase] - sub edi,128 - mov [rBase],edi - sub [height],1 - jnz .l81 - ret -.img_24: - add eax, [esi] - mov [pQuad],eax - add eax, 0xC00 - mov [pAnd],eax - mov eax,[esi+BI.biWidth] - mov [width],eax - mov ebx,[esi+BI.biHeight] - shr ebx,1 - mov [height],ebx - - mov edi, [dst] - add edi, 32*31*4 - mov [rBase],edi - - mov esi,[pAnd] - mov ebx, [pQuad] -.row_24: - mov eax, [esi] - bswap eax - mov [counter], 32 -@@: - xor edx, edx - shl eax,1 - setc dl - dec edx - - mov ecx, [ebx] - and ecx, 0x00FFFFFF - and ecx, edx - and edx, 0xFF000000 - or edx, ecx - mov [edi], edx - add ebx, 3 - add edi, 4 - dec [counter] - jnz @B - - add esi, 4 - mov edi,[rBase] - sub edi,128 - mov [rBase],edi - sub [height],1 - jnz .row_24 - ret -endp - -align 4 -proc set_cursor stdcall, hcursor:dword - mov eax, [hcursor] - cmp [eax+CURSOR.magic], 'CURS' - jne .fail -; cmp [eax+CURSOR.size], CURSOR_SIZE -; jne .fail - mov ebx, [current_slot] - xchg eax, [ebx+APPDATA.cursor] - ret -.fail: - mov eax, [def_cursor] - mov ebx, [current_slot] - xchg eax, [ebx+APPDATA.cursor] - ret -endp - -; param -; eax= pid -; ebx= src -; ecx= flags - -create_cursor: -.src equ esp -.flags equ esp+4 -.hcursor equ esp+8 - - sub esp, 4 ;space for .hcursor - push ecx - push ebx - - mov ebx, eax - mov eax, CURSOR.sizeof - call create_kernel_object - test eax, eax - jz .fail - - mov [.hcursor],eax - - xor ebx, ebx - mov [eax+CURSOR.magic], 'CURS' - mov [eax+CURSOR.destroy], destroy_cursor - mov [eax+CURSOR.hot_x], ebx - mov [eax+CURSOR.hot_y], ebx - - stdcall kernel_alloc, 0x1000 - test eax, eax - jz .fail - - mov edi, [.hcursor] - mov [edi+CURSOR.base], eax - - mov esi, [.src] - mov ebx, [.flags] - cmp bx, LOAD_INDIRECT - je .indirect - - movzx ecx, word [esi+10] - movzx edx, word [esi+12] - mov [edi+CURSOR.hot_x], ecx - mov [edi+CURSOR.hot_y], edx - - stdcall init_cursor, eax, esi - - mov eax, [.hcursor] - lea eax, [eax+CURSOR.list_next] - lea edx, [_display.cr_list.next] - - pushfd - cli - mov ecx, [edx] - - mov [eax], ecx - mov [eax+4], edx - - mov [ecx+4], eax - mov [edx], eax - popfd - - mov eax, [.hcursor] -.check_hw: - cmp [_display.init_cursor], 0 - je .fail - - push eax - call [_display.init_cursor] - add esp, 4 - - mov eax, [.hcursor] -.fail: - add esp, 12 - ret -.indirect: - shr ebx, 16 - movzx ecx, bh - movzx edx, bl - mov [eax+CURSOR.hot_x], ecx - mov [eax+CURSOR.hot_y], edx - - xchg edi, eax - mov ecx, 1024 - cld - rep movsd - jmp .check_hw - -align 4 -proc load_cursor stdcall, src:dword, flags:dword - locals - handle dd ? - endl - - xor eax, eax - cmp [create_cursor], eax - je .fail2 - - mov [handle], eax - cmp word [flags], LOAD_FROM_FILE - jne @F - - stdcall load_file, [src] - test eax, eax - jz .fail - mov [src], eax -@@: - push ebx - push esi - push edi - - mov eax, [CURRENT_TASK] - shl eax, 5 - mov eax, [CURRENT_TASK+eax+4] - mov ebx, [src] - mov ecx, [flags] - call create_cursor ;eax, ebx, ecx - mov [handle], eax - - cmp word [flags], LOAD_FROM_FILE - jne .exit - stdcall kernel_free, [src] -.exit: - pop edi - pop esi - pop ebx -.fail: - mov eax, [handle] -.fail2: - ret -endp - -align 4 -proc delete_cursor stdcall, hcursor:dword - locals - hsrv dd ? - io_code dd ? - input dd ? - inp_size dd ? - output dd ? - out_size dd ? - endl - - mov esi, [hcursor] - cmp [esi+CURSOR.magic], 'CURS' - jne .fail - - mov ebx, [CURRENT_TASK] - shl ebx, 5 - mov ebx, [CURRENT_TASK+ebx+4] - cmp ebx, [esi+CURSOR.pid] - jne .fail - - mov ebx, [current_slot] - cmp esi, [ebx+APPDATA.cursor] - jne @F - mov eax, [def_cursor] - mov [ebx+APPDATA.cursor], eax -@@: - mov eax, [hcursor] - call [eax+APPOBJ.destroy] -.fail: - ret -endp - -; param -; eax= cursor - -align 4 -destroy_cursor: - - push eax - stdcall kernel_free, [eax+CURSOR.base] - pop eax - - call destroy_kernel_object - ret - -align 4 -select_cursor: - mov eax, [esp+4] - mov [_display.cursor], eax - ret 4 - -align 4 -proc restore_24 stdcall, x:dword, y:dword - - push ebx - - mov ebx, [cur_saved_base] - mov edx, [cur.h] - test edx, edx - jz .ret - - push esi - push edi - - mov esi, cur_saved_data - mov ecx, [cur.w] - lea ecx, [ecx+ecx*2] - push ecx -@@: - mov edi, ebx - add ebx, [BytesPerScanLine] - - mov ecx, [esp] - rep movsb - dec edx - jnz @B - - pop ecx - pop edi - pop esi -.ret: - pop ebx - ret -endp - -align 4 -proc restore_32 stdcall, x:dword, y:dword - - push ebx - - mov ebx, [cur_saved_base] - mov edx, [cur.h] - test edx, edx - jz .ret - - push esi - push edi - - mov esi, cur_saved_data -@@: - mov edi, ebx - add ebx, [BytesPerScanLine] - - mov ecx, [cur.w] - rep movsd - dec edx - jnz @B - - pop edi -.ret: - pop esi - pop ebx - ret -endp - -align 4 -proc move_cursor_24 stdcall, hcursor:dword, x:dword, y:dword - locals - h dd ? - _dx dd ? - _dy dd ? - endl - - mov esi, [hcursor] - mov ecx, [x] - mov eax, [y] - mov ebx, [BytesPerScanLine] - - xor edx, edx - sub ecx, [esi+CURSOR.hot_x] - lea ebx, [ecx+32-1] - mov [x], ecx - sets dl - dec edx - and ecx, edx ;clip x to 0<=x - mov [cur.left], ecx - mov edi, ecx - sub edi, [x] - mov [_dx], edi - - xor edx, edx - sub eax, [esi+CURSOR.hot_y] - lea edi, [eax+32-1] - mov [y], eax - sets dl - dec edx - and eax, edx ;clip y to 0<=y - mov [cur.top], eax - mov edx, eax - sub edx, [y] - mov [_dy], edx - - mul dword [BytesPerScanLine] - lea edx, [LFB_BASE+ecx*3] - add edx, eax - mov [cur_saved_base],edx - - cmp ebx, [Screen_Max_X] - jbe @F - mov ebx, [Screen_Max_X] -@@: - cmp edi, [Screen_Max_Y] - jbe @F - mov edi, [Screen_Max_Y] -@@: - mov [cur.right], ebx - mov [cur.bottom], edi - - sub ebx, [x] - sub edi, [y] - inc ebx - inc edi - - mov [cur.w], ebx - mov [cur.h], edi - mov [h], edi - - mov eax, edi - mov edi, cur_saved_data -@@: - mov esi, edx - add edx, [BytesPerScanLine] - mov ecx, [cur.w] - lea ecx, [ecx+ecx*2] - rep movsb - dec eax - jnz @B - -;draw cursor - mov ebx, [cur_saved_base] - mov eax, [_dy] - shl eax, 5 - add eax, [_dx] - - mov esi, [hcursor] - mov esi, [esi+CURSOR.base] - lea edx, [esi+eax*4] -.row: - mov ecx, [cur.w] - mov esi, edx - mov edi, ebx - add edx, 32*4 - add ebx, [BytesPerScanLine] -.pix: - lodsd - test eax, 0xFF000000 - jz @F - mov [edi], ax - shr eax, 16 - mov [edi+2],al -@@: - add edi, 3 - dec ecx - jnz .pix - - dec [h] - jnz .row - ret -endp - - -align 4 -proc move_cursor_32 stdcall, hcursor:dword, x:dword, y:dword - locals - h dd ? - _dx dd ? - _dy dd ? - endl - - mov esi, [hcursor] - mov ecx, [x] - mov eax, [y] - - xor edx, edx - sub ecx, [esi+CURSOR.hot_x] - lea ebx, [ecx+32-1] - mov [x], ecx - sets dl - dec edx - and ecx, edx ;clip x to 0<=x - mov [cur.left], ecx - mov edi, ecx - sub edi, [x] - mov [_dx], edi - - xor edx, edx - sub eax, [esi+CURSOR.hot_y] - lea edi, [eax+32-1] - mov [y], eax - sets dl - dec edx - and eax, edx ;clip y to 0<=y - mov [cur.top], eax - mov edx, eax - sub edx, [y] - mov [_dy], edx - - mul dword [BytesPerScanLine] - lea edx, [LFB_BASE+eax+ecx*4] - mov [cur_saved_base],edx - - cmp ebx, [Screen_Max_X] - jbe @F - mov ebx, [Screen_Max_X] -@@: - cmp edi, [Screen_Max_Y] - jbe @F - mov edi, [Screen_Max_Y] -@@: - mov [cur.right], ebx - mov [cur.bottom], edi - - sub ebx, [x] - sub edi, [y] - inc ebx - inc edi - - mov [cur.w], ebx - mov [cur.h], edi - mov [h], edi - - mov eax, edi - mov edi, cur_saved_data -@@: - mov esi, edx - add edx, [BytesPerScanLine] - mov ecx, [cur.w] - rep movsd - dec eax - jnz @B - -;draw cursor - mov ebx, [cur_saved_base] - mov eax, [_dy] - shl eax, 5 - add eax, [_dx] - - mov esi, [hcursor] - mov esi, [esi+CURSOR.base] - lea edx, [esi+eax*4] -.row: - mov ecx, [cur.w] - mov esi, edx - mov edi, ebx - add edx, 32*4 - add ebx, [BytesPerScanLine] -.pix: - lodsd - test eax, 0xFF000000 - jz @F - mov [edi], eax -@@: - add edi, 4 - dec ecx - jnz .pix - - dec [h] - jnz .row - ret -endp - - -align 4 -get_display: - mov eax, _display - ret - -align 4 -init_display: - - xor eax, eax - mov edi, _display - - mov [edi+display_t.init_cursor], eax - mov [edi+display_t.select_cursor], eax - mov [edi+display_t.show_cursor], eax - mov [edi+display_t.move_cursor], eax - mov [edi+display_t.restore_cursor], eax - - lea ecx, [edi+display_t.cr_list.next] - mov [edi+display_t.cr_list.next], ecx - mov [edi+display_t.cr_list.prev], ecx - - cmp [SCR_MODE],word 0x13 - jbe .fail - - test word [SCR_MODE], 0x4000 - jz .fail - - mov ebx, restore_32 - mov ecx, move_cursor_32 - movzx eax, byte [ScreenBPP] - cmp eax, 32 - je @F - - mov ebx, restore_24 - mov ecx, move_cursor_24 - cmp eax, 24 - jne .fail -@@: - mov [_display.select_cursor], select_cursor - mov [_display.move_cursor], ecx - mov [_display.restore_cursor], ebx - - stdcall load_cursor, def_arrow, dword LOAD_FROM_MEM - mov [def_cursor], eax - ret -.fail: - xor eax, eax - mov [_display.select_cursor], eax - mov [_display.move_cursor], eax - ret - - - - - - - - - - -align 4 -def_arrow: - file 'arrow.cur' - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +LOAD_FROM_FILE equ 0 +LOAD_FROM_MEM equ 1 +LOAD_INDIRECT equ 2 +LOAD_SYSTEM equ 3 + +struc BITMAPINFOHEADER { + .biSize dd ? ; DWORD + .biWidth dd ? ; LONG + .biHeight dd ? ; LONG + .biPlanes dw ? ; WORD + .biBitCount dw ? ; WORD + .biCompression dd ? ; DWORD + .biSizeImage dd ? ; DWORD + .biXPelsPerMeter dd ? ; LONG + .biYPelsPerMeter dd ? ; LONG + .biClrUsed dd ? ; DWORD + .biClrImportant dd ? ; DWORD +} + +virtual at 0 + BI BITMAPINFOHEADER +end virtual + +align 4 +proc init_cursor stdcall, dst:dword, src:dword + locals + rBase dd ? + pQuad dd ? + pBits dd ? + pAnd dd ? + width dd ? + height dd ? + counter dd ? + endl + + mov esi, [src] + add esi, [esi+18] + mov eax, esi + + cmp [esi+BI.biBitCount], 24 + je .img_24 + cmp [esi+BI.biBitCount], 8 + je .img_8 + cmp [esi+BI.biBitCount], 4 + je .img_4 + +.img_2: + add eax, [esi] + mov [pQuad], eax + add eax, 8 + mov [pBits], eax + add eax, 128 + mov [pAnd], eax + mov eax, [esi+4] + mov [width], eax + mov ebx, [esi+8] + shr ebx, 1 + mov [height], ebx + + mov edi, [dst] + add edi, 32*31*4 + mov [rBase], edi + + mov esi, [pQuad] +.l21: + mov ebx, [pBits] + mov ebx, [ebx] + bswap ebx + mov eax, [pAnd] + mov eax, [eax] + bswap eax + mov [counter], 32 +@@: + xor edx, edx + shl eax, 1 + setc dl + dec edx + + xor ecx, ecx + shl ebx, 1 + setc cl + mov ecx, [esi+ecx*4] + and ecx, edx + and edx, 0xFF000000 + or edx, ecx + mov [edi], edx + + add edi, 4 + dec [counter] + jnz @B + + add [pBits], 4 + add [pAnd], 4 + mov edi, [rBase] + sub edi, 128 + mov [rBase], edi + sub [height], 1 + jnz .l21 + ret + +.img_4: + add eax, [esi] + mov [pQuad], eax + add eax, 64 + mov [pBits], eax + add eax, 0x200 + mov [pAnd], eax + mov eax, [esi+4] + mov [width], eax + mov ebx, [esi+8] + shr ebx, 1 + mov [height], ebx + + mov edi, [dst] + add edi, 32*31*4 + mov [rBase], edi + + mov esi, [pQuad] + mov ebx, [pBits] +.l4: + mov eax, [pAnd] + mov eax, [eax] + bswap eax + mov [counter], 16 +@@: + xor edx, edx + shl eax, 1 + setc dl + dec edx + + movzx ecx, byte [ebx] + and cl, 0xF0 + shr ecx, 2 + mov ecx, [esi+ecx] + and ecx, edx + and edx, 0xFF000000 + or edx, ecx + mov [edi], edx + + xor edx, edx + shl eax, 1 + setc dl + dec edx + + movzx ecx, byte [ebx] + and cl, 0x0F + mov ecx, [esi+ecx*4] + and ecx, edx + and edx, 0xFF000000 + or edx, ecx + mov [edi+4], edx + + inc ebx + add edi, 8 + dec [counter] + jnz @B + + add [pAnd], 4 + mov edi, [rBase] + sub edi, 128 + mov [rBase], edi + sub [height], 1 + jnz .l4 + ret +.img_8: + add eax, [esi] + mov [pQuad], eax + add eax, 1024 + mov [pBits], eax + add eax, 1024 + mov [pAnd], eax + mov eax, [esi+4] + mov [width], eax + mov ebx, [esi+8] + shr ebx, 1 + mov [height], ebx + + mov edi, [dst] + add edi, 32*31*4 + mov [rBase], edi + + mov esi, [pQuad] + mov ebx, [pBits] +.l81: + mov eax, [pAnd] + mov eax, [eax] + bswap eax + mov [counter], 32 +@@: + xor edx, edx + shl eax, 1 + setc dl + dec edx + + movzx ecx, byte [ebx] + mov ecx, [esi+ecx*4] + and ecx, edx + and edx, 0xFF000000 + or edx, ecx + mov [edi], edx + + inc ebx + add edi, 4 + dec [counter] + jnz @B + + add [pAnd], 4 + mov edi, [rBase] + sub edi, 128 + mov [rBase], edi + sub [height], 1 + jnz .l81 + ret +.img_24: + add eax, [esi] + mov [pQuad], eax + add eax, 0xC00 + mov [pAnd], eax + mov eax, [esi+BI.biWidth] + mov [width], eax + mov ebx, [esi+BI.biHeight] + shr ebx, 1 + mov [height], ebx + + mov edi, [dst] + add edi, 32*31*4 + mov [rBase], edi + + mov esi, [pAnd] + mov ebx, [pQuad] +.row_24: + mov eax, [esi] + bswap eax + mov [counter], 32 +@@: + xor edx, edx + shl eax, 1 + setc dl + dec edx + + mov ecx, [ebx] + and ecx, 0x00FFFFFF + and ecx, edx + and edx, 0xFF000000 + or edx, ecx + mov [edi], edx + add ebx, 3 + add edi, 4 + dec [counter] + jnz @B + + add esi, 4 + mov edi, [rBase] + sub edi, 128 + mov [rBase], edi + sub [height], 1 + jnz .row_24 + ret +endp + +align 4 +proc set_cursor stdcall, hcursor:dword + mov eax, [hcursor] + cmp [eax+CURSOR.magic], 'CURS' + jne .fail +; cmp [eax+CURSOR.size], CURSOR_SIZE +; jne .fail + mov ebx, [current_slot] + xchg eax, [ebx+APPDATA.cursor] + ret +.fail: + mov eax, [def_cursor] + mov ebx, [current_slot] + xchg eax, [ebx+APPDATA.cursor] + ret +endp + +; param +; eax= pid +; ebx= src +; ecx= flags + +create_cursor: +.src equ esp +.flags equ esp+4 +.hcursor equ esp+8 + + sub esp, 4 ;space for .hcursor + push ecx + push ebx + + mov ebx, eax + mov eax, CURSOR.sizeof + call create_kernel_object + test eax, eax + jz .fail + + mov [.hcursor], eax + + xor ebx, ebx + mov [eax+CURSOR.magic], 'CURS' + mov [eax+CURSOR.destroy], destroy_cursor + mov [eax+CURSOR.hot_x], ebx + mov [eax+CURSOR.hot_y], ebx + + stdcall kernel_alloc, 0x1000 + test eax, eax + jz .fail + + mov edi, [.hcursor] + mov [edi+CURSOR.base], eax + + mov esi, [.src] + mov ebx, [.flags] + cmp bx, LOAD_INDIRECT + je .indirect + + movzx ecx, word [esi+10] + movzx edx, word [esi+12] + mov [edi+CURSOR.hot_x], ecx + mov [edi+CURSOR.hot_y], edx + + stdcall init_cursor, eax, esi + + mov eax, [.hcursor] + lea eax, [eax+CURSOR.list_next] + lea edx, [_display.cr_list.next] + + pushfd + cli + mov ecx, [edx] + + mov [eax], ecx + mov [eax+4], edx + + mov [ecx+4], eax + mov [edx], eax + popfd + + mov eax, [.hcursor] +.check_hw: + cmp [_display.init_cursor], 0 + je .fail + + push eax + call [_display.init_cursor] + add esp, 4 + + mov eax, [.hcursor] +.fail: + add esp, 12 + ret +.indirect: + shr ebx, 16 + movzx ecx, bh + movzx edx, bl + mov [eax+CURSOR.hot_x], ecx + mov [eax+CURSOR.hot_y], edx + + xchg edi, eax + mov ecx, 1024 + cld + rep movsd + jmp .check_hw + +align 4 +proc load_cursor stdcall, src:dword, flags:dword + locals + handle dd ? + endl + + xor eax, eax + cmp [create_cursor], eax + je .fail2 + + mov [handle], eax + cmp word [flags], LOAD_FROM_FILE + jne @F + + stdcall load_file, [src] + test eax, eax + jz .fail + mov [src], eax +@@: + push ebx + push esi + push edi + + mov eax, [CURRENT_TASK] + shl eax, 5 + mov eax, [CURRENT_TASK+eax+4] + mov ebx, [src] + mov ecx, [flags] + call create_cursor ;eax, ebx, ecx + mov [handle], eax + + cmp word [flags], LOAD_FROM_FILE + jne .exit + stdcall kernel_free, [src] +.exit: + pop edi + pop esi + pop ebx +.fail: + mov eax, [handle] +.fail2: + ret +endp + +align 4 +proc delete_cursor stdcall, hcursor:dword + locals + hsrv dd ? + io_code dd ? + input dd ? + inp_size dd ? + output dd ? + out_size dd ? + endl + + mov esi, [hcursor] + cmp [esi+CURSOR.magic], 'CURS' + jne .fail + + mov ebx, [CURRENT_TASK] + shl ebx, 5 + mov ebx, [CURRENT_TASK+ebx+4] + cmp ebx, [esi+CURSOR.pid] + jne .fail + + mov ebx, [current_slot] + cmp esi, [ebx+APPDATA.cursor] + jne @F + mov eax, [def_cursor] + mov [ebx+APPDATA.cursor], eax +@@: + mov eax, [hcursor] + call [eax+APPOBJ.destroy] +.fail: + ret +endp + +; param +; eax= cursor + +align 4 +destroy_cursor: + + push eax + stdcall kernel_free, [eax+CURSOR.base] + pop eax + + call destroy_kernel_object + ret + +align 4 +select_cursor: + mov eax, [esp+4] + mov [_display.cursor], eax + ret 4 + +align 4 +proc restore_24 stdcall, x:dword, y:dword + + push ebx + + mov ebx, [cur_saved_base] + mov edx, [cur.h] + test edx, edx + jz .ret + + push esi + push edi + + mov esi, cur_saved_data + mov ecx, [cur.w] + lea ecx, [ecx+ecx*2] + push ecx +@@: + mov edi, ebx + add ebx, [BytesPerScanLine] + + mov ecx, [esp] + rep movsb + dec edx + jnz @B + + pop ecx + pop edi + pop esi +.ret: + pop ebx + ret +endp + +align 4 +proc restore_32 stdcall, x:dword, y:dword + + push ebx + + mov ebx, [cur_saved_base] + mov edx, [cur.h] + test edx, edx + jz .ret + + push esi + push edi + + mov esi, cur_saved_data +@@: + mov edi, ebx + add ebx, [BytesPerScanLine] + + mov ecx, [cur.w] + rep movsd + dec edx + jnz @B + + pop edi +.ret: + pop esi + pop ebx + ret +endp + +align 4 +proc move_cursor_24 stdcall, hcursor:dword, x:dword, y:dword + locals + h dd ? + _dx dd ? + _dy dd ? + endl + + mov esi, [hcursor] + mov ecx, [x] + mov eax, [y] + mov ebx, [BytesPerScanLine] + + xor edx, edx + sub ecx, [esi+CURSOR.hot_x] + lea ebx, [ecx+32-1] + mov [x], ecx + sets dl + dec edx + and ecx, edx ;clip x to 0<=x + mov [cur.left], ecx + mov edi, ecx + sub edi, [x] + mov [_dx], edi + + xor edx, edx + sub eax, [esi+CURSOR.hot_y] + lea edi, [eax+32-1] + mov [y], eax + sets dl + dec edx + and eax, edx ;clip y to 0<=y + mov [cur.top], eax + mov edx, eax + sub edx, [y] + mov [_dy], edx + + mul dword [BytesPerScanLine] + lea edx, [LFB_BASE+ecx*3] + add edx, eax + mov [cur_saved_base], edx + + cmp ebx, [Screen_Max_X] + jbe @F + mov ebx, [Screen_Max_X] +@@: + cmp edi, [Screen_Max_Y] + jbe @F + mov edi, [Screen_Max_Y] +@@: + mov [cur.right], ebx + mov [cur.bottom], edi + + sub ebx, [x] + sub edi, [y] + inc ebx + inc edi + + mov [cur.w], ebx + mov [cur.h], edi + mov [h], edi + + mov eax, edi + mov edi, cur_saved_data +@@: + mov esi, edx + add edx, [BytesPerScanLine] + mov ecx, [cur.w] + lea ecx, [ecx+ecx*2] + rep movsb + dec eax + jnz @B + +;draw cursor + mov ebx, [cur_saved_base] + mov eax, [_dy] + shl eax, 5 + add eax, [_dx] + + mov esi, [hcursor] + mov esi, [esi+CURSOR.base] + lea edx, [esi+eax*4] +.row: + mov ecx, [cur.w] + mov esi, edx + mov edi, ebx + add edx, 32*4 + add ebx, [BytesPerScanLine] +.pix: + lodsd + test eax, 0xFF000000 + jz @F + mov [edi], ax + shr eax, 16 + mov [edi+2], al +@@: + add edi, 3 + dec ecx + jnz .pix + + dec [h] + jnz .row + ret +endp + + +align 4 +proc move_cursor_32 stdcall, hcursor:dword, x:dword, y:dword + locals + h dd ? + _dx dd ? + _dy dd ? + endl + + mov esi, [hcursor] + mov ecx, [x] + mov eax, [y] + + xor edx, edx + sub ecx, [esi+CURSOR.hot_x] + lea ebx, [ecx+32-1] + mov [x], ecx + sets dl + dec edx + and ecx, edx ;clip x to 0<=x + mov [cur.left], ecx + mov edi, ecx + sub edi, [x] + mov [_dx], edi + + xor edx, edx + sub eax, [esi+CURSOR.hot_y] + lea edi, [eax+32-1] + mov [y], eax + sets dl + dec edx + and eax, edx ;clip y to 0<=y + mov [cur.top], eax + mov edx, eax + sub edx, [y] + mov [_dy], edx + + mul dword [BytesPerScanLine] + lea edx, [LFB_BASE+eax+ecx*4] + mov [cur_saved_base], edx + + cmp ebx, [Screen_Max_X] + jbe @F + mov ebx, [Screen_Max_X] +@@: + cmp edi, [Screen_Max_Y] + jbe @F + mov edi, [Screen_Max_Y] +@@: + mov [cur.right], ebx + mov [cur.bottom], edi + + sub ebx, [x] + sub edi, [y] + inc ebx + inc edi + + mov [cur.w], ebx + mov [cur.h], edi + mov [h], edi + + mov eax, edi + mov edi, cur_saved_data +@@: + mov esi, edx + add edx, [BytesPerScanLine] + mov ecx, [cur.w] + rep movsd + dec eax + jnz @B + +;draw cursor + mov ebx, [cur_saved_base] + mov eax, [_dy] + shl eax, 5 + add eax, [_dx] + + mov esi, [hcursor] + mov esi, [esi+CURSOR.base] + lea edx, [esi+eax*4] +.row: + mov ecx, [cur.w] + mov esi, edx + mov edi, ebx + add edx, 32*4 + add ebx, [BytesPerScanLine] +.pix: + lodsd + test eax, 0xFF000000 + jz @F + mov [edi], eax +@@: + add edi, 4 + dec ecx + jnz .pix + + dec [h] + jnz .row + ret +endp + + +align 4 +get_display: + mov eax, _display + ret + +align 4 +init_display: + + xor eax, eax + mov edi, _display + + mov [edi+display_t.init_cursor], eax + mov [edi+display_t.select_cursor], eax + mov [edi+display_t.show_cursor], eax + mov [edi+display_t.move_cursor], eax + mov [edi+display_t.restore_cursor], eax + + lea ecx, [edi+display_t.cr_list.next] + mov [edi+display_t.cr_list.next], ecx + mov [edi+display_t.cr_list.prev], ecx + + cmp [SCR_MODE], word 0x13 + jbe .fail + + test word [SCR_MODE], 0x4000 + jz .fail + + mov ebx, restore_32 + mov ecx, move_cursor_32 + movzx eax, byte [ScreenBPP] + cmp eax, 32 + je @F + + mov ebx, restore_24 + mov ecx, move_cursor_24 + cmp eax, 24 + jne .fail +@@: + mov [_display.select_cursor], select_cursor + mov [_display.move_cursor], ecx + mov [_display.restore_cursor], ebx + + stdcall load_cursor, def_arrow, dword LOAD_FROM_MEM + mov [def_cursor], eax + ret +.fail: + xor eax, eax + mov [_display.select_cursor], eax + mov [_display.move_cursor], eax + ret + + + + + + + + + + +align 4 +def_arrow: + file 'arrow.cur' + diff --git a/kernel/trunk/video/vesa12.inc b/kernel/trunk/video/vesa12.inc index 603479075..b10dad968 100644 --- a/kernel/trunk/video/vesa12.inc +++ b/kernel/trunk/video/vesa12.inc @@ -1,1004 +1,1004 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; VESA12.INC ;; -;; ;; -;; Vesa 1.2 functions for MenuetOS ;; -;; ;; -;; Copyright 2002 Ville Turjanmaa ;; -;; ;; -;; quickcode@mail.ru - bankswitch for S3 cards ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -TRIDENT equ 0 -S3_VIDEO equ 0 -INTEL_VIDEO equ 0 - -if TRIDENT - if S3_VIDEO or INTEL_VIDEO - stop - end if -end if - -if S3_VIDEO - if TRIDENT or INTEL_VIDEO - stop - end if -end if - -if INTEL_VIDEO - if S3_VIDEO or TRIDENT - stop - end if -end if - - -; A complete video driver should include the following types of function -; -; Putpixel -; Getpixel -; -; Drawimage -; Drawbar -; -; Drawbackground -; -; -; Modifying the set_bank -function is mostly enough -; for different Vesa 1.2 setups. - -;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -; set_bank for Trident videocards, work on Trident 9440 -; modified by Mario79 - -if TRIDENT -set_bank: - pushfd - cli - cmp al,[BANK_RW] - je .retsb - - mov [BANK_RW],al - push dx - mov dx,3D8h - out dx,al - pop dx -.retsb: - popfd - ret -end if - -;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -; set_bank for S3 videocards, work on S3 ViRGE PCI (325) -; modified by kmeaw - -if S3_VIDEO -set_bank: - pushfd - cli - cmp al,[BANK_RW] - je .retsb - - mov [BANK_RW],al - push ax - push dx - push cx - mov cl, al - mov dx, 0x3D4 - mov al, 0x38 - out dx, al ;CR38 Register Lock 1 ;Note: Traditionally 48h is used to - ;unlock and 00h to lock - inc dx - mov al, 0x48 - out dx, al ;3d5 -? - dec dx - mov al, 0x31 - out dx, al ;CR31 Memory Configuration Register -;0 Enable Base Address Offset (CPUA BASE). Enables bank operation if set, ;disables if clear. -;4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index 51h, -;for the 864/964 see index 69h. - - inc dx - in al, dx - dec dx - mov ah, al - mov al, 0x31 - out dx, ax - mov al, ah - or al, 9 - inc dx - out dx, al - dec dx - mov al, 0x35 - out dx, al ;CR35 CRT Register Lock - inc dx - in al, dx - dec dx - and al, 0xF0 - mov ch, cl - and ch, 0x0F - or ch, al - mov al, 0x35 - out dx, al - inc dx - mov al, ch - out dx, ax - dec dx - mov al, 0x51 ;Extended System Control 2 Register - out dx, al - inc dx - in al, dx - dec dx - and al, 0xF3 - shr cl, 2 - and cl, 0x0C - or cl, al - mov al, 0x51 - out dx, al - inc dx - mov al, cl - out dx, al - dec dx - mov al, 0x38 - out dx, al - inc dx - xor al, al - out dx, al - dec dx - pop cx - pop dx - pop ax -.retsb: - popfd - ret -end if - -;Set bank function for Intel 810/815 chipsets -; *****Modified by Protopopius, Russia.***** -; ********* http://menuetos.hut.ru ************** -; ************************************************ - -if INTEL_VIDEO - -set_bank: - pushfd - cli - - cmp al,[BANK_RW] - je .retsb - - mov [BANK_RW],al - push ax - push dx - mov dx,3CEh - mov ah,al ; Save value for later use - mov al,10h ; Index GR10 (Address Mapping) - out dx,al ; Select GR10 - inc dl - mov al,3 ; Set bits 0 and 1 (Enable linear page mapping) - out dx,al ; Write value - dec dl - mov al,11h ; Index GR11 (Page Selector) - out dx,al ; Select GR11 - inc dl - mov al,ah ; Write address - out dx,al ; Write the value - pop dx - pop ax -.retsb: - popfd - ret -end if - -;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} - -if (TRIDENT or S3_VIDEO or INTEL_VIDEO) -else -set_bank: - pushfd - cli - - cmp al,[BANK_RW] - je .retsb - - mov [BANK_RW],al - push ax - push dx - mov ah,al - mov dx,0x03D4 - mov al,0x39 - out dx,al - inc dl - mov al,0xA5 - out dx,al - dec dl - mov al,6Ah - out dx,al - inc dl - mov al,ah - out dx,al - dec dl - mov al,0x39 - out dx,al - inc dl - mov al,0x5A - out dx,al - dec dl - pop dx - pop ax - -.retsb: - popfd - ret -end if - -vesa12_drawbackground: - - call [_display.disable_mouse] - - push eax - push ebx - push ecx - push edx - - xor edx,edx - mov eax,dword[BgrDataWidth] - mov ebx,dword[BgrDataHeight] - mul ebx - mov ebx,3 - mul ebx - mov [imax],eax - mov eax,[draw_data+32+RECT.left] - mov ebx,[draw_data+32+RECT.top] - xor edi,edi ;no force - - v12dp3: - - push eax - push ebx - - cmp [BgrDrawMode],dword 1 ; tiled background - jne no_vesa12_tiled_bgr - - push edx - - xor edx,edx - div dword [BgrDataWidth] - - push edx - mov eax,ebx - xor edx,edx - div dword [BgrDataHeight] - mov ebx,edx - pop eax - - pop edx - - no_vesa12_tiled_bgr: - - cmp [BgrDrawMode],dword 2 ; stretched background - jne no_vesa12_stretched_bgr - - push edx - - mul dword [BgrDataWidth] - mov ecx,[Screen_Max_X] - inc ecx - div ecx - - push eax - mov eax,ebx - mul dword [BgrDataHeight] - mov ecx,[Screen_Max_Y] - inc ecx - div ecx - mov ebx,eax - pop eax - - pop edx - - no_vesa12_stretched_bgr: - - - mov esi,ebx - imul esi, dword [BgrDataWidth] - add esi,eax - lea esi,[esi*3] - add esi,[img_background] ;IMG_BACKGROUND - pop ebx - pop eax - - v12di4: - - mov cl,[esi+2] - shl ecx,16 - mov cx,[esi] - pusha - mov esi,eax - mov edi,ebx - mov eax,[Screen_Max_X] - add eax,1 - mul ebx - add eax, [_WinMapAddress] - cmp [eax+esi],byte 1 - jnz v12nbgp - mov eax,[BytesPerScanLine] - mov ebx,edi - mul ebx - add eax, esi - lea eax, [VGABasePtr+eax+esi*2] - cmp [ScreenBPP],byte 24 - jz v12bgl3 - add eax,esi - - v12bgl3: - - push ebx - push eax - - sub eax,VGABasePtr - - shr eax,16 - call set_bank - pop eax - and eax,65535 - add eax,VGABasePtr - pop ebx - - mov [eax],cx - add eax,2 - shr ecx,16 - mov [eax],cl - sti - - v12nbgp: - - popa - add esi,3 - inc eax - cmp eax,[draw_data+32+RECT.right] - jg v12nodp31 - jmp v12dp3 - - v12nodp31: - - mov eax,[draw_data+32+RECT.left] - inc ebx - cmp ebx,[draw_data+32+RECT.bottom] - jg v12dp4 - jmp v12dp3 - - v12dp4: - - pop edx - pop ecx - pop ebx - pop eax - ret - - -vesa12_drawbar: - - call [_display.disable_mouse] - -;; mov [novesachecksum],dword 0 - sub edx,ebx - sub ecx,eax - push esi - push edi - push eax - push ebx - push ecx - push edx - mov ecx,[TASK_BASE] - add eax,[ecx-twdw+WDATA.box.left] - add ebx,[ecx-twdw+WDATA.box.top] - push eax - mov eax,ebx ; y - mov ebx,[BytesPerScanLine] - mul ebx - pop ecx - add eax,ecx ; x - add eax,ecx - add eax,ecx - cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x start - jz dbpi2412 - add eax,ecx - - dbpi2412: - - add eax,VGABasePtr - mov edi,eax - - ; x size - - mov eax,[esp+4] ; [esp+6] - mov ecx,eax - add ecx,eax - add ecx,eax - cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x size - jz dbpi24312 - add ecx,eax - - dbpi24312: - - mov ebx,[esp+0] - - ; check limits ? - - push eax - push ecx - mov eax,[TASK_BASE] - mov ecx,[eax+draw_data-CURRENT_TASK+RECT.left] - cmp ecx,0 - jnz dbcblimitlset12 - mov ecx,[eax+draw_data-CURRENT_TASK+RECT.top] - cmp ecx,0 - jnz dbcblimitlset12 - mov ecx,[eax+draw_data-CURRENT_TASK+RECT.right] - cmp ecx,[Screen_Max_X] - jnz dbcblimitlset12 - mov ecx,[eax+draw_data-CURRENT_TASK+RECT.bottom] - cmp ecx,[Screen_Max_Y] - jnz dbcblimitlset12 - pop ecx - pop eax - push dword 0 - jmp dbcblimitlno12 - - dbcblimitlset12: - - pop ecx - pop eax - push dword 1 - - dbcblimitlno12: - - cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - jz dbpi24bit12 - jmp dbpi32bit12 - - -; DRAWBAR 24 BBP - - -dbpi24bit12: - - push eax - push ebx - push edx - mov eax,ecx - mov ebx,3 - div ebx - mov ecx,eax - pop edx - pop ebx - pop eax - cld - - dbnewpi12: - - push ebx - push edi - push ecx - - xor edx,edx - mov eax,edi - sub eax,VGABasePtr - mov ebx,3 - div ebx - add eax, [_WinMapAddress] - mov ebx,[CURRENT_TASK] - cld - - dbnp2412: - - mov dl,[eax] - push eax - push ecx - cmp dl,bl - jnz dbimp24no12 - cmp [esp+5*4],dword 0 - jz dbimp24yes12 -; call dbcplimit -; jnz dbimp24no12 - - dbimp24yes12: - - push edi - mov eax,edi - sub eax,VGABasePtr - shr eax,16 - call set_bank - and edi,0xffff - add edi,VGABasePtr - mov eax,[esp+8+3*4+16+4+4] - stosw - shr eax,16 - stosb - sti - pop edi - add edi,3 - pop ecx - pop eax - inc eax - loop dbnp2412 - jmp dbnp24d12 - - dbimp24no12: - - pop ecx - pop eax - cld - add edi,3 - inc eax - loop dbnp2412 - - dbnp24d12: - - mov eax,[esp+3*4+16+4] - test eax,0x80000000 - jz nodbgl2412 - cmp al,0 - jz nodbgl2412 - dec eax - mov [esp+3*4+16+4],eax - - nodbgl2412: - - pop ecx - pop edi - pop ebx - add edi,[BytesPerScanLine] - dec ebx - jz dbnonewpi12 - jmp dbnewpi12 - - dbnonewpi12: - - add esp,7*4 - - ret - - -; DRAWBAR 32 BBP - - - dbpi32bit12: - - cld - shr ecx,2 - - dbnewpi3212: - - push ebx - push edi - push ecx - - mov eax,edi - sub eax,VGABasePtr - shr eax,2 - add eax, [_WinMapAddress] - mov ebx,[CURRENT_TASK] - cld - - dbnp3212: - - mov dl,[eax] - push eax - push ecx - cmp dl,bl - jnz dbimp32no12 - cmp [esp+5*4],dword 0 - jz dbimp32yes12 -; call dbcplimit -; jnz dbimp32no12 - - dbimp32yes12: - - push edi - mov eax,edi - sub eax,VGABasePtr - shr eax,16 - call set_bank - and edi,0xffff - add edi,VGABasePtr - mov eax,[esp+8+3*4+16+4+4] - stosw - shr eax,16 - stosb - sti - pop edi - add edi,4 - inc ebp - pop ecx - pop eax - inc eax - loop dbnp3212 - jmp dbnp32d12 - - dbimp32no12: - - pop ecx - pop eax - inc eax - add edi,4 - inc ebp - loop dbnp3212 - - dbnp32d12: - - mov eax,[esp+12+16+4] - test eax,0x80000000 - jz nodbgl3212 - cmp al,0 - jz nodbgl3212 - dec eax - mov [esp+12+16+4],eax - - nodbgl3212: - - pop ecx - pop edi - pop ebx - add edi,[BytesPerScanLine] - dec ebx - jz nodbnewpi3212 - jmp dbnewpi3212 - - nodbnewpi3212: - - add esp,7*4 - ret - - -Vesa12_putpixel24: - - mov edi,eax ; x - mov eax,ebx ; y - lea edi,[edi+edi*2] - mov ebx,[BytesPerScanLine] - mul ebx - add edi,eax - mov eax,edi - shr eax,16 - call set_bank - and edi,65535 - add edi,VGABasePtr - mov eax,[esp+28] - stosw - shr eax,16 - mov [edi],al - sti - ret - - - -Vesa12_putpixel32: - - mov edi,eax ; x - mov eax,ebx ; y - shl edi,2 - mov ebx,[BytesPerScanLine] - mul ebx - add edi,eax - mov eax,edi - shr eax,16 - call set_bank - and edi,65535 - add edi,VGABasePtr - mov ecx,[esp+28] - mov [edi],ecx - sti - ret - - -Vesa12_getpixel24: - - mov edi,eax ; x - mov eax,ebx ; y - lea edi,[edi+edi*2] - mov ebx,[BytesPerScanLine] - mul ebx - add edi,eax - mov eax,edi - shr eax,16 - call set_bank - and edi,65535 - add edi,VGABasePtr - mov ecx,[edi] - and ecx,255*256*256+255*256+255 - sti - ret - - -Vesa12_getpixel32: - - mov edi,eax ; x - mov eax,ebx ; y - shl edi,2 - mov ebx,[BytesPerScanLine] - xor edx,edx - mul ebx - add edi,eax - mov eax,edi - shr eax,16 - call set_bank - and edi,65535 - add edi,VGABasePtr - mov ecx,[edi] - and ecx,255*256*256+255*256+255 - sti - - ret - - - -vesa12_putimage: -; ebx = pointer to image -; ecx = size [x|y] -; edx = coordinates [x|y] -; ebp = pointer to 'get' function -; esi = pointer to 'init' function -; edi = parameter for 'get' function - -; mov ebx,image -; mov ecx,320*65536+240 -; mov edx,20*65536+20 - - call [_display.disable_mouse] - - mov [novesachecksum],dword 0 - push esi - push edi - push eax - push ebx - push ecx - push edx - movzx eax,word [esp+2] - movzx ebx,word [esp+0] - mov ecx,[TASK_BASE] - add eax,[ecx-twdw+WDATA.box.left] - add ebx,[ecx-twdw+WDATA.box.top] - push eax - mov eax,ebx ; y - mul dword [BytesPerScanLine] - pop ecx - add eax,ecx ; x - add eax,ecx - add eax,ecx - cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - x start - jz pi2412 - add eax,ecx - - pi2412: - - add eax,VGABasePtr - mov edi,eax - - ; x size - - movzx ecx,word [esp+6] - - mov esi,[esp+8] - movzx ebx,word [esp+4] - - ; check limits while draw ? - - push ecx - mov eax,[TASK_BASE] - cmp dword [eax+draw_data-CURRENT_TASK+RECT.left], 0 - jnz dbcblimitlset212 - cmp dword [eax+draw_data-CURRENT_TASK+RECT.top], 0 - jnz dbcblimitlset212 - mov ecx,[eax+draw_data-CURRENT_TASK+RECT.right] - cmp ecx,[Screen_Max_X] - jnz dbcblimitlset212 - mov ecx,[eax+draw_data-CURRENT_TASK+RECT.bottom] - cmp ecx,[Screen_Max_Y] - jnz dbcblimitlset212 - pop ecx - push 0 - jmp dbcblimitlno212 - - dbcblimitlset212: - - pop ecx - push 1 - - dbcblimitlno212: - - cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - jnz pi32bit12 - - pi24bit12: - - newpi12: - - push edi - push ecx - push ebx - - mov edx,edi - sub edx,VGABasePtr - mov ebx,3 - div ebx - add edx, [_WinMapAddress] - mov ebx,[CURRENT_TASK] - mov bh,[esp+4*3] - - np2412: - - cmp bl,[edx] - jnz imp24no12 -; mov eax,[esi] - push dword [esp+4*3+20] - call ebp -; cmp bh,0 -; jz imp24yes12 -; call dbcplimit -; jnz imp24no12 - - imp24yes12: - - push edi - push eax - mov eax,edi - sub eax,VGABasePtr - shr eax,16 - call set_bank - pop eax - and edi,0xffff - add edi,VGABasePtr - mov [edi],ax - shr eax,16 - mov [edi+2],al - pop edi - - imp24no12: - - inc edx -; add esi,3 - add edi,3 - dec ecx - jnz np2412 - - np24d12: - - pop ebx - pop ecx - pop edi - - add edi,[BytesPerScanLine] - add esi,[esp+32] - cmp ebp,putimage_get1bpp - jz .correct - cmp ebp,putimage_get2bpp - jz .correct - cmp ebp,putimage_get4bpp - jnz @f -.correct: - mov eax,[esp+20] - mov byte[eax],80h -@@: - dec ebx - jnz newpi12 - - nonewpi12: - - pop eax edx ecx ebx eax edi esi - xor eax, eax - ret - - - pi32bit12: - - newpi3212: - - push edi - push ecx - push ebx - - mov edx,edi - sub edx,VGABasePtr - shr edx,2 - add edx, [_WinMapAddress] - mov ebx,[CURRENT_TASK] - mov bh,[esp+4*3] - - np3212: - - cmp bl,[edx] - jnz imp32no12 -; mov eax,[esi] - push dword [esp+4*3+20] - call ebp -; cmp bh,0 -; jz imp32yes12 -; call dbcplimit -; jnz imp32no12 - - imp32yes12: - - push edi - push eax - mov eax,edi - sub eax,VGABasePtr - shr eax,16 - call set_bank - pop eax - and edi,0xffff - mov [edi+VGABasePtr],eax - pop edi - - imp32no12: - - inc edx -; add esi,3 - add edi,4 - dec ecx - jnz np3212 - - np32d12: - - pop ebx - pop ecx - pop edi - - add edi,[BytesPerScanLine] - cmp ebp,putimage_get1bpp - jz .correct - cmp ebp,putimage_get2bpp - jz .correct - cmp ebp,putimage_get4bpp - jnz @f -.correct: - mov eax,[esp+20] - mov byte[eax],80h -@@: - dec ebx - jnz newpi3212 - - nonewpi3212: - - pop eax edx ecx ebx eax edi esi - xor eax, eax - ret - - -vesa12_read_screen_pixel: - - and eax,0x3FFFFF - cmp [ScreenBPP],byte 24 ; 24 or 32 bpp ? - jz v12rsp24 - mov edi,eax - shl edi,2 - mov eax,edi - shr eax,16 - call set_bank - and edi,65535 - add edi,VGABasePtr - mov eax,[edi] - and eax,0x00ffffff - ret - v12rsp24: - - imul eax,3 - mov edi,eax - shr eax,16 - call set_bank - and edi,65535 - add edi,VGABasePtr - mov eax,[edi] - and eax,0x00ffffff - ret - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; VESA12.INC ;; +;; ;; +;; Vesa 1.2 functions for MenuetOS ;; +;; ;; +;; Copyright 2002 Ville Turjanmaa ;; +;; ;; +;; quickcode@mail.ru - bankswitch for S3 cards ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +TRIDENT equ 0 +S3_VIDEO equ 0 +INTEL_VIDEO equ 0 + +if TRIDENT + if S3_VIDEO or INTEL_VIDEO + stop + end if +end if + +if S3_VIDEO + if TRIDENT or INTEL_VIDEO + stop + end if +end if + +if INTEL_VIDEO + if S3_VIDEO or TRIDENT + stop + end if +end if + + +; A complete video driver should include the following types of function +; +; Putpixel +; Getpixel +; +; Drawimage +; Drawbar +; +; Drawbackground +; +; +; Modifying the set_bank -function is mostly enough +; for different Vesa 1.2 setups. + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; set_bank for Trident videocards, work on Trident 9440 +; modified by Mario79 + +if TRIDENT +set_bank: + pushfd + cli + cmp al, [BANK_RW] + je .retsb + + mov [BANK_RW], al + push dx + mov dx, 3D8h + out dx, al + pop dx +.retsb: + popfd + ret +end if + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +; set_bank for S3 videocards, work on S3 ViRGE PCI (325) +; modified by kmeaw + +if S3_VIDEO +set_bank: + pushfd + cli + cmp al, [BANK_RW] + je .retsb + + mov [BANK_RW], al + push ax + push dx + push cx + mov cl, al + mov dx, 0x3D4 + mov al, 0x38 + out dx, al ;CR38 Register Lock 1 ;Note: Traditionally 48h is used to + ;unlock and 00h to lock + inc dx + mov al, 0x48 + out dx, al ;3d5 -? + dec dx + mov al, 0x31 + out dx, al ;CR31 Memory Configuration Register +;0 Enable Base Address Offset (CPUA BASE). Enables bank operation if set, ;disables if clear. +;4-5 Bit 16-17 of the Display Start Address. For the 801/5,928 see index 51h, +;for the 864/964 see index 69h. + + inc dx + in al, dx + dec dx + mov ah, al + mov al, 0x31 + out dx, ax + mov al, ah + or al, 9 + inc dx + out dx, al + dec dx + mov al, 0x35 + out dx, al ;CR35 CRT Register Lock + inc dx + in al, dx + dec dx + and al, 0xF0 + mov ch, cl + and ch, 0x0F + or ch, al + mov al, 0x35 + out dx, al + inc dx + mov al, ch + out dx, ax + dec dx + mov al, 0x51 ;Extended System Control 2 Register + out dx, al + inc dx + in al, dx + dec dx + and al, 0xF3 + shr cl, 2 + and cl, 0x0C + or cl, al + mov al, 0x51 + out dx, al + inc dx + mov al, cl + out dx, al + dec dx + mov al, 0x38 + out dx, al + inc dx + xor al, al + out dx, al + dec dx + pop cx + pop dx + pop ax +.retsb: + popfd + ret +end if + +;Set bank function for Intel 810/815 chipsets +; *****Modified by Protopopius, Russia.***** +; ********* http://menuetos.hut.ru ************** +; ************************************************ + +if INTEL_VIDEO + +set_bank: + pushfd + cli + + cmp al, [BANK_RW] + je .retsb + + mov [BANK_RW], al + push ax + push dx + mov dx, 3CEh + mov ah, al ; Save value for later use + mov al, 10h ; Index GR10 (Address Mapping) + out dx, al ; Select GR10 + inc dl + mov al, 3 ; Set bits 0 and 1 (Enable linear page mapping) + out dx, al ; Write value + dec dl + mov al, 11h ; Index GR11 (Page Selector) + out dx, al ; Select GR11 + inc dl + mov al, ah ; Write address + out dx, al ; Write the value + pop dx + pop ax +.retsb: + popfd + ret +end if + +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!} + +if (TRIDENT or S3_VIDEO or INTEL_VIDEO) +else +set_bank: + pushfd + cli + + cmp al, [BANK_RW] + je .retsb + + mov [BANK_RW], al + push ax + push dx + mov ah, al + mov dx, 0x03D4 + mov al, 0x39 + out dx, al + inc dl + mov al, 0xA5 + out dx, al + dec dl + mov al, 6Ah + out dx, al + inc dl + mov al, ah + out dx, al + dec dl + mov al, 0x39 + out dx, al + inc dl + mov al, 0x5A + out dx, al + dec dl + pop dx + pop ax + +.retsb: + popfd + ret +end if + +vesa12_drawbackground: + + call [_display.disable_mouse] + + push eax + push ebx + push ecx + push edx + + xor edx, edx + mov eax, dword[BgrDataWidth] + mov ebx, dword[BgrDataHeight] + mul ebx + mov ebx, 3 + mul ebx + mov [imax], eax + mov eax, [draw_data+32+RECT.left] + mov ebx, [draw_data+32+RECT.top] + xor edi, edi;no force + + v12dp3: + + push eax + push ebx + + cmp [BgrDrawMode], dword 1 ; tiled background + jne no_vesa12_tiled_bgr + + push edx + + xor edx, edx + div dword [BgrDataWidth] + + push edx + mov eax, ebx + xor edx, edx + div dword [BgrDataHeight] + mov ebx, edx + pop eax + + pop edx + + no_vesa12_tiled_bgr: + + cmp [BgrDrawMode], dword 2 ; stretched background + jne no_vesa12_stretched_bgr + + push edx + + mul dword [BgrDataWidth] + mov ecx, [Screen_Max_X] + inc ecx + div ecx + + push eax + mov eax, ebx + mul dword [BgrDataHeight] + mov ecx, [Screen_Max_Y] + inc ecx + div ecx + mov ebx, eax + pop eax + + pop edx + + no_vesa12_stretched_bgr: + + + mov esi, ebx + imul esi, dword [BgrDataWidth] + add esi, eax + lea esi, [esi*3] + add esi, [img_background];IMG_BACKGROUND + pop ebx + pop eax + + v12di4: + + mov cl, [esi+2] + shl ecx, 16 + mov cx, [esi] + pusha + mov esi, eax + mov edi, ebx + mov eax, [Screen_Max_X] + add eax, 1 + mul ebx + add eax, [_WinMapAddress] + cmp [eax+esi], byte 1 + jnz v12nbgp + mov eax, [BytesPerScanLine] + mov ebx, edi + mul ebx + add eax, esi + lea eax, [VGABasePtr+eax+esi*2] + cmp [ScreenBPP], byte 24 + jz v12bgl3 + add eax, esi + + v12bgl3: + + push ebx + push eax + + sub eax, VGABasePtr + + shr eax, 16 + call set_bank + pop eax + and eax, 65535 + add eax, VGABasePtr + pop ebx + + mov [eax], cx + add eax, 2 + shr ecx, 16 + mov [eax], cl + sti + + v12nbgp: + + popa + add esi, 3 + inc eax + cmp eax, [draw_data+32+RECT.right] + jg v12nodp31 + jmp v12dp3 + + v12nodp31: + + mov eax, [draw_data+32+RECT.left] + inc ebx + cmp ebx, [draw_data+32+RECT.bottom] + jg v12dp4 + jmp v12dp3 + + v12dp4: + + pop edx + pop ecx + pop ebx + pop eax + ret + + +vesa12_drawbar: + + call [_display.disable_mouse] + +;; mov [novesachecksum],dword 0 + sub edx, ebx + sub ecx, eax + push esi + push edi + push eax + push ebx + push ecx + push edx + mov ecx, [TASK_BASE] + add eax, [ecx-twdw+WDATA.box.left] + add ebx, [ecx-twdw+WDATA.box.top] + push eax + mov eax, ebx ; y + mov ebx, [BytesPerScanLine] + mul ebx + pop ecx + add eax, ecx ; x + add eax, ecx + add eax, ecx + cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x start + jz dbpi2412 + add eax, ecx + + dbpi2412: + + add eax, VGABasePtr + mov edi, eax + + ; x size + + mov eax, [esp+4]; [esp+6] + mov ecx, eax + add ecx, eax + add ecx, eax + cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x size + jz dbpi24312 + add ecx, eax + + dbpi24312: + + mov ebx, [esp+0] + + ; check limits ? + + push eax + push ecx + mov eax, [TASK_BASE] + mov ecx, [eax+draw_data-CURRENT_TASK+RECT.left] + cmp ecx, 0 + jnz dbcblimitlset12 + mov ecx, [eax+draw_data-CURRENT_TASK+RECT.top] + cmp ecx, 0 + jnz dbcblimitlset12 + mov ecx, [eax+draw_data-CURRENT_TASK+RECT.right] + cmp ecx, [Screen_Max_X] + jnz dbcblimitlset12 + mov ecx, [eax+draw_data-CURRENT_TASK+RECT.bottom] + cmp ecx, [Screen_Max_Y] + jnz dbcblimitlset12 + pop ecx + pop eax + push dword 0 + jmp dbcblimitlno12 + + dbcblimitlset12: + + pop ecx + pop eax + push dword 1 + + dbcblimitlno12: + + cmp [ScreenBPP], byte 24; 24 or 32 bpp ? + jz dbpi24bit12 + jmp dbpi32bit12 + + +; DRAWBAR 24 BBP + + +dbpi24bit12: + + push eax + push ebx + push edx + mov eax, ecx + mov ebx, 3 + div ebx + mov ecx, eax + pop edx + pop ebx + pop eax + cld + + dbnewpi12: + + push ebx + push edi + push ecx + + xor edx, edx + mov eax, edi + sub eax, VGABasePtr + mov ebx, 3 + div ebx + add eax, [_WinMapAddress] + mov ebx, [CURRENT_TASK] + cld + + dbnp2412: + + mov dl, [eax] + push eax + push ecx + cmp dl, bl + jnz dbimp24no12 + cmp [esp+5*4], dword 0 + jz dbimp24yes12 +; call dbcplimit +; jnz dbimp24no12 + + dbimp24yes12: + + push edi + mov eax, edi + sub eax, VGABasePtr + shr eax, 16 + call set_bank + and edi, 0xffff + add edi, VGABasePtr + mov eax, [esp+8+3*4+16+4+4] + stosw + shr eax, 16 + stosb + sti + pop edi + add edi, 3 + pop ecx + pop eax + inc eax + loop dbnp2412 + jmp dbnp24d12 + + dbimp24no12: + + pop ecx + pop eax + cld + add edi, 3 + inc eax + loop dbnp2412 + + dbnp24d12: + + mov eax, [esp+3*4+16+4] + test eax, 0x80000000 + jz nodbgl2412 + cmp al, 0 + jz nodbgl2412 + dec eax + mov [esp+3*4+16+4], eax + + nodbgl2412: + + pop ecx + pop edi + pop ebx + add edi, [BytesPerScanLine] + dec ebx + jz dbnonewpi12 + jmp dbnewpi12 + + dbnonewpi12: + + add esp, 7*4 + + ret + + +; DRAWBAR 32 BBP + + + dbpi32bit12: + + cld + shr ecx, 2 + + dbnewpi3212: + + push ebx + push edi + push ecx + + mov eax, edi + sub eax, VGABasePtr + shr eax, 2 + add eax, [_WinMapAddress] + mov ebx, [CURRENT_TASK] + cld + + dbnp3212: + + mov dl, [eax] + push eax + push ecx + cmp dl, bl + jnz dbimp32no12 + cmp [esp+5*4], dword 0 + jz dbimp32yes12 +; call dbcplimit +; jnz dbimp32no12 + + dbimp32yes12: + + push edi + mov eax, edi + sub eax, VGABasePtr + shr eax, 16 + call set_bank + and edi, 0xffff + add edi, VGABasePtr + mov eax, [esp+8+3*4+16+4+4] + stosw + shr eax, 16 + stosb + sti + pop edi + add edi, 4 + inc ebp + pop ecx + pop eax + inc eax + loop dbnp3212 + jmp dbnp32d12 + + dbimp32no12: + + pop ecx + pop eax + inc eax + add edi, 4 + inc ebp + loop dbnp3212 + + dbnp32d12: + + mov eax, [esp+12+16+4] + test eax, 0x80000000 + jz nodbgl3212 + cmp al, 0 + jz nodbgl3212 + dec eax + mov [esp+12+16+4], eax + + nodbgl3212: + + pop ecx + pop edi + pop ebx + add edi, [BytesPerScanLine] + dec ebx + jz nodbnewpi3212 + jmp dbnewpi3212 + + nodbnewpi3212: + + add esp, 7*4 + ret + + +Vesa12_putpixel24: + + mov edi, eax; x + mov eax, ebx; y + lea edi, [edi+edi*2] + mov ebx, [BytesPerScanLine] + mul ebx + add edi, eax + mov eax, edi + shr eax, 16 + call set_bank + and edi, 65535 + add edi, VGABasePtr + mov eax, [esp+28] + stosw + shr eax, 16 + mov [edi], al + sti + ret + + + +Vesa12_putpixel32: + + mov edi, eax; x + mov eax, ebx; y + shl edi, 2 + mov ebx, [BytesPerScanLine] + mul ebx + add edi, eax + mov eax, edi + shr eax, 16 + call set_bank + and edi, 65535 + add edi, VGABasePtr + mov ecx, [esp+28] + mov [edi], ecx + sti + ret + + +Vesa12_getpixel24: + + mov edi, eax; x + mov eax, ebx; y + lea edi, [edi+edi*2] + mov ebx, [BytesPerScanLine] + mul ebx + add edi, eax + mov eax, edi + shr eax, 16 + call set_bank + and edi, 65535 + add edi, VGABasePtr + mov ecx, [edi] + and ecx, 255*256*256+255*256+255 + sti + ret + + +Vesa12_getpixel32: + + mov edi, eax; x + mov eax, ebx; y + shl edi, 2 + mov ebx, [BytesPerScanLine] + xor edx, edx + mul ebx + add edi, eax + mov eax, edi + shr eax, 16 + call set_bank + and edi, 65535 + add edi, VGABasePtr + mov ecx, [edi] + and ecx, 255*256*256+255*256+255 + sti + + ret + + + +vesa12_putimage: +; ebx = pointer to image +; ecx = size [x|y] +; edx = coordinates [x|y] +; ebp = pointer to 'get' function +; esi = pointer to 'init' function +; edi = parameter for 'get' function + +; mov ebx,image +; mov ecx,320*65536+240 +; mov edx,20*65536+20 + + call [_display.disable_mouse] + + mov [novesachecksum], dword 0 + push esi + push edi + push eax + push ebx + push ecx + push edx + movzx eax, word [esp+2] + movzx ebx, word [esp+0] + mov ecx, [TASK_BASE] + add eax, [ecx-twdw+WDATA.box.left] + add ebx, [ecx-twdw+WDATA.box.top] + push eax + mov eax, ebx ; y + mul dword [BytesPerScanLine] + pop ecx + add eax, ecx ; x + add eax, ecx + add eax, ecx + cmp [ScreenBPP], byte 24; 24 or 32 bpp ? - x start + jz pi2412 + add eax, ecx + + pi2412: + + add eax, VGABasePtr + mov edi, eax + + ; x size + + movzx ecx, word [esp+6] + + mov esi, [esp+8] + movzx ebx, word [esp+4] + + ; check limits while draw ? + + push ecx + mov eax, [TASK_BASE] + cmp dword [eax+draw_data-CURRENT_TASK+RECT.left], 0 + jnz dbcblimitlset212 + cmp dword [eax+draw_data-CURRENT_TASK+RECT.top], 0 + jnz dbcblimitlset212 + mov ecx, [eax+draw_data-CURRENT_TASK+RECT.right] + cmp ecx, [Screen_Max_X] + jnz dbcblimitlset212 + mov ecx, [eax+draw_data-CURRENT_TASK+RECT.bottom] + cmp ecx, [Screen_Max_Y] + jnz dbcblimitlset212 + pop ecx + push 0 + jmp dbcblimitlno212 + + dbcblimitlset212: + + pop ecx + push 1 + + dbcblimitlno212: + + cmp [ScreenBPP], byte 24; 24 or 32 bpp ? + jnz pi32bit12 + + pi24bit12: + + newpi12: + + push edi + push ecx + push ebx + + mov edx, edi + sub edx, VGABasePtr + mov ebx, 3 + div ebx + add edx, [_WinMapAddress] + mov ebx, [CURRENT_TASK] + mov bh, [esp+4*3] + + np2412: + + cmp bl, [edx] + jnz imp24no12 +; mov eax,[esi] + push dword [esp+4*3+20] + call ebp +; cmp bh,0 +; jz imp24yes12 +; call dbcplimit +; jnz imp24no12 + + imp24yes12: + + push edi + push eax + mov eax, edi + sub eax, VGABasePtr + shr eax, 16 + call set_bank + pop eax + and edi, 0xffff + add edi, VGABasePtr + mov [edi], ax + shr eax, 16 + mov [edi+2], al + pop edi + + imp24no12: + + inc edx +; add esi,3 + add edi, 3 + dec ecx + jnz np2412 + + np24d12: + + pop ebx + pop ecx + pop edi + + add edi, [BytesPerScanLine] + add esi, [esp+32] + cmp ebp, putimage_get1bpp + jz .correct + cmp ebp, putimage_get2bpp + jz .correct + cmp ebp, putimage_get4bpp + jnz @f +.correct: + mov eax, [esp+20] + mov byte[eax], 80h +@@: + dec ebx + jnz newpi12 + + nonewpi12: + + pop eax edx ecx ebx eax edi esi + xor eax, eax + ret + + + pi32bit12: + + newpi3212: + + push edi + push ecx + push ebx + + mov edx, edi + sub edx, VGABasePtr + shr edx, 2 + add edx, [_WinMapAddress] + mov ebx, [CURRENT_TASK] + mov bh, [esp+4*3] + + np3212: + + cmp bl, [edx] + jnz imp32no12 +; mov eax,[esi] + push dword [esp+4*3+20] + call ebp +; cmp bh,0 +; jz imp32yes12 +; call dbcplimit +; jnz imp32no12 + + imp32yes12: + + push edi + push eax + mov eax, edi + sub eax, VGABasePtr + shr eax, 16 + call set_bank + pop eax + and edi, 0xffff + mov [edi+VGABasePtr], eax + pop edi + + imp32no12: + + inc edx +; add esi,3 + add edi, 4 + dec ecx + jnz np3212 + + np32d12: + + pop ebx + pop ecx + pop edi + + add edi, [BytesPerScanLine] + cmp ebp, putimage_get1bpp + jz .correct + cmp ebp, putimage_get2bpp + jz .correct + cmp ebp, putimage_get4bpp + jnz @f +.correct: + mov eax, [esp+20] + mov byte[eax], 80h +@@: + dec ebx + jnz newpi3212 + + nonewpi3212: + + pop eax edx ecx ebx eax edi esi + xor eax, eax + ret + + +vesa12_read_screen_pixel: + + and eax, 0x3FFFFF + cmp [ScreenBPP], byte 24; 24 or 32 bpp ? + jz v12rsp24 + mov edi, eax + shl edi, 2 + mov eax, edi + shr eax, 16 + call set_bank + and edi, 65535 + add edi, VGABasePtr + mov eax, [edi] + and eax, 0x00ffffff + ret + v12rsp24: + + imul eax, 3 + mov edi, eax + shr eax, 16 + call set_bank + and edi, 65535 + add edi, VGABasePtr + mov eax, [edi] + and eax, 0x00ffffff + ret + + diff --git a/kernel/trunk/video/vesa20.inc b/kernel/trunk/video/vesa20.inc index 7b035c8ff..368ce3fbd 100644 --- a/kernel/trunk/video/vesa20.inc +++ b/kernel/trunk/video/vesa20.inc @@ -1,1150 +1,1150 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; VESA20.INC ;; -;; ;; -;; Vesa 2.0 functions for MenuetOS ;; -;; ;; -;; Copyright 2002 Ville Turjanmaa ;; -;; Alexey, kgaz@crosswindws.net ;; -;; - Voodoo compatible graphics ;; -;; Juan M. Caravaca ;; -;; - Graphics optimimizations eg. drawline ;; -;; ;; -;; See file COPYING for details ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -; If you're planning to write your own video driver I suggest -; you replace the VESA12.INC file and see those instructions. - -;Screen_Max_X equ 0xfe00 -;Screen_Max_Y equ 0xfe04 -;BytesPerScanLine equ 0xfe08 -;LFBAddress equ 0xfe80 -;ScreenBPP equ 0xfbf1 - - - -;************************************************* -; getpixel -; -; in: -; eax = x coordinate -; ebx = y coordinate -; -; ret: -; ecx = 00 RR GG BB - -getpixel: - push eax ebx edx edi - call dword [GETPIXEL] - pop edi edx ebx eax - ret - -Vesa20_getpixel24: -; eax = x -; ebx = y - imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier - lea edi, [eax+eax*2] ; edi = x*3 - add edi, ebx ; edi = x*3+(y*y multiplier) - mov ecx, [LFB_BASE+edi] - and ecx, 0xffffff - ret - -Vesa20_getpixel32: - imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier - lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier) - mov ecx, [LFB_BASE+edi] - and ecx, 0xffffff - ret - -;************************************************* - -virtual at esp - putimg: - .real_sx dd ? - .real_sy dd ? - .image_sx dd ? - .image_sy dd ? - .image_cx dd ? - .image_cy dd ? - .pti dd ? - .abs_cx dd ? - .abs_cy dd ? - .line_increment dd ? - .winmap_newline dd ? - .screen_newline dd ? - .stack_data = 4*12 - .edi dd ? - .esi dd ? - .ebp dd ? - .esp dd ? - .ebx dd ? - .edx dd ? - .ecx dd ? - .eax dd ? - .ret_addr dd ? - .arg_0 dd ? -end virtual - -align 16 -; ebx = pointer -; ecx = size [x|y] -; edx = coordinates [x|y] -; ebp = pointer to 'get' function -; esi = pointer to 'init' function -; edi = parameter for 'get' function - -vesa20_putimage: - pushad - call [_display.disable_mouse] - sub esp, putimg.stack_data -; save pointer to image - mov [putimg.pti], ebx -; unpack the size - mov eax, ecx - and ecx, 0xFFFF - shr eax, 16 - mov [putimg.image_sx], eax - mov [putimg.image_sy], ecx -; unpack the coordinates - mov eax, edx - and edx, 0xFFFF - shr eax, 16 - mov [putimg.image_cx], eax - mov [putimg.image_cy], edx -; calculate absolute (i.e. screen) coordinates - mov eax, [TASK_BASE] - mov ebx, [eax-twdw + WDATA.box.left] - add ebx, [putimg.image_cx] - mov [putimg.abs_cx], ebx - mov ebx, [eax-twdw + WDATA.box.top] - add ebx, [putimg.image_cy] - mov [putimg.abs_cy], ebx -; real_sx = MIN(wnd_sx-image_cx, image_sx); - mov ebx, [eax-twdw + WDATA.box.width] ; ebx = wnd_sx -; \begin{diamond}[20.08.2006] -; note that WDATA.box.width is one pixel less than real window x-size - inc ebx -; \end{diamond}[20.08.2006] - sub ebx, [putimg.image_cx] - ja @f - add esp, putimg.stack_data - popad - ret -@@: - cmp ebx, [putimg.image_sx] - jbe .end_x - mov ebx, [putimg.image_sx] -.end_x: - mov [putimg.real_sx], ebx -; init real_sy - mov ebx, [eax-twdw + WDATA.box.height] ; ebx = wnd_sy -; \begin{diamond}[20.08.2006] - inc ebx -; \end{diamond}[20.08.2006] - sub ebx, [putimg.image_cy] - ja @f - add esp, putimg.stack_data - popad - ret -@@: - cmp ebx, [putimg.image_sy] - jbe .end_y - mov ebx, [putimg.image_sy] -.end_y: - mov [putimg.real_sy], ebx -; line increment - mov eax, [putimg.image_sx] - mov ecx, [putimg.real_sx] - sub eax, ecx -;; imul eax, [putimg.source_bpp] -; lea eax, [eax + eax * 2] - call esi - add eax, [putimg.arg_0] - mov [putimg.line_increment], eax -; winmap new line increment - mov eax, [Screen_Max_X] - inc eax - sub eax, [putimg.real_sx] - mov [putimg.winmap_newline], eax -; screen new line increment - mov eax, [BytesPerScanLine] - movzx ebx, byte [ScreenBPP] - shr ebx, 3 - imul ecx, ebx - sub eax, ecx - mov [putimg.screen_newline], eax -; pointer to image - mov esi, [putimg.pti] -; pointer to screen - mov edx, [putimg.abs_cy] - imul edx, [BytesPerScanLine] - mov eax, [putimg.abs_cx] - movzx ebx, byte [ScreenBPP] - shr ebx, 3 - imul eax, ebx - add edx, eax -; pointer to pixel map - mov eax, [putimg.abs_cy] - imul eax, [Screen_Max_X] - add eax, [putimg.abs_cy] - add eax, [putimg.abs_cx] - add eax, [_WinMapAddress] - xchg eax, ebp -; get process number - mov ebx, [CURRENT_TASK] - cmp byte [ScreenBPP], 32 - je put_image_end_32 -;put_image_end_24: - mov edi, [putimg.real_sy] -align 4 -.new_line: - mov ecx, [putimg.real_sx] -; push ebp edx -align 4 -.new_x: - push [putimg.edi] - mov eax, [putimg.ebp+4] - call eax - cmp [ebp], bl - jne .skip -; mov eax, [esi] ; eax = RRBBGGRR - mov [LFB_BASE+edx], ax - shr eax, 16 - mov [LFB_BASE+edx+2], al -.skip: -; add esi, 3 ;[putimg.source_bpp] - add edx, 3 - inc ebp - dec ecx - jnz .new_x -; pop edx ebp - add esi, [putimg.line_increment] - add edx, [putimg.screen_newline] ;[BytesPerScanLine] - add ebp, [putimg.winmap_newline] ;[Screen_Max_X] -; inc ebp - cmp [putimg.ebp], putimage_get1bpp - jz .correct - cmp [putimg.ebp], putimage_get2bpp - jz .correct - cmp [putimg.ebp], putimage_get4bpp - jnz @f -.correct: - mov eax, [putimg.edi] - mov byte [eax], 80h -@@: - dec edi - jnz .new_line -.finish: - add esp, putimg.stack_data - popad - ret - -put_image_end_32: - mov edi, [putimg.real_sy] -align 4 -.new_line: - mov ecx, [putimg.real_sx] -; push ebp edx -align 4 -.new_x: - push [putimg.edi] - mov eax, [putimg.ebp+4] - call eax - cmp [ebp], bl - jne .skip -; mov eax, [esi] ; ecx = RRBBGGRR - mov [LFB_BASE+edx], eax -.skip: -; add esi, [putimg.source_bpp] - add edx, 4 - inc ebp - dec ecx - jnz .new_x -; pop edx ebp - add esi, [putimg.line_increment] - add edx, [putimg.screen_newline] ;[BytesPerScanLine] - add ebp, [putimg.winmap_newline] ;[Screen_Max_X] -; inc ebp - cmp [putimg.ebp], putimage_get1bpp - jz .correct - cmp [putimg.ebp], putimage_get2bpp - jz .correct - cmp [putimg.ebp], putimage_get4bpp - jnz @f -.correct: - mov eax, [putimg.edi] - mov byte [eax], 80h -@@: - dec edi - jnz .new_line -.finish: - add esp, putimg.stack_data - popad - call VGA__putimage - mov [EGA_counter],1 - ret - - -;************************************************* -align 4 -__sys_putpixel: - -; eax = x coordinate -; ebx = y coordinate -; ecx = ?? RR GG BB ; 0x01000000 negation -; edi = 0x00000001 force - -;;; mov [novesachecksum], dword 0 - pushad - cmp [Screen_Max_X], eax - jb .exit - cmp [Screen_Max_Y], ebx - jb .exit - test edi,1 ; force ? - jnz .forced - -; not forced: - - push eax - mov edx,[_display.width] ; screen x size - imul edx, ebx - add eax, [_WinMapAddress] - movzx edx, byte [eax+edx] - cmp edx, [CURRENT_TASK] - pop eax - jne .exit - -.forced: -; check if negation - test ecx,0x01000000 - jz .noneg - call getpixel - not ecx - mov [esp+32-8],ecx -.noneg: -; OK to set pixel - call dword [PUTPIXEL] ; call the real put_pixel function -.exit: - popad - ret - -align 4 -Vesa20_putpixel24: -; eax = x -; ebx = y - imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier - lea edi, [eax+eax*2] ; edi = x*3 - mov eax, [esp+32-8+4] - mov [LFB_BASE+ebx+edi], ax - shr eax, 16 - mov [LFB_BASE+ebx+edi+2], al - ret - - -align 4 -Vesa20_putpixel32: -; eax = x -; ebx = y - imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier - lea edi, [ebx+eax*4] ; edi = x*4+(y*y multiplier) - mov eax, [esp+32-8+4] ; eax = color - mov [LFB_BASE+edi], eax - ret - -;************************************************* - -;align 4 -calculate_edi: - mov edi, ebx - imul edi, [Screen_Max_X] - add edi, ebx - add edi, eax - ret - -;************************************************* - -; DRAWLINE - -align 4 -__sys_draw_line: -; inc [mouse_pause] - call [_display.disable_mouse] - -; draw a line -; eax = HIWORD = x1 -; LOWORD = x2 -; ebx = HIWORD = y1 -; LOWORD = y2 -; ecx = color -; edi = force ? - pusha - -dl_x1 equ esp+20 -dl_y1 equ esp+16 -dl_x2 equ esp+12 -dl_y2 equ esp+8 -dl_dx equ esp+4 -dl_dy equ esp+0 - - xor edx, edx ; clear edx - xor esi, esi ; unpack arguments - xor ebp, ebp - mov si, ax ; esi = x2 - mov bp, bx ; ebp = y2 - shr eax, 16 ; eax = x1 - shr ebx, 16 ; ebx = y1 - push eax ; save x1 - push ebx ; save y1 - push esi ; save x2 - push ebp ; save y2 -; checking x-axis... - sub esi, eax ; esi = x2-x1 - push esi ; save y2-y1 - jl .x2lx1 ; is x2 less than x1 ? - jg .no_vline ; x1 > x2 ? - mov edx, ebp ; else (if x1=x2) - call vline - push edx ; necessary to rightly restore stack frame at .exit - jmp .exit -.x2lx1: - neg esi ; get esi absolute value -.no_vline: -; checking y-axis... - sub ebp, ebx ; ebp = y2-y1 - push ebp ; save y2-y1 - jl .y2ly1 ; is y2 less than y1 ? - jg .no_hline ; y1 > y2 ? - mov edx, [dl_x2] ; else (if y1=y2) - call hline - jmp .exit - -.y2ly1: - neg ebp ; get ebp absolute value -.no_hline: - cmp ebp, esi - jle .x_rules ; |y2-y1| < |x2-x1| ? - cmp [dl_y2], ebx ; make sure y1 is at the begining - jge .no_reverse1 - neg dword [dl_dx] - mov edx, [dl_x2] - mov [dl_x2], eax - mov [dl_x1], edx - mov edx, [dl_y2] - mov [dl_y2], ebx - mov [dl_y1], edx -.no_reverse1: - mov eax, [dl_dx] - cdq ; extend eax sing to edx - shl eax, 16 ; using 16bit fix-point maths - idiv ebp ; eax = ((x2-x1)*65536)/(y2-y1) - mov edx, ebp ; edx = counter (number of pixels to draw) - mov ebp, 1 *65536 ; <<16 ; ebp = dy = 1.0 - mov esi, eax ; esi = dx - jmp .y_rules - -.x_rules: - cmp [dl_x2], eax ; make sure x1 is at the begining - jge .no_reverse2 - neg dword [dl_dy] - mov edx, [dl_x2] - mov [dl_x2], eax - mov [dl_x1], edx - mov edx, [dl_y2] - mov [dl_y2], ebx - mov [dl_y1], edx -.no_reverse2: - xor edx, edx - mov eax, [dl_dy] - cdq ; extend eax sing to edx - shl eax, 16 ; using 16bit fix-point maths - idiv esi ; eax = ((y2-y1)*65536)/(x2-x1) - mov edx, esi ; edx = counter (number of pixels to draw) - mov esi, 1 *65536 ;<< 16 ; esi = dx = 1.0 - mov ebp, eax ; ebp = dy -.y_rules: - mov eax, [dl_x1] - mov ebx, [dl_y1] - shl eax, 16 - shl ebx, 16 -align 4 -.draw: - push eax ebx - shr eax, 16 - shr ebx, 16 - call [putpixel] - pop ebx eax - add ebx, ebp ; y = y+dy - add eax, esi ; x = x+dx - dec edx - jnz .draw -; force last drawn pixel to be at (x2,y2) - mov eax, [dl_x2] - mov ebx, [dl_y2] - call [putpixel] -.exit: - add esp, 6*4 - popa -; dec [mouse_pause] - call [draw_pointer] - ret - - -hline: -; draw an horizontal line -; eax = x1 -; edx = x2 -; ebx = y -; ecx = color -; edi = force ? - push eax edx - cmp edx, eax ; make sure x2 is above x1 - jge @f - xchg eax, edx -align 4 -@@: - call [putpixel] - inc eax - cmp eax, edx - jle @b - pop edx eax - ret - - -vline: -; draw a vertical line -; eax = x -; ebx = y1 -; edx = y2 -; ecx = color -; edi = force ? - push ebx edx - cmp edx, ebx ; make sure y2 is above y1 - jge @f - xchg ebx, edx -align 4 -@@: - call [putpixel] - inc ebx - cmp ebx, edx - jle @b - pop edx ebx - ret - - -;************************************************* - - -virtual at esp -drbar: - .bar_sx dd ? - .bar_sy dd ? - .bar_cx dd ? - .bar_cy dd ? - .abs_cx dd ? - .abs_cy dd ? - .real_sx dd ? - .real_sy dd ? - .color dd ? - .line_inc_scr dd ? - .line_inc_map dd ? - .stack_data = 4*11 -end virtual - -align 4 -; eax cx -; ebx cy -; ecx xe -; edx ye -; edi color -vesa20_drawbar: - pushad - call [_display.disable_mouse] - sub esp, drbar.stack_data - mov [drbar.color], edi - sub edx, ebx - jle .exit ;// mike.dld, 2005-01-29 - sub ecx, eax - jle .exit ;// mike.dld, 2005-01-29 - mov [drbar.bar_sy], edx - mov [drbar.bar_sx], ecx - mov [drbar.bar_cx], eax - mov [drbar.bar_cy], ebx - mov edi, [TASK_BASE] - add eax, [edi-twdw + WDATA.box.left] ; win_cx - add ebx, [edi-twdw + WDATA.box.top] ; win_cy - mov [drbar.abs_cx], eax - mov [drbar.abs_cy], ebx -; real_sx = MIN(wnd_sx-bar_cx, bar_sx); - mov ebx, [edi-twdw + WDATA.box.width] ; ebx = wnd_sx -; \begin{diamond}[20.08.2006] -; note that WDATA.box.width is one pixel less than real window x-size - inc ebx -; \end{diamond}[20.08.2006] - sub ebx, [drbar.bar_cx] - ja @f -.exit: ;// mike.dld, 2005-01-29 - add esp, drbar.stack_data - popad - xor eax, eax - inc eax - ret -@@: - cmp ebx, [drbar.bar_sx] - jbe .end_x - mov ebx, [drbar.bar_sx] -.end_x: - mov [drbar.real_sx], ebx -; real_sy = MIN(wnd_sy-bar_cy, bar_sy); - mov ebx, [edi-twdw + WDATA.box.height] ; ebx = wnd_sy -; \begin{diamond}[20.08.2006] - inc ebx -; \end{diamond} - sub ebx, [drbar.bar_cy] - ja @f - add esp, drbar.stack_data - popad - xor eax, eax - inc eax - ret -@@: - cmp ebx, [drbar.bar_sy] - jbe .end_y - mov ebx, [drbar.bar_sy] -.end_y: - mov [drbar.real_sy], ebx -; line_inc_map - mov eax, [Screen_Max_X] - sub eax, [drbar.real_sx] - inc eax - mov [drbar.line_inc_map], eax -; line_inc_scr - mov eax, [drbar.real_sx] - movzx ebx, byte [ScreenBPP] - shr ebx, 3 - imul eax, ebx - neg eax - add eax, [BytesPerScanLine] - mov [drbar.line_inc_scr], eax -; pointer to screen - mov edx, [drbar.abs_cy] - imul edx, [BytesPerScanLine] - mov eax, [drbar.abs_cx] -; movzx ebx, byte [ScreenBPP] -; shr ebx, 3 - imul eax, ebx - add edx, eax -; pointer to pixel map - mov eax, [drbar.abs_cy] - imul eax, [Screen_Max_X] - add eax, [drbar.abs_cy] - add eax, [drbar.abs_cx] - add eax, [_WinMapAddress] - xchg eax, ebp -; get process number - mov ebx, [CURRENT_TASK] - cmp byte [ScreenBPP], 24 - jne draw_bar_end_32 -draw_bar_end_24: - mov eax, [drbar.color] ;; BBGGRR00 - mov bh, al ;; bh = BB - shr eax, 8 ;; eax = RRGG -; eax - color high RRGG -; bl - process num -; bh - color low BB -; ecx - temp -; edx - pointer to screen -; esi - counter -; edi - counter - mov esi, [drbar.real_sy] -align 4 -.new_y: - mov edi, [drbar.real_sx] -align 4 -.new_x: - cmp byte [ebp], bl - jne .skip - - mov [LFB_BASE+edx], bh - mov [LFB_BASE+edx + 1], ax -.skip: -; add pixel - add edx, 3 - inc ebp - dec edi - jnz .new_x -; add line - add edx, [drbar.line_inc_scr] - add ebp, [drbar.line_inc_map] -; drawing gradient bars - test eax, 0x00800000 - jz @f - test bh, bh - jz @f - dec bh -@@: -; - dec esi - jnz .new_y - add esp, drbar.stack_data - popad - xor eax, eax - ret - -draw_bar_end_32: - mov eax, [drbar.color] ;; BBGGRR00 - mov esi, [drbar.real_sy] -align 4 -.new_y: - mov edi, [drbar.real_sx] -align 4 -.new_x: - cmp byte [ebp], bl - jne .skip - - mov [LFB_BASE+edx], eax -.skip: -; add pixel - add edx, 4 - inc ebp - dec edi - jnz .new_x -; add line - add edx, [drbar.line_inc_scr] - add ebp, [drbar.line_inc_map] -; drawing gradient bars - test eax, 0x80000000 - jz @f - test al, al - jz @f - dec al -@@: -; - dec esi - jnz .new_y - add esp, drbar.stack_data - popad - call VGA_draw_bar - xor eax, eax - mov [EGA_counter],1 - ret - -align 4 -vesa20_drawbackground_tiled: - call [_display.disable_mouse] - pushad -; External loop for all y from start to end - mov ebx, [draw_data+32+RECT.top] ; y start -dp2: - mov ebp, [draw_data+32+RECT.left] ; x start -; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] -; and LFB data (output for our function) [edi] - mov eax, [BytesPerScanLine] - mul ebx - xchg ebp, eax - add ebp, eax - add ebp, eax - add ebp, eax - cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size - jz @f - add ebp, eax -@@: - add ebp, LFB_BASE -; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB - call calculate_edi - xchg edi, ebp - add ebp, [_WinMapAddress] -; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress -; 2) Calculate offset in background memory block - push eax - xor edx, edx - mov eax, ebx - div dword [BgrDataHeight] ; edx := y mod BgrDataHeight - pop eax - push eax - mov ecx, [BgrDataWidth] - mov esi, edx - imul esi, ecx ; esi := (y mod BgrDataHeight) * BgrDataWidth - xor edx, edx - div ecx ; edx := x mod BgrDataWidth - sub ecx, edx - add esi, edx ; esi := (y mod BgrDataHeight)*BgrDataWidth + (x mod BgrDataWidth) - pop eax - lea esi, [esi*3] - add esi, [img_background] - xor edx, edx - inc edx -; 3) Loop through redraw rectangle and copy background data -; Registers meaning: -; eax = x, ebx = y (screen coordinates) -; ecx = deltax - number of pixels left in current tile block -; edx = 1 -; esi -> bgr memory, edi -> output -; ebp = offset in WinMapAddress -dp3: - cmp [ebp], dl - jnz nbgp - movsb - movsb - movsb - jmp @f -nbgp: - add esi, 3 - add edi, 3 -@@: - cmp [ScreenBPP], byte 25 ; 24 or 32 bpp? - sbb edi, -1 ; +1 for 32 bpp -; I do not use 'inc eax' because this is slightly slower then 'add eax,1' - add ebp, edx - add eax, edx - cmp eax, [draw_data+32+RECT.right] - ja dp4 - sub ecx, edx - jnz dp3 -; next tile block on x-axis - mov ecx, [BgrDataWidth] - sub esi, ecx - sub esi, ecx - sub esi, ecx - jmp dp3 -dp4: -; next scan line - inc ebx - cmp ebx, [draw_data+32+RECT.bottom] - jbe dp2 - popad - mov [EGA_counter], 1 - call VGA_drawbackground - ret - -; ---------- - - -vesa20_drawbackground_stretch: - call [_display.disable_mouse] - pushad -; Helper variables -; calculate 2^32*(BgrDataWidth-1) mod (ScreenWidth-1) - mov eax, [BgrDataWidth] - dec eax - xor edx, edx - div dword [Screen_Max_X] - push eax ; high - xor eax, eax - div dword [Screen_Max_X] - push eax ; low -; the same for height - mov eax, [BgrDataHeight] - dec eax - xor edx, edx - div dword [Screen_Max_Y] - push eax ; high - xor eax, eax - div dword [Screen_Max_Y] - push eax ; low -; External loop for all y from start to end - mov ebx, [draw_data+32+RECT.top] ; y start - mov ebp, [draw_data+32+RECT.left] ; x start -; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] -; and LFB data (output for our function) [edi] - mov eax, [BytesPerScanLine] - mul ebx - xchg ebp, eax - add ebp, eax - add ebp, eax - add ebp, eax - cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size - jz @f - add ebp, eax -@@: -; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB - call calculate_edi - xchg edi, ebp -; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress - push ebx - push eax -; 2) Calculate offset in background memory block - mov eax, ebx - imul ebx, dword [esp+12] - mul dword [esp+8] - add edx, ebx ; edx:eax = y * 2^32*(BgrDataHeight-1)/(ScreenHeight-1) - mov esi, edx - imul esi, [BgrDataWidth] - push edx - push eax - mov eax, [esp+8] - mul dword [esp+28] - push eax - mov eax, [esp+12] - mul dword [esp+28] - add [esp], edx - pop edx ; edx:eax = x * 2^32*(BgrDataWidth-1)/(ScreenWidth-1) - add esi, edx - lea esi, [esi*3] - add esi, [img_background] - push eax - push edx - push esi -; 3) Smooth horizontal -bgr_resmooth0: - mov ecx, [esp+8] - mov edx, [esp+4] - mov esi, [esp] - push edi - mov edi, bgr_cur_line - call smooth_line -bgr_resmooth1: - mov eax, [esp+16+4] - inc eax - cmp eax, [BgrDataHeight] - jae bgr.no2nd - mov ecx, [esp+8+4] - mov edx, [esp+4+4] - mov esi, [esp+4] - add esi, [BgrDataWidth] - add esi, [BgrDataWidth] - add esi, [BgrDataWidth] - mov edi, bgr_next_line - call smooth_line -bgr.no2nd: - pop edi -sdp3: - xor esi, esi - mov ecx, [esp+12] -; 4) Loop through redraw rectangle and copy background data -; Registers meaning: -; esi = offset in current line, edi -> output -; ebp = offset in WinMapAddress -; dword [esp] = offset in bgr data -; qword [esp+4] = x * 2^32 * (BgrDataWidth-1) / (ScreenWidth-1) -; qword [esp+12] = y * 2^32 * (BgrDataHeight-1) / (ScreenHeight-1) -; dword [esp+20] = x -; dword [esp+24] = y -; precalculated constants: -; qword [esp+28] = 2^32*(BgrDataHeight-1)/(ScreenHeight-1) -; qword [esp+36] = 2^32*(BgrDataWidth-1)/(ScreenWidth-1) -sdp3a: - mov eax, [_WinMapAddress] - cmp [ebp+eax], byte 1 - jnz snbgp - mov eax, [bgr_cur_line+esi] - test ecx, ecx - jz .novert - mov ebx, [bgr_next_line+esi] - call [overlapping_of_points_ptr] -.novert: - - mov [LFB_BASE+edi], ax - shr eax, 16 - - mov [LFB_BASE+edi+2], al -snbgp: - cmp [ScreenBPP], byte 25 - sbb edi, -4 - add ebp, 1 - mov eax, [esp+20] - add eax, 1 - mov [esp+20], eax - add esi, 4 - cmp eax, [draw_data+32+RECT.right] - jbe sdp3a -sdp4: -; next y - mov ebx, [esp+24] - add ebx, 1 - mov [esp+24], ebx - cmp ebx, [draw_data+32+RECT.bottom] - ja sdpdone -; advance edi, ebp to next scan line - sub eax, [draw_data+32+RECT.left] - sub ebp, eax - add ebp, [Screen_Max_X] - add ebp, 1 - sub edi, eax - sub edi, eax - sub edi, eax - cmp [ScreenBPP], byte 24 - jz @f - sub edi, eax -@@: - add edi, [BytesPerScanLine] -; restore ecx,edx; advance esi to next background line - mov eax, [esp+28] - mov ebx, [esp+32] - add [esp+12], eax - mov eax, [esp+16] - adc [esp+16], ebx - sub eax, [esp+16] - mov ebx, eax - lea eax, [eax*3] - imul eax, [BgrDataWidth] - sub [esp], eax - mov eax, [draw_data+32+RECT.left] - mov [esp+20], eax - test ebx, ebx - jz sdp3 - cmp ebx, -1 - jnz bgr_resmooth0 - push edi - mov esi, bgr_next_line - mov edi, bgr_cur_line - mov ecx, [Screen_Max_X] - inc ecx - rep movsd - jmp bgr_resmooth1 -sdpdone: - add esp, 44 - popad - mov [EGA_counter],1 - call VGA_drawbackground - ret - -uglobal -align 4 -bgr_cur_line rd 1920 ; maximum width of screen -bgr_next_line rd 1920 -endg - -smooth_line: - mov al, [esi+2] - shl eax, 16 - mov ax, [esi] - test ecx, ecx - jz @f - mov ebx, [esi+2] - shr ebx, 8 - call [overlapping_of_points_ptr] -@@: - stosd - mov eax, [esp+20+8] - add eax, 1 - mov [esp+20+8], eax - cmp eax, [draw_data+32+RECT.right] - ja @f - add ecx, [esp+36+8] - mov eax, edx - adc edx, [esp+40+8] - sub eax, edx - lea eax, [eax*3] - sub esi, eax - jmp smooth_line -@@: - mov eax, [draw_data+32+RECT.left] - mov [esp+20+8], eax - ret - -align 16 -overlapping_of_points: -if 0 -; this version of procedure works, but is slower than next version - push ecx edx - mov edx, eax - push esi - shr ecx, 24 - mov esi, ecx - mov ecx, ebx - movzx ebx, dl - movzx eax, cl - sub eax, ebx - movzx ebx, dh - imul eax, esi - add dl, ah - movzx eax, ch - sub eax, ebx - imul eax, esi - add dh, ah - ror ecx, 16 - ror edx, 16 - movzx eax, cl - movzx ebx, dl - sub eax, ebx - imul eax, esi - pop esi - add dl, ah - mov eax, edx - pop edx - ror eax, 16 - pop ecx - ret -else - push ecx edx - mov edx, eax - push esi - shr ecx, 26 - mov esi, ecx - mov ecx, ebx - shl esi, 9 - movzx ebx, dl - movzx eax, cl - sub eax, ebx - movzx ebx, dh - add dl, [BgrAuxTable+(eax+0x100)+esi] - movzx eax, ch - sub eax, ebx - add dh, [BgrAuxTable+(eax+0x100)+esi] - ror ecx, 16 - ror edx, 16 - movzx eax, cl - movzx ebx, dl - sub eax, ebx - add dl, [BgrAuxTable+(eax+0x100)+esi] - pop esi - mov eax, edx - pop edx - ror eax, 16 - pop ecx - ret -end if - -iglobal -align 4 -overlapping_of_points_ptr dd overlapping_of_points -endg - -init_background: - mov edi, BgrAuxTable - xor edx, edx -.loop2: - mov eax, edx - shl eax, 8 - neg eax - mov ecx, 0x200 -.loop1: - mov byte [edi], ah - inc edi - add eax, edx - loop .loop1 - add dl, 4 - jnz .loop2 - test byte [cpu_caps+(CAPS_MMX/8)], 1 shl (CAPS_MMX mod 8) - jz @f - mov [overlapping_of_points_ptr], overlapping_of_points_mmx -@@: - ret - -align 16 -overlapping_of_points_mmx: - movd mm0, eax - movd mm4, eax - movd mm1, ebx - pxor mm2, mm2 - punpcklbw mm0, mm2 - punpcklbw mm1, mm2 - psubw mm1, mm0 - movd mm3, ecx - psrld mm3, 24 - packuswb mm3, mm3 - packuswb mm3, mm3 - pmullw mm1, mm3 - psrlw mm1, 8 - packuswb mm1, mm2 - paddb mm4, mm1 - movd eax, mm4 - ret +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; VESA20.INC ;; +;; ;; +;; Vesa 2.0 functions for MenuetOS ;; +;; ;; +;; Copyright 2002 Ville Turjanmaa ;; +;; Alexey, kgaz@crosswindws.net ;; +;; - Voodoo compatible graphics ;; +;; Juan M. Caravaca ;; +;; - Graphics optimimizations eg. drawline ;; +;; ;; +;; See file COPYING for details ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +; If you're planning to write your own video driver I suggest +; you replace the VESA12.INC file and see those instructions. + +;Screen_Max_X equ 0xfe00 +;Screen_Max_Y equ 0xfe04 +;BytesPerScanLine equ 0xfe08 +;LFBAddress equ 0xfe80 +;ScreenBPP equ 0xfbf1 + + + +;************************************************* +; getpixel +; +; in: +; eax = x coordinate +; ebx = y coordinate +; +; ret: +; ecx = 00 RR GG BB + +getpixel: + push eax ebx edx edi + call dword [GETPIXEL] + pop edi edx ebx eax + ret + +Vesa20_getpixel24: +; eax = x +; ebx = y + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [eax+eax*2]; edi = x*3 + add edi, ebx ; edi = x*3+(y*y multiplier) + mov ecx, [LFB_BASE+edi] + and ecx, 0xffffff + ret + +Vesa20_getpixel32: + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier) + mov ecx, [LFB_BASE+edi] + and ecx, 0xffffff + ret + +;************************************************* + +virtual at esp + putimg: + .real_sx dd ? + .real_sy dd ? + .image_sx dd ? + .image_sy dd ? + .image_cx dd ? + .image_cy dd ? + .pti dd ? + .abs_cx dd ? + .abs_cy dd ? + .line_increment dd ? + .winmap_newline dd ? + .screen_newline dd ? + .stack_data = 4*12 + .edi dd ? + .esi dd ? + .ebp dd ? + .esp dd ? + .ebx dd ? + .edx dd ? + .ecx dd ? + .eax dd ? + .ret_addr dd ? + .arg_0 dd ? +end virtual + +align 16 +; ebx = pointer +; ecx = size [x|y] +; edx = coordinates [x|y] +; ebp = pointer to 'get' function +; esi = pointer to 'init' function +; edi = parameter for 'get' function + +vesa20_putimage: + pushad + call [_display.disable_mouse] + sub esp, putimg.stack_data +; save pointer to image + mov [putimg.pti], ebx +; unpack the size + mov eax, ecx + and ecx, 0xFFFF + shr eax, 16 + mov [putimg.image_sx], eax + mov [putimg.image_sy], ecx +; unpack the coordinates + mov eax, edx + and edx, 0xFFFF + shr eax, 16 + mov [putimg.image_cx], eax + mov [putimg.image_cy], edx +; calculate absolute (i.e. screen) coordinates + mov eax, [TASK_BASE] + mov ebx, [eax-twdw + WDATA.box.left] + add ebx, [putimg.image_cx] + mov [putimg.abs_cx], ebx + mov ebx, [eax-twdw + WDATA.box.top] + add ebx, [putimg.image_cy] + mov [putimg.abs_cy], ebx +; real_sx = MIN(wnd_sx-image_cx, image_sx); + mov ebx, [eax-twdw + WDATA.box.width]; ebx = wnd_sx +; \begin{diamond}[20.08.2006] +; note that WDATA.box.width is one pixel less than real window x-size + inc ebx +; \end{diamond}[20.08.2006] + sub ebx, [putimg.image_cx] + ja @f + add esp, putimg.stack_data + popad + ret +@@: + cmp ebx, [putimg.image_sx] + jbe .end_x + mov ebx, [putimg.image_sx] +.end_x: + mov [putimg.real_sx], ebx +; init real_sy + mov ebx, [eax-twdw + WDATA.box.height]; ebx = wnd_sy +; \begin{diamond}[20.08.2006] + inc ebx +; \end{diamond}[20.08.2006] + sub ebx, [putimg.image_cy] + ja @f + add esp, putimg.stack_data + popad + ret +@@: + cmp ebx, [putimg.image_sy] + jbe .end_y + mov ebx, [putimg.image_sy] +.end_y: + mov [putimg.real_sy], ebx +; line increment + mov eax, [putimg.image_sx] + mov ecx, [putimg.real_sx] + sub eax, ecx +;; imul eax, [putimg.source_bpp] +; lea eax, [eax + eax * 2] + call esi + add eax, [putimg.arg_0] + mov [putimg.line_increment], eax +; winmap new line increment + mov eax, [Screen_Max_X] + inc eax + sub eax, [putimg.real_sx] + mov [putimg.winmap_newline], eax +; screen new line increment + mov eax, [BytesPerScanLine] + movzx ebx, byte [ScreenBPP] + shr ebx, 3 + imul ecx, ebx + sub eax, ecx + mov [putimg.screen_newline], eax +; pointer to image + mov esi, [putimg.pti] +; pointer to screen + mov edx, [putimg.abs_cy] + imul edx, [BytesPerScanLine] + mov eax, [putimg.abs_cx] + movzx ebx, byte [ScreenBPP] + shr ebx, 3 + imul eax, ebx + add edx, eax +; pointer to pixel map + mov eax, [putimg.abs_cy] + imul eax, [Screen_Max_X] + add eax, [putimg.abs_cy] + add eax, [putimg.abs_cx] + add eax, [_WinMapAddress] + xchg eax, ebp +; get process number + mov ebx, [CURRENT_TASK] + cmp byte [ScreenBPP], 32 + je put_image_end_32 +;put_image_end_24: + mov edi, [putimg.real_sy] +align 4 +.new_line: + mov ecx, [putimg.real_sx] +; push ebp edx +align 4 +.new_x: + push [putimg.edi] + mov eax, [putimg.ebp+4] + call eax + cmp [ebp], bl + jne .skip +; mov eax, [esi] ; eax = RRBBGGRR + mov [LFB_BASE+edx], ax + shr eax, 16 + mov [LFB_BASE+edx+2], al +.skip: +; add esi, 3 ;[putimg.source_bpp] + add edx, 3 + inc ebp + dec ecx + jnz .new_x +; pop edx ebp + add esi, [putimg.line_increment] + add edx, [putimg.screen_newline];[BytesPerScanLine] + add ebp, [putimg.winmap_newline];[Screen_Max_X] +; inc ebp + cmp [putimg.ebp], putimage_get1bpp + jz .correct + cmp [putimg.ebp], putimage_get2bpp + jz .correct + cmp [putimg.ebp], putimage_get4bpp + jnz @f +.correct: + mov eax, [putimg.edi] + mov byte [eax], 80h +@@: + dec edi + jnz .new_line +.finish: + add esp, putimg.stack_data + popad + ret + +put_image_end_32: + mov edi, [putimg.real_sy] +align 4 +.new_line: + mov ecx, [putimg.real_sx] +; push ebp edx +align 4 +.new_x: + push [putimg.edi] + mov eax, [putimg.ebp+4] + call eax + cmp [ebp], bl + jne .skip +; mov eax, [esi] ; ecx = RRBBGGRR + mov [LFB_BASE+edx], eax +.skip: +; add esi, [putimg.source_bpp] + add edx, 4 + inc ebp + dec ecx + jnz .new_x +; pop edx ebp + add esi, [putimg.line_increment] + add edx, [putimg.screen_newline];[BytesPerScanLine] + add ebp, [putimg.winmap_newline];[Screen_Max_X] +; inc ebp + cmp [putimg.ebp], putimage_get1bpp + jz .correct + cmp [putimg.ebp], putimage_get2bpp + jz .correct + cmp [putimg.ebp], putimage_get4bpp + jnz @f +.correct: + mov eax, [putimg.edi] + mov byte [eax], 80h +@@: + dec edi + jnz .new_line +.finish: + add esp, putimg.stack_data + popad + call VGA__putimage + mov [EGA_counter], 1 + ret + + +;************************************************* +align 4 +__sys_putpixel: + +; eax = x coordinate +; ebx = y coordinate +; ecx = ?? RR GG BB ; 0x01000000 negation +; edi = 0x00000001 force + +;;; mov [novesachecksum], dword 0 + pushad + cmp [Screen_Max_X], eax + jb .exit + cmp [Screen_Max_Y], ebx + jb .exit + test edi, 1 ; force ? + jnz .forced + +; not forced: + + push eax + mov edx, [_display.width]; screen x size + imul edx, ebx + add eax, [_WinMapAddress] + movzx edx, byte [eax+edx] + cmp edx, [CURRENT_TASK] + pop eax + jne .exit + +.forced: +; check if negation + test ecx, 0x01000000 + jz .noneg + call getpixel + not ecx + mov [esp+32-8], ecx +.noneg: +; OK to set pixel + call dword [PUTPIXEL]; call the real put_pixel function +.exit: + popad + ret + +align 4 +Vesa20_putpixel24: +; eax = x +; ebx = y + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [eax+eax*2]; edi = x*3 + mov eax, [esp+32-8+4] + mov [LFB_BASE+ebx+edi], ax + shr eax, 16 + mov [LFB_BASE+ebx+edi+2], al + ret + + +align 4 +Vesa20_putpixel32: +; eax = x +; ebx = y + imul ebx, [BytesPerScanLine] ; ebx = y * y multiplier + lea edi, [ebx+eax*4]; edi = x*4+(y*y multiplier) + mov eax, [esp+32-8+4]; eax = color + mov [LFB_BASE+edi], eax + ret + +;************************************************* + +;align 4 +calculate_edi: + mov edi, ebx + imul edi, [Screen_Max_X] + add edi, ebx + add edi, eax + ret + +;************************************************* + +; DRAWLINE + +align 4 +__sys_draw_line: +; inc [mouse_pause] + call [_display.disable_mouse] + +; draw a line +; eax = HIWORD = x1 +; LOWORD = x2 +; ebx = HIWORD = y1 +; LOWORD = y2 +; ecx = color +; edi = force ? + pusha + +dl_x1 equ esp+20 +dl_y1 equ esp+16 +dl_x2 equ esp+12 +dl_y2 equ esp+8 +dl_dx equ esp+4 +dl_dy equ esp+0 + + xor edx, edx ; clear edx + xor esi, esi ; unpack arguments + xor ebp, ebp + mov si, ax ; esi = x2 + mov bp, bx ; ebp = y2 + shr eax, 16 ; eax = x1 + shr ebx, 16 ; ebx = y1 + push eax ; save x1 + push ebx ; save y1 + push esi ; save x2 + push ebp ; save y2 +; checking x-axis... + sub esi, eax ; esi = x2-x1 + push esi ; save y2-y1 + jl .x2lx1 ; is x2 less than x1 ? + jg .no_vline ; x1 > x2 ? + mov edx, ebp ; else (if x1=x2) + call vline + push edx ; necessary to rightly restore stack frame at .exit + jmp .exit +.x2lx1: + neg esi ; get esi absolute value +.no_vline: +; checking y-axis... + sub ebp, ebx ; ebp = y2-y1 + push ebp ; save y2-y1 + jl .y2ly1 ; is y2 less than y1 ? + jg .no_hline ; y1 > y2 ? + mov edx, [dl_x2]; else (if y1=y2) + call hline + jmp .exit + +.y2ly1: + neg ebp ; get ebp absolute value +.no_hline: + cmp ebp, esi + jle .x_rules ; |y2-y1| < |x2-x1| ? + cmp [dl_y2], ebx; make sure y1 is at the begining + jge .no_reverse1 + neg dword [dl_dx] + mov edx, [dl_x2] + mov [dl_x2], eax + mov [dl_x1], edx + mov edx, [dl_y2] + mov [dl_y2], ebx + mov [dl_y1], edx +.no_reverse1: + mov eax, [dl_dx] + cdq ; extend eax sing to edx + shl eax, 16 ; using 16bit fix-point maths + idiv ebp ; eax = ((x2-x1)*65536)/(y2-y1) + mov edx, ebp ; edx = counter (number of pixels to draw) + mov ebp, 1 *65536; <<16 ; ebp = dy = 1.0 + mov esi, eax ; esi = dx + jmp .y_rules + +.x_rules: + cmp [dl_x2], eax ; make sure x1 is at the begining + jge .no_reverse2 + neg dword [dl_dy] + mov edx, [dl_x2] + mov [dl_x2], eax + mov [dl_x1], edx + mov edx, [dl_y2] + mov [dl_y2], ebx + mov [dl_y1], edx +.no_reverse2: + xor edx, edx + mov eax, [dl_dy] + cdq ; extend eax sing to edx + shl eax, 16 ; using 16bit fix-point maths + idiv esi ; eax = ((y2-y1)*65536)/(x2-x1) + mov edx, esi ; edx = counter (number of pixels to draw) + mov esi, 1 *65536;<< 16 ; esi = dx = 1.0 + mov ebp, eax ; ebp = dy +.y_rules: + mov eax, [dl_x1] + mov ebx, [dl_y1] + shl eax, 16 + shl ebx, 16 +align 4 +.draw: + push eax ebx + shr eax, 16 + shr ebx, 16 + call [putpixel] + pop ebx eax + add ebx, ebp ; y = y+dy + add eax, esi ; x = x+dx + dec edx + jnz .draw +; force last drawn pixel to be at (x2,y2) + mov eax, [dl_x2] + mov ebx, [dl_y2] + call [putpixel] +.exit: + add esp, 6*4 + popa +; dec [mouse_pause] + call [draw_pointer] + ret + + +hline: +; draw an horizontal line +; eax = x1 +; edx = x2 +; ebx = y +; ecx = color +; edi = force ? + push eax edx + cmp edx, eax ; make sure x2 is above x1 + jge @f + xchg eax, edx +align 4 +@@: + call [putpixel] + inc eax + cmp eax, edx + jle @b + pop edx eax + ret + + +vline: +; draw a vertical line +; eax = x +; ebx = y1 +; edx = y2 +; ecx = color +; edi = force ? + push ebx edx + cmp edx, ebx ; make sure y2 is above y1 + jge @f + xchg ebx, edx +align 4 +@@: + call [putpixel] + inc ebx + cmp ebx, edx + jle @b + pop edx ebx + ret + + +;************************************************* + + +virtual at esp +drbar: + .bar_sx dd ? + .bar_sy dd ? + .bar_cx dd ? + .bar_cy dd ? + .abs_cx dd ? + .abs_cy dd ? + .real_sx dd ? + .real_sy dd ? + .color dd ? + .line_inc_scr dd ? + .line_inc_map dd ? + .stack_data = 4*11 +end virtual + +align 4 +; eax cx +; ebx cy +; ecx xe +; edx ye +; edi color +vesa20_drawbar: + pushad + call [_display.disable_mouse] + sub esp, drbar.stack_data + mov [drbar.color], edi + sub edx, ebx + jle .exit ;// mike.dld, 2005-01-29 + sub ecx, eax + jle .exit ;// mike.dld, 2005-01-29 + mov [drbar.bar_sy], edx + mov [drbar.bar_sx], ecx + mov [drbar.bar_cx], eax + mov [drbar.bar_cy], ebx + mov edi, [TASK_BASE] + add eax, [edi-twdw + WDATA.box.left]; win_cx + add ebx, [edi-twdw + WDATA.box.top]; win_cy + mov [drbar.abs_cx], eax + mov [drbar.abs_cy], ebx +; real_sx = MIN(wnd_sx-bar_cx, bar_sx); + mov ebx, [edi-twdw + WDATA.box.width]; ebx = wnd_sx +; \begin{diamond}[20.08.2006] +; note that WDATA.box.width is one pixel less than real window x-size + inc ebx +; \end{diamond}[20.08.2006] + sub ebx, [drbar.bar_cx] + ja @f +.exit: ;// mike.dld, 2005-01-29 + add esp, drbar.stack_data + popad + xor eax, eax + inc eax + ret +@@: + cmp ebx, [drbar.bar_sx] + jbe .end_x + mov ebx, [drbar.bar_sx] +.end_x: + mov [drbar.real_sx], ebx +; real_sy = MIN(wnd_sy-bar_cy, bar_sy); + mov ebx, [edi-twdw + WDATA.box.height]; ebx = wnd_sy +; \begin{diamond}[20.08.2006] + inc ebx +; \end{diamond} + sub ebx, [drbar.bar_cy] + ja @f + add esp, drbar.stack_data + popad + xor eax, eax + inc eax + ret +@@: + cmp ebx, [drbar.bar_sy] + jbe .end_y + mov ebx, [drbar.bar_sy] +.end_y: + mov [drbar.real_sy], ebx +; line_inc_map + mov eax, [Screen_Max_X] + sub eax, [drbar.real_sx] + inc eax + mov [drbar.line_inc_map], eax +; line_inc_scr + mov eax, [drbar.real_sx] + movzx ebx, byte [ScreenBPP] + shr ebx, 3 + imul eax, ebx + neg eax + add eax, [BytesPerScanLine] + mov [drbar.line_inc_scr], eax +; pointer to screen + mov edx, [drbar.abs_cy] + imul edx, [BytesPerScanLine] + mov eax, [drbar.abs_cx] +; movzx ebx, byte [ScreenBPP] +; shr ebx, 3 + imul eax, ebx + add edx, eax +; pointer to pixel map + mov eax, [drbar.abs_cy] + imul eax, [Screen_Max_X] + add eax, [drbar.abs_cy] + add eax, [drbar.abs_cx] + add eax, [_WinMapAddress] + xchg eax, ebp +; get process number + mov ebx, [CURRENT_TASK] + cmp byte [ScreenBPP], 24 + jne draw_bar_end_32 +draw_bar_end_24: + mov eax, [drbar.color] ;; BBGGRR00 + mov bh, al ;; bh = BB + shr eax, 8 ;; eax = RRGG +; eax - color high RRGG +; bl - process num +; bh - color low BB +; ecx - temp +; edx - pointer to screen +; esi - counter +; edi - counter + mov esi, [drbar.real_sy] +align 4 +.new_y: + mov edi, [drbar.real_sx] +align 4 +.new_x: + cmp byte [ebp], bl + jne .skip + + mov [LFB_BASE+edx], bh + mov [LFB_BASE+edx + 1], ax +.skip: +; add pixel + add edx, 3 + inc ebp + dec edi + jnz .new_x +; add line + add edx, [drbar.line_inc_scr] + add ebp, [drbar.line_inc_map] +; drawing gradient bars + test eax, 0x00800000 + jz @f + test bh, bh + jz @f + dec bh +@@: +; + dec esi + jnz .new_y + add esp, drbar.stack_data + popad + xor eax, eax + ret + +draw_bar_end_32: + mov eax, [drbar.color] ;; BBGGRR00 + mov esi, [drbar.real_sy] +align 4 +.new_y: + mov edi, [drbar.real_sx] +align 4 +.new_x: + cmp byte [ebp], bl + jne .skip + + mov [LFB_BASE+edx], eax +.skip: +; add pixel + add edx, 4 + inc ebp + dec edi + jnz .new_x +; add line + add edx, [drbar.line_inc_scr] + add ebp, [drbar.line_inc_map] +; drawing gradient bars + test eax, 0x80000000 + jz @f + test al, al + jz @f + dec al +@@: +; + dec esi + jnz .new_y + add esp, drbar.stack_data + popad + call VGA_draw_bar + xor eax, eax + mov [EGA_counter], 1 + ret + +align 4 +vesa20_drawbackground_tiled: + call [_display.disable_mouse] + pushad +; External loop for all y from start to end + mov ebx, [draw_data+32+RECT.top] ; y start +dp2: + mov ebp, [draw_data+32+RECT.left] ; x start +; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] +; and LFB data (output for our function) [edi] + mov eax, [BytesPerScanLine] + mul ebx + xchg ebp, eax + add ebp, eax + add ebp, eax + add ebp, eax + cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size + jz @f + add ebp, eax +@@: + add ebp, LFB_BASE +; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB + call calculate_edi + xchg edi, ebp + add ebp, [_WinMapAddress] +; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress +; 2) Calculate offset in background memory block + push eax + xor edx, edx + mov eax, ebx + div dword [BgrDataHeight] ; edx := y mod BgrDataHeight + pop eax + push eax + mov ecx, [BgrDataWidth] + mov esi, edx + imul esi, ecx ; esi := (y mod BgrDataHeight) * BgrDataWidth + xor edx, edx + div ecx ; edx := x mod BgrDataWidth + sub ecx, edx + add esi, edx ; esi := (y mod BgrDataHeight)*BgrDataWidth + (x mod BgrDataWidth) + pop eax + lea esi, [esi*3] + add esi, [img_background] + xor edx, edx + inc edx +; 3) Loop through redraw rectangle and copy background data +; Registers meaning: +; eax = x, ebx = y (screen coordinates) +; ecx = deltax - number of pixels left in current tile block +; edx = 1 +; esi -> bgr memory, edi -> output +; ebp = offset in WinMapAddress +dp3: + cmp [ebp], dl + jnz nbgp + movsb + movsb + movsb + jmp @f +nbgp: + add esi, 3 + add edi, 3 +@@: + cmp [ScreenBPP], byte 25 ; 24 or 32 bpp? + sbb edi, -1 ; +1 for 32 bpp +; I do not use 'inc eax' because this is slightly slower then 'add eax,1' + add ebp, edx + add eax, edx + cmp eax, [draw_data+32+RECT.right] + ja dp4 + sub ecx, edx + jnz dp3 +; next tile block on x-axis + mov ecx, [BgrDataWidth] + sub esi, ecx + sub esi, ecx + sub esi, ecx + jmp dp3 +dp4: +; next scan line + inc ebx + cmp ebx, [draw_data+32+RECT.bottom] + jbe dp2 + popad + mov [EGA_counter], 1 + call VGA_drawbackground + ret + +; ---------- + + +vesa20_drawbackground_stretch: + call [_display.disable_mouse] + pushad +; Helper variables +; calculate 2^32*(BgrDataWidth-1) mod (ScreenWidth-1) + mov eax, [BgrDataWidth] + dec eax + xor edx, edx + div dword [Screen_Max_X] + push eax ; high + xor eax, eax + div dword [Screen_Max_X] + push eax ; low +; the same for height + mov eax, [BgrDataHeight] + dec eax + xor edx, edx + div dword [Screen_Max_Y] + push eax ; high + xor eax, eax + div dword [Screen_Max_Y] + push eax ; low +; External loop for all y from start to end + mov ebx, [draw_data+32+RECT.top] ; y start + mov ebp, [draw_data+32+RECT.left] ; x start +; 1) Calculate pointers in WinMapAddress (does pixel belong to OS thread?) [ebp] +; and LFB data (output for our function) [edi] + mov eax, [BytesPerScanLine] + mul ebx + xchg ebp, eax + add ebp, eax + add ebp, eax + add ebp, eax + cmp [ScreenBPP], byte 24 ; 24 or 32 bpp ? - x size + jz @f + add ebp, eax +@@: +; ebp:=Y*BytesPerScanLine+X*BytesPerPixel+AddrLFB + call calculate_edi + xchg edi, ebp +; Now eax=x, ebx=y, edi->output, ebp=offset in WinMapAddress + push ebx + push eax +; 2) Calculate offset in background memory block + mov eax, ebx + imul ebx, dword [esp+12] + mul dword [esp+8] + add edx, ebx ; edx:eax = y * 2^32*(BgrDataHeight-1)/(ScreenHeight-1) + mov esi, edx + imul esi, [BgrDataWidth] + push edx + push eax + mov eax, [esp+8] + mul dword [esp+28] + push eax + mov eax, [esp+12] + mul dword [esp+28] + add [esp], edx + pop edx ; edx:eax = x * 2^32*(BgrDataWidth-1)/(ScreenWidth-1) + add esi, edx + lea esi, [esi*3] + add esi, [img_background] + push eax + push edx + push esi +; 3) Smooth horizontal +bgr_resmooth0: + mov ecx, [esp+8] + mov edx, [esp+4] + mov esi, [esp] + push edi + mov edi, bgr_cur_line + call smooth_line +bgr_resmooth1: + mov eax, [esp+16+4] + inc eax + cmp eax, [BgrDataHeight] + jae bgr.no2nd + mov ecx, [esp+8+4] + mov edx, [esp+4+4] + mov esi, [esp+4] + add esi, [BgrDataWidth] + add esi, [BgrDataWidth] + add esi, [BgrDataWidth] + mov edi, bgr_next_line + call smooth_line +bgr.no2nd: + pop edi +sdp3: + xor esi, esi + mov ecx, [esp+12] +; 4) Loop through redraw rectangle and copy background data +; Registers meaning: +; esi = offset in current line, edi -> output +; ebp = offset in WinMapAddress +; dword [esp] = offset in bgr data +; qword [esp+4] = x * 2^32 * (BgrDataWidth-1) / (ScreenWidth-1) +; qword [esp+12] = y * 2^32 * (BgrDataHeight-1) / (ScreenHeight-1) +; dword [esp+20] = x +; dword [esp+24] = y +; precalculated constants: +; qword [esp+28] = 2^32*(BgrDataHeight-1)/(ScreenHeight-1) +; qword [esp+36] = 2^32*(BgrDataWidth-1)/(ScreenWidth-1) +sdp3a: + mov eax, [_WinMapAddress] + cmp [ebp+eax], byte 1 + jnz snbgp + mov eax, [bgr_cur_line+esi] + test ecx, ecx + jz .novert + mov ebx, [bgr_next_line+esi] + call [overlapping_of_points_ptr] +.novert: + + mov [LFB_BASE+edi], ax + shr eax, 16 + + mov [LFB_BASE+edi+2], al +snbgp: + cmp [ScreenBPP], byte 25 + sbb edi, -4 + add ebp, 1 + mov eax, [esp+20] + add eax, 1 + mov [esp+20], eax + add esi, 4 + cmp eax, [draw_data+32+RECT.right] + jbe sdp3a +sdp4: +; next y + mov ebx, [esp+24] + add ebx, 1 + mov [esp+24], ebx + cmp ebx, [draw_data+32+RECT.bottom] + ja sdpdone +; advance edi, ebp to next scan line + sub eax, [draw_data+32+RECT.left] + sub ebp, eax + add ebp, [Screen_Max_X] + add ebp, 1 + sub edi, eax + sub edi, eax + sub edi, eax + cmp [ScreenBPP], byte 24 + jz @f + sub edi, eax +@@: + add edi, [BytesPerScanLine] +; restore ecx,edx; advance esi to next background line + mov eax, [esp+28] + mov ebx, [esp+32] + add [esp+12], eax + mov eax, [esp+16] + adc [esp+16], ebx + sub eax, [esp+16] + mov ebx, eax + lea eax, [eax*3] + imul eax, [BgrDataWidth] + sub [esp], eax + mov eax, [draw_data+32+RECT.left] + mov [esp+20], eax + test ebx, ebx + jz sdp3 + cmp ebx, -1 + jnz bgr_resmooth0 + push edi + mov esi, bgr_next_line + mov edi, bgr_cur_line + mov ecx, [Screen_Max_X] + inc ecx + rep movsd + jmp bgr_resmooth1 +sdpdone: + add esp, 44 + popad + mov [EGA_counter], 1 + call VGA_drawbackground + ret + +uglobal +align 4 +bgr_cur_line rd 1920 ; maximum width of screen +bgr_next_line rd 1920 +endg + +smooth_line: + mov al, [esi+2] + shl eax, 16 + mov ax, [esi] + test ecx, ecx + jz @f + mov ebx, [esi+2] + shr ebx, 8 + call [overlapping_of_points_ptr] +@@: + stosd + mov eax, [esp+20+8] + add eax, 1 + mov [esp+20+8], eax + cmp eax, [draw_data+32+RECT.right] + ja @f + add ecx, [esp+36+8] + mov eax, edx + adc edx, [esp+40+8] + sub eax, edx + lea eax, [eax*3] + sub esi, eax + jmp smooth_line +@@: + mov eax, [draw_data+32+RECT.left] + mov [esp+20+8], eax + ret + +align 16 +overlapping_of_points: +if 0 +; this version of procedure works, but is slower than next version + push ecx edx + mov edx, eax + push esi + shr ecx, 24 + mov esi, ecx + mov ecx, ebx + movzx ebx, dl + movzx eax, cl + sub eax, ebx + movzx ebx, dh + imul eax, esi + add dl, ah + movzx eax, ch + sub eax, ebx + imul eax, esi + add dh, ah + ror ecx, 16 + ror edx, 16 + movzx eax, cl + movzx ebx, dl + sub eax, ebx + imul eax, esi + pop esi + add dl, ah + mov eax, edx + pop edx + ror eax, 16 + pop ecx + ret +else + push ecx edx + mov edx, eax + push esi + shr ecx, 26 + mov esi, ecx + mov ecx, ebx + shl esi, 9 + movzx ebx, dl + movzx eax, cl + sub eax, ebx + movzx ebx, dh + add dl, [BgrAuxTable+(eax+0x100)+esi] + movzx eax, ch + sub eax, ebx + add dh, [BgrAuxTable+(eax+0x100)+esi] + ror ecx, 16 + ror edx, 16 + movzx eax, cl + movzx ebx, dl + sub eax, ebx + add dl, [BgrAuxTable+(eax+0x100)+esi] + pop esi + mov eax, edx + pop edx + ror eax, 16 + pop ecx + ret +end if + +iglobal +align 4 +overlapping_of_points_ptr dd overlapping_of_points +endg + +init_background: + mov edi, BgrAuxTable + xor edx, edx +.loop2: + mov eax, edx + shl eax, 8 + neg eax + mov ecx, 0x200 +.loop1: + mov byte [edi], ah + inc edi + add eax, edx + loop .loop1 + add dl, 4 + jnz .loop2 + test byte [cpu_caps+(CAPS_MMX/8)], 1 shl (CAPS_MMX mod 8) + jz @f + mov [overlapping_of_points_ptr], overlapping_of_points_mmx +@@: + ret + +align 16 +overlapping_of_points_mmx: + movd mm0, eax + movd mm4, eax + movd mm1, ebx + pxor mm2, mm2 + punpcklbw mm0, mm2 + punpcklbw mm1, mm2 + psubw mm1, mm0 + movd mm3, ecx + psrld mm3, 24 + packuswb mm3, mm3 + packuswb mm3, mm3 + pmullw mm1, mm3 + psrlw mm1, 8 + packuswb mm1, mm2 + paddb mm4, mm1 + movd eax, mm4 + ret diff --git a/kernel/trunk/video/vga.inc b/kernel/trunk/video/vga.inc index bd23d1a1c..ecce28edc 100644 --- a/kernel/trunk/video/vga.inc +++ b/kernel/trunk/video/vga.inc @@ -1,450 +1,450 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; -;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; -;; Distributed under terms of the GNU General Public License ;; -;; ;; -;; VGA.INC ;; -;; ;; -;; 640x480 mode 0x12 VGA functions for MenuetOS ;; -;; ;; -;; Paul Butcher, paul.butcher@asa.co.uk ;; -;; ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -$Revision$ - - -paletteVGA: - -;16 colour palette - mov dx,0x3c8 - mov al,0 - out dx,al - - mov ecx,16 - mov dx,0x3c9 - xor eax,eax - - palvganew: - - mov al,0 - test ah,4 - jz palvgalbl1 - add al,31 - test ah,8 - jz palvgalbl1 - add al,32 - palvgalbl1: - out dx,al ; red 0,31 or 63 - mov al,0 - test ah,2 - jz palvgalbl2 - add al,31 - test ah,8 - jz palvgalbl2 - add al,32 - palvgalbl2: - out dx,al ; blue 0,31 or 63 - mov al,0 - test ah,1 - jz palvgalbl3 - add al,31 - test ah,8 - jz palvgalbl3 - add al,32 - palvgalbl3: - out dx,al ; green 0,31 or 63 - add ah,1 - loop palvganew -; mov dx, 3ceh -; mov ax, 0005h -; out dx, ax - ret - -palette320x200: - - mov edx,0x3c8 - xor eax, eax - out dx,al - mov ecx,256 - mov edx,0x3c9 - xor eax,eax - - palnew: - mov al,0 - test ah,64 - jz pallbl1 - add al,21 - pallbl1: - test ah,128 - jz pallbl2 - add al,42 - pallbl2: - out dx,al - mov al,0 - test ah,8 - jz pallbl3 - add al,8 - pallbl3: - test ah,16 - jz pallbl4 - add al,15 - pallbl4: - test ah,32 - jz pallbl5 - add al,40 - pallbl5: - out dx,al - mov al,0 - test ah,1 - jz pallbl6 - add al,8 - pallbl6: - test ah,2 - jz pallbl7 - add al,15 - pallbl7: - test ah,4 - jz pallbl8 - add al,40 - pallbl8: - out dx,al - add ah,1 - loop palnew - - ret -align 4 -uglobal - novesachecksum dd 0x0 - EGA_counter db 0 - VGA_drawing_screen db 0 - VGA_8_pixels: - rb 16 - temp: - .cx dd 0 -endg -align 4 -checkVga_N13: - - cmp [SCR_MODE],dword 0x13 - jne @f - -; cnvl: - pushad - cmp [EGA_counter],1 - je novesal - mov ecx,[MOUSE_X] - cmp ecx,[novesachecksum] - jne novesal - popad - @@: - ret - - novesal: - mov [novesachecksum],ecx - mov ecx,0 - movzx eax,word [MOUSE_Y] - cmp eax,100 - jge m13l3 - mov eax,100 - m13l3: - cmp eax,480-100 - jbe m13l4 - mov eax,480-100 - m13l4: - sub eax,100 - imul eax,640*4 - add ecx,eax - movzx eax,word [MOUSE_X] - cmp eax,160 - jge m13l1 - mov eax,160 - m13l1: - cmp eax,640-160 - jbe m13l2 - mov eax,640-160 - m13l2: - sub eax,160 - shl eax,2 - add ecx,eax - mov esi,[LFBAddress] - add esi,ecx - mov edi,VGABasePtr - mov edx,200 - mov ecx,320 - cld - m13pix: - lodsd - test eax,eax - jz .save_pixel - push eax - mov ebx,eax - and eax,(128+64+32) ; blue - shr eax,5 - and ebx,(128+64+32)*256 ; green - shr ebx,8+2 - add eax,ebx - pop ebx - and ebx,(128+64)*256*256 ; red - shr ebx,8+8 - add eax,ebx - .save_pixel: - stosb - loop m13pix - mov ecx,320 - add esi,4*(640-320) - dec edx - jnz m13pix - mov [EGA_counter],0 - popad - ret - -VGA_drawbackground: -; draw all - cmp [SCR_MODE],dword 0x12 - jne .end - pushad - mov esi,[LFBAddress] - mov edi,VGABasePtr - mov ebx,640/32 ; 640*480/(8*4) - mov edx,480 - @@: - push ebx edx esi edi - shl edx,9 - lea edx,[edx+edx*4] - add esi,edx - shr edx,5 - add edi,edx - call VGA_draw_long_line - pop edi esi edx ebx - dec edx - jnz @r - call VGA_draw_long_line_1 - popad - .end: - ret - -VGA_draw_long_line: - mov dx,3ceh - mov ax,0ff08h - cli - out dx, ax - mov ax,0005h - out dx, ax - m12pix: - call VGA_draw_32_pixels - dec ebx - jnz m12pix - mov dx,3c4h - mov ax,0ff02h - out dx,ax - mov dx,3ceh - mov ax,0205h - out dx,ax - mov dx,3ceh - mov al,08h - out dx,al - sti - ret - -VGA_draw_32_pixels: - xor eax,eax - mov ebp,VGA_8_pixels - mov [ebp],eax - mov [ebp+4],eax - mov [ebp+8],eax - mov [ebp+12],eax - mov ch,4 - .main_loop: - mov cl,8 - .convert_pixels_to_VGA: - lodsd ; eax = 24bit colour - test eax,eax - jz .end - rol eax,8 - mov al,ch - ror eax,8 - mov ch,1 - dec cl - shl ch,cl - cmp al,85 - jbe .p13green - or [ebp],ch - cmp al,170 - jbe .p13green - or [ebp+12],ch - .p13green: - cmp ah,85 - jbe .p13red - or [ebp+4],ch - cmp ah,170 - jbe .p13red - or [ebp+12],ch - .p13red: - shr eax,8 - cmp ah,85 - jbe .p13cont - or [ebp+8],ch - cmp ah,170 - jbe .p13cont - or [ebp+12],ch - .p13cont: - ror eax,8 - mov ch,ah - inc cl - .end: - dec cl - jnz .convert_pixels_to_VGA - inc ebp - dec ch - jnz .main_loop - push esi - sub ebp,4 - mov esi,ebp - mov dx, 3c4h - mov ah, 1h - @@: - mov al, 02h - out dx,ax - xchg ax,bp - lodsd - mov [edi],eax - xchg ax,bp - shl ah, 1 - cmp ah, 10h - jnz @r - add edi,4 - pop esi - ret - -VGA_putpixel: - ; eax = x - ; ebx = y - mov ecx,eax - mov eax, [esp+32-8+4] ; color - shl ebx,9 - lea ebx,[ebx+ebx*4] ; умножение на 5 - lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32) - mov edi,edx - add edi, [LFBAddress] ; + LFB address - mov [edi], eax ; write to LFB for Vesa2.0 - shr edx,5 ; change BytesPerPixel to 1/8 - mov edi,edx - add edi, VGABasePtr ; address of pixel in VGA area - and ecx,0x07 ; bit no. (modulo 8) - pushfd - ; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8) - xor edx,edx - test eax,eax - jz .p13cont - cmp al,85 - jbe .p13green - or dl,0x01 - cmp al,170 - jbe .p13green - or dl,0x08 -.p13green: - cmp ah,85 - jbe .p13red - or dl,0x02 - cmp ah,170 - jbe .p13red - or dl,0x08 -.p13red: - shr eax,8 - cmp ah,85 - jbe .p13cont - or dl,0x04 - cmp ah,170 - jbe .p13cont - or dl,0x08 -.p13cont: - ror edx,8 - inc cl - xor eax,eax - inc ah - shr ax,cl - mov dx,3cfh - cli - out dx,al - mov al,[edi] ; dummy read - rol edx,8 - mov [edi],dl - popfd -;.end: - ret - -VGA__putimage: -; ecx = size [x|y] -; edx = coordinates [x|y] - cmp [SCR_MODE],dword 0x12 - jne @f - pushad - rol edx,16 - movzx eax,dx - rol edx,16 - movzx ebx,dx - movzx edx,cx - rol ecx,16 - movzx ecx,cx - call VGA_draw_bar_1 - popad -@@: - ret - -VGA_draw_bar: -; eax cx -; ebx cy -; ecx xe -; edx ye - cmp [SCR_MODE],dword 0x12 - jne @f - pushad - sub ecx,eax - sub edx,ebx - and eax,0xffff - and ebx,0xffff - and ecx,0xffff - and edx,0xffff - call VGA_draw_bar_1 - popad -@@: - ret - -VGA_draw_bar_1: - mov [temp.cx],eax - mov eax, [TASK_BASE] - add ebx, [eax-twdw + 4] - mov eax, [eax-twdw + 0] - add eax, [temp.cx] - and eax,0xfff8 - shl ebx,9 - lea ebx,[ebx+ebx*4] ; умножение на 5 - lea ebx, [ebx+eax*4] ; + x*BytesPerPixel (Vesa2.0 32) - mov esi,ebx - add esi, [LFBAddress] ; + LFB address - shr ebx,5 ; change BytesPerPixel to 1/8 - mov edi,ebx - add edi, VGABasePtr ; address of pixel in VGA area - mov ebx,ecx - shr ebx,5 - inc ebx -.main_loop: - call VGA_draw_long_line_1 - dec edx - jnz .main_loop - call VGA_draw_long_line_1 - ret - -VGA_draw_long_line_1: - push ebx edx esi edi - shl edx,9 - lea edx,[edx+edx*4] - add esi,edx - shr edx,5 - add edi,edx - call VGA_draw_long_line - pop edi esi edx ebx - ret - - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;; VGA.INC ;; +;; ;; +;; 640x480 mode 0x12 VGA functions for MenuetOS ;; +;; ;; +;; Paul Butcher, paul.butcher@asa.co.uk ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +$Revision$ + + +paletteVGA: + +;16 colour palette + mov dx, 0x3c8 + mov al, 0 + out dx, al + + mov ecx, 16 + mov dx, 0x3c9 + xor eax, eax + + palvganew: + + mov al, 0 + test ah, 4 + jz palvgalbl1 + add al, 31 + test ah, 8 + jz palvgalbl1 + add al, 32 + palvgalbl1: + out dx, al; red 0,31 or 63 + mov al, 0 + test ah, 2 + jz palvgalbl2 + add al, 31 + test ah, 8 + jz palvgalbl2 + add al, 32 + palvgalbl2: + out dx, al; blue 0,31 or 63 + mov al, 0 + test ah, 1 + jz palvgalbl3 + add al, 31 + test ah, 8 + jz palvgalbl3 + add al, 32 + palvgalbl3: + out dx, al; green 0,31 or 63 + add ah, 1 + loop palvganew +; mov dx, 3ceh +; mov ax, 0005h +; out dx, ax + ret + +palette320x200: + + mov edx, 0x3c8 + xor eax, eax + out dx, al + mov ecx, 256 + mov edx, 0x3c9 + xor eax, eax + + palnew: + mov al, 0 + test ah, 64 + jz pallbl1 + add al, 21 + pallbl1: + test ah, 128 + jz pallbl2 + add al, 42 + pallbl2: + out dx, al + mov al, 0 + test ah, 8 + jz pallbl3 + add al, 8 + pallbl3: + test ah, 16 + jz pallbl4 + add al, 15 + pallbl4: + test ah, 32 + jz pallbl5 + add al, 40 + pallbl5: + out dx, al + mov al, 0 + test ah, 1 + jz pallbl6 + add al, 8 + pallbl6: + test ah, 2 + jz pallbl7 + add al, 15 + pallbl7: + test ah, 4 + jz pallbl8 + add al, 40 + pallbl8: + out dx, al + add ah, 1 + loop palnew + + ret +align 4 +uglobal + novesachecksum dd 0x0 + EGA_counter db 0 + VGA_drawing_screen db 0 + VGA_8_pixels: + rb 16 + temp: + .cx dd 0 +endg +align 4 +checkVga_N13: + + cmp [SCR_MODE], dword 0x13 + jne @f + +; cnvl: + pushad + cmp [EGA_counter], 1 + je novesal + mov ecx, [MOUSE_X] + cmp ecx, [novesachecksum] + jne novesal + popad + @@: + ret + + novesal: + mov [novesachecksum], ecx + mov ecx, 0 + movzx eax, word [MOUSE_Y] + cmp eax, 100 + jge m13l3 + mov eax, 100 + m13l3: + cmp eax, 480-100 + jbe m13l4 + mov eax, 480-100 + m13l4: + sub eax, 100 + imul eax, 640*4 + add ecx, eax + movzx eax, word [MOUSE_X] + cmp eax, 160 + jge m13l1 + mov eax, 160 + m13l1: + cmp eax, 640-160 + jbe m13l2 + mov eax, 640-160 + m13l2: + sub eax, 160 + shl eax, 2 + add ecx, eax + mov esi, [LFBAddress] + add esi, ecx + mov edi, VGABasePtr + mov edx, 200 + mov ecx, 320 + cld + m13pix: + lodsd + test eax, eax + jz .save_pixel + push eax + mov ebx, eax + and eax, (128+64+32) ; blue + shr eax, 5 + and ebx, (128+64+32)*256; green + shr ebx, 8+2 + add eax, ebx + pop ebx + and ebx, (128+64)*256*256; red + shr ebx, 8+8 + add eax, ebx + .save_pixel: + stosb + loop m13pix + mov ecx, 320 + add esi, 4*(640-320) + dec edx + jnz m13pix + mov [EGA_counter], 0 + popad + ret + +VGA_drawbackground: +; draw all + cmp [SCR_MODE], dword 0x12 + jne .end + pushad + mov esi, [LFBAddress] + mov edi, VGABasePtr + mov ebx, 640/32; 640*480/(8*4) + mov edx, 480 + @@: + push ebx edx esi edi + shl edx, 9 + lea edx, [edx+edx*4] + add esi, edx + shr edx, 5 + add edi, edx + call VGA_draw_long_line + pop edi esi edx ebx + dec edx + jnz @r + call VGA_draw_long_line_1 + popad + .end: + ret + +VGA_draw_long_line: + mov dx, 3ceh + mov ax, 0ff08h + cli + out dx, ax + mov ax, 0005h + out dx, ax + m12pix: + call VGA_draw_32_pixels + dec ebx + jnz m12pix + mov dx, 3c4h + mov ax, 0ff02h + out dx, ax + mov dx, 3ceh + mov ax, 0205h + out dx, ax + mov dx, 3ceh + mov al, 08h + out dx, al + sti + ret + +VGA_draw_32_pixels: + xor eax, eax + mov ebp, VGA_8_pixels + mov [ebp], eax + mov [ebp+4], eax + mov [ebp+8], eax + mov [ebp+12], eax + mov ch, 4 + .main_loop: + mov cl, 8 + .convert_pixels_to_VGA: + lodsd ; eax = 24bit colour + test eax, eax + jz .end + rol eax, 8 + mov al, ch + ror eax, 8 + mov ch, 1 + dec cl + shl ch, cl + cmp al, 85 + jbe .p13green + or [ebp], ch + cmp al, 170 + jbe .p13green + or [ebp+12], ch + .p13green: + cmp ah, 85 + jbe .p13red + or [ebp+4], ch + cmp ah, 170 + jbe .p13red + or [ebp+12], ch + .p13red: + shr eax, 8 + cmp ah, 85 + jbe .p13cont + or [ebp+8], ch + cmp ah, 170 + jbe .p13cont + or [ebp+12], ch + .p13cont: + ror eax, 8 + mov ch, ah + inc cl + .end: + dec cl + jnz .convert_pixels_to_VGA + inc ebp + dec ch + jnz .main_loop + push esi + sub ebp, 4 + mov esi, ebp + mov dx, 3c4h + mov ah, 1h + @@: + mov al, 02h + out dx, ax + xchg ax, bp + lodsd + mov [edi], eax + xchg ax, bp + shl ah, 1 + cmp ah, 10h + jnz @r + add edi, 4 + pop esi + ret + +VGA_putpixel: + ; eax = x + ; ebx = y + mov ecx, eax + mov eax, [esp+32-8+4] ; color + shl ebx, 9 + lea ebx, [ebx+ebx*4] ; умножение на 5 + lea edx, [ebx+ecx*4] ; + x*BytesPerPixel (Vesa2.0 32) + mov edi, edx + add edi, [LFBAddress] ; + LFB address + mov [edi], eax ; write to LFB for Vesa2.0 + shr edx, 5 ; change BytesPerPixel to 1/8 + mov edi, edx + add edi, VGABasePtr ; address of pixel in VGA area + and ecx, 0x07 ; bit no. (modulo 8) + pushfd + ; edi = address, eax = 24bit colour, ecx = bit no. (modulo 8) + xor edx, edx + test eax, eax + jz .p13cont + cmp al, 85 + jbe .p13green + or dl, 0x01 + cmp al, 170 + jbe .p13green + or dl, 0x08 +.p13green: + cmp ah, 85 + jbe .p13red + or dl, 0x02 + cmp ah, 170 + jbe .p13red + or dl, 0x08 +.p13red: + shr eax, 8 + cmp ah, 85 + jbe .p13cont + or dl, 0x04 + cmp ah, 170 + jbe .p13cont + or dl, 0x08 +.p13cont: + ror edx, 8 + inc cl + xor eax, eax + inc ah + shr ax, cl + mov dx, 3cfh + cli + out dx, al + mov al, [edi] ; dummy read + rol edx, 8 + mov [edi], dl + popfd +;.end: + ret + +VGA__putimage: +; ecx = size [x|y] +; edx = coordinates [x|y] + cmp [SCR_MODE], dword 0x12 + jne @f + pushad + rol edx, 16 + movzx eax, dx + rol edx, 16 + movzx ebx, dx + movzx edx, cx + rol ecx, 16 + movzx ecx, cx + call VGA_draw_bar_1 + popad +@@: + ret + +VGA_draw_bar: +; eax cx +; ebx cy +; ecx xe +; edx ye + cmp [SCR_MODE], dword 0x12 + jne @f + pushad + sub ecx, eax + sub edx, ebx + and eax, 0xffff + and ebx, 0xffff + and ecx, 0xffff + and edx, 0xffff + call VGA_draw_bar_1 + popad +@@: + ret + +VGA_draw_bar_1: + mov [temp.cx], eax + mov eax, [TASK_BASE] + add ebx, [eax-twdw + 4] + mov eax, [eax-twdw + 0] + add eax, [temp.cx] + and eax, 0xfff8 + shl ebx, 9 + lea ebx, [ebx+ebx*4]; умножение на 5 + lea ebx, [ebx+eax*4] ; + x*BytesPerPixel (Vesa2.0 32) + mov esi, ebx + add esi, [LFBAddress] ; + LFB address + shr ebx, 5 ; change BytesPerPixel to 1/8 + mov edi, ebx + add edi, VGABasePtr ; address of pixel in VGA area + mov ebx, ecx + shr ebx, 5 + inc ebx +.main_loop: + call VGA_draw_long_line_1 + dec edx + jnz .main_loop + call VGA_draw_long_line_1 + ret + +VGA_draw_long_line_1: + push ebx edx esi edi + shl edx, 9 + lea edx, [edx+edx*4] + add esi, edx + shr edx, 5 + add edi, edx + call VGA_draw_long_line + pop edi esi edx ebx + ret + +