Obsah
DMA (direct memory access)
DMA umožňuje využít až 8 kanálú pro rychlej přenost dat ze zařízení do paměti
nebo obráceně.
Múže používat pouze prvních 16 MiB paměti.
DMA_MODE_DEMAND = 0
DMA_MODE_SINGLE = 40h
DMA_MODE_BLOCK = 80h
DMA_MODE_CASCADE = 0C0h
DMA_MODE_INC = 0
DMA_MODE_DEC = 20h
DMA_MODE_AUTOINIT = 10h
DMA_MODE_VERIFY = 0
DMA_MODE_READ = 6
DMA_MODE_WRITE = 0Ah
DMA_PORTOFS_MODE = 0
DMA_PORTOFS_MASK = 1
DMA_PORTOFS_CLEARFF = 2
DMA_PORTOFS_PAGE = 3
DMA_PORTOFS_ADR = 4
DMA_PORTOFS_COUNT = 5
DMA_ERC_INVALID_CHANNEL_NUMBER = 13h
DMA_ERC_INVALID_MEMORY_ADDRESS = 14h
DMA_ERC_INVALID_COUNT = 15h
dma_ports_const:
// mode, mask, clear flip-flop, page, address, count, -, -
// DMA 0
db 0Bh, 0Ah, 0Ch, 87h, 0, 1, 0, 0
// DMA 1
db 0Bh, 0Ah, 0Ch, 83h, 2, 3, 0, 0
// DMA 2
db 0Bh, 0Ah, 0Ch, 81h, 4, 5, 0, 0
// DMA 3
db 0Bh, 0Ah, 0Ch, 82h, 6, 7, 0, 0
// DMA 4
db 0D6h, 0D4h, 0D8h, 8Fh, 0C0h, 0C2h, 0, 0
// DMA 5
db 0D6h, 0D4h, 0D8h, 8Bh, 0C4h, 0C6h, 0, 0
// DMA 6
db 0D6h, 0D4h, 0D8h, 89h, 0C8h, 0CAh, 0, 0
// DMA 7
db 0D6h, 0D4h, 0D8h, 8Ah, 0CCh, 0CEh, 0, 0
h_dma_init:
ret
l_h_dma_read_xchn:
mov al, DMA_ERC_INVALID_CHANNEL_NUMBER
ret
l_h_dma_read_xmemadr:
mov al, DMA_ERC_INVALID_MEMORY_ADDRESS
ret
l_h_dma_read_xcount:
mov al, DMA_ERC_INVALID_COUNT
ret
// DMA Read - transfer data from device to memory
// IN: al = channel, ah = mode
// ecx = count, ebx = memory addr
// DESTROY: edx, esi
// OUT: al = 0 || errorcode
h_dma_read:
or ah, DMA_MODE_READ
l_h_dma_common: // h_dma_write jumps here too
cmp al, 8
jnb l_h_dma_read_xchn
movzx esi, al
shl esi, 3 // esi = channel offset
cmp ebx, 0xFFFFFF
ja l_h_dma_read_xmemadr
dec ecx
cmp ecx, 65536
jnb l_h_dma_read_xcount
pushfd
cli
// Disable Channel
and al, 3
xor edx, edx
or al, 4 // al = 4 + (channel & 3)
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_MASK]
out dx, al
// Set Transfer Count
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_CLEARFF]
out dx, al
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_COUNT]
mov al, cl
out dx, al
call delay
mov al, ch
out dx, al
// Set Memory Address
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_CLEARFF]
out dx, al
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_ADR]
mov al, bl
out dx, al
call delay
mov al, bh
out dx, al
shr ebx, 16
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_PAGE]
mov al, bl
out dx, al
// Set Mode
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_MODE]
mov al, ah
out dx, al
// Enable Channel
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_MASK]
mov eax, esi
shr eax, 3
and al, 3
out dx, al
popfd
mov al, 0
ret
// DMA Write - transfer data from memory to device
// IN: al = channel, ah = mode
// ecx = count, ebx = memory addr
// DESTROY: edx, esi
// OUT: al = 0 || errorcode
h_dma_write:
or ah, DMA_MODE_WRITE
jmp l_h_dma_common
// Finalize transfer
// IN: al = channel
// DESTROY: eax, edx, esi
h_dma_release:
and al, 7
movzx esi, al
shl esi, 3 // esi = channel offset
and al, 3
xor edx, edx
or al, 4 // al = 4 + (channel & 3)
mov dl, [cs:offset dma_ports_const + esi + DMA_PORTOFS_MASK]
out dx, al
ret