1 ;****************************************************************************
3 ;* SciTech OS Portability Manager Library
5 ;* ========================================================================
7 ;* The contents of this file are subject to the SciTech MGL Public
8 ;* License Version 1.0 (the "License"); you may not use this file
9 ;* except in compliance with the License. You may obtain a copy of
10 ;* the License at http://www.scitechsoft.com/mgl-license.txt
12 ;* Software distributed under the License is distributed on an
13 ;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 ;* implied. See the License for the specific language governing
15 ;* rights and limitations under the License.
17 ;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 ;* The Initial Developer of the Original Code is SciTech Software, Inc.
20 ;* All Rights Reserved.
22 ;* ========================================================================
24 ;* Language: 80386 Assembler, TASM 4.0 or NASM
25 ;* Environment: 16/32 bit Ring 0 device driver
27 ;* Description: Assembler support routines for ISA DMA controller.
29 ;****************************************************************************
33 include "scitech.mac" ; Memory model macros
35 header _dma ; Set up memory model
37 begdataseg _dma ; Start of data segment
39 cpublic _PM_DMADataStart
41 ; DMA register I/O addresses for channels 0-7 (except 4)
43 DMAC_page db 087h,083h,081h,082h, -1,08Bh,089h,08Ah
44 DMAC_addr db 000h,002h,004h,006h, -1,0C4h,0C8h,0CCh
45 DMAC_cnt db 001h,003h,005h,007h, -1,0C6h,0CAh,0CEh
46 DMAC_mask db 00Ah,00Ah,00Ah,00Ah, -1,0D4h,0D4h,0D4h
47 DMAC_mode db 00Bh,00Bh,00Bh,00Bh, -1,0D6h,0D6h,0D6h
48 DMAC_FF db 00Ch,00Ch,00Ch,00Ch, -1,0D8h,0D8h,0D8h
50 cpublic _PM_DMADataEnd
54 begcodeseg _dma ; Start of code segment
58 cpublic _PM_DMACodeStart
60 ;----------------------------------------------------------------------------
61 ; void PM_DMACDisable(int channel);
62 ;----------------------------------------------------------------------------
63 ; Masks DMA channel, inhibiting DMA transfers
64 ;----------------------------------------------------------------------------
65 cprocstart PM_DMACDisable
71 mov ecx,[channel] ; ECX indexes DMAC register tables
72 mov dh,0 ; DH = 0 for DMAC register port access
75 or al,100b ; AL = (channel & 3) | "set mask bit"
76 mov dl,[DMAC_mask+ecx]
83 ;----------------------------------------------------------------------------
84 ; void PM_DMACEnable(int channel);
85 ;----------------------------------------------------------------------------
86 ; Unmasks DMA channel, enabling DMA transfers
87 ;----------------------------------------------------------------------------
88 cprocstart PM_DMACEnable
94 mov ecx,[channel] ; ECX indexes DMAC register tables
95 mov dh,0 ; DH = 0 for DMAC register port access
97 and al,11b ; AL = (channel & 3), "set mask bit"=0
98 mov dl,[DMAC_mask+ecx]
105 ;----------------------------------------------------------------------------
106 ; void PM_DMACProgram(int channel,int mode,ulong bufferPhys,int count);
107 ;----------------------------------------------------------------------------
108 ; Purpose: Program DMA controller to perform transfer from first 16MB
109 ; based on previously selected mode and channel. DMA transfer may be enabled
110 ; by subsequent call to PM_DMACEnable.
112 ; Entry: channel - DMA channel in use (0-7)
113 ; mode - Selected DMAMODE type for transfer
114 ; buffer - 32-bit physical address of DMA buffer
115 ; count - DMA byte count (1-65536 bytes)
116 ;----------------------------------------------------------------------------
117 cprocstart PM_DMACProgram
119 ARG channel:UINT, mode:UINT, bufferPhys:ULONG, count:UINT
123 cli ; Disable interrupts
125 ; Mask DMA channel to disable it
127 mov ebx,[channel] ; EBX indexes DMAC register tables
128 mov dh,0 ; DH = 0 for DMAC register port access
131 or al,100b ; AL = (channel & 3) | "set mask bit"
132 mov dl,[DMAC_mask+ebx]
135 ; Generate IOW to clear FF toggle state
141 ; Compute buffer address to program
143 mov eax,[bufferPhys] ; AX := DMA address offset
145 shr ecx,16 ; CL := bufferPhys >> 16 (DMA page)
146 mov esi,[count] ; ESI = # of bytes to transfer
147 cmp ebx,4 ; 16-bit channel?
148 jb @@WriteDMAC ; No, program DMAC
149 shr eax,1 ; Yes, convert address and count
150 shr esi,1 ; to 16-bit, 128K/page format
152 ; Set the DMA address word (bits 0-15)
155 mov dl,[DMAC_addr+ebx]
160 ; Set DMA transfer count
163 dec eax ; ESI = # of bytes to transfer - 1
164 mov dl,[DMAC_cnt+ebx]
169 ; Set DMA page byte (bits 16-23)
172 mov dl,[DMAC_page+ebx]
175 ; Set the DMA channel mode
179 or al,[BYTE mode] ; EAX = (channel & 3) | mode
180 mov dl,[DMAC_mode+ebx]
183 pop eax ; SMP safe interrupt state restore!
192 ;----------------------------------------------------------------------------
193 ; ulong PMAPI PM_DMACPosition(int channel);
194 ;----------------------------------------------------------------------------
195 ; Returns the current position in a dma transfer. Interrupts should be
196 ; disabled before calling this function.
197 ;----------------------------------------------------------------------------
198 cprocstart PM_DMACPosition
203 mov ecx,[channel] ; ECX indexes DMAC register tables
204 mov dh,0 ; DH = 0 for DMAC register port access
206 ; Generate IOW to clear FF toggle state
214 ; Now read the current position for the channel
217 mov dl,[DMAC_cnt+ebx]
222 mov ch,al ; ECX := first count read
226 xchg al,ah ; EAX := second count read
230 cmp ebx,4 ; 16-bit channel?
231 jb @@Exit ; No, we are done
232 shl eax,1 ; Yes, adjust to byte address
240 cpublic _PM_DMACodeEnd