4 ; Copyright (C) 1992, Thomas G. Lane.
 
   5 ; This file is part of the Independent JPEG Group's software.
 
   6 ; For conditions of distribution and use, see the accompanying README file.
 
   8 ; This file contains low-level interface routines to support the MS-DOS
 
   9 ; backing store manager (jmemdos.c).  Routines are provided to access disk
 
  10 ; files through direct DOS calls, and to access XMS and EMS drivers.
 
  12 ; This file should assemble with Microsoft's MASM or any compatible
 
  13 ; assembler (including Borland's Turbo Assembler).  If you haven't got
 
  14 ; a compatible assembler, better fall back to jmemansi.c or jmemname.c.
 
  16 ; To minimize dependence on the C compiler's register usage conventions,
 
  17 ; we save and restore all 8086 registers, even though most compilers only
 
  18 ; require SI,DI,DS to be preserved.  Also, we use only 16-bit-wide return
 
  19 ; values, which everybody returns in AX.
 
  21 ; Based on code contributed by Ge' Weijers.
 
  24 JMEMDOSA_TXT    segment byte public 'CODE'
 
  26                 assume  cs:JMEMDOSA_TXT
 
  33                 public  _jxms_getdriver
 
  34                 public  _jxms_calldriver
 
  35                 public  _jems_available
 
  36                 public  _jems_calldriver
 
  39 ; short far jdos_open (short far * handle, char far * filename)
 
  41 ; Create and open a temporary file
 
  46                 push    si                      ; save all registers for safety
 
  53                 mov     cx,0                    ; normal file attributes
 
  54                 lds     dx,dword ptr [bp+10]    ; get filename pointer
 
  55                 mov     ah,3ch                  ; create file
 
  57                 jc      open_err                ; if failed, return error code
 
  58                 lds     bx,dword ptr [bp+6]     ; get handle pointer
 
  59                 mov     word ptr [bx],ax        ; save the handle
 
  60                 xor     ax,ax                   ; return zero for OK
 
  61 open_err:       pop     ds                      ; restore registers and exit
 
  74 ; short far jdos_close (short handle)
 
  76 ; Close the file handle
 
  81                 push    si                      ; save all registers for safety
 
  88                 mov     bx,word ptr [bp+6]      ; file handle
 
  89                 mov     ah,3eh                  ; close file
 
  91                 jc      close_err               ; if failed, return error code
 
  92                 xor     ax,ax                   ; return zero for OK
 
  93 close_err:      pop     ds                      ; restore registers and exit
 
 106 ; short far jdos_seek (short handle, long offset)
 
 113                 push    si                      ; save all registers for safety
 
 120                 mov     bx,word ptr [bp+6]      ; file handle
 
 121                 mov     dx,word ptr [bp+8]      ; LS offset
 
 122                 mov     cx,word ptr [bp+10]     ; MS offset
 
 123                 mov     ax,4200h                ; absolute seek
 
 125                 jc      seek_err                ; if failed, return error code
 
 126                 xor     ax,ax                   ; return zero for OK
 
 127 seek_err:       pop     ds                      ; restore registers and exit
 
 140 ; short far jdos_read (short handle, void far * buffer, unsigned short count)
 
 147                 push    si                      ; save all registers for safety
 
 154                 mov     bx,word ptr [bp+6]      ; file handle
 
 155                 lds     dx,dword ptr [bp+8]     ; buffer address
 
 156                 mov     cx,word ptr [bp+12]     ; number of bytes
 
 157                 mov     ah,3fh                  ; read file
 
 159                 jc      read_err                ; if failed, return error code
 
 160                 cmp     ax,word ptr [bp+12]     ; make sure all bytes were read
 
 162                 mov     ax,1                    ; else return 1 for not OK
 
 164 read_ok:        xor     ax,ax                   ; return zero for OK
 
 165 read_err:       pop     ds                      ; restore registers and exit
 
 178 ; short far jdos_write (short handle, void far * buffer, unsigned short count)
 
 185                 push    si                      ; save all registers for safety
 
 192                 mov     bx,word ptr [bp+6]      ; file handle
 
 193                 lds     dx,dword ptr [bp+8]     ; buffer address
 
 194                 mov     cx,word ptr [bp+12]     ; number of bytes
 
 195                 mov     ah,40h                  ; write file
 
 197                 jc      write_err               ; if failed, return error code
 
 198                 cmp     ax,word ptr [bp+12]     ; make sure all bytes written
 
 200                 mov     ax,1                    ; else return 1 for not OK
 
 202 write_ok:       xor     ax,ax                   ; return zero for OK
 
 203 write_err:      pop     ds                      ; restore registers and exit
 
 216 ; void far jxms_getdriver (XMSDRIVER far *)
 
 218 ; Get the address of the XMS driver, or NULL if not available
 
 220 _jxms_getdriver proc    far
 
 223                 push    si                      ; save all registers for safety
 
 230                 mov     ax,4300h                ; call multiplex interrupt with
 
 231                 int     2fh                     ; a magic cookie, hex 4300
 
 232                 cmp     al,80h                  ; AL should contain hex 80
 
 234                 xor     dx,dx                   ; no XMS driver available
 
 235                 xor     ax,ax                   ; return a nil pointer
 
 236                 jmp     short xmsavail_done
 
 237 xmsavail:       mov     ax,4310h                ; fetch driver address with
 
 238                 int     2fh                     ; another magic cookie
 
 239                 mov     dx,es                   ; copy address to dx:ax
 
 241 xmsavail_done:  les     bx,dword ptr [bp+6]     ; get pointer to return value
 
 242                 mov     word ptr es:[bx],ax
 
 243                 mov     word ptr es:[bx+2],dx
 
 244                 pop     ds                      ; restore registers and exit
 
 257 ; void far jxms_calldriver (XMSDRIVER, XMScontext far *)
 
 259 ; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.
 
 260 ; These are loaded, the XMS call is performed, and the new values of the
 
 261 ; AX,DX,BX registers are written back to the context structure.
 
 263 _jxms_calldriver        proc    far
 
 266                 push    si                      ; save all registers for safety
 
 273                 les     bx,dword ptr [bp+10]    ; get XMScontext pointer
 
 274                 mov     ax,word ptr es:[bx]     ; load registers
 
 275                 mov     dx,word ptr es:[bx+2]
 
 276                 mov     si,word ptr es:[bx+6]
 
 277                 mov     ds,word ptr es:[bx+8]
 
 278                 mov     bx,word ptr es:[bx+4]
 
 279                 call    dword ptr [bp+6]        ; call the driver
 
 280                 mov     cx,bx                   ; save returned BX for a sec
 
 281                 les     bx,dword ptr [bp+10]    ; get XMScontext pointer
 
 282                 mov     word ptr es:[bx],ax     ; put back ax,dx,bx
 
 283                 mov     word ptr es:[bx+2],dx
 
 284                 mov     word ptr es:[bx+4],cx
 
 285                 pop     ds                      ; restore registers and exit
 
 294 _jxms_calldriver        endp
 
 298 ; short far jems_available (void)
 
 300 ; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)
 
 302 _jems_available proc    far
 
 303                 push    si                      ; save all registers for safety
 
 310                 mov     ax,3567h                ; get interrupt vector 67h
 
 314                 mov     di,000ah                ; check offs 10 in returned seg
 
 315                 lea     si,ASCII_device_name    ; against literal string
 
 320                 mov     ax,1                    ; match, it's there
 
 322 no_ems:         xor     ax,ax                   ; it's not there
 
 323 avail_done:     pop     ds                      ; restore registers and exit
 
 332 ASCII_device_name       db      "EMMXXXX0"
 
 338 ; void far jems_calldriver (EMScontext far *)
 
 340 ; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers.
 
 341 ; These are loaded, the EMS trap is performed, and the new values of the
 
 342 ; AX,DX,BX registers are written back to the context structure.
 
 344 _jems_calldriver        proc far
 
 347                 push    si                      ; save all registers for safety
 
 354                 les     bx,dword ptr [bp+6]     ; get EMScontext pointer
 
 355                 mov     ax,word ptr es:[bx]     ; load registers
 
 356                 mov     dx,word ptr es:[bx+2]
 
 357                 mov     si,word ptr es:[bx+6]
 
 358                 mov     ds,word ptr es:[bx+8]
 
 359                 mov     bx,word ptr es:[bx+4]
 
 360                 int     67h                     ; call the EMS driver
 
 361                 mov     cx,bx                   ; save returned BX for a sec
 
 362                 les     bx,dword ptr [bp+6]     ; get EMScontext pointer
 
 363                 mov     word ptr es:[bx],ax     ; put back ax,dx,bx
 
 364                 mov     word ptr es:[bx+2],dx
 
 365                 mov     word ptr es:[bx+4],cx
 
 366                 pop     ds                      ; restore registers and exit
 
 375 _jems_calldriver        endp