;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; RDOS operating system ; Copyright (C) 1988-2000, Leif Ekblad ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. The only exception to this rule ; is for commercial usage in embedded systems. For information on ; usage in commercial embedded systems, contact embedded@rdos.net ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program; if not, write to the Free Software ; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ; ; The author of this program may be contacted at leif@rdos.net ; ; DRIVE.ASM ; Basic physical drive support module ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INCLUDE ..\driver.def INCLUDE protseg.def INCLUDE ..\user.def INCLUDE ..\os.def INCLUDE ..\user.inc INCLUDE ..\os.inc INCLUDE system.def INCLUDE int.def INCLUDE system.inc INCLUDE ..\drive.inc MAX_DRIVES = 'Z' - 'A' + 1 DRIVE_WAIT_NUM = 32 POLL_TIMEOUT EQU 119200 MIN_TIMEOUT EQU 1192000 drive_wait_struc STRUC dws_link DW ? dws_thread DW ? drive_wait_struc ENDS DISC_FLAG_STOPPED = 1 DISC_FLAG_USE32 = 2 disc_def_struc STRUC disc_nr DB ? disc_flags DB ? disc_units DD ? disc_bytes_per_sector DW ? disc_sectors_per_unit DW ? disc_sectors_per_cyl DW ? disc_heads DW ? disc_cached_sectors DD ? disc_cache_limit DD ? disc_thread DW ? disc_timer_id DW ? disc_data_list DD ? disc_handle_list DD ? disc_readahead DD ? disc_free DD ? disc_section section_typ <> disc_spinlock spinlock_typ <> disc_pend_list DD ? disc_pend_first DD ? disc_awrite_list DD ? disc_awrite_timer DW ? disc_awrite_timeout DD ?,? disc_seq_list DW ? disc_param DD ?,? disc_handle DW ? disc_pend_count DW ? disc_io_count DW ? disc_change_proc DD ?,? disc_vendor_str DB 256 DUP(?) disc_unit_arr DD ? disc_def_struc ENDS disc_unit_struc STRUC disc_sectors DW ? disc_sector_arr DD ? disc_unit_struc ENDS drive_def_struc STRUC drive_disc DW ? drive_start_sector DD ? drive_sectors DD ? drive_def_struc ENDS disc_seq_struc STRUC dss_prev DW ? dss_next DW ? dss_buf_sel DW ? dss_insert_index DW ? dss_perform_index DW ? dss_arr DD ? disc_seq_struc ENDS boot_media_struc STRUC boot_bytes_per_sector DW 512 boot_resv1 DB 0 boot_mapping_sectors DW 1 boot_resv3 DB 0 boot_resv4 DW 0 boot_small_sectors DW 0 boot_media DB 0F8h boot_resv6 DW 0 boot_sectors_per_cyl DW 1 boot_heads DW 1 boot_hidden_sectors DD 1 boot_sectors DD 0 boot_drive_nr DB 0,0 boot_signature DB 0 boot_serial DD 0 boot_volume DB 11 DUP(0) boot_fs DB 8 DUP(0) boot_media_struc ENDS boot_struc STRUC boot_jmp DB ?,?,? boot_name DB 8 DUP(?) boot_param boot_media_struc <> boot_struc ENDS data SEGMENT byte public 'DATA' disc_params DB ? disc_curr_param DW ? disc_param_arr DD MAX_DRIVES DUP(?,?) disc_def_arr DW MAX_DRIVES DUP(?) drive_def_arr DW MAX_DRIVES DUP(?) drive_wait_arr DB 4*DRIVE_WAIT_NUM DUP(?) drive_wait_free DW ? drive_wait_count DW ? disc_handler_section section_typ <> disc_handlers DW ? disc_start_thread DW ? data ENDS IFDEF __WASM__ .686p .xmm2 ELSE .386p ENDIF code SEGMENT byte public use16 'CODE' assume cs:code,ds:data extrn init_ramdrive:near extrn init_filedisc:near extrn init_stddev:near ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; NAME: Boot sector. DO NOT MOVE THIS CODE!!! ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; db 0EBh db SIZE boot_struc - 2 ; jmp StartBoot db 90h db 'Rdos ' BootMedia boot_media_struc <> StartBoot: db 0EAh dw OFFSET JmpBootCode dw 07C0h JmpBootCode: cli mov bx,800h mov ss,bx mov sp,100h sti mov bx,70h mov es,bx xor bx,bx mov cx,8 xor dx,dx mov ax,1 LoadBootNext: push cx mov cx,3 LoadBootRetry: call ReadSector jnc BootSectorOk push ax mov ax,0 int 13h pop ax loop LoadBootRetry stc BootSectorOk: pop cx jc BootFail add ax,1 adc dx,0 add bx,512 loop LoadBootNext ; mov ax,cs mov es,ax db 0EAh public BootLoadOffset BootLoadOffset: dw 0 dw 70h BootFail: mov si,OFFSET DiskError call BootWriteAsciiz BootStop: jmp BootStop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: BootWriteAsciiz ; ; DESCRIPTION: Write a message ; ; PARAMETERS: CS:SI Message to write ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BootWriteAsciiz Proc near lods byte ptr cs:[si] or al,al jz WriteAsciizDone mov ah,0Eh mov bx,7 int 10h jmp BootWriteAsciiz WriteAsciizDone: ret BootWriteAsciiz Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ReadSector ; ; DESCRIPTION: Read a sector ; ; PARAMETERS: DX:AX Sector # ; ES:BX Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ReadSector Proc near push ax push cx push dx push bx div cs:BootMedia.boot_sectors_per_cyl inc dl mov bl,dl xor dx,dx div cs:BootMedia.boot_heads mov bh,dl mov dx,ax mov ax,201h mov cl,6 shl dh,cl or dh,bl mov cx,dx xchg ch,cl mov dl,cs:BootMedia.boot_drive_nr mov dh,bh pop bx int 13h pop dx pop cx pop ax ret ReadSector Endp DiskError: db 'Disk error',0Dh,0Ah,0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Boot sector ends here ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CheckPending ; ; DESCRIPTION: Check pending test ; ; PARAMETERS: EDX:AX Sector # ; ES:BX Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CheckPending Proc near xor cx,cx mov edi,ds:disc_pend_first mov ebp,edi or edi,edi jz cpdone ; mov edx,es:[edi].dh_unit mov ax,es:[edi].dh_sector cploop: test es:[edi].dh_flags, FLAG_IO_PENDING jz cpfail ; cmp es:[edi].dh_state,STATE_DIRTY je cpvalid ; cmp es:[edi].dh_state,STATE_EMPTY jne cpfail cpvalid: test es:[edi].dh_flags, FLAG_ASYNC_WRITE jnz cpfail ; cmp edx,es:[edi].dh_unit je cpunit jb cpnext ; int 3 jmp cpfail cpunit: cmp ax,es:[edi].dh_sector jbe cpnext ; int 3 cpfail: int 3 mov al,es:[edi].dh_state ; STATE_DIRTY mov ah,es:[edi].dh_flags ; FLAG_ASYNC_WRITE | FLAG_EXT_DATA jmp cpdone cpnext: mov edx,es:[edi].dh_unit mov ax,es:[edi].dh_sector ; mov edi,es:[edi].dh_next cmp edi,ebp jz cpdone ; loop cploop ; int 3 cpdone: ret CheckPending Endp CheckAsyncWrite Proc near xor cx,cx mov edi,ds:disc_awrite_list mov eax,edi or edi,edi jz cawdone cawloop: test es:[edi].dh_flags, FLAG_ASYNC_WRITE jz cawfail ; cmp es:[edi].dh_state,STATE_DIRTY je cawnext cawfail: int 3 mov al,es:[edi].dh_state mov ah,es:[edi].dh_flags jmp cawdone cawnext: mov edi,es:[edi].dh_next cmp edi,eax jz cawdone ; loop cawloop ; int 3 cawdone: ret CheckAsyncWrite Endp CheckAll Proc near push es pushad ; mov ax,flat_sel mov es,ax call CheckPending call CheckAsyncWrite ; popad pop es ret CheckAll Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IsPending ; ; DESCRIPTION: Is block in pending list? ; ; PARAMETERS: EDI ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IsPending Proc near push es pushad ; mov ax,flat_sel mov es,ax ; xor cx,cx mov esi,ds:disc_pend_first mov ebp,esi or esi,esi jz ipdone iploop: cmp esi,edi je ipfound ; mov esi,es:[esi].dh_next cmp esi,ebp jz ipdone ; loop iploop ipfound: int 3 ipdone: popad pop es ret IsPending Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CheckDeleted ; ; DESCRIPTION: Check if block is deleted ; ; PARAMETERS: EDI ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CheckDeleted Proc near push es pushad ; mov ax,flat_sel mov es,ax ; xor cx,cx mov esi,ds:disc_handle_list mov ebp,esi or esi,esi jz cddone cdloop: cmp esi,edi je cdfound ; mov esi,es:[esi].dh_next or esi,esi jz cddone ; loop cdloop cdfound: int 3 cddone: popad pop es ret CheckDeleted Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CheckBuffered ; ; DESCRIPTION: Make sure sector is buffered ; ; PARAMETERS: DS Disc selector ; ES Flat_sel ; EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CheckBuffered PROC near push es pushad ; mov ax,flat_sel mov es,ax ; mov esi,es:[edi].dh_unit mov eax,ds:[4*esi].disc_unit_arr or eax,eax jz cbFail ; movzx esi,es:[edi].dh_sector mov eax,es:[4*esi+eax].disc_sector_arr ; or eax,eax jnz cbDone cbFail: int 3 cbDone: popad pop es ret CheckBuffered ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CheckDriveWait ; ; DESCRIPTION: Check consistency of drive-wait list ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CheckDriveWait Proc near push ds pushad ; mov ax,SEG data mov ds,ax xor cx,cx mov bx,ds:drive_wait_free cdwLoop: or bx,bx jz cdwCheck ; mov bx,[bx] inc cx jmp cdwLoop cdwCheck: cmp cx,ds:drive_wait_count je cdwSizeOk ; int 3 cdwSizeOk: or cx,cx jnz cdwNotEmpty ; int 3 cdwNotEmpty: popad pop ds ret CheckDriveWait Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Fixup_data ; ; DESCRIPTION: Fixup data for 32-bit only discs ; ; PARAMETERS: DS Disc selector ; ESI Linear address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; fixup_data PROC near test ds:disc_flags,DISC_FLAG_USE32 jz fdDone ; push eax push ebx push edx ; mov edx,esi GetPageEntry test al,1 jz fdAlloc ; or ebx,ebx jz fdInRange ; int 3 fdAlloc: AllocatePhysical32 mov al,13h SetPageEntry fdInRange: pop edx pop ebx pop eax fdDone: ret fixup_data ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ALLOCATE_DATA ; ; DESCRIPTION: Allocate data ; ; PARAMETERS: DS Disc selector ; ; RETURNS: EDX Data address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; allocate_data PROC near push eax push ecx ; mov edx,ds:disc_data_list or edx,edx jnz allocate_data_done ; mov eax,1000h AllocateBigLinear test ds:disc_flags,DISC_FLAG_USE32 jz allocate_data_phys_ok ; push ebx AllocatePhysical32 mov al,13h SetPageEntry pop ebx allocate_data_phys_ok: movzx ecx,ds:disc_bytes_per_sector mov ds:disc_data_list,edx allocate_init_data_loop: mov eax,edx add eax,ecx mov es:[edx],eax mov edx,eax test dx,0FFFh jnz allocate_init_data_loop ; sub edx,ecx mov dword ptr es:[edx],0 mov edx,ds:disc_data_list allocate_data_done: mov eax,es:[edx] mov ds:disc_data_list,eax ; pop ecx pop eax ret allocate_data ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FREE_DATA ; ; DESCRIPTION: Free data ; ; PARAMETERS: DS Disc selector ; EDX Data address ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; free_data PROC near push eax mov eax,ds:disc_data_list mov es:[edx],eax mov ds:disc_data_list,edx pop eax ret free_data ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FREE_HANDLE ; ; DESCRIPTION: Free handle ; ; PARAMETERS: DS Disc selector ; EDI Disc buf handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; free_handle PROC near ifdef DEBUG call CheckDeleted call IsPending endif push eax test es:[edi].dh_flags, FLAG_EXT_DATA jnz free_handle_do ; push edx mov edx,es:[edi].dh_data call free_data pop edx free_handle_do: mov es:[edi].dh_flags,0 mov eax,ds:disc_handle_list mov es:[edi],eax mov ds:disc_handle_list,edi dec ds:disc_cached_sectors pop eax ifdef DEBUG call CheckAll endif ret free_handle ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: swap_block ; ; DESCRIPTION: Free physical memory, disc block ; ; PARAMETERS: ES Flat sel ; EDX Disc block ; EDI Unit block entry ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; swap_block Proc near inc ebp mov edi,edx test es:[edi].dh_flags,FLAG_EXT_DATA OR BUSY_FLAGS jnz swap_block_done ; mov al,es:[edi].dh_lock_count or al,al jnz swap_block_done ; mov al,es:[edi].dh_usage or al,al jnz swap_block_upd_usage ; dec ebp call remove_buf call free_handle jmp swap_block_done swap_block_upd_usage: dec al mov es:[edi].dh_usage,al swap_block_done: ret swap_block Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: swap_unit ; ; DESCRIPTION: Free disc buffers on a disc unit ; ; PARAMETERS: DS Disc sel ; EDX Unit block ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; swap_unit Proc near mov ax,flat_sel mov es,ax mov edi,edx movzx ecx,ds:disc_sectors_per_unit mov si,es:[edx].disc_sectors lea edi,[edi].disc_sector_arr swap_sector_loop: or ecx,ecx jz swap_unit_done ; xor eax,eax repz scas dword ptr es:[edi] mov eax,es:[edi-4] or eax,eax jz swap_sector_loop ; push ecx push edx push si push edi mov edx,eax call swap_block pop edi pop si pop edx pop ecx sub si,1 jnz swap_sector_loop swap_unit_done: ret swap_unit Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: swap_disc ; ; DESCRIPTION: Free disc buffers on a disc ; ; PARAMETERS: DS Disc sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; swap_disc Proc near push ds push es pushad ; xor ebp,ebp mov ax,ds mov es,ax mov edi,OFFSET disc_unit_arr mov ecx,ds:disc_units swap_unit_loop: or ecx,ecx jz swap_disc_done ; xor eax,eax repz scas dword ptr es:[edi] mov edx,es:[edi-4] or edx,edx jz swap_unit_loop ; push es push ecx push edi call swap_unit pop edi pop ecx pop es jmp swap_unit_loop swap_disc_done: cmp ebp,ds:disc_cached_sectors je swap_disc_end ; int 3 swap_disc_end: popad pop es pop ds ret swap_disc Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ALLOCATE_HANDLE ; ; DESCRIPTION: Allocate handle ; ; PARAMETERS: DS Disc selector ; ; RETURNS: EDI Discbuf handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; allocate_handle PROC near push eax push edx ; mov eax,ds:disc_cached_sectors cmp eax,ds:disc_cache_limit jc alloc_handle_no_swap ; call swap_disc mov eax,ds:disc_cached_sectors cmp eax,ds:disc_cache_limit jc alloc_handle_no_swap ; call swap_disc mov eax,ds:disc_cached_sectors cmp eax,ds:disc_cache_limit jc alloc_handle_no_swap ; shr eax,2 inc eax add ds:disc_cache_limit,eax alloc_handle_no_swap: inc ds:disc_cached_sectors mov edi,ds:disc_handle_list or edi,edi jnz allocate_handle_done ; push cx mov eax,1000h AllocateBigLinear mov ds:disc_handle_list,edx pop cx allocate_init_handle_loop: add edx,DISC_HANDLE_SIZE mov es:[edx-DISC_HANDLE_SIZE].dh_next,edx test dx,0FFFh jnz allocate_init_handle_loop ; mov es:[edx-DISC_HANDLE_SIZE].dh_next,0 mov edi,ds:disc_handle_list allocate_handle_done: mov eax,es:[edi].dh_next mov ds:disc_handle_list,eax ifdef DEBUG call IsPending call CheckDeleted endif pop edx pop eax ret allocate_handle ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: INSERT_PENDING ; ; DESCRIPTION: Insert block into pending request list ; ; PARAMETERS: DS DiscBuf handle ; ES Flat_sel ; EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; insert_pending PROC near push eax push ebx push ecx push dx ifdef DEBUG call CheckDeleted call CheckAll call CheckBuffered endif test es:[edi].dh_flags,FLAG_ASYNC_WRITE jz insert_noaw ; int 3 insert_noaw: test es:[edi].dh_flags,FLAG_IO_PENDING jz insert_pend_do ; int 3 call CheckAll ; mov eax,ds:disc_pend_first or eax,eax jz insert_pend_do ; mov ebx,eax cmp eax,edi je insert_pend_err insert_pend_check: mov eax,es:[eax].dh_next cmp eax,edi je insert_pend_err ; cmp eax,ebx jnz insert_pend_check jmp insert_pend_do insert_pend_err: int 3 jmp insert_pend_done insert_pend_do: or es:[edi].dh_flags,FLAG_IO_PENDING ; mov eax,ds:disc_pend_first or eax,eax jne insert_pend_used insert_pend_empty: mov es:[edi].dh_prev,edi mov es:[edi].dh_next,edi mov ds:disc_pend_list,edi mov ds:disc_pend_first,edi jmp insert_pend_done insert_pend_used: mov ecx,es:[edi].dh_unit mov dx,es:[edi].dh_sector cmp ecx,es:[eax].dh_unit jc insert_pend_first ; jnz insert_pend_search_loop cmp dx,es:[eax].dh_sector jnc insert_pend_search_loop insert_pend_first: mov ds:disc_pend_first,edi jmp insert_pend_link insert_pend_search_loop: mov eax,es:[eax].dh_next cmp eax,ds:disc_pend_first je insert_pend_link ; cmp ecx,es:[eax].dh_unit jc insert_pend_link ; jnz insert_pend_search_loop ; cmp dx,es:[eax].dh_sector jnc insert_pend_search_loop insert_pend_link: mov ebx,es:[eax].dh_prev mov es:[eax].dh_prev,edi mov es:[ebx].dh_next,edi mov es:[edi].dh_prev,ebx mov es:[edi].dh_next,eax insert_pend_done: inc ds:disc_pend_count ifdef DEBUG call CheckAll endif pop dx pop ecx pop ebx pop eax ret insert_pending ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GET_PENDING ; ; DESCRIPTION: Get next pending request ; ; PARAMETERS: DS Disc selector ; ES Flat_sel ; ; RETURNS: EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_pending PROC near mov edi,ds:disc_pend_list or edi,edi stc jz get_pend_done ifdef DEBUG call CheckDeleted endif mov eax,es:[edi].dh_next mov ebx,es:[edi].dh_prev mov es:[ebx].dh_next,eax mov es:[eax].dh_prev,ebx cmp eax,edi jne get_pend_unlink ; mov ds:disc_pend_list,0 mov ds:disc_pend_first,0 clc jmp get_pend_done get_pend_unlink: mov ds:disc_pend_list,eax cmp edi,ds:disc_pend_first jne get_pend_first_ok ; mov ds:disc_pend_first,eax get_pend_first_ok: clc get_pend_done: ret get_pending ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: INSERT_ASYNC_WRITE ; ; DESCRIPTION: Insert block into async write request list ; ; PARAMETERS: DS DiscBuf handle ; ES Flat_sel ; EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; insert_async_write PROC near push eax push ebx ifdef DEBUG call CheckDeleted endif test es:[edi].dh_flags, FLAG_IO_PENDING jnz insert_awrite_end ; test es:[edi].dh_flags, FLAG_ASYNC_WRITE jnz insert_awrite_done insert_awrite_do: or es:[edi].dh_flags, FLAG_ASYNC_WRITE ; mov eax,ds:disc_awrite_list or eax,eax jne insert_awrite_used insert_awrite_empty: mov es:[edi].dh_prev,edi mov es:[edi].dh_next,edi jmp insert_awrite_done insert_awrite_used: mov ebx,es:[eax].dh_prev mov es:[eax].dh_prev,edi mov es:[ebx].dh_next,edi mov es:[edi].dh_prev,ebx mov es:[edi].dh_next,eax insert_awrite_done: mov ds:disc_awrite_list,edi insert_awrite_end: pop ebx pop eax ret insert_async_write ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UPDATE_ASYNC_WRITE ; ; DESCRIPTION: Update async write list ; ; PARAMETERS: DS Disc selector ; ES Flat sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; update_async_write PROC near GetSystemTime sub eax,ds:disc_awrite_timeout sbb edx,ds:disc_awrite_timeout+4 jc update_async_done update_async_loop: mov edi,ds:disc_awrite_list or edi,edi jz update_async_done ; GetSystemTime sub eax,MIN_TIMEOUT sbb edx,0 ; mov edi,es:[edi].dh_prev sub eax,es:[edi].dh_time_lsb jc update_async_done ; mov eax,es:[edi].dh_next mov ebx,es:[edi].dh_prev mov es:[ebx].dh_next,eax mov es:[eax].dh_prev,ebx cmp eax,edi jne update_async_insert ; mov dword ptr ds:disc_awrite_list,0 update_async_insert: and es:[edi].dh_flags, NOT FLAG_ASYNC_WRITE call insert_pending jmp update_async_loop update_async_done: ret update_async_write ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FLUSH_ASYNC_WRITE ; ; DESCRIPTION: Flush async write list ; ; PARAMETERS: DS Disc selector ; ES Flat sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; flush_async_write PROC near mov edi,ds:disc_awrite_list or edi,edi jz flush_async_done ; mov edi,es:[edi].dh_prev mov eax,es:[edi].dh_next mov ebx,es:[edi].dh_prev mov es:[ebx].dh_next,eax mov es:[eax].dh_prev,ebx cmp eax,edi jne flush_async_insert ; mov dword ptr ds:disc_awrite_list,0 flush_async_insert: and es:[edi].dh_flags, NOT FLAG_ASYNC_WRITE call insert_pending jmp flush_async_write flush_async_done: ret flush_async_write ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ASYNC_WRITE_TIMEOUT ; ; DESCRIPTION: Async write timeout ; ; PARAMETERS: CX Disc thread ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; async_write_timeout Proc far mov ds,cx RequestSpinlock ds:disc_spinlock mov ds:disc_awrite_timer,0 ReleaseSpinlock ds:disc_spinlock ; mov bx,ds:disc_thread Signal retf32 async_write_timeout Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UPDATE_ASYNC_TIMER ; ; DESCRIPTION: Update async write timer ; ; PARAMETERS: DS Disc selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; update_async_timer Proc near RequestSpinlock ds:disc_spinlock mov ax,ds:disc_awrite_timer or ax,ax jnz update_async_timer_release ; mov edi,ds:disc_awrite_list or edi,edi jz update_async_timer_release ; mov ds:disc_awrite_timer,1 ReleaseSpinlock ds:disc_spinlock ; GetSystemTime add eax,POLL_TIMEOUT adc edx,0 mov ds:disc_awrite_timeout,eax mov ds:disc_awrite_timeout+4,edx push es mov bx,cs mov es,bx mov cx,ds mov edi,OFFSET async_write_timeout StartTimer pop es jmp update_async_timer_done update_async_timer_release: ReleaseSpinlock ds:disc_spinlock update_async_timer_done: ret update_async_timer Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UPDATE_DISC_SEQ ; ; DESCRIPTION: Update seq write lists ; ; PARAMETERS: DS Disc selector ; ES Flat sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; update_disc_seq PROC far mov ax,ds:disc_seq_list or ax,ax jz update_seq_done ; push fs pushad ; mov bp,ax update_seq_loop: mov fs,ax movzx ebx,fs:dss_perform_index update_seq_discard_loop: mov edi,fs:[4*ebx].dss_arr cmp es:[edi].dh_state,STATE_SEQ je update_seq_move_loop ; mov fs:[4*ebx].dss_arr,0 inc bx mov fs:dss_perform_index,bx cmp bx,fs:dss_insert_index jne update_seq_discard_loop ; push es mov ax,fs mov es,ax xor ax,ax mov fs,ax mov ds:disc_seq_list,es push ds mov di,es:dss_next cmp di,ds:disc_seq_list mov ds:disc_seq_list,di mov si,es:dss_prev mov ds,di mov ds:dss_prev,si mov ds,si mov ds:dss_next,di pop ds jne update_seq_free ; mov ds:disc_seq_list,0 update_seq_free: FreeMem pop es mov ax,ds:disc_seq_list or ax,ax jz update_seq_pop_done ; mov bp,ax jmp update_seq_loop update_seq_move_loop: mov dx,es:[edi].dh_sector mov eax,es:[edi].dh_unit test es:[edi].dh_flags,FLAG_IO_PENDING jnz update_seq_moved ; call insert_pending update_seq_moved: inc bx inc dx cmp bx,fs:dss_insert_index je update_seq_pop_done ; mov edi,fs:[4*ebx].dss_arr cmp eax,es:[edi].dh_unit jne update_seq_next ; cmp dx,es:[edi].dh_sector je update_seq_move_loop update_seq_next: mov ax,fs:dss_next cmp ax,bp jne update_seq_loop update_seq_pop_done: popad pop fs update_seq_done: ret update_disc_seq ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CHECK_BUF ; ; DESCRIPTION: Check if sector is in buffer cache ; ; PARAMETERS: DS Disc selector ; ES Flat_sel ; ECX Unit # ; DX Sector # ; ; RETURNS: EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; check_buf PROC near push esi mov esi,ecx mov edi,ds:[4*esi].disc_unit_arr or edi,edi jz check_buf_fail ; movzx esi,dx mov edi,es:[4*esi+edi].disc_sector_arr ifdef DEBUG or edi,edi jz check_no_del call CheckDeleted check_no_del: endif or edi,edi clc jnz check_buf_done check_buf_fail: stc check_buf_done: pop esi ret check_buf ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: INSERT_BUF ; ; DESCRIPTION: Insert block in buffer list ; ; PARAMETERS: DS DiscBuf handle ; ES Flat_sel ; EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; insert_buf PROC near push eax push ecx push edx push esi ifdef DEBUG call CheckDeleted endif mov esi,es:[edi].dh_unit mov edx,ds:[4*esi].disc_unit_arr or edx,edx jne insert_buf_used ; push edi mov edi,OFFSET disc_sector_arr movzx ecx,ds:disc_sectors_per_unit mov eax,ecx shl eax,2 add eax,edi AllocateSmallLinear mov ds:[4*esi].disc_unit_arr,edx mov es:[edx].disc_sectors,0 add edi,edx xor eax,eax rep stos dword ptr es:[edi] pop edi insert_buf_used: mov eax,es:[edi].dh_unit inc es:[edx].disc_sectors movzx esi,es:[edi].dh_sector mov es:[4*esi+edx].disc_sector_arr,edi ; pop esi pop edx pop ecx pop eax ret insert_buf ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: REMOVE_BUF ; ; DESCRIPTION: Remove block from buffer list ; ; PARAMETERS: DS Disc selector ; ES Flat_sel ; EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; remove_buf PROC near push ecx push edx push esi ifdef DEBUG call CheckDeleted call CheckBuffered endif mov esi,es:[edi].dh_unit mov edx,ds:[4*esi].disc_unit_arr or edx,edx jz remove_buf_done ; movzx ecx,es:[edi].dh_sector mov es:[4*ecx+edx].disc_sector_arr,0 sub es:[edx].disc_sectors,1 jnz remove_buf_done ; mov ds:[4*esi].disc_unit_arr,0 movzx ecx,ds:disc_sectors_per_unit shl ecx,2 add ecx,OFFSET disc_sector_arr FreeLinear remove_buf_done: pop esi pop edx pop ecx ret remove_buf ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: Block ; ; DESCRIPTION: Block until IO complete ; ; PARAMETERS: DS Disc selector ; ES Flat_sel ; EDI DiscBlock handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; block Proc near push ax push bx push dx mov ax,es:[edi].dh_thread or ax,ax jnz block_no_signal ; GetThread mov es:[edi].dh_thread,ax mov bx,ds:disc_thread Signal jmp block_do block_no_signal: push ds ifdef DEBUG call CheckDriveWait endif mov ax,SEG data mov ds,ax mov bx,ds:drive_wait_free mov ax,[bx] mov ds:drive_wait_free,ax GetThread mov ds:[bx].dws_thread,ax mov ax,es:[edi].dh_wait mov ds:[bx].dws_link,ax mov es:[edi].dh_wait,bx ifdef DEBUG dec ds:drive_wait_count call CheckDriveWait endif pop ds block_do: LeaveSection ds:disc_section WaitForSignal EnterSection ds:disc_section ; mov bx,es:[edi].dh_thread cmp ax,bx je block_do ; push ds mov bx,SEG data mov ds,bx ; GetThread mov bx,es:[edi].dh_wait block_check_loop: or bx,bx jz block_exit_pop ; cmp ax,ds:[bx].dws_thread je block_cont_pop ; mov bx,ds:[bx].dws_link jmp block_check_loop block_cont_pop: pop ds jmp block_do block_exit_pop: pop ds block_exit: pop dx pop bx pop ax ret block Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: START_DISC ; ; DESCRIPTION: Start disc ; ; PARAMETERS: BX Disc sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; start_disc_name DB 'Start Disc',0 start_disc Proc far push ds push es pusha ; mov ax,SEG data mov ds,ax mov cx,MAX_DRIVES mov si,OFFSET drive_def_arr start_drives_loop: mov ax,[si] or ax,ax jz start_drives_next ; cmp ax,-1 je start_drives_next ; mov es,ax cmp bx,es:drive_disc jne start_drives_next ; push ecx mov ecx,es:drive_sectors mov ax,si sub ax,OFFSET drive_def_arr shr ax,1 StartFileSystem pop ecx start_drives_next: add si,2 loop start_drives_loop ; popa pop es pop ds retf32 start_disc Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: STOP_DISC ; ; DESCRIPTION: Stop disc ; ; PARAMETERS: BX Disc sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; stop_disc_name DB 'Stop Disc',0 stop_disc Proc far push ds push es pusha ; mov ax,SEG data mov ds,ax mov cx,MAX_DRIVES mov si,OFFSET drive_def_arr stop_drives_loop: mov ax,[si] or ax,ax jz stop_drives_next ; cmp ax,-1 je stop_drives_next ; mov es,ax cmp bx,es:drive_disc jne stop_drives_next ; mov ax,si sub ax,OFFSET drive_def_arr shr ax,1 StopFileSystem CloseDrive stop_drives_next: add si,2 loop stop_drives_loop ; mov ax,SEG data mov ds,ax mov si,OFFSET disc_def_arr mov cx,MAX_DRIVES stop_disc_loop: cmp bx,[si] je stop_disc_do ; add si,2 loop stop_disc_loop ; jmp stop_disc_done stop_disc_do: mov word ptr ds:[si],0 mov es,bx FreeMem stop_disc_done: popa pop es pop ds retf32 stop_disc Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SET_DISC_PARAM ; ; DESCRIPTION: Set disc parameters ; ; PARAMETERS: AX Sectors per unit ; BX Disc sel ; CX Bytes per sector ; EDX Units ; SI BIOS sectors / cylinder ; DI BIOS heads ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; set_disc_param_name DB 'Set Disc Param',0 set_disc_param Proc far push ds push es push eax push ecx push si push edi ; mov ds,bx mov ds:disc_sectors_per_unit,ax mov ds:disc_bytes_per_sector,cx mov ds:disc_units,edx mov ds:disc_sectors_per_cyl,si mov ds:disc_heads,di ; push edx GetFreePhysical or edx,edx jz set_param_low ; mov eax,0FFFFFFFFh set_param_low: pop edx shr eax,5 ; use 1/32 of physical memory per disc cmp eax,10000h ; use a minimum of 64k per disc ja set_param_max ; mov eax,10000h set_param_max: shr eax,9 mov ds:disc_cache_limit,eax mov ds:disc_cached_sectors,0 ; mov ecx,OFFSET disc_unit_arr mov eax,edx shl eax,2 add eax,ecx AllocateSmallGlobalMem xor di,di xor si,si rep movsb ; xor eax,eax movzx edi,di mov ecx,edx rep stos dword ptr es:[edi] ; mov si,ds mov di,es mov ax,gdt_sel mov ds,ax cli mov eax,[si] xchg eax,[di] mov [si],eax mov eax,[si+4] xchg eax,[di+4] mov [si+4],eax sti jmp short $+2 mov ds,si mov es,di FreeMem ; pop edi pop si pop ecx pop eax pop es pop ds retf32 set_disc_param Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GET_DISC_VENDOR_INFO_BUF ; ; DESCRIPTION: Get disc vendor info buffer ; ; PARAMETERS: BX Disc sel ; ; RETURNS: ES:EDI Vendor info buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_disc_vendor_info_buf_name DB 'Get Disc Vendor Info Buf',0 get_disc_vendor_info_buf Proc far mov es,bx mov edi,OFFSET disc_vendor_str retf32 get_disc_vendor_info_buf Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SET_DISC_USE32 ; ; DESCRIPTION: Set disc to always allocte 32-bit physical blocks ; ; PARAMETERS: BX Disc sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; set_disc_use32_name DB 'Set Disc Use32',0 set_disc_use32 Proc far push ds mov ds,bx or ds:disc_flags,DISC_FLAG_USE32 pop ds retf32 set_disc_use32 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: REGISTER_DISC_CHANGE ; ; DESCRIPTION: Register disc-change procedure ; ; PARAMETERS: BX Disc sel ; ES:EDI Disc change proc ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; register_disc_change_name DB 'Register Disc Change',0 register_disc_change Proc far push ds push bx ; mov ds,bx mov dword ptr ds:disc_change_proc,edi mov word ptr ds:disc_change_proc+4,es ; pop bx pop ds retf32 register_disc_change Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: stop_disc_request ; ; DESCRIPTION: stop disc request ; ; PARAMETERS: BX Disc selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; stop_disc_request_name DB 'Stop Disc Request', 0 stop_disc_request Proc far push ds push bx ; or bx,bx jz sdrDone ; mov ds,bx or ds:disc_flags,DISC_FLAG_STOPPED mov bx,ds:disc_thread Signal sdrDone: pop bx pop ds retf32 stop_disc_request Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: wait_for_disc_request ; ; DESCRIPTION: wait for a new disc request ; ; PARAMETERS: BX Disc selector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wait_for_disc_request_name DB 'Wait For Disc Request', 0 wait_for_disc_request Proc far push ds push es pushad ; mov ds,bx mov ax,flat_sel mov es,ax ; ClearSignal wait_for_disc_req_loop: EnterSection ds:disc_section GetThread mov ds:disc_thread,ax call update_async_write call update_async_timer LeaveSection ds:disc_section ; RequestSpinlock ds:disc_spinlock mov ebx,ds:disc_pend_list or ebx,ebx jnz wait_for_disc_req_done ; ReleaseSpinlock ds:disc_spinlock sti ; test ds:disc_flags,DISC_FLAG_STOPPED stc jnz wait_for_disc_req_end ; WaitForSignal mov ds:disc_thread,0 jmp wait_for_disc_req_loop wait_for_disc_req_done: mov ds:disc_thread,0 ReleaseSpinlock ds:disc_spinlock clc jmp wait_for_disc_req_end wait_for_disc_req_end: popad pop es pop ds retf32 wait_for_disc_request Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: poll_disc_request ; ; DESCRIPTION: poll for a new disc request ; ; PARAMETERS: BX Disc selector ; ; RETURNS: EDI Disc handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; poll_disc_request_name DB 'Poll Disc Request', 0 poll_disc_request Proc far push ds ; mov ds,bx mov edi,ds:disc_pend_list or edi,edi stc jz poll_disc_req_done ; clc poll_disc_req_done: pop ds retf32 poll_disc_request Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: get_disc_request ; ; DESCRIPTION: get a disc request ; ; PARAMETERS: BX Disc selector ; ; RETURNS: EDI Disc handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_disc_request_name DB 'Get Disc Request', 0 get_disc_request Proc far push ds push es push eax push ebx push ecx push edx push esi ; mov ax,flat_sel mov es,ax mov ds,bx EnterSection ds:disc_section call update_async_write call update_async_timer call update_disc_seq call get_pending jnc get_disc_req_ok get_disc_req_fail: LeaveSection ds:disc_section stc jmp get_disc_req_done get_disc_req_ok: or es:[edi].dh_flags,FLAG_IO_BUSY LeaveSection ds:disc_section clc get_disc_req_done: pop esi pop edx pop ecx pop ebx pop eax pop es pop ds retf32 get_disc_request Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: new_disc_request ; ; DESCRIPTION: Create a new disc request and return the handle ; ; PARAMETERS: BX Disc selector ; AX Sector ; DX Unit ; ; RETURNS: EDI Disc handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; new_disc_request_name DB 'New Disc Request', 0 new_disc_request Proc far push ds push es push ecx push dx ; mov ds,bx mov cx,flat_sel mov es,cx movzx ecx,dx mov dx,ax EnterSection ds:disc_section ; call check_buf jnc new_disc_req_fail ; cmp dx,ds:disc_sectors_per_unit jae new_disc_req_fail ; cmp ecx,ds:disc_units jae new_disc_req_fail ; call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 call insert_buf inc es:[edi].dh_lock_count LeaveSection ds:disc_section clc jmp new_disc_req_done new_disc_req_fail: LeaveSection ds:disc_section stc new_disc_req_done: pop dx pop ecx pop es pop ds retf32 new_disc_request Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: LOCK_DISC_REQUEST ; ; DESCRIPTION: Lock disc sector and return handle ; ; PARAMETERS: BX Disc selector ; AX Sector ; DX Unit ; ; RETURNS: EDI Disc handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lock_disc_request_name DB 'Lock Disc Request',0 lock_disc_request PROC far push ds push es push ax push ebx push ecx push edx ; mov ds,bx mov cx,flat_sel mov es,cx movzx ecx,dx mov dx,ax EnterSection ds:disc_section lock_disc_loop: call check_buf jnc lock_disc_ok ; call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,0 call insert_buf inc es:[edi].dh_lock_count lock_disc_ok: clc lock_disc_done: pop edx pop ecx pop ebx pop ax pop es pop ds retf32 lock_disc_request ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: MODIFY_DISC_REQUEST ; ; DESCRIPTION: Modify disc request ; ; PARAMETERS: EDI Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; modify_disc_request_name DB 'Modify Disc Request',0 modify_disc_request PROC far push ds push es pushad ; mov ax,flat_sel mov es,ax mov ds,es:[edi].dh_buf_sel ; mov al,es:[edi].dh_state cmp al,STATE_USED jne modify_disc_done ; mov es:[edi].dh_state,STATE_DIRTY ; test es:[edi].dh_flags, FLAG_IO_PENDING jnz modify_disc_done ; GetSystemTime mov es:[edi].dh_time_lsb,eax call insert_async_write call update_async_timer modify_disc_done: clc ; popad pop es pop ds retf32 modify_disc_request ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UNLOCK_DISC_REQUEST ; ; DESCRIPTION: UNlock disc request ; ; PARAMETERS: EDI Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; unlock_disc_request_name DB 'Unlock Disc Request',0 unlock_disc_request PROC far push ds ; mov ds,es:[edi].dh_buf_sel LeaveSection ds:disc_section ; pop ds clc retf32 unlock_disc_request ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: disc_request_completed ; ; DESCRIPTION: Disc request completed ; ; PARAMETERS: BX Disc selector ; EDI Disc handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; disc_request_completed_name DB 'Disc Request Completed', 0 disc_request_completed Proc far push ds push es push eax push bx push dx ; mov ax,flat_sel mov es,ax mov ds,bx EnterSection ds:disc_section ifdef DEBUG call CheckDeleted call CheckBuffered endif dec ds:disc_io_count ; and es:[edi].dh_flags, NOT (FLAG_IO_PENDING OR FLAG_IO_BUSY) xor bx,bx xchg bx,es:[edi].dh_thread Signal mov bx,es:[edi].dh_wait or bx,bx jz completed_wakeup_done ; push ds mov ax,SEG data mov ds,ax completed_wakeup_loop: push bx mov bx,ds:[bx].dws_thread Signal pop bx ifdef DEBUG call CheckDriveWait endif mov dx,ds:[bx].dws_link mov ax,ds:drive_wait_free mov [bx],ax mov ds:drive_wait_free,bx ifdef DEBUG inc ds:drive_wait_count call CheckDriveWait endif mov bx,dx or bx,bx jnz completed_wakeup_loop ; pop ds completed_wakeup_done: mov es:[edi].dh_wait,0 ; test es:[edi].dh_flags, FLAG_EXT_DATA jz completed_done ; cmp es:[edi].dh_lock_count,0 jnz completed_done ifdef DEBUG call IsPending endif call remove_buf mov es:[edi].dh_state, STATE_EMPTY mov eax,ds:disc_handle_list mov es:[edi],eax mov ds:disc_handle_list,edi dec ds:disc_cached_sectors ifdef DEBUG call CheckAll endif completed_done: LeaveSection ds:disc_section xor edi,edi ; pop dx pop bx pop eax pop es pop ds retf32 disc_request_completed Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: get_disc_request_array ; ; DESCRIPTION: get a disc request array ; ; PARAMETERS: BX Disc selector ; ECX Max number of entries ; ; RETURNS: ESI Disc array ; ECX Number of entries ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_disc_request_array_name DB 'Get Disc Request Array', 0 get_disc_request_array Proc far push ds push es push eax push ebx push edx push edi push ebp ; mov ebp,ecx mov ax,flat_sel mov es,ax mov ds,bx EnterSection ds:disc_section ifdef DEBUG call CheckAll endif call update_async_write call update_async_timer call update_disc_seq xor ecx,ecx mov edi,ds:disc_pend_list or edi,edi jz get_disc_req_arr_done ; movzx edx,es:[edi].dh_sector mov esi,es:[edi].dh_unit mov esi,ds:[4*esi].disc_unit_arr lea ebx,[4*edx+esi].disc_sector_arr mov edi,es:[4*edx+esi].disc_sector_arr or edi,edi jz get_disc_req_arr_done ; or es:[edi].dh_flags,FLAG_IO_BUSY mov al,es:[edi].dh_state cmp al,STATE_EMPTY je get_disc_req_arr_read get_disc_req_arr_write: inc edx inc ecx cmp ecx,ebp jnc get_disc_req_arr_unlink ; cmp dx,ds:disc_sectors_per_unit jae get_disc_req_arr_unlink ; mov edi,es:[4*edx+esi].disc_sector_arr or edi,edi jz get_disc_req_arr_unlink ; mov al,es:[edi].dh_flags test al,FLAG_IO_PENDING jz get_disc_req_arr_unlink ; test al,FLAG_IO_BUSY jnz get_disc_req_arr_unlink ; mov al,es:[edi].dh_state cmp al,STATE_DIRTY jne get_disc_req_arr_check_seq ; or es:[edi].dh_flags,FLAG_IO_BUSY jmp get_disc_req_arr_write get_disc_req_arr_check_seq: cmp al,STATE_SEQ jne get_disc_req_arr_unlink ; or es:[edi].dh_flags,FLAG_IO_BUSY jmp get_disc_req_arr_write get_disc_req_arr_read: inc edx inc ecx cmp ecx,ebp jnc get_disc_req_arr_unlink ; cmp dx,ds:disc_sectors_per_unit jae get_disc_req_arr_unlink ; mov edi,es:[4*edx+esi].disc_sector_arr or edi,edi jz get_disc_req_arr_unlink ; mov al,es:[edi].dh_flags test al,FLAG_IO_PENDING jz get_disc_req_arr_unlink ; test al,FLAG_IO_BUSY jnz get_disc_req_arr_unlink ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY jne get_disc_req_arr_unlink ; or es:[edi].dh_flags,FLAG_IO_BUSY jmp get_disc_req_arr_read get_disc_req_arr_unlink: add ds:disc_io_count,cx sub ds:disc_pend_count,cx ; mov esi,ebx mov edx,es:[esi] mov edi,es:[esi+4*ecx-4] mov eax,es:[edi].dh_next mov ebx,es:[edx].dh_prev mov es:[ebx].dh_next,eax mov es:[eax].dh_prev,ebx cmp eax,edx jne get_disc_req_arr_unlinked ; mov ax,ds:disc_pend_count or ax,ax jz get_disc_req_arr_pend_ok ; int 3 get_disc_req_arr_pend_ok: mov ds:disc_pend_list,0 mov ds:disc_pend_first,0 clc jmp get_disc_req_arr_done get_disc_req_arr_unlinked: mov ds:disc_pend_list,eax cmp edx,ds:disc_pend_first jne get_disc_req_arr_done ; mov ds:disc_pend_first,eax get_disc_req_arr_done: ifdef DEBUG call CheckAll endif LeaveSection ds:disc_section or ecx,ecx stc jz get_disc_req_arr_end ; clc get_disc_req_arr_end: pop ebp pop edi pop edx pop ebx pop eax pop es pop ds retf32 get_disc_request_array Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: INSTALL_DISC ; ; DESCRIPTION: Install disc unit ; ; PARAMETERS: BX Handle ; ECX Readahead ; ; RETURNS: AL Disc # ; BX Disc sel ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; install_disc_name DB 'Install Disc',0 install_disc Proc far push ds push es push cx push si push di ; push cx mov ax,SEG data mov ds,ax mov si,OFFSET disc_def_arr mov cx,MAX_DRIVES install_disc_loop: mov ax,[si] or ax,ax jnz install_disc_next ; push bx mov bx,ds:disc_curr_param push dword ptr [bx+4] push dword ptr [bx] mov eax,SIZE disc_def_struc AllocateSmallGlobalMem xor di,di mov cx,ax xor al,al rep stosb mov [si],es mov ax,es mov ds,ax mov ax,si sub ax,OFFSET disc_def_arr shr ax,1 mov ds:disc_nr,al mov ds:disc_flags,0 mov ds:disc_handle_list,0 mov ds:disc_data_list,0 mov ds:disc_pend_list,0 mov ds:disc_pend_first,0 mov ds:disc_awrite_list,0 mov ds:disc_awrite_timer,0 mov ds:disc_awrite_timeout,0 mov ds:disc_awrite_timeout+4,0 mov ds:disc_seq_list,0 mov ds:disc_free,0 mov ds:disc_timer_id,0 mov ds:disc_thread,0 mov ds:disc_change_proc,0 mov ds:disc_change_proc+4,0 mov ds:disc_cached_sectors,0 mov ds:disc_vendor_str,0 pop dword ptr ds:disc_param pop dword ptr ds:disc_param+4 pop ds:disc_handle pop cx mov ds:disc_readahead,ecx InitSection ds:disc_section InitSpinlock ds:disc_spinlock mov ds:disc_pend_count,0 mov ds:disc_io_count,0 mov bx,ds mov al,ds:disc_nr clc jmp install_disc_done install_disc_next: add si,2 sub cx,1 jnz install_disc_loop add sp,2 stc install_disc_done: pop di pop si pop cx pop es pop ds retf32 install_disc Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: IsDiscIdle ; ; DESCRIPTION: Check if disc is idle ; ; PARAMETERS: AL Disc # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; is_disc_idle_name DB 'Is Disc Idle',0 is_disc_idle Proc far push ds push ebx ; mov bx,SEG data mov ds,bx ; cmp al,MAX_DRIVES jae is_disc_idle_ok ; movzx bx,al shl bx,1 mov ds,ds:[bx].disc_def_arr mov ebx,ds:disc_pend_list or ebx,ebx jz is_disc_idle_ok ; stc jmp is_disc_idle_done is_disc_idle_ok: clc is_disc_idle_done: pop ebx pop ds retf32 is_disc_idle Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ALLOCATE_FIXED_DRIVE ; ; DESCRIPTION: Allocate fixed drive ; ; PARAMETERS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; allocate_fixed_drive_name DB 'Allocate Fixed Drive',0 allocate_fixed_drive Proc far push ds push ax push bx ; mov bx,SEG data mov ds,bx movzx bx,al shl bx,1 mov ax,[bx].drive_def_arr or ax,ax stc jnz afdDone ; mov word ptr [bx].drive_def_arr,-1 clc afdDone: pop bx pop ax pop ds retf32 allocate_fixed_drive Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ALLOCATE_STATIC_DRIVE ; ; DESCRIPTION: Allocate static drive (first) ; ; RETURNS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; allocate_static_drive_name DB 'Allocate Static Drive',0 allocate_static_drive Proc far push ds push cx push si ; push ax mov ax,SEG data mov ds,ax mov si,OFFSET drive_def_arr mov cx,MAX_DRIVES allocate_static_drive_loop: mov ax,[si] or ax,ax jnz allocate_static_drive_next mov word ptr [si],-1 mov cx,si sub cx,OFFSET drive_def_arr shr cx,1 pop ax mov al,cl clc jmp allocate_static_drive_done allocate_static_drive_next: add si,2 loop allocate_static_drive_loop pop ax stc allocate_static_drive_done: pop si pop cx pop ds retf32 allocate_static_drive Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ALLOCATE_DYNAMIC_DRIVE ; ; DESCRIPTION: Allocate dynamic drive (last) ; ; RETURNS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; allocate_dynamic_drive_name DB 'Allocate Dynamic Drive',0 allocate_dynamic_drive Proc far push ds push cx push si ; push ax mov ax,SEG data mov ds,ax mov si,OFFSET drive_def_arr + 2 * (MAX_DRIVES - 1) mov cx,MAX_DRIVES allocate_dynamic_drive_loop: mov ax,[si] or ax,ax jnz allocate_dynamic_drive_next mov word ptr [si],-1 mov cx,si sub cx,OFFSET drive_def_arr shr cx,1 pop ax mov al,cl clc jmp allocate_dynamic_drive_done allocate_dynamic_drive_next: sub si,2 loop allocate_dynamic_drive_loop pop ax stc allocate_dynamic_drive_done: pop si pop cx pop ds retf32 allocate_dynamic_drive Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: OPEN_DRIVE ; ; DESCRIPTION: Open drive ; ; PARAMETERS: AL Drive # ; AH Disc # ; EDX Start sector ; ECX Sectors ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; open_drive_name DB 'Open Drive',0 open_drive Proc far push ds push es push bx push si push di ; push ax mov ax,SEG data mov ds,ax ; mov eax,SIZE drive_def_struc AllocateSmallGlobalMem mov es:drive_start_sector,edx mov es:drive_sectors,ecx pop ax movzx bx,ah shl bx,1 mov bx,ds:[bx].disc_def_arr mov es:drive_disc,bx ; movzx si,al shl si,1 mov [si].drive_def_arr,es ; mov ds,bx mov di,word ptr ds:disc_change_proc+4 or di,di jz open_drive_done ; mov es,di mov edi,dword ptr ds:disc_change_proc mov bx,ds:disc_handle DefineMediaCheck open_drive_done: clc ; pop di pop si pop bx pop es pop ds retf32 open_drive Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CLOSE_DRIVE ; ; DESCRIPTION: Close drive ; ; PARAMETERS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; close_drive_name DB 'Close Drive',0 close_drive Proc far push ds push ax push bx ; FlushDrive mov bx,SEG data mov ds,bx movzx bx,al shl bx,1 xor ax,ax xchg ax,[bx].drive_def_arr or ax,ax jz cdrDone ; cmp ax,-1 je cdrDone ; mov es,ax FreeMem cdrDone: pop bx pop ax pop ds retf32 close_drive Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FlushDrive ; ; DESCRIPTION: Flush drive ; ; PARAMETERS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; flush_drive_name DB 'Flush Drive',0 flush_drive Proc far push ds push es pushad ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ds,ds:[bx].drive_def_arr mov ax,flat_sel mov es,ax mov edx,ds:drive_start_sector mov ecx,ds:drive_sectors mov ds,ds:drive_disc ; EnterSection ds:disc_section movzx ebp,ds:disc_sectors_per_unit push edx pop ax pop dx div bp movzx esi,ax movzx ebx,dx flush_loop: mov edx,ds:[4*esi].disc_unit_arr or edx,edx jz flush_next_unit ; push ecx lea edi,[4*ebx+edx].disc_sector_arr mov eax,ebp sub eax,ebx cmp eax,ecx ja flush_sector_loop ; mov ecx,eax flush_sector_loop: xor eax,eax repe scas dword ptr es:[edi] sub edi,4 xchg eax,es:[edi] or eax,eax jz flush_unit_done ; push edi mov edi,eax call free_handle pop edi sub es:[edx].disc_sectors,1 jnz flush_sector_loop ; mov ds:[4*esi].disc_unit_arr,0 movzx ecx,ds:disc_sectors_per_unit shl ecx,2 add ecx,OFFSET disc_sector_arr FreeLinear xor ecx,ecx flush_unit_done: mov eax,ebp sub eax,ebx sub eax,ecx pop ecx sub ecx,eax jz flush_leave ; xor ebx,ebx inc esi mov eax,ds:disc_units cmp esi,eax jb flush_loop jmp flush_leave flush_next_unit: mov edx,ebp sub edx,ebx sub ecx,edx jbe flush_leave ; xor ebx,ebx inc esi mov eax,ds:disc_units cmp esi,eax jb flush_loop jmp flush_leave flush_leave: LeaveSection ds:disc_section ; popad pop es pop ds retf32 flush_drive Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetDriveParam ; ; DESCRIPTION: Get drive param ; ; PARAMETERS: AL Drive # ; ; RETURNS: EAX Readahead ; ECX Size ; SI Sectors per unit ; EDI Units ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_drive_param_name DB 'Get Drive Param',0 get_drive_param PROC far push ds push bx push edx ; cmp al,MAX_DRIVES jnc get_drive_param_fail ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ax,ds:[bx].drive_def_arr cmp ax,-1 je get_drive_param_fail ; mov ds,ax mov ax,ds:drive_disc or ax,ax jz get_drive_param_fail ; mov ds,ax mov ax,ds:disc_bytes_per_sector mov dx,ds:disc_sectors_per_unit mul dx push dx push ax pop eax mov edx,ds:disc_units mul edx or edx,edx jz get_param_size_ok ; mov eax,-1 get_param_size_ok: mov ecx,eax mov eax,ds:disc_readahead mov si,ds:disc_sectors_per_unit mov edi,ds:disc_units clc jmp get_drive_param_done get_drive_param_fail: xor eax,eax xor ecx,ecx xor si,si xor edi,edi stc get_drive_param_done: pop edx pop bx pop ds retf32 get_drive_param ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: NEW_SECTOR ; ; DESCRIPTION: Create a new sector cache entry without reading ; ; PARAMETERS: AL Drive # ; EDX Sector # ; ; RETURNS: EBX Handle ; ESI Logical address of buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; new_sector_name DB 'New Sector',0 new_sector PROC far push ds push es push ax push ecx push edx push edi ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ds,ds:[bx].drive_def_arr mov ax,flat_sel mov es,ax cmp edx,ds:drive_sectors jc new_inrange ; stc jmp new_leave new_inrange: add edx,ds:drive_start_sector mov ds,ds:drive_disc push edx pop ax pop dx div ds:disc_sectors_per_unit movzx ecx,ax EnterSection ds:disc_section new_loop: call check_buf jnc new_done ; call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_USED mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 call insert_buf new_done: inc es:[edi].dh_lock_count LeaveSection ds:disc_section mov esi,es:[edi].dh_data mov ebx,edi new_leave: pop edi pop edx pop ecx pop ax pop es pop ds retf32 new_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: LOCK_SECTOR ; ; DESCRIPTION: Lock sector and return address ; ; PARAMETERS: AL Drive # ; EDX Sector # ; ; RETURNS: EBX Handle ; ESI Logical address of buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lock_sector_name DB 'Lock Sector',0 lock_sector PROC far push ds push es push eax push ecx push edx push edi ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ax,ds:[bx].drive_def_arr or ax,ax stc jz lock_done ; mov ds,ax mov ax,flat_sel mov es,ax cmp edx,ds:drive_sectors jc lock_inrange ; stc jmp lock_done lock_inrange: add edx,ds:drive_start_sector mov ds,ds:drive_disc push edx pop ax pop dx div ds:disc_sectors_per_unit movzx ecx,ax EnterSection ds:disc_section lock_loop: call check_buf jnc lock_found ; ClearSignal call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,0 call insert_buf call insert_pending lock_read_ahead: push dx push edi inc dx cmp dx,ds:disc_sectors_per_unit je lock_read_ahead_done ; call check_buf jnc lock_read_ahead_done jmp lock_read_ahead_done ; call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,FLAGS_READ_AHEAD mov es:[edi].dh_time_lsb,0 call insert_buf call insert_pending lock_read_ahead_done: pop edi pop dx lock_read_signal: test es:[edi].dh_flags,FLAGS_READ_AHEAD jz lock_read_check_empty ; and es:[edi].dh_flags, NOT FLAGS_READ_AHEAD jmp lock_read_ahead lock_read_check_empty: mov al,es:[edi].dh_state cmp al,STATE_EMPTY clc jne lock_found lock_read_block: call block jmp lock_loop lock_found: test es:[edi].dh_flags, FLAG_IO_BUSY jnz lock_read_block ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY je lock_read_signal ; inc es:[edi].dh_lock_count inc es:[edi].dh_usage LeaveSection ds:disc_section mov al,es:[edi].dh_state cmp al,STATE_USED je lock_get_adds ; cmp al,STATE_DIRTY je lock_get_adds ; cmp al,STATE_SEQ je lock_get_adds ; stc jmp lock_done lock_get_adds: mov esi,es:[edi].dh_data mov ebx,edi lock_done: pop edi pop edx pop ecx pop eax pop es pop ds retf32 lock_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: MODIFY_SECTOR ; ; DESCRIPTION: Modify sector contents ; ; PARAMETERS: EBX Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; modify_sector_name DB 'Modify Sector',0 modify_sector PROC far push ds push es pushad ; mov ax,flat_sel mov es,ax mov edi,ebx mov ds,es:[edi].dh_buf_sel ClearSignal EnterSection ds:disc_section ifdef DEBUG call CheckBuffered endif modify_try_again: test es:[edi].dh_flags, FLAG_IO_BUSY jz modify_not_busy ; call block jmp modify_try_again modify_not_busy: mov al,es:[edi].dh_state cmp al,STATE_USED jne modify_done modify_clean: mov es:[edi].dh_state,STATE_DIRTY ; test es:[edi].dh_flags, FLAG_IO_PENDING jnz modify_done ; GetSystemTime mov es:[edi].dh_time_lsb,eax call insert_async_write call update_async_timer modify_done: LeaveSection ds:disc_section clc ; popad pop es pop ds retf32 modify_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FLUSH_SECTOR ; ; DESCRIPTION: Flush sector contents ; ; PARAMETERS: EBX Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; flush_sector_name DB 'Flush Sector',0 flush_sector PROC far push ds push es pushad ; mov ax,flat_sel mov es,ax mov edi,ebx mov ds,es:[edi].dh_buf_sel ClearSignal EnterSection ds:disc_section ifdef DEBUG call CheckBuffered endif flush_try_again: test es:[edi].dh_flags, FLAG_IO_BUSY jz flush_not_busy flush_block: call block jmp flush_try_again flush_not_busy: mov al,es:[edi].dh_state cmp al,STATE_DIRTY jne flush_done flush_dirty: call flush_async_write mov bx,ds:disc_thread Signal flush_done: LeaveSection ds:disc_section clc ; popad pop es pop ds retf32 flush_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CREATE_DISC_SEQ ; ; DESCRIPTION: Create a sequence ; ; PARAMETERS: CX Max number of sectors in sequence ; ; RETURNS: AX Sequence handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; create_disc_seq_name DB 'Create Disc Seq',0 create_disc_seq PROC far push es push ecx push edi ; movzx ecx,cx movzx eax,cx lea eax,[4*eax].dss_arr AllocateSmallGlobalMem mov edi,OFFSET dss_arr xor eax,eax rep stos dword ptr es:[edi] mov es:dss_buf_sel,0 mov es:dss_insert_index,0 mov es:dss_perform_index,0 mov ax,es ; pop edi pop ecx pop es retf32 create_disc_seq ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: MODIFY_SEQ_SECTOR ; ; DESCRIPTION: Modify sequential sector contents ; ; PARAMETERS: AX Seq handle ; EBX Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; modify_seq_sector_name DB 'Modify Seq Sector',0 modify_seq_sector PROC far push ds push es push fs pushad ; mov fs,ax mov ax,flat_sel mov es,ax mov edi,ebx mov ds,es:[edi].dh_buf_sel ClearSignal EnterSection ds:disc_section ifdef DEBUG call CheckBuffered endif modify_seq_try_again: test es:[edi].dh_flags, FLAG_IO_BUSY jz modify_seq_not_busy modify_seq_block: call block jmp modify_seq_try_again modify_seq_not_busy: mov al,es:[edi].dh_state cmp al,STATE_USED jne modify_seq_block modify_seq_clean: mov es:[edi].dh_state,STATE_SEQ mov bx,fs:dss_insert_index shl bx,2 mov fs:[bx].dss_arr,edi inc fs:dss_insert_index mov fs:dss_buf_sel,ds modify_seq_done: LeaveSection ds:disc_section clc ; popad pop fs pop es pop ds retf32 modify_seq_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: PERFORM_DISC_SEQ ; ; DESCRIPTION: Perform a sequence ; ; PARAMETERS: AX Sequence handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; perform_disc_seq_name DB 'Perform Disc Seq',0 perform_disc_seq PROC far push ds push es push eax push ebx ; mov es,ax mov ax,es:dss_buf_sel or ax,ax jz perform_disc_fail ; mov ds,ax EnterSection ds:disc_section ; mov bx,ds:disc_seq_list or bx,bx je perform_disc_empty ; push ds push si mov ds,bx mov si,ds:dss_prev mov ds:dss_prev,es mov ds,si mov ds:dss_next,es mov es:dss_next,bx mov es:dss_prev,si pop si pop ds jmp perform_disc_do perform_disc_empty: mov es:dss_next,es mov es:dss_prev,es mov ds:disc_seq_list,es perform_disc_do: mov ax,flat_sel mov es,ax call update_disc_seq jmp perform_disc_leave perform_disc_fail: FreeMem stc jmp perform_disc_done perform_disc_leave: LeaveSection ds:disc_section mov bx,ds:disc_thread Signal clc perform_disc_done: pop ebx pop eax pop es pop ds retf32 perform_disc_seq ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: UNLOCK_SECTOR ; ; DESCRIPTION: UNlock sector ; ; PARAMETERS: EBX Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; unlock_sector_name DB 'Unlock Sector',0 unlock_sector PROC far push ds push es push eax push edi ; mov ax,flat_sel mov es,ax mov edi,ebx mov ds,es:[edi].dh_buf_sel EnterSection ds:disc_section ifdef DEBUG call CheckBuffered endif sub es:[edi].dh_lock_count,1 jnz unlock_done ; test es:[edi].dh_flags, FLAG_EXT_DATA jz unlock_done ; test es:[edi].dh_flags, BUSY_FLAGS jnz unlock_done ; cmp es:[edi].dh_state, STATE_USED jne unlock_done ifdef DEBUG call IsPending endif call remove_buf mov es:[edi].dh_state, STATE_EMPTY mov eax,ds:disc_handle_list mov es:[edi],eax mov ds:disc_handle_list,edi dec ds:disc_cached_sectors ifdef DEBUG call CheckAll endif unlock_done: LeaveSection ds:disc_section xor ebx,ebx ; pop edi pop eax pop es pop ds clc retf32 unlock_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ReqSector ; ; DESCRIPTION: Request a sector, but don't block ; ; PARAMETERS: AL Drive # ; EDX Sector # ; ESI Logical address of buffer ; ; RETURNS: EBX Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; req_sector_name DB 'Req Sector',0 req_sector PROC far push ds push es push ax push ecx push edx push edi ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ds,ds:[bx].drive_def_arr mov ax,flat_sel mov es,ax cmp edx,ds:drive_sectors jc req_inrange ; stc jmp req_done req_inrange: add edx,ds:drive_start_sector mov ds,ds:drive_disc call fixup_data ; push edx pop ax pop dx div ds:disc_sectors_per_unit movzx ecx,ax EnterSection ds:disc_section req_loop: call check_buf jnc req_found ; call allocate_handle mov es:[edi].dh_data,esi mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,FLAG_EXT_DATA call insert_buf call insert_pending jmp req_ok req_read_signal: mov al,es:[edi].dh_state cmp al,STATE_EMPTY clc jne req_found req_read_block: call block jmp req_loop req_found: test es:[edi].dh_flags, FLAG_IO_BUSY jnz req_read_block ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY je req_read_signal ; mov edx,es:[edi].dh_data cmp edx,esi je req_ok ; or edx,edx jz req_new_save ; movzx ecx,ds:disc_bytes_per_sector shr ecx,2 push esi push edi mov edi,esi mov esi,edx rep movs dword ptr es:[edi],es:[esi] pop edi pop esi ; test es:[edi].dh_flags, FLAG_EXT_DATA jnz req_new_save ; call free_data req_new_save: mov es:[edi].dh_data,esi or es:[edi].dh_flags,FLAG_EXT_DATA req_ok: inc es:[edi].dh_lock_count inc es:[edi].dh_usage LeaveSection ds:disc_section ; mov bx,ds:disc_thread Signal clc mov ebx,edi req_done: pop edi pop edx pop ecx pop ax pop es pop ds retf32 req_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: DefineSector ; ; DESCRIPTION: Define sector contents, don't block or read ; ; PARAMETERS: AL Drive # ; EDX Sector # ; ESI Logical address of buffer ; ; RETURNS: EBX Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; define_sector_name DB 'Define Sector',0 define_sector PROC far push ds push es push ax push ecx push edx push edi ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ds,ds:[bx].drive_def_arr mov ax,flat_sel mov es,ax cmp edx,ds:drive_sectors jc define_inrange ; stc jmp define_done define_inrange: add edx,ds:drive_start_sector mov ds,ds:drive_disc call fixup_data ; push edx pop ax pop dx div ds:disc_sectors_per_unit movzx ecx,ax EnterSection ds:disc_section define_loop: call check_buf jnc define_found ; ClearSignal call allocate_handle mov es:[edi].dh_data,esi mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_USED mov es:[edi].dh_usage,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,FLAG_EXT_DATA call insert_buf jmp define_found define_read_signal: mov al,es:[edi].dh_state cmp al,STATE_EMPTY clc jne define_found define_read_block: call block jmp define_loop define_found: test es:[edi].dh_flags, FLAG_IO_BUSY jnz define_read_block ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY je define_read_signal ; mov edx,es:[edi].dh_data cmp edx,esi je define_ok ; or edx,edx jz define_new_save ; movzx ecx,ds:disc_bytes_per_sector shr ecx,2 push esi push edi mov edi,esi mov esi,edx rep movs dword ptr es:[edi],es:[esi] pop edi pop esi ; test es:[edi].dh_flags, FLAG_EXT_DATA jnz define_new_save ; call free_data define_new_save: mov es:[edi].dh_data,esi or es:[edi].dh_flags,FLAG_EXT_DATA define_ok: inc es:[edi].dh_lock_count inc es:[edi].dh_usage LeaveSection ds:disc_section mov al,es:[edi].dh_state cmp al,STATE_USED je define_valid ; cmp al,STATE_DIRTY je define_valid ; cmp al,STATE_SEQ je define_valid ; stc jmp define_done define_valid: mov ebx,edi clc define_done: pop edi pop edx pop ecx pop ax pop es pop ds retf32 define_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EraseSectors ; ; DESCRIPTION: Erase a number of sectors ; ; PARAMETERS: AL Drive # ; ECX Number of sectors ; EDX Start sector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; erase_sectors_name DB 'Erase Sectors',0 erase_sectors Proc far push ds push es pushad ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,[bx].drive_def_arr or bx,bx jz erase_sectors_fail ; cmp bx,-1 je erase_sectors_fail ; mov ds,bx mov ds,ds:drive_disc mov bx,ds:disc_handle lds esi,ds:disc_param call fword ptr ds:[esi].ds_erase_proc jnc erase_sectors_done ; mov bx,flat_sel mov es,bx erase_loop: NewSector mov edi,esi push ecx push eax mov eax,-1 mov ecx,80h rep stos dword ptr es:[edi] pop eax pop ecx ModifySector UnlockSector ; inc edx loop erase_loop ; clc jmp erase_sectors_done erase_sectors_fail: stc erase_sectors_done: popad pop es pop ds retf32 erase_sectors Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EraseDiscSectors ; ; DESCRIPTION: Erase a number of sectors on a disc ; ; PARAMETERS: AL Disc # ; ECX Number of sectors ; EDX Start sector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; erase_disc_sectors_name DB 'Erase Disc Sectors',0 erase_disc_sectors Proc near push ds push es pushad ; cmp al,MAX_DRIVES jae erase_disc_sectors_fail ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,[bx].disc_def_arr or bx,bx jz erase_disc_sectors_fail ; cmp bx,-1 je erase_disc_sectors_fail ; mov ds,bx mov bx,ds:disc_handle lds esi,ds:disc_param call fword ptr ds:[esi].ds_erase_proc jnc erase_disc_sectors_done ; mov bx,flat_sel mov es,bx erase_disc_loop: NewSector mov edi,esi push ecx push eax mov eax,-1 mov ecx,80h rep stos dword ptr es:[edi] pop eax pop ecx ModifySector UnlockSector ; inc edx loop erase_disc_loop ; clc jmp erase_disc_sectors_done erase_disc_sectors_fail: stc erase_disc_sectors_done: popad pop es pop ds ret erase_disc_sectors Endp erase_disc_sectors32 Proc far call erase_disc_sectors retf32 erase_disc_sectors32 Endp erase_disc_sectors16 Proc far push ecx ; movzx ecx,cx call erase_disc_sectors ; pop ecx retf32 erase_disc_sectors16 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: WaitForSector ; ; DESCRIPTION: Wait until sector is idle ; ; PARAMETERS: AL Drive # ; EBX Handle ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; wait_for_sector_name DB 'Wait For Sector',0 wait_for_sector PROC far push ds push es push ax push edi ; mov ax,flat_sel mov es,ax mov edi,ebx mov ds,es:[edi].dh_buf_sel EnterSection ds:disc_section ifdef DEBUG call CheckBuffered endif wait_sector_loop: cmp es:[edi].dh_state,STATE_EMPTY je wait_sector_block ; cmp es:[edi].dh_state,STATE_SEQ je wait_sector_block ; cmp es:[edi].dh_state,STATE_DIRTY clc jne wait_sector_found wait_sector_block: call block jmp wait_sector_loop wait_sector_found: LeaveSection ds:disc_section clc ; pop edi pop ax pop es pop ds retf32 wait_for_sector ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ResetDrive ; ; DESCRIPTION: Try to reset drive ; ; PARAMETERS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; reset_drive_name DB 'Reset Disc',0 reset_drive PROC far push ds push ax push bx ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ax,ds:[bx].drive_def_arr or ax,ax jz reset_drive_done ; mov ds,ax mov bx,ds:disc_thread Signal reset_drive_done: pop bx pop ax pop ds retf32 reset_drive ENDP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GET_OLD_DISC_INFO ; ; DESCRIPTION: Get 32-bit disc info ; ; PARAMETERS: AL Disc # ; ; RETURNS; CX Bytes / sector ; EDX Total sectors ; SI BIOS sectors / cylinder ; DI BIOS heads ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_old_disc_info_name DB 'Get Old Disc Info',0 get_old_disc_info PROC far push ds push eax push bx ; cmp al,MAX_DRIVES jae get_old_disc_info_fail ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx jz get_old_disc_info_fail ; mov ds,bx mov eax,ds:disc_units mul ds:disc_sectors_per_unit push dx push ax pop edx mov cx,ds:disc_bytes_per_sector mov si,ds:disc_sectors_per_cyl mov di,ds:disc_heads clc jmp get_old_disc_info_done get_old_disc_info_fail: xor cx,cx xor edx,edx xor si,si xor di,di stc get_old_disc_info_done: pop bx pop eax pop ds retf32 get_old_disc_info Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GET_DISC_INFO ; ; DESCRIPTION: Get disc info ; ; PARAMETERS: AL Disc # ; ; RETURNS; CX Bytes / sector ; EDX:EAX Total sectors ; SI BIOS sectors / cylinder ; DI BIOS heads ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_disc_info_name DB 'Get Disc Info',0 get_disc_info PROC far push ds push bx ; cmp al,MAX_DRIVES jae get_disc_info_fail ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx jz get_disc_info_fail ; mov ds,bx movzx eax,ds:disc_sectors_per_unit mul ds:disc_units mov cx,ds:disc_bytes_per_sector mov si,ds:disc_sectors_per_cyl mov di,ds:disc_heads clc jmp get_disc_info_done get_disc_info_fail: xor cx,cx xor eax,eax xor edx,edx xor si,si xor di,di stc get_disc_info_done: pop bx pop ds retf32 get_disc_info Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: SET_DISC_INFO ; ; DESCRIPTION: Set disc info ; ; PARAMETERS: AL Disc # ; CX Bytes / sector ; EDX Total sectors ; SI BIOS sectors / cylinder ; DI BIOS heads ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; set_disc_info_name DB 'Set Disc Info',0 set_disc_info PROC far push ds push eax push ebx push edx ; cmp al,MAX_DRIVES jae set_disc_info_fail ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx jz set_disc_info_fail ; push bx mov ax,si push edx mul di movzx ebx,ax pop eax xor edx,edx div ebx mov dx,bx pop bx xchg ax,dx movzx edx,dx SetDiscParam clc jmp set_disc_info_done set_disc_info_fail: stc set_disc_info_done: pop edx pop ebx pop eax pop ds retf32 set_disc_info Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GET_DISC_VENDOR_INFO ; ; DESCRIPTION: Get disc vendor info ; ; PARAMETERS: AL Disc # ; ES:(E)DI Vendor buffer ; (E)CX Buffer size ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_disc_vendor_info_name DB 'Get Disc Vendor Info',0 get_disc_vendor_info PROC near push ds push ecx push edx push esi push edi ; cmp al,MAX_DRIVES jae get_disc_vendor_info_fail ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx stc jz get_disc_vendor_info_fail ; sub ecx,1 jbe get_disc_vendor_info_fail ; cmp ecx,255 jb get_disc_vendor_info_size_ok ; mov ds,bx mov si,OFFSET disc_vendor_str mov ecx,255 get_disc_vendor_info_size_ok: xor edx,edx get_disc_vendor_info_copy: lodsb or al,al jz get_disc_vendor_eob ; inc edx stos byte ptr es:[edi] loop get_disc_vendor_info_copy get_disc_vendor_eob: get_disc_vendor_info_trim: sub edx,1 jbe get_disc_vendor_info_term ; mov al,es:[edi-1] cmp al,' ' jne get_disc_vendor_info_term ; sub edi,1 jmp get_disc_vendor_info_trim get_disc_vendor_info_term: xor al,al stos byte ptr es:[edi] clc get_disc_vendor_info_fail: pop edi pop esi pop edx pop ecx pop ds ret get_disc_vendor_info Endp get_disc_vendor_info16 Proc far push ecx push edi movzx edi,di movzx ecx,cx call get_disc_vendor_info pop edi pop ecx retf32 get_disc_vendor_info16 Endp get_disc_vendor_info32 Proc far call get_disc_vendor_info retf32 get_disc_vendor_info32 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ReadShortDisc ; ; DESCRIPTION: Read disc, 32-bit version ; ; PARAMETERS: AL Disc # ; EDX Sector # ; (E)CX Size ; ES:(E)DI Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; read_short_disc_name DB 'Read Short Disc',0 read_short_disc PROC near push ds push es pushad ; cmp al,MAX_DRIVES jae read_short_disc_fail ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx jz read_short_disc_fail ; mov ds,bx push ds push es push ecx push edi ; mov ax,flat_sel mov es,ax push edx pop ax pop dx div ds:disc_sectors_per_unit movzx ecx,ax EnterSection ds:disc_section read_short_disc_loop: call check_buf jnc read_short_disc_found ; ClearSignal call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,0 call insert_buf call insert_pending read_short_disc_signal: mov al,es:[edi].dh_state cmp al,STATE_EMPTY clc jne read_short_disc_found read_short_disc_block: call block jmp read_short_disc_loop read_short_disc_found: test es:[edi].dh_flags, FLAG_IO_BUSY jnz read_short_disc_block ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY je read_short_disc_signal ; mov esi,es:[edi].dh_data mov ax,es mov ds,ax pop edi pop ecx pop es ; shr ecx,2 rep movs dword ptr es:[edi],ds:[esi] pop ds LeaveSection ds:disc_section clc jmp read_short_disc_done read_short_disc_fail: stc read_short_disc_done: popad pop es pop ds ret read_short_disc ENDP read_short_disc32 Proc far call read_short_disc retf32 read_short_disc32 Endp read_short_disc16 Proc far push ecx push edi ; movzx ecx,cx movzx edi,di call read_short_disc ; pop edi pop ecx retf32 read_short_disc16 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: WriteShortDisc ; ; DESCRIPTION: Write disc, 32-bit version ; ; PARAMETERS: AL Disc # ; EDX Sector # ; (E)CX Size ; ES:(E)DI Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; write_short_disc_name DB 'Write Short Disc',0 write_short_disc PROC near push ds push es pushad ; cmp al,MAX_DRIVES jae write_short_disc_fail ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx jz write_short_disc_fail ; mov ds,bx push ds push es push ecx push edi ; mov ax,flat_sel mov es,ax push edx pop ax pop dx div ds:disc_sectors_per_unit movzx ecx,ax EnterSection ds:disc_section write_short_disc_loop: call check_buf jnc write_short_disc_found ; ClearSignal call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,0 call insert_buf call insert_pending write_short_disc_signal: mov al,es:[edi].dh_state cmp al,STATE_EMPTY clc jne write_short_disc_found write_short_disc_block: call block jmp write_short_disc_loop write_short_disc_found: test es:[edi].dh_flags, FLAG_IO_BUSY jnz write_short_disc_block ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY je write_short_disc_signal ; mov ebx,edi mov edi,es:[edi].dh_data pop esi pop ecx pop ds ; shr ecx,2 rep movs dword ptr es:[edi],ds:[esi] ; mov edi,ebx pop ds GetSystemTime mov es:[edi].dh_time_lsb,eax mov es:[edi].dh_state,STATE_DIRTY call insert_async_write call update_async_timer LeaveSection ds:disc_section clc jmp write_short_disc_done write_short_disc_fail: stc write_short_disc_done: popad pop es pop ds ret write_short_disc ENDP write_short_disc32 Proc far call write_short_disc retf32 write_short_disc32 Endp write_short_disc16 Proc far push ecx push edi ; movzx ecx,cx movzx edi,di call write_short_disc ; pop edi pop ecx retf32 write_short_disc16 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: ReadLongDisc ; ; DESCRIPTION: Read disc, 64-bit version ; ; PARAMETERS: BL Disc # ; EDX:EAX Sector # ; (E)CX Size ; ES:(E)DI Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; read_long_disc_name DB 'Read Long Disc',0 read_long_disc PROC near push ds push es pushad ; cmp bl,MAX_DRIVES jae read_long_disc_fail ; push bx mov bx,SEG data mov ds,bx pop bx movzx bx,bl add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx jz read_long_disc_fail ; mov ds,bx push ds push es push ecx push edi ; mov bx,flat_sel mov es,bx movzx ebx,ds:disc_sectors_per_unit div ebx mov ecx,eax EnterSection ds:disc_section read_long_disc_loop: call check_buf jnc read_long_disc_found ; ClearSignal call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,0 call insert_buf call insert_pending read_long_disc_signal: mov al,es:[edi].dh_state cmp al,STATE_EMPTY clc jne read_long_disc_found read_long_disc_block: call block jmp read_long_disc_loop read_long_disc_found: test es:[edi].dh_flags, FLAG_IO_BUSY jnz read_long_disc_block ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY je read_long_disc_signal ; mov esi,es:[edi].dh_data mov ax,es mov ds,ax pop edi pop ecx pop es ; shr ecx,2 rep movs dword ptr es:[edi],ds:[esi] pop ds LeaveSection ds:disc_section clc jmp read_long_disc_done read_long_disc_fail: stc read_long_disc_done: popad pop es pop ds ret read_long_disc ENDP read_long_disc32 Proc far call read_long_disc retf32 read_long_disc32 Endp read_long_disc16 Proc far push ecx push edi ; movzx ecx,cx movzx edi,di call read_long_disc ; pop edi pop ecx retf32 read_long_disc16 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: WriteLongDisc ; ; DESCRIPTION: Write disc, 64-bit version ; ; PARAMETERS: BL Disc # ; EDX:EAX Sector # ; (E)CX Size ; ES:(E)DI Buffer ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; write_long_disc_name DB 'Write Long Disc',0 write_long_disc PROC near push ds push es pushad ; cmp bl,MAX_DRIVES jae write_long_disc_fail ; push bx mov bx,SEG data mov ds,bx pop bx movzx bx,bl add bx,bx mov bx,ds:[bx].disc_def_arr or bx,bx jz write_long_disc_fail ; mov ds,bx push ds push es push ecx push edi ; mov bx,flat_sel mov es,bx movzx ebx,ds:disc_sectors_per_unit div ebx mov ecx,eax EnterSection ds:disc_section write_long_disc_loop: call check_buf jnc write_long_disc_found ; ClearSignal call allocate_handle push edx call allocate_data mov es:[edi].dh_data,edx pop edx mov es:[edi].dh_buf_sel,ds mov es:[edi].dh_sector,dx movzx ecx,cx mov es:[edi].dh_unit,ecx mov es:[edi].dh_wait,0 mov es:[edi].dh_thread,0 mov es:[edi].dh_lock_count,0 mov es:[edi].dh_state,STATE_EMPTY mov es:[edi].dh_usage,0 mov es:[edi].dh_flags,0 mov es:[edi].dh_time_lsb,0 mov es:[edi].dh_flags,0 call insert_buf call insert_pending write_long_disc_signal: mov al,es:[edi].dh_state cmp al,STATE_EMPTY clc jne write_long_disc_found write_long_disc_block: call block jmp write_long_disc_loop write_long_disc_found: test es:[edi].dh_flags, FLAG_IO_BUSY jnz write_long_disc_block ; mov al,es:[edi].dh_state cmp al,STATE_EMPTY je write_long_disc_signal ; mov ebx,edi mov edi,es:[edi].dh_data pop esi pop ecx pop ds ; shr ecx,2 rep movs dword ptr es:[edi],ds:[esi] ; mov edi,ebx pop ds GetSystemTime mov es:[edi].dh_time_lsb,eax mov es:[edi].dh_state,STATE_DIRTY call insert_async_write call update_async_timer LeaveSection ds:disc_section clc jmp write_long_disc_done write_long_disc_fail: stc write_long_disc_done: popad pop es pop ds ret write_long_disc ENDP write_long_disc32 Proc far call write_long_disc retf32 write_long_disc32 Endp write_long_disc16 Proc far push ecx push edi ; movzx ecx,cx movzx edi,di call write_long_disc ; pop edi pop ecx retf32 write_long_disc16 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: GetDriveDiscParam ; ; DESCRIPTION: Get disc parameters for drive ; ; PARAMETERS: AL Drive # ; ; RETURNS: AL Disc # ; ECX Total number of sectors ; EDX Start sector ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; get_drive_disc_param_name DB 'Get Drive Disc Param',0 get_drive_disc_param Proc far push ds push bx ; movzx bx,al shl bx,1 mov ax,SEG data mov ds,ax mov ax,ds:[bx].drive_def_arr or ax,ax stc jz get_drive_disc_param_done ; cmp ax,-1 stc je get_drive_disc_param_done ; mov ds,ax mov ecx,ds:drive_sectors mov edx,ds:drive_start_sector mov ds,ds:drive_disc mov al,ds:disc_nr clc get_drive_disc_param_done: pop bx pop ds retf32 get_drive_disc_param Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: FormatDrive ; ; DESCRIPTION: Format a drive ; ; PARAMETERS: AL Disc # ; EDX Start sector ; ECX Number of sectors ; ES:(E)DI FS name ; ; RETURNS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; format_drive_name DB 'Format Drive',0 format_drive Proc near push ds push es push fs push ebx push ecx push edx push esi push edi push ebp ; push ax mov ax,es mov ds,ax mov esi,edi mov eax,10h AllocateSmallGlobalMem xor edi,edi movs dword ptr es:[edi],ds:[esi] movs dword ptr es:[edi],ds:[esi] movs dword ptr es:[edi],ds:[esi] movs dword ptr es:[edi],ds:[esi] pop ax xor edi,edi IsFileSystemAvailable jc format_fail ; mov bx,SEG data mov ds,bx movzx di,al shl di,1 mov di,ds:[di].disc_def_arr mov si,OFFSET drive_def_arr mov bp,MAX_DRIVES format_find_drive_loop: mov bx,[si] or bx,bx je format_find_drive_next ; cmp bx,-1 je format_find_drive_next ; mov fs,bx cmp di,fs:drive_disc jne format_find_drive_next ; mov ebx,edx sub ebx,fs:drive_start_sector jz format_drive_found ja format_find_drive_above format_find_drive_below: add ebx,fs:drive_sectors jc format_fail jmp format_find_drive_next format_find_drive_above: ; sub ebx,fs:drive_sectors ; jc format_fail format_find_drive_next: add si,2 sub bp,1 jnz format_find_drive_loop ; mov ah,al AllocateStaticDrive OpenDrive jmp format_perf format_drive_found: push dx mov dl,al sub si,OFFSET drive_def_arr mov ax,si shr al,1 mov ah,dl pop dx FlushDrive format_do: cmp ecx,fs:drive_sectors jbe format_perf ; mov ecx,fs:drive_sectors format_perf: dec ecx or edx,edx jz format_mbr format_part: push edx push es mov dx,flat_sel mov es,dx mov dx,cs mov ds,dx xor edx,edx LockSector ; mov edx,1 mov es:[esi].boot_param.boot_mapping_sectors,dx sub ecx,edx mov edx,ecx mov es:[esi].boot_param.boot_sectors,edx cmp edx,10000h jae format_no_small ; mov es:[esi].boot_param.boot_small_sectors,dx format_no_small: pop es ; push cx push esi ; mov dx,flat_sel mov ds,dx xor di,di mov cx,8 lea esi,[esi].boot_param.boot_fs format_name_loop: mov dl,es:[di] or dl,dl jz format_name_space ; inc di mov [esi],dl inc esi jmp format_name_next format_name_space: mov dl,' ' mov [esi],dl inc esi format_name_next: loop format_name_loop ; pop esi pop cx ; ModifySector UnlockSector pop edx jmp format_do_sys format_mbr: push edx push es mov dx,flat_sel mov es,dx mov dx,cs mov ds,dx xor edx,edx LockSector pop es ; push cx push esi ; mov dx,flat_sel mov ds,dx xor di,di mov cx,8 lea esi,[esi].boot_param.boot_fs format_mbr_name_loop: mov dl,es:[di] or dl,dl jz format_mbr_name_space ; inc di mov [esi],dl inc esi jmp format_mbr_name_next format_mbr_name_space: mov dl,' ' mov [esi],dl inc esi format_mbr_name_next: loop format_mbr_name_loop ; pop esi pop cx ; ModifySector UnlockSector pop edx format_do_sys: xor di,di FormatFileSystem jc format_fail ; FreeMem clc jmp format_done format_fail: FreeMem stc format_done: pop ebp pop edi pop esi pop edx pop ecx pop ebx pop fs pop es pop ds ret format_drive Endp format_drive32 Proc far call format_drive retf32 format_drive32 Endp format_drive16 Proc far push edi movzx edi,di call format_drive pop edi retf32 format_drive16 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: BeginDiscHandler ; ; DESCRIPTION: Begin a disc-handler ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; begin_disc_handler_name DB 'Begin Disc Handler',0 begin_disc_handler Proc far push ds push ax mov ax,SEG data mov ds,ax EnterSection ds:disc_handler_section inc ds:disc_handlers LeaveSection ds:disc_handler_section pop ax pop ds retf32 begin_disc_handler Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: EndDiscHandler ; ; DESCRIPTION: End a disc-handler ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; end_disc_handler_name DB 'End Disc Handler',0 end_disc_handler Proc far push ds push ax push bx ; mov ax,SEG data mov ds,ax EnterSection ds:disc_handler_section sub ds:disc_handlers,1 jnz edhDone ; mov bx,ds:disc_start_thread Signal edhDone: LeaveSection ds:disc_handler_section pop bx pop ax pop ds retf32 end_disc_handler Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: CondBeginDiscHandler ; ; DESCRIPTION: Conditionally begin disc handler ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cond_begin_disc_handler_name DB 'Cond Begin Disc Handler',0 cond_begin_disc_handler Proc far push ds push ax ; mov ax,SEG data mov ds,ax EnterSection ds:disc_handler_section mov ax,ds:disc_handlers or ax,ax stc jnz hdhcDone ; inc ds:disc_handlers clc hdhcDone: LeaveSection ds:disc_handler_section pop ax pop ds retf32 cond_begin_disc_handler Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: HOOK_INIT_DISC ; ; DESCRIPTION: Add an InitDisc hook ; ; PARAMETERS: ES:EDI Parameter block ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; hook_init_disc_name DB 'Hook Init Disc',0 hook_init_disc Proc far push ds push ax push bx push cx mov ax,SEG data mov ds,ax mov al,ds:disc_params mov bl,al xor bh,bh shl bx,3 add bx,OFFSET disc_param_arr mov [bx],edi mov [bx+4],es inc al mov ds:disc_params,al pop cx pop bx pop ax pop ds retf32 hook_init_disc Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: RUN_DISC_ASSIGN ; ; DESCRIPTION: Run all disc-assign hooks ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; run_disc_assign Proc near push ds push ax push bx push cx ; mov ax,SEG data mov ds,ax movzx cx,ds:disc_params mov bx,OFFSET disc_param_arr jcxz run_disc_assign_done run_disc_assign_loop: push ds push ebx push cx mov ds:disc_curr_param,bx lds ebx,[bx] call fword ptr [ebx].ds_disc_assign_proc pop cx pop ebx pop ds add bx,8 loop run_disc_assign_loop run_disc_assign_done: pop cx pop bx pop ax pop ds ret run_disc_assign Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: RUN_DRIVE_ASSIGN1 ; ; DESCRIPTION: Run drive assign pass 1 for all discs ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; run_drive_assign1 Proc near push ds push ax push bx push cx push si ; mov ax,SEG data mov ds,ax xor si,si mov cx,MAX_DRIVES run_drive_assign1_loop: mov bx,[si].disc_def_arr or bx,bx jz run_drive_assign1_next ; push ds push bx push cx push esi ; mov ds,bx mov bx,ds:disc_handle lds esi,ds:disc_param call fword ptr ds:[esi].ds_drive_assign1_proc ; pop esi pop cx pop bx pop ds run_drive_assign1_next: add si,2 sub cx,1 jnz run_drive_assign1_loop ; pop si pop cx pop bx pop ax pop ds ret run_drive_assign1 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: RUN_DRIVE_ASSIGN2 ; ; DESCRIPTION: Run drive assign pass 2 for all discs ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; run_drive_assign2 Proc near push ds push ax push bx push cx push si ; mov ax,SEG data mov ds,ax xor si,si mov cx,MAX_DRIVES run_drive_assign2_loop: mov bx,[si].disc_def_arr or bx,bx jz run_drive_assign2_next ; push ds push bx push cx push esi ; mov ds,bx mov bx,ds:disc_handle lds esi,ds:disc_param call fword ptr ds:[esi].ds_drive_assign2_proc ; pop esi pop cx pop bx pop ds run_drive_assign2_next: add si,2 sub cx,1 jnz run_drive_assign2_loop ; pop si pop cx pop bx pop ax pop ds ret run_drive_assign2 Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: DEMAND_LOAD_DRIVE ; ; DESCRIPTION: Run demand-load for disc exporting drive ; ; PARAMETERS: AL Drive # ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; demand_load_drive_name DB 'Demand Load Drive', 0 demand_load_drive Proc far push ds pushad ; mov bx,SEG data mov ds,bx movzx bx,al add bx,bx mov ax,[bx].drive_def_arr or ax,ax jz demand_load_drive_fail ; cmp ax,-1 je demand_load_drive_fail ; mov ds,ax mov ds,ds:drive_disc mov bx,ds:disc_handle lds esi,ds:disc_param call fword ptr ds:[esi].ds_demand_mount_proc jmp demand_load_drive_done demand_load_drive_fail: stc demand_load_drive_done: popad pop ds retf32 demand_load_drive Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: INIT_DISC ; ; DESCRIPTION: Init discs ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init_disc Proc far mov ax,SEG data mov ds,ax ClearSignal GetThread mov ds:disc_start_thread,ax sub ds:disc_handlers,1 jz init_disc_do init_disc_retry: mov ax,ds:disc_handlers or ax,ax jz init_disc_do ; WaitForSignal jmp init_disc_retry init_disc_do: EnterSection ds:disc_handler_section call run_disc_assign call run_drive_assign1 call run_drive_assign2 ; mov ax,SEG data mov ds,ax LeaveSection ds:disc_handler_section mov ds:disc_start_thread,0 retf32 init_disc Endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; NAME: INIT ; ; DESCRIPTION: Init drive ; ; PARAMETERS: ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init PROC far mov ax,cs mov ds,ax mov es,ax ; mov esi,OFFSET hook_init_disc mov edi,OFFSET hook_init_disc_name mov ax,hook_init_disc_nr RegisterOsGate ; mov esi,OFFSET begin_disc_handler mov edi,OFFSET begin_disc_handler_name mov ax,begin_disc_handler_nr RegisterOsGate ; mov esi,OFFSET end_disc_handler mov edi,OFFSET end_disc_handler_name mov ax,end_disc_handler_nr RegisterOsGate ; mov esi,OFFSET cond_begin_disc_handler mov edi,OFFSET cond_begin_disc_handler_name mov ax,cond_begin_disc_handler_nr RegisterOsGate ; mov esi,OFFSET install_disc mov edi,OFFSET install_disc_name mov ax,install_disc_nr RegisterOsGate ; mov esi,OFFSET set_disc_param mov edi,OFFSET set_disc_param_name mov ax,set_disc_param_nr RegisterOsGate ; mov esi,OFFSET get_disc_vendor_info_buf mov edi,OFFSET get_disc_vendor_info_buf_name mov ax,get_disc_vendor_info_buf_nr RegisterOsGate ; mov esi,OFFSET set_disc_use32 mov edi,OFFSET set_disc_use32_name mov ax,set_disc_use32_nr RegisterOsGate ; mov esi,OFFSET register_disc_change mov edi,OFFSET register_disc_change_name mov ax,register_disc_change_nr RegisterOsGate ; mov esi,OFFSET start_disc mov edi,OFFSET start_disc_name mov ax,start_disc_nr RegisterOsGate ; mov esi,OFFSET stop_disc mov edi,OFFSET stop_disc_name mov ax,stop_disc_nr RegisterOsGate ; mov esi,OFFSET stop_disc_request mov edi,OFFSET stop_disc_request_name mov ax,stop_disc_request_nr RegisterOsGate ; mov esi,OFFSET wait_for_disc_request mov edi,OFFSET wait_for_disc_request_name mov ax,wait_for_disc_request_nr RegisterOsGate ; mov esi,OFFSET poll_disc_request mov edi,OFFSET poll_disc_request_name mov ax,poll_disc_request_nr RegisterOsGate ; mov esi,OFFSET get_disc_request mov edi,OFFSET get_disc_request_name mov ax,get_disc_request_nr RegisterOsGate ; mov esi,OFFSET new_disc_request mov edi,OFFSET new_disc_request_name mov ax,new_disc_request_nr RegisterOsGate ; mov esi,OFFSET lock_disc_request mov edi,OFFSET lock_disc_request_name mov ax,lock_disc_request_nr RegisterOsGate ; mov esi,OFFSET modify_disc_request mov edi,OFFSET modify_disc_request_name mov ax,modify_disc_request_nr RegisterOsGate ; mov esi,OFFSET unlock_disc_request mov edi,OFFSET unlock_disc_request_name mov ax,unlock_disc_request_nr RegisterOsGate ; mov esi,OFFSET disc_request_completed mov edi,OFFSET disc_request_completed_name mov ax,disc_request_completed_nr RegisterOsGate ; mov esi,OFFSET get_disc_request_array mov edi,OFFSET get_disc_request_array_name mov ax,get_disc_request_array_nr RegisterOsGate ; mov esi,OFFSET open_drive mov edi,OFFSET open_drive_name mov ax,open_drive_nr RegisterOsGate ; mov esi,OFFSET close_drive mov edi,OFFSET close_drive_name mov ax,close_drive_nr RegisterOsGate ; mov esi,OFFSET flush_drive mov edi,OFFSET flush_drive_name mov ax,flush_drive_nr RegisterOsGate ; mov esi,OFFSET new_sector mov edi,OFFSET new_sector_name mov ax,new_sector_nr RegisterOsGate ; mov esi,OFFSET get_drive_param mov edi,OFFSET get_drive_param_name mov ax,get_drive_param_nr RegisterOsGate ; mov esi,OFFSET lock_sector mov edi,OFFSET lock_sector_name mov ax,lock_sector_nr RegisterOsGate ; mov esi,OFFSET unlock_sector mov edi,OFFSET unlock_sector_name mov ax,unlock_sector_nr RegisterOsGate ; mov esi,OFFSET modify_sector mov edi,OFFSET modify_sector_name mov ax,modify_sector_nr RegisterOsGate ; mov esi,OFFSET flush_sector mov edi,OFFSET flush_sector_name mov ax,flush_sector_nr RegisterOsGate ; mov esi,OFFSET create_disc_seq mov edi,OFFSET create_disc_seq_name mov ax,create_disc_seq_nr RegisterOsGate ; mov esi,OFFSET modify_seq_sector mov edi,OFFSET modify_seq_sector_name mov ax,modify_seq_sector_nr RegisterOsGate ; mov esi,OFFSET perform_disc_seq mov edi,OFFSET perform_disc_seq_name mov ax,perform_disc_seq_nr RegisterOsGate ; mov esi,OFFSET req_sector mov edi,OFFSET req_sector_name mov ax,req_sector_nr RegisterOsGate ; mov esi,OFFSET define_sector mov edi,OFFSET define_sector_name mov ax,define_sector_nr RegisterOsGate ; mov esi,OFFSET erase_sectors mov edi,OFFSET erase_sectors_name mov ax,erase_sectors_nr RegisterOsGate ; mov esi,OFFSET wait_for_sector mov edi,OFFSET wait_for_sector_name mov ax,wait_for_sector_nr RegisterOsGate ; mov esi,OFFSET reset_drive mov edi,OFFSET reset_drive_name mov ax,reset_drive_nr RegisterOsGate ; mov esi,OFFSET get_old_disc_info mov edi,OFFSET get_old_disc_info_name xor dx,dx mov ax,get_old_disc_info_nr RegisterBimodalUserGate ; mov esi,OFFSET get_disc_info mov edi,OFFSET get_disc_info_name xor dx,dx mov ax,get_disc_info_nr RegisterBimodalUserGate ; mov esi,OFFSET set_disc_info mov edi,OFFSET set_disc_info_name xor dx,dx mov ax,set_disc_info_nr RegisterBimodalUserGate ; mov esi,OFFSET is_disc_idle mov edi,OFFSET is_disc_idle_name xor dx,dx mov ax,is_disc_idle_nr RegisterBimodalUserGate ; mov esi,OFFSET allocate_fixed_drive mov edi,OFFSET allocate_fixed_drive_name xor dx,dx mov ax,allocate_fixed_drive_nr RegisterBimodalUserGate ; mov esi,OFFSET allocate_static_drive mov edi,OFFSET allocate_static_drive_name xor dx,dx mov ax,allocate_static_drive_nr RegisterBimodalUserGate ; mov esi,OFFSET allocate_dynamic_drive mov edi,OFFSET allocate_dynamic_drive_name xor dx,dx mov ax,allocate_dynamic_drive_nr RegisterBimodalUserGate ; mov esi,OFFSET get_drive_disc_param mov edi,OFFSET get_drive_disc_param_name xor dx,dx mov ax,get_drive_disc_param_nr RegisterBimodalUserGate ; mov ebx,OFFSET get_disc_vendor_info16 mov esi,OFFSET get_disc_vendor_info32 mov edi,OFFSET get_disc_vendor_info_name mov dx,virt_es_in mov ax,get_disc_vendor_info_nr RegisterUserGate ; mov esi,OFFSET demand_load_drive mov edi,OFFSET demand_load_drive_name mov ax,demand_load_drive_nr RegisterBimodalUserGate ; mov ebx,OFFSET format_drive16 mov esi,OFFSET format_drive32 mov edi,OFFSET format_drive_name mov dx,virt_es_in mov ax,format_drive_nr RegisterUserGate ; mov ebx,OFFSET read_short_disc16 mov esi,OFFSET read_short_disc32 mov edi,OFFSET read_short_disc_name mov dx,virt_es_in mov ax,read_short_disc_nr RegisterUserGate ; mov ebx,OFFSET write_short_disc16 mov esi,OFFSET write_short_disc32 mov edi,OFFSET write_short_disc_name mov dx,virt_es_in mov ax,write_short_disc_nr RegisterUserGate ; mov ebx,OFFSET read_long_disc16 mov esi,OFFSET read_long_disc32 mov edi,OFFSET read_long_disc_name mov dx,virt_es_in mov ax,read_long_disc_nr RegisterUserGate ; mov ebx,OFFSET write_long_disc16 mov esi,OFFSET write_long_disc32 mov edi,OFFSET write_long_disc_name mov dx,virt_es_in mov ax,write_long_disc_nr RegisterUserGate ; mov ebx,OFFSET erase_disc_sectors16 mov esi,OFFSET erase_disc_sectors32 mov edi,OFFSET erase_disc_sectors_name xor dx,dx mov ax,erase_disc_sectors_nr RegisterUserGate ; mov edi,OFFSET init_disc HookInitFileSystem ; mov bx,SEG data mov es,bx InitSection es:disc_handler_section mov es:disc_params,0 mov es:disc_handlers,1 ; mov cx,MAX_DRIVES mov di,OFFSET disc_def_arr xor ax,ax rep stosw ; mov cx,MAX_DRIVES mov di,OFFSET drive_def_arr xor ax,ax rep stosw ; mov cx,DRIVE_WAIT_NUM mov di,4*DRIVE_WAIT_NUM + OFFSET drive_wait_arr xor ax,ax init_drive_wait_loop: sub di,4 mov es:[di],ax mov ax,di loop init_drive_wait_loop mov es:drive_wait_free,di mov es:drive_wait_count,DRIVE_WAIT_NUM ; call init_ramdrive call init_filedisc call init_stddev ret init ENDP code ENDS END init