aboutsummaryrefslogtreecommitdiff
path: root/board/MAI/bios_emulator/scitech/src/pm/common/_dma.asm
blob: 2b6e1e8b561e9b6e0dddfa7e8ff2ab0be27aefd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
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