-
Notifications
You must be signed in to change notification settings - Fork 6
/
dma.386
513 lines (445 loc) · 13.3 KB
/
dma.386
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
;***************************************************************************
;
; Copyright (c) 1997, 1998 Timpanogas Research Group, Inc. All Rights
; Reserved.
;
; AUTHOR : Jeff V. Merkey
; FILE : DMA.386
; DESCRIP : 8290 DMA Code for MANOS v1.0
; DATE : November 12, 1997
;
;
;***************************************************************************
.486P ; select the processor
model flat
;========== DMA Equates for DMA amd PAGE registers =========
;NOTES: With 8 bit DMA, the lower WORD (bits 15-0) are placed into
; the address registers of the DMA, and the Page register is the next
; most significant byte (bits 23-16). With WORD DMA moves (channels 5-7),
; address bits 16-1 are placed in the address registers, while 23-17 are
; put in the page register. Bit 16 is ignored by the page register.
;
;
; DMA 1 Port addresses and page registers
DMA10Add EQU 00h ; Ch 0 Address
DMA10Cnt EQU 01h ; Ch 0 Word Count
DMA11Add EQU 02h ; Ch 1 Address
DMA11Cnt EQU 03h ; Ch 1 Word Count
DMA12Add EQU 04h ; Ch 2 Address
DMA12Cnt EQU 05h ; Ch 2 Word Count
DMA13Add EQU 06h ; Ch 3 Address
DMA13Cnt EQU 07h ; Ch 3 Word Count
DMA1StatCmd EQU 08h ; Read Status/Write Command
DMA1RqReg EQU 09h ; Read/Write DMA Rq Register
DMA1RCmdWbm EQU 0Ah ; Read Command/Write Single bit mask
DMA1Mode EQU 0Bh ; Read/Write Mode register
DMA1FF EQU 0Ch ; Writing this address clears byte ptr flip flop
DMA1Clear EQU 0Dh ; Write causes MASTER Clear (Read from Temp Reg)
DMA1ClrMode EQU 0Eh ; Rd clears mode reg count/Wr Clr ALL mask bits
DMA1MskBts EQU 0Fh ; Read/Write DMA Rq Mask Register
; DMA 2 Port addresses
DMA20Add EQU 0C0h ; Ch 0 Address
DMA20Cnt EQU 0C2h ; Ch 0 Word Count
DMA21Add EQU 0C4h ; Ch 1 Address
DMA21Cnt EQU 0C6h ; Ch 1 Word Count
DMA22Add EQU 0C8h ; Ch 2 Address
DMA22Cnt EQU 0CAh ; Ch 2 Word Count
DMA23Add EQU 0CCh ; Ch 3 Address
DMA23Cnt EQU 0CEh ; Ch 3 Word Count
DMA2StatCmd EQU 0D0h ; Read Status/Write Command
DMA2RqReg EQU 0D2h ; Read/Write DMA Rq Register
DMA2RCmdWbm EQU 0D4h ; Read Command/Write Single bit mask
DMA2Mode EQU 0D6h ; Read/Write Mode register
DMA2FF EQU 0D8h ; Writing this address clears byte ptr flip flop
DMA2Clear EQU 0DAh ; Write causes MASTER Clear (Read from Temp Reg)
DMA2ClrMode EQU 0DCh ; Rd clears mode reg count/Wr Clr ALL mask bits
DMA2MskBts EQU 0DEh ; Read/Write DMA Rq Mask Register
;DMA Page register by DRQ/DACK number
DMAPage0 EQU 87h ; DMA DACK0 Page register
DMAPage1 EQU 83h ; DACK1 (etc. etc. etc.)
DMAPage2 EQU 81h
DMAPage3 EQU 82h
DMAPage5 EQU 8Bh
DMAPage6 EQU 89h
DMAPage7 EQU 8Ah
CGROUP GROUP _TEXT
DGROUP GROUP _DATA
ASSUME cs:_TEXT, ds:_DATA, es:_DATA, fs:_DATA
_DATA SEGMENT PUBLIC USE32 'DATA'
_DATA ENDS
_TEXT SEGMENT PUBLIC USE32 'CODE'
ASSUME cs:_TEXT, ds:_DATA, es:_DATA, fs:_DATA
;
; The following code sets up the initial DMA channel values for
; both chips to most probable use. Includes cascade mode for CH4
; which is DMA channel 0 on chip 2
;
align 16
public InitDMA
InitDMA:
mov al, 04 ; Master disable
out DMA1StatCmd, al
out DMA2StatCmd, al
xor al, al ; MASTER CLEAR (same as hardware reset)
out DMA1Clear, al
out DMA2Clear, al
xor al, al ; All commands set to default (0)
out DMA1StatCmd, al
out DMA2StatCmd, al
mov al, 40h ; CH 0 DMA 1
out DMA1Mode, al ;
mov al, 0C0h ; CH 0 DMA 2 (Cascade Mode)
out DMA2Mode, al ;
mov al, 41h ; CH 1 DMA 1 & 2
out DMA1Mode, al ;
out DMA2Mode, al ;
mov al, 42h ; CH 2 DMA 1 & 2
out DMA1Mode, al ;
out DMA2Mode, al ;
mov al, 43h ; CH 3 DMA 1 & 2
out DMA1Mode, al ;
out DMA2Mode, al ;
xor al, al
out DMA1ClrMode, al ; Enable ALL DMA 1 Channels
out DMA2ClrMode, al ; Enable ALL DMA 2 Channels
ret
;
;-----------------------------------------------------------
; The following code sets up a single DMA channel for the caller.
; DMA is crippled because it can't move across 64K physical
; boundries. It's the caller's responsibility to know if he is
; crossing a boundry! If he does, this will wrap around over the segment!!!
; This code is completely reentrant.
; There is only one call for DMA set up.
; The caller sets the type of DMA operation (In, Out, Verify).
; For channels 5,6 & 7, the address & count must be divided by
; two for the DMA hardware. This routine does this for you!
; Algorythm - Put mode byte bits (except channel bits) in BL, then jump to
; correct routine for that channel. The call will allow set up of
; all the differnet types of DMA modes for read and write with this
; single call. The call:
;
; DmaSetUp(addr, size, channel, type, mode)
;
; addr is physical memory address
; size is nBytes to move (STILL bytes for word xfers, we do math)
; channel (0,1,2,3,5,6,7)
; type - 0 = Verify, 1 = In (Write Mem), 2 = Out (Read memory)
; mode - 0 Demand Mode, 1 Single Cycle, (Disk I/O uses 1)
; 2 Block, 3 Cascade
;
align 16
public DMASetUp
DMASetUp:
push ebp
push edi
push esi
push ebx
mov eax, [esp + 36] ; mode
cmp eax, 04 ; Mode must be < 4
jb DMAModeOK
mov eax, -2 ; mode error
jmp DMAEnd
DMAModeOK:
shl eax, 6 ; Move Mode bits to 6 and 7
mov bl, al ; Put it in bl
mov eax, [esp + 32] ; get type
and bl, 0C0h ; Set to Verify by default (low bits 0)
cmp eax, 0 ; Check fType (Verify?)
je DMASelect ; Yes
cmp eax, 1 ; In? (Write)
je DMAWrite ; Yes (if no then fall thru to Read)
DMARead:
or bl, 00001000b ; or read command to bl (out)
jmp DMASelect
DMAWrite:
or bl, 00000100b ; or write command to bl (in)
DMASelect:
mov eax, [esp + 28] ; Jump table for channel selection
cmp eax, 0 ;
je DMA0
cmp eax, 1
je DMA1
cmp eax, 2
je DMA2
cmp eax, 3
je DMA3
cmp eax, 5
je DMA5
cmp eax, 6
je DMA6
cmp eax, 7
je DMA7
mov eax, -1
jmp DMAEnd
DMA0:
cli
mov al, 00000100b ; channel 0 Set Mask for DRQ
out DMA1RCmdWbm, al ;
mov al, 00000000b ; CH0 (CH is last 2 bits)
or al, bl ; or with MODE
out DMA1Mode, al
out DMA1FF, al ; Clear FlipFLop (Val in al irrelevent)
mov eax, [esp + 20] ; PhyMem
out DMA10Add, al ; Lo byte address
shr eax, 8
out DMA10Add, al ; Hi Byte
shr eax, 8
out DMAPage0, al ; Highest byte (to page register)
mov eax, [esp + 24] ; size
dec eax
out DMA10Cnt, al
shr eax, 8
out DMA10Cnt, al
mov al, 00000000b ; channel 0 Clear Mask for DRQ
out DMA1RCmdWbm, al
sti
xor eax, eax
jmp DMAEnd
DMA1:
cli
mov al, 00000101b ; channel 1 Set Mask for DRQ
out DMA1RCmdWbm, al
mov al, 00000001b ; CH1
or al, bl ; or with MODE/TYPE
out DMA1Mode, al
out DMA1FF, al ; Clear FlipFLop (Val in al irrelevent)
mov eax, [esp + 20] ; PhyMem
out DMA11Add, al ; Lo byte address
shr eax, 8
out DMA11Add, al ; Hi Byte
shr eax, 8
out DMAPage1, al ; Highest byte (to page register)
mov eax, [esp + 24] ; size
dec eax
out DMA11Cnt, al
shr eax, 8
out DMA11Cnt, al
mov al, 00000001b ; channel 1 Clear Mask for DRQ
out DMA1RCmdWbm, al
sti
xor eax, eax
jmp DMAEnd
DMA2:
cli
mov al, 00000110b ; channel 2 Set Mask for DRQ
out DMA1RCmdWbm, al
mov al, 00000010b ; CH2
or al, bl ; or with MODE
out DMA1Mode, al
out DMA1FF, al ; Clear FlipFLop (Val in al irrelevent)
mov eax, [esp + 20] ; PhyMem
out DMA12Add, al ; Lo byte address
shr eax, 8
out DMA12Add, al ; Hi Byte
shr eax, 8
out DMAPage2, al ; Highest byte (to page register)
mov eax, [esp + 24] ; size
dec eax
out DMA12Cnt, al
shr eax, 8
out DMA12Cnt, al
mov al, 00000010b ; channel 2 Clear Mask for DRQ
out DMA1RCmdWbm, al
sti
xor eax, eax
jmp DMAEnd
DMA3:
cli
mov al, 00000111b ; channel 3 Set Mask for DRQ
out DMA1RCmdWbm, al
mov al, 00000011b ; CH3
or al, bl ; or with MODE
out DMA1Mode, al
out DMA1FF, al ; Clear FlipFLop (Val in al irrelevent)
mov eax, [esp + 20] ; PhyMem
out DMA13Add, al ; Lo byte address
shr eax, 8
out DMA13Add, al ; Hi Byte
shr eax, 8
out DMAPage3, al ; Highest byte (to page register)
mov eax, [esp + 24] ; size
dec eax
out DMA13Cnt, al
shr eax, 8
out DMA13Cnt, al
mov al, 00000011b ; channel 3 Clear Mask for DRQ
out DMA1RCmdWbm, al
sti
xor eax, eax
jmp DMAEnd
; NOTE: DMA channels 5-7 are on DMA2 and numbered 1-3 for chip select purposes
DMA5:
cli
mov al, 00000101b ; channel 1 DMA2 Set Mask for DRQ
out DMA2RCmdWbm, al
mov al, 00000001b ; CH1 on DMA 2
or al, bl ; or with MODE
out DMA2Mode, al
out DMA2FF, al ; Clear FlipFLop (Val in al irrelevent)
mov eax, [esp + 20] ; PhyMem
mov ebx, eax ; Save ebx for page
and eax, 0FFFFh ; Rid of all but lower 16
shr eax, 1 ; DIV by 2 for WORD Xfer (bits 16-1)
out DMA21Add, al ; Lo byte address
shr eax, 8
out DMA21Add, al ; Hi Byte
mov eax, ebx
shr eax, 15 ; We only need 23-17 for the page
out DMAPage5, al ; Highest byte (to page register)
mov eax, [esp + 24] ; size
shr eax, 1 ; DIV by 2 for WORD Xfer
dec eax ; One less word
out DMA21Cnt, al
shr eax, 8
out DMA21Cnt, al
mov al, 00000001b ; channel 1 Clear Mask for DRQ
out DMA2RCmdWbm, al
sti
xor eax, eax
jmp DMAEnd
;
DMA6:
cli
mov al, 00000110b ; channel 2 Set Mask for DRQ
out DMA2RCmdWbm, al
mov al, 00000010b ; CH2 on DMA 2
or al, bl ; or with MODE
out DMA2Mode, al
out DMA2FF, al ; Clear FlipFLop (Val in al irrelevent)
mov eax, [esp + 20] ; PhyMem
mov ebx, eax
and eax, 0FFFFh ; Rid of all but lower 16
shr eax, 1 ; DIV by 2 for WORD Xfer
out DMA22Add, al ; Lo byte address
shr eax, 8
out DMA22Add, al ; Hi Byte
mov eax, ebx
shr eax, 15
out DMAPage6, al ; Highest byte (to page register)
mov eax, [esp + 24] ; size
shr eax, 1 ; DIV by 2 for WORD Xfer
dec eax
out DMA22Cnt, al
shr eax, 8
out DMA22Cnt, al
mov al, 00000010b ; channel 2 Clear Mask for DRQ
out DMA2RCmdWbm, al
sti
xor eax, eax
jmp DMAEnd
;
DMA7:
cli
mov al, 00000111b ; channel 3 Set Mask for DRQ
out DMA2RCmdWbm, al
mov al, 00000011b ; CH3 on DMA 2
or al, bl ; or with MODE
out DMA2Mode, al
out DMA2FF, al ; Clear FlipFLop (Val in al irrelevent)
mov eax, [esp + 20] ; PhyMem
mov ebx, eax
and eax, 0FFFFh ; Rid of all but lower 16
shr eax, 1 ; DIV by 2 for WORD Xfer
out DMA23Add, al ; Lo byte address
shr eax, 8
out DMA23Add, al ; Hi Byte
mov eax, ebx
shr eax, 15
out DMAPage6, al ; Highest byte (to page register)
mov eax, [esp + 24] ; size
shr eax, 1 ; DIV by 2 for WORD Xfer
dec eax
out DMA23Cnt, al
shr eax, 8
out DMA23Cnt, al
mov al, 00000011b ; channel 3 Clear Mask for DRQ
out DMA2RCmdWbm, al
sti
xor eax, eax
DMAEnd:
pop ebx
pop esi
pop edi
pop ebp
ret
;------------------------------------------------------------
; GetDMACount returns the number of bytes or words left in the
; DMA count register for the channel specified. For channels
; 5-7 this will be the number of WORDS. For 0-3 this will be BYTES!
; Programmers should note (I should tell them) this value will read
; one less byte/word than is really in the channel. This is because
; 0 = 1 for set purposes. to move 64K, you actually set the
; channel 65,535.
;
; GetDMACount(channel, CountRet)
;
; channel (0,1,2,3,5,6,7)
; CountRet is a pointer to a Word (2 byte unsigned value) where
; the count will be returned. The count is number of WORDS-1
; for channels 5-7 and BYTES-1 for channels 0-3.
align 16
public GetDMACount
GetDMACount:
push ebp
push edi
push esi
push ebx
mov eax, [esp + 24] ; channel
mov esi, [esp + 20] ; return address for count
DMACSelect:
cmp eax, 0 ;
jne DMAC1
mov dx, DMA10Cnt ;
jmp DMACDoIt
DMAC1:
cmp eax, 1
jne DMAC2
mov dx, DMA11Cnt ;
jmp DMACDoIt
DMAC2:
cmp eax, 2
jne DMAC3
mov dx, DMA12Cnt ;
jmp DMACDoIt
DMAC3:
cmp eax, 3
jne DMAC5
mov dx, DMA13Cnt ;
jmp DMACDoIt
DMAC5:
cmp eax, 5
jne DMAC6
mov dx, DMA21Cnt ;
jmp DMACDoIt
DMAC6:
cmp eax, 6
jne DMAC7
mov dx, DMA22Cnt ;
jmp DMACDoIt
DMAC7:
mov dx, DMA23Cnt ;
cmp eax, 7
je DMACDoIt
mov eax, -1 ; No such channel!
pop ebx
pop esi
pop edi
pop ebp
ret
DMACDoIt:
cli
in al, dx ;
mov cl, al ;
in al, dx ;
mov ch, al ; CX has words/bytes left in DMA
sti ;
mov word ptr [esi], cx ;
xor eax, eax ; No Error
pop ebx
pop esi
pop edi
pop ebp
ret
_TEXT ENDS
END