;----------------------------------------------------------;
; BOS kernel                Christoffer Bubach, 2004-2005. ;
;----------------------------------------------------------;
;                                                          ;
;    DMA transfer code.                                    ;
;                                                          ;
;----------------------------------------------------------;


;------------------------------------------;
;  Lookup table for DMA controller ports   ;
;------------------------------------------;
    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


;-----------------------------------;
;   dma transfer                    ;
;                                   ;
;  in:  ecx = page:offset           ;
;       bl  = channel               ;
;       bh  = 1=read, 0=write       ;
;       esi = count                 ;
;                                   ;
;  out: nothing.                    ;
;-----------------------------------;
dma_transfer:
         push    eax
         push    edx
         push    esi
         cli
         or      bh, bh
         jz      .dont_read

         mov     bh, bl
         add     bh, 0x48
         jmp     .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                              ; disable the channel

         movzx   eax, bl
         mov     dx, word [(eax*2)+dma_clear_reg]
         mov     al, 0
         out     dx, al                              ; initialize flip-flop

         movzx   eax, bl
         mov     dx, word [(eax*2)+dma_mode_reg]
         mov     al, bh
         out     dx, al                              ; set DMA mode

         movzx   eax, bl
         mov     dx, word [(eax*2)+dma_addr_port]
         mov     al, cl
         out     dx, al                              ; write low offset part
         mov     al, ch
         out     dx, al                              ; and high offset part

         movzx   eax, bl
         mov     dx, word [(eax*2)+dma_page_port]
         mov     eax, ecx
         shr     eax, 16
         out     dx, al                              ; write page.

         movzx   eax, bl
         mov     dx, word [(eax*2)+dma_count_port]
         mov     eax, esi
         out     dx, al                              ; low count
         mov     al, ah
         out     dx, al                              ; high count

         movzx   eax, bl
         mov     dx, word [(eax*2)+dma_mask_reg]
         mov     al, bl
         out     dx, al                              ; enable channel

         sti
         pop     esi
         pop     edx
         pop     eax
         ret