📄 _dma.asm
字号:
;****************************************************************************;*;* 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.;*;**************************************************************************** IDEALinclude "scitech.mac" ; Memory model macrosheader _dma ; Set up memory modelbegdataseg _dma ; Start of data segmentcpublic _PM_DMADataStart; DMA register I/O addresses for channels 0-7 (except 4)DMAC_page db 087h,083h,081h,082h, -1,08Bh,089h,08AhDMAC_addr db 000h,002h,004h,006h, -1,0C4h,0C8h,0CChDMAC_cnt db 001h,003h,005h,007h, -1,0C6h,0CAh,0CEhDMAC_mask db 00Ah,00Ah,00Ah,00Ah, -1,0D4h,0D4h,0D4hDMAC_mode db 00Bh,00Bh,00Bh,00Bh, -1,0D6h,0D6h,0D6hDMAC_FF db 00Ch,00Ch,00Ch,00Ch, -1,0D8h,0D8h,0D8hcpublic _PM_DMADataEndenddataseg _dmabegcodeseg _dma ; Start of code segmentifdef flatmodelcpublic _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 retcprocend;----------------------------------------------------------------------------; 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 retcprocend;----------------------------------------------------------------------------; 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 retcprocend;----------------------------------------------------------------------------; 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 retcprocendcpublic _PM_DMACodeEndendifendcodeseg _dma END ; End of module
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -