summaryrefslogtreecommitdiffstats
path: root/private/mvdm/vdd/samples/sample2/16bits/16bits.asm
blob: 093e69e914a7ccefaa9681c124baf00c9b663ba1 (plain) (blame)
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
    TITLE Sample 16 Bits DOS application
;---------------------------------------------------------------;
;
    include 16bits.inc

    DOSSEG
    .MODEL SMALL

    .STACK 100h

    .DATA


DMAWriteBuffer	label	byte
	    db	    64 dup (?)
DMA_BUFFER_SIZE     equ $ - DMAWriteBuffer

DMAReadBuffer	 label	 byte
	    db	    DMA_BUFFER_SIZE dup (?)

MIOPattern  label   byte
	    db	    00, 0FFh, 0AAh, 055h
MIOPATTERN_SIZE equ	$ - MIOPattern

public	start

    .CODE
start:
    jmp     short RealStart
OldVector   label   dword
    dd	    ?
DMACompleted db     ?

RealStart:
    mov     ax,@DATA
    mov     ds,ax
    mov     es,ax
    assume  ds:@DATA, es:@DATA

;Hook interrupt(DMA terminate count notification)
    push    ds
    mov     al, DMA_INTERRUPT
    mov     ah, 35h
    int     21h
    mov     word ptr cs:OldVector, bx
    mov     word ptr cs:OldVector + 2, es
    mov     dx, offset ISRDMACompleted
    mov     ax, cs
    mov     ds, ax
    mov     al, DMA_INTERRUPT
    mov     ah, 25h
    int     21h
    pop     ds


;VDD operation.
;(1). Hook the I/O port.
;(2). Keep the port status up-to-date if a write operation is performed
;     by 16 bits application(this program).
;(3). Simulate DMA operation and generate a fake interrupt for 16bits
;     applicatiion if the DMA operation reaches its TC.
;
;
;16bits application
;(1). Output one byte to the port and then request DMA operation.
;(2). Wait for DMA operation completed.
;(3). goto step (1) if there are more data to be transferred.
;Note that the given I/O must be a R/W port.

;Here we do a DMA write operation upon I/O mapped I/O
    mov     cx, DMA_BUFFER_SIZE
    mov     si, offset DMAWriteBuffer
DMATransferLoop_Fast:
    mov     dx, IO_PORT_DMA
    mov     al, cl
    out     dx, al			;write I/O the current count
    cli
    mov     cs:DMACompleted, FALSE	;reset TC flag
    sti
;channel #1, write op, no auto init, addr inc, single transfer
    mov     al, 01000101B
    call    SetupDMAOperation
;Fire the DMA WRITE operation, this will cause VDD to gain control
;and start DMA operation.
    mov     dx, IO_PORT_FIRE_DMA_FAST
    out     dx, al
;In real world(there is a real hardware adapter), we won't do this
;idle loop, rather, we can do something useful(like, read the DMA current
;count and display the progress and so forth)provided that we can regain
;control while DMA operation is in progress(VDD spawns a new thread to
;handle DMA operation and returns to us immediately)
;
;Since we are simulating DMA operation without hardware, we always
;start the DMA operation with transfer count set to 1 byte. In reality
;this is should not be the case because it will slow down the data transfer.

WaitForDMA_Fast:
    cmp     cs:DMACompleted, TRUE
    jnz	    WaitForDMA_Fast
    inc     si
    loop    DMATransferLoop_Fast
;
;Now do a DMA read operation
    mov     cx, DMA_BUFFER_SIZE
    mov     si, offset DMAWriteBuffer
    mov     di, offset DMAReadBuffer
DMATransferLoop_Slow:
;channel #1, read op, no auto init, addr inc, single transfer
    mov     al, 01001001B
    cli
    mov     cs:DMACompleted, FALSE
    sti
    call    SetupDMAOperation
;Fire the DMA READ operation
    mov     dx, IO_PORT_FIRE_DMA_SLOW
    out     dx, al
WaitForDMA_Slow:
    cmp     cs:DMACompleted, TRUE
    jne     WaitForDMA_Slow
    mov     dx, IO_PORT_DMA
    in	    al, dx
    mov     [di], al
    inc     di				;advance our buffer
    inc     si				;and the DMA buffer
    loop    DMATransferLoop_Slow
;
;The DMAWriteBuffer and DMAReadBuffer should have the same contents.
;If they don't, it failed. ....


;Memory mapped I/O
    mov     ax, MIO_SEGMENT
    mov     es, ax
    mov     bx, MIOPATTERN_SIZE
    mov     si, offset MIOPattern

MIO_Loop:
    cld
    lodsb				;get next pattern
    mov     cx, MIO_PORT_RANGE
    mov     di, MIO_PORT_FIRST
rep stosb				;fill all I/O with the pattern
    mov     cx, MIO_PORT_RANGE
    dec     di
    std
repe	scasb				;
    je	    @F
;   call    ErrorMIO			;if any i/o failed,
@@:
    dec     bx				;next pattern
    jnz     MIO_Loop

;Before terminate, retsore everything we have touched
    push    ds
    lds     dx, cs:OldVector
    mov     al, DMA_INTERRUPT
    mov     ah, 25h
    int     21h
    pop     ds
    mov     ah, 04Ch
    int     21h

;-------------------------------------------------------;
;Setup DMA operation
;Input: ds:si = seg:offset of memeory address
;	al = DMA mode
;output: NONE
;Modified: AX, DX
;-------------------------------------------------------;
SetupDMAOperation proc
    push    cx
    mov     dx, DMA_PORT_FLIPFLOP
    out     dx, al
    mov     dx, DMA_PORT_MODE		    ;more register
    out     dx, al
    mov     ax, ds			    ;transfer address -> page:offset
    mov     cl, 4			    ;page: A16 ~ A19, offset A0 ~ A15
    rol     ax, cl
    mov     ch, al
    and     al, 0F0h
    add     ax, si
    jnc     @F
    inc     ch
@@:
    mov     dx, DMA_PORT_ADDR
    out     dx, al			    ;offset lower byte
    mov     al, ah
    out     dx, al			    ;and higher byte
    mov     dx, DMA_PORT_PAGE		    ;page register
    mov     al, ch
    and     al, 0Fh			    ;only 4 bits allowed
    out     dx, al
    mov     al, 1			    ;single transfer, one byte
    mov     dx, DMA_PORT_COUNT
    out     dx, al
    dec     al
    out     dx, al			    ;higher byte set to 0
    mov     dx, DMA_PORT_REQUEST	    ;request channel #1
    mov     al, 00000101B
    out     dx, al
    mov     dx, DMA_PORT_SNGLE_MASK	    ;start DMA transfer
    mov     al, 00000001B
    out     dx, al
    pop     cx
    ret
SetupDMAOperation endp


ISRDMACompleted proc	far
    mov     byte ptr DMACompleted, TRUE
    mov al, 20h
    out 20h, al
    out 0A0h, al
    iret
ISRDMACompleted	endp

END start