| ;**************************************************************************** |
| ;* |
| ;* 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 |