; dma.asm
;
; Robert Östling, 2002-03-14

%define _dma_asm 0


[bits 32]
[section .text]


%include "dma.inc"


global	dma_transfer


; dma_transfer
;
; ecx = page:offset
; bl = channel
; bh = read (0 = false, 1 = true)
; esi = count
;
; Returns:
; All register unchanged




dma_transfer:
		push	eax
		push	edx
		push	esi

		cli					; leave me alone! :)

		or	bh,bh				; read?
		jz	.dont_read

		mov	bh,bl
		add	bh,0x48
		jmp	short .read
.dont_read:
		mov	bh,bl
		add	bh,0x44
.read:
		dec	esi

		movzx	eax,bl
		mov	dx,word[(eax*2)+dma_mask_reg]
		mov	al,bl
		or	al,0x04
		out	dx,al

		movzx	eax,bl
		mov	dx,word[(eax*2)+dma_clear_reg]
		mov	al,0
		out	dx,al

		movzx	eax,bl
		mov	dx,word[(eax*2)+dma_mode_reg]
		mov	al,bh
		out	dx,al

		movzx	eax,bl
		mov	dx,word[(eax*2)+dma_addr_port]
		mov	al,cl
		out	dx,al
		mov	al,ch
		out	dx,al

		movzx	eax,bl
		mov	dx,word[(eax*2)+dma_page_port]
		mov	eax,ecx
		shr	eax,16
		out	dx,al

		movzx	eax,bl
		mov	dx,word[(eax*2)+dma_count_port]
		mov	eax,esi
		out	dx,al
		mov	al,ah
		out	dx,al

		movzx	eax,bl
		mov	dx,word[(eax*2)+dma_mask_reg]
		mov	al,bl
		out	dx,al

		sti

		pop	esi
		pop	edx
		pop	eax
		ret


[section .data]

dma_mask_reg	dw	0x0a,0x0a,0x0a,0x0a,0xd4,0xd4,0xd4,0xd4
dma_mode_reg	dw	0x0b,0x0b,0x0b,0x0b,0xd6,0xd6,0xd6,0xd6
dma_clear_reg	dw	0x0c,0x0c,0x0c,0x0c,0xd8,0xd8,0xd8,0xd8

dma_page_port	dw	0x87,0x83,0x81,0x82,0x8f,0x8b,0x89,0x8a
dma_addr_port	dw	0x00,0x02,0x04,0x06,0xc0,0xc4,0xc8,0xcc
dma_count_port	dw	0x01,0x03,0x05,0x07,0xc2,0xc6,0xca,0xce
