/*      $NetBSD: dos_file.S,v 1.1 2024/06/29 13:45:14 rin Exp $ */

/* extracted from Tor Egge's patches for NetBSD boot */

#include <machine/asm.h>

/*
# MSDOS call "INT 0x21 Function 0x3d" to open a file.
# Call with     %ah = 0x3d
#               %al = 0x0  (access and sharing modes)
#               %ds:%dx = ASCIZ filename
#               %cl = attribute mask of files to look for
*/

       .globl _C_LABEL(doserrno)
_C_LABEL(doserrno):     .long 1

ENTRY(dosopen)
       .code32
       pushl   %ebp
       movl    %esp, %ebp
       pushl   %edx
       pushl   %ebx
       pushl   %esi
       pushl   %edi

       movl    0x8(%ebp), %edx         # File name.

       call    _C_LABEL(prot_to_real)  # enter real mode
       .code16

       push    %ds
       movl    %edx, %eax
       shrl    $4, %eax
       mov     %ds, %si
       add     %si, %ax
       mov     %ax, %ds
       and     $0xf, %dx

       movb    $0x3d, %ah              # Open existing file.
       movb    $0x0 , %al              # ro

       sti
       int     $0x21
       cli
       pop     %ds

       jnc     ok1
       mov     %ax, _C_LABEL(doserrno)
       movl    $-1, %edx
       jmp err1
ok1:
       movl    $0,%edx
       mov     %ax, %dx
err1:
       calll   _C_LABEL(real_to_prot) # back to protected mode
       .code32

       movl    %edx, %eax              # return value in %eax

       popl    %edi
       popl    %esi
       popl    %ebx
       popl    %edx
       popl    %ebp
       ret

ENTRY(dosread)
       .code32
       pushl   %ebp
       movl    %esp, %ebp
       pushl   %ebx
       pushl   %ecx
       pushl   %edx
       pushl   %esi
       pushl   %edi

       movl    0x8(%ebp), %ebx         # File handle
       movl    0xc(%ebp), %edx         # Buffer.
       movl    0x10(%ebp), %ecx        # Bytes to read

       call    _C_LABEL(prot_to_real)  # enter real mode
       .code16

       push    %ds
       movl    %edx, %eax
       shrl    $4, %eax
       mov     %ds, %si
       add     %si, %ax
       mov     %ax, %ds
       and     $0xf, %dx

       movb    $0x3f, %ah              # Read from file or device

       sti
       int     $0x21
       cli
       pop     %ds

       jnc     ok2
       mov     %ax, _C_LABEL(doserrno)
       movl    $-1, %edx
       jmp     err2
ok2:
       movl    $0,%edx
       mov     %ax, %dx
err2:
       calll   _C_LABEL(real_to_prot)  # back to protected mode
       .code32

       movl    %edx, %eax              # return value in %eax

       popl    %edi
       popl    %esi
       popl    %edx
       popl    %ecx
       popl    %ebx
       popl    %ebp
       ret

ENTRY(dosclose)
       .code32
       pushl %ebp
       movl  %esp, %ebp
       pushl   %ebx
       pushl   %esi
       pushl   %edi

       movl    0x8(%ebp), %ebx         # File handle

       call    _C_LABEL(prot_to_real)  # enter real mode
       .code16

       movb    $0x3e, %ah              # Close file.

       sti
       int     $0x21
       cli

       jnc     ok3
       mov     %ax, _C_LABEL(doserrno)
       movl    $-1, %ebx
       jmp     err3
ok3:
       movl    $0, %ebx
err3:
       calll   _C_LABEL(real_to_prot) # back to protected mode
       .code32

       movl    %ebx, %eax              # return value in %eax

       popl    %edi
       popl    %esi
       popl    %ebx
       popl    %ebp
       ret

ENTRY(dosseek)
       .code32
       pushl   %ebp
       movl    %esp, %ebp
       pushl   %ebx
       pushl   %ecx
       pushl   %edx
       pushl   %esi
       pushl   %edi

       movl    0x8(%ebp), %ebx         # File handle
       movl    0xc(%ebp), %ecx         # Offset
       movl    0x10(%ebp) , %edx       # whence

       call    _C_LABEL(prot_to_real)  # enter real mode
       .code16

       movb    $0x42, %ah              # Seek
       movb    %dl, %al                # whence
       mov     %cx, %dx                #offs lo
       shrl    $0x10, %ecx             #offs hi

       sti
       int     $0x21
       cli

       jnc     ok4
       mov     %ax, _C_LABEL(doserrno)
       movl    $-1, %edx
       jmp     err4
ok4:
       shll    $0x10, %edx     #new ofs hi
       mov     %ax, %dx        #new ofs lo
err4:
       calll   _C_LABEL(real_to_prot) # back to protected mode
       .code32

       movl    %edx, %eax              # return value in %eax

       popl    %edi
       popl    %esi
       popl    %edx
       popl    %ecx
       popl    %ebx
       popl    %ebp
       ret