Metropoli BBS
VIEWER: dma.asm MODE: TEXT (ASCII)
;DMA buffer alloc funcs

include qlib.inc

.code

;this will alloc upto a 64k DMA buffer and will not cross a 64k DMA boundry
dma_alloc64 proc,dmas:dword
  callp _alloc,dmas,64
  ret
dma_alloc64 endp

;this will alloc upto a 128k DMA buffer and will not cross a 128k DMA boundry
;and it will be WORD ALIGNED!
dma_alloc128 proc,dmas:dword
  callp _alloc,dmas,128
  ret
dma_alloc128 endp

_alloc proc private,dmas:dword,siz:byte
  ;use DOS
  pushad
  mov esi,dmas
  mov ebx,[esi].dma_s.siz
  .if siz==64
    mov eax,64*1024
  .else
    mov eax,128*1024
  .endif
  .if ( (ebx>eax) || (!ebx) )
    popad
    mov eax,ERROR
    ret
  .endif
  shl ebx,1        ; alloc twice as much needed  (any better ideas?)
  shr ebx,4        ; convert to paragraph size
  .if [esi].dma_s.siz & 0fh
    inc ebx
  .endif
  mov ax,100h  ;alloc DOS ram
  int 31h
  .if carry?
bad:
    popad
    mov eax,ERROR
    ret
  .endif
  xor ecx,ecx
  mov cx,ax
  shl ecx,4
   ;ecx = linear addr
  mov [esi].dma_s.sel,dx

  mov eax,ecx
  mov ebx,ecx
  shr eax,16
  add ecx,[esi].dma_s.siz
  dec ecx  ;check last byte in DMA buffer
  shr ecx,16
  .if cl!=al
    .if siz==128
      dec cl
      .if cl==al
        jmp ok
      .endif
    .endif
    shl ecx,16
    mov [esi].dma_s.phys,ecx  ;linear addr
  .else
ok:
    mov [esi].dma_s.phys,ebx  ;linear addr
    mov dx,[esi].dma_s.sel
    mov ebx,[esi].dma_s.siz
    shr ebx,4    ;paragraph size
    .if [esi].dma_s.siz & 0fh
      inc ebx
    .endif
    mov ax,102h  ;resize DOS block
    int 31h      ;resize block
  .endif
  popad
  xor eax,eax
  ret
_alloc endp

dma_free proc,dmas:dword
  pushad
  mov esi,dmas
  mov ax,101h  ;free DOS ram
  mov dx,[esi].dma_s.sel
  int 31h
  .if carry?
    popad
    mov eax,ERROR
    ret
  .endif
  popad
  xor eax,eax
  ret
dma_free endp

end
[ RETURN TO DIRECTORY ]