diff options
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/pm/common/_dma.asm')
-rw-r--r-- | board/MAI/bios_emulator/scitech/src/pm/common/_dma.asm | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/pm/common/_dma.asm b/board/MAI/bios_emulator/scitech/src/pm/common/_dma.asm new file mode 100644 index 0000000..2b6e1e8 --- /dev/null +++ b/board/MAI/bios_emulator/scitech/src/pm/common/_dma.asm @@ -0,0 +1,246 @@ +;**************************************************************************** +;* +;* SciTech OS Portability Manager Library +;* +;* ======================================================================== +;* +;* The contents of this file are subject to the SciTech MGL Public +;* License Version 1.0 (the "License"); you may not use this file +;* except in compliance with the License. You may obtain a copy of +;* the License at http://www.scitechsoft.com/mgl-license.txt +;* +;* Software distributed under the License is distributed on an +;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +;* implied. See the License for the specific language governing +;* rights and limitations under the License. +;* +;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. +;* +;* The Initial Developer of the Original Code is SciTech Software, Inc. +;* All Rights Reserved. +;* +;* ======================================================================== +;* +;* Language: 80386 Assembler, TASM 4.0 or NASM +;* Environment: 16/32 bit Ring 0 device driver +;* +;* Description: Assembler support routines for ISA DMA controller. +;* +;**************************************************************************** + + IDEAL + +include "scitech.mac" ; Memory model macros + +header _dma ; Set up memory model + +begdataseg _dma ; Start of data segment + +cpublic _PM_DMADataStart + +; DMA register I/O addresses for channels 0-7 (except 4) + +DMAC_page db 087h,083h,081h,082h, -1,08Bh,089h,08Ah +DMAC_addr db 000h,002h,004h,006h, -1,0C4h,0C8h,0CCh +DMAC_cnt db 001h,003h,005h,007h, -1,0C6h,0CAh,0CEh +DMAC_mask db 00Ah,00Ah,00Ah,00Ah, -1,0D4h,0D4h,0D4h +DMAC_mode db 00Bh,00Bh,00Bh,00Bh, -1,0D6h,0D6h,0D6h +DMAC_FF db 00Ch,00Ch,00Ch,00Ch, -1,0D8h,0D8h,0D8h + +cpublic _PM_DMADataEnd + +enddataseg _dma + +begcodeseg _dma ; Start of code segment + +ifdef flatmodel + +cpublic _PM_DMACodeStart + +;---------------------------------------------------------------------------- +; void PM_DMACDisable(int channel); +;---------------------------------------------------------------------------- +; Masks DMA channel, inhibiting DMA transfers +;---------------------------------------------------------------------------- +cprocstart PM_DMACDisable + + ARG channel:UINT + + push ebp + mov ebp,esp + mov ecx,[channel] ; ECX indexes DMAC register tables + mov dh,0 ; DH = 0 for DMAC register port access + mov al,cl + and al,11b + or al,100b ; AL = (channel & 3) | "set mask bit" + mov dl,[DMAC_mask+ecx] + out dx,al + pop ebp + ret + +cprocend + +;---------------------------------------------------------------------------- +; void PM_DMACEnable(int channel); +;---------------------------------------------------------------------------- +; Unmasks DMA channel, enabling DMA transfers +;---------------------------------------------------------------------------- +cprocstart PM_DMACEnable + + ARG channel:UINT + + push ebp + mov ebp,esp + mov ecx,[channel] ; ECX indexes DMAC register tables + mov dh,0 ; DH = 0 for DMAC register port access + mov al,cl + and al,11b ; AL = (channel & 3), "set mask bit"=0 + mov dl,[DMAC_mask+ecx] + out dx,al + pop ebp + ret + +cprocend + +;---------------------------------------------------------------------------- +; void PM_DMACProgram(int channel,int mode,ulong bufferPhys,int count); +;---------------------------------------------------------------------------- +; Purpose: Program DMA controller to perform transfer from first 16MB +; based on previously selected mode and channel. DMA transfer may be enabled +; by subsequent call to PM_DMACEnable. +; +; Entry: channel - DMA channel in use (0-7) +; mode - Selected DMAMODE type for transfer +; buffer - 32-bit physical address of DMA buffer +; count - DMA byte count (1-65536 bytes) +;---------------------------------------------------------------------------- +cprocstart PM_DMACProgram + + ARG channel:UINT, mode:UINT, bufferPhys:ULONG, count:UINT + + enter_c + pushfd + cli ; Disable interrupts + +; Mask DMA channel to disable it + + mov ebx,[channel] ; EBX indexes DMAC register tables + mov dh,0 ; DH = 0 for DMAC register port access + mov al,bl + and al,11b + or al,100b ; AL = (channel & 3) | "set mask bit" + mov dl,[DMAC_mask+ebx] + out dx,al + +; Generate IOW to clear FF toggle state + + mov al,0 + mov dl,[DMAC_FF+ebx] + out dx,al + +; Compute buffer address to program + + mov eax,[bufferPhys] ; AX := DMA address offset + mov ecx,eax + shr ecx,16 ; CL := bufferPhys >> 16 (DMA page) + mov esi,[count] ; ESI = # of bytes to transfer + cmp ebx,4 ; 16-bit channel? + jb @@WriteDMAC ; No, program DMAC + shr eax,1 ; Yes, convert address and count + shr esi,1 ; to 16-bit, 128K/page format + +; Set the DMA address word (bits 0-15) + +@@WriteDMAC: + mov dl,[DMAC_addr+ebx] + out dx,al + mov al,ah + out dx,al + +; Set DMA transfer count + + mov eax,esi + dec eax ; ESI = # of bytes to transfer - 1 + mov dl,[DMAC_cnt+ebx] + out dx,al + mov al,ah + out dx,al + +; Set DMA page byte (bits 16-23) + + mov al,cl + mov dl,[DMAC_page+ebx] + out dx,al + +; Set the DMA channel mode + + mov al,bl + and al,11b + or al,[BYTE mode] ; EAX = (channel & 3) | mode + mov dl,[DMAC_mode+ebx] + out dx,al + + pop eax ; SMP safe interrupt state restore! + test eax,200h + jz @@1 + sti +@@1: leave_c + ret + +cprocend + +;---------------------------------------------------------------------------- +; ulong PMAPI PM_DMACPosition(int channel); +;---------------------------------------------------------------------------- +; Returns the current position in a dma transfer. Interrupts should be +; disabled before calling this function. +;---------------------------------------------------------------------------- +cprocstart PM_DMACPosition + + ARG channel:UINT + + enter_c + mov ecx,[channel] ; ECX indexes DMAC register tables + mov dh,0 ; DH = 0 for DMAC register port access + +; Generate IOW to clear FF toggle state + + mov al,0 + mov dl,[DMAC_FF+ebx] + out dx,al + xor eax,eax + xor ecx,ecx + +; Now read the current position for the channel + +@@ReadLoop: + mov dl,[DMAC_cnt+ebx] + out dx,al + in al,dx + mov cl,al + in al,dx + mov ch,al ; ECX := first count read + in al,dx + mov ah,al + in al,dx + xchg al,ah ; EAX := second count read + sub ecx,eax + cmp ecx,40h + jg @@ReadLoop + cmp ebx,4 ; 16-bit channel? + jb @@Exit ; No, we are done + shl eax,1 ; Yes, adjust to byte address + +@@Exit: leave_c + ret + +cprocend + + +cpublic _PM_DMACodeEnd + +endif + +endcodeseg _dma + + END ; End of module |