summaryrefslogtreecommitdiffstats
path: root/private/mvdm/vdd/samples/sample2/16bits/16bits.asm
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/vdd/samples/sample2/16bits/16bits.asm')
-rw-r--r--private/mvdm/vdd/samples/sample2/16bits/16bits.asm217
1 files changed, 217 insertions, 0 deletions
diff --git a/private/mvdm/vdd/samples/sample2/16bits/16bits.asm b/private/mvdm/vdd/samples/sample2/16bits/16bits.asm
new file mode 100644
index 000000000..093e69e91
--- /dev/null
+++ b/private/mvdm/vdd/samples/sample2/16bits/16bits.asm
@@ -0,0 +1,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