;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