windows-nt/Source/XPSP1/NT/base/mvdm/sim16/sim16.asm
2020-09-26 16:20:57 +08:00

908 lines
17 KiB
NASM

;******************************************************************************
;
; Simulator 16
;
; Author : Chandan Chauhan
;
; Date : 1/28/91
;
;******************************************************************************
include incs.inc ; segment definitions
MAXSIZE EQU 1024 ; 1k length
Arg1 EQU [bp+6]
Arg2 EQU [bp+8]
WOW32_Buffer EQU [bp+6] ; buffer address
WOW32_Size EQU [bp+8] ; length of VDM memory
WOW32_Off EQU [bp+10] ; off of VDM memory
WOW32_Sel EQU [bp+12] ; sel of VDM memory
WOWStackNP EQU [bp+6] ; WOWStack
WOWStackOff EQU [bp+6]
WOWStackSel EQU [bp+8]
extrn Initialize:near
MAIN_DATA SEGMENT
PUBLIC TransmitPkt, ReceivePkt, ReceivePktPtr, RespPkt, ToWOW32Pkt
PUBLIC ACKPkt, NAKPkt, GetMemPkt, SetMemPkt, WAKEUPPkt
PUBLIC fReceive, fRxCount, fRxError, RxPktLen
PUBLIC fTxCount, fTransmitting
PUBLIC fInitTime
PUBLIC VDMAddress
PUBLIC WOWStack, WOW32Buffer
Reserved DB 16 DUP (0) ; reserved
TransmitPkt DD -1 ; packet being transmitted
TransmitPktLen DW 0 ; packet being transmitted
TransmitPktPtr DW 0 ; byte to Tx
ReceivePkt DB MAXSIZE DUP (0FFh) ; packet being received
ReceivePktPtr DW 0 ; packet being received
RespPkt DB MAXSIZE DUP (0FFh) ; packet being transmitted
ToWOW32Pkt DB 9 DUP (?) ; ToWOW32 packet
DB 0
WAKEUPPkt DB 9 DUP (0) ; WAKEUP packet
DB 0
ACKPkt DB 5 DUP (?) ; ACK packet
DB 0
NAKPkt DB 5 DUP (?) ; NAK packet
DB 0
GetMemPkt DB MAXSIZE DUP (?) ;***************
SetMemPkt DB MAXSIZE DUP (?) ;***************
VDMAddress DD -1 ; stores VDM sel:off
VDMLength DW -1 ; number of bytes
WOW32Buffer DD -1 ; ptr caller's buffer
WOWStack DD -1 ; ptr to caller's WOWStack
fTxCount DW 0
fTransmitting DW 0
fReceive DW 0
fRxCount DW 0
fRxError DW 0
fInitTime DW 0
fInitDLL DW 0
RxPktLen DW 0
Stack DW 256 DUP (?)
StackTop DW ?
OldSS DW ?
OldSP DW ?
Scratch DW ?
fStackUse DW -1
IntRoutines LABEL WORD
DW COMISR_MSR
DW COMISR_Transmit
DW COMISR_Receive
DW COMISR_LSR
HelloString DB cr, lf, 'WOW Simulator *****', cr, lf, lf
DB 'Hello, this is a test string !!!!!!!!!!', cr, lf
HelloStringLen EQU $ - HelloString
MAIN_DATA ENDS
MAIN_CODE SEGMENT
ASSUME CS:MAIN_CODE, DS:MAIN_DATA, ES:NOTHING
;*****************************************************************************
; S I M U L A T O R L A Y E R
;*****************************************************************************
;*****************************************************************************
;
; Sim32SendSim16
;
;*****************************************************************************
;***************
PROCEDURE Sim32SendSim16 PUBLIC, FAR
push bp ; save stack frame
mov bp, sp
pusha ; temps...
push ds ; temps...
push es ; temps...
mov bx, ds
mov ax, SEG MAIN_DATA
mov ds, ax
mov si, OFFSET WAKEUPPkt ; DS:SI -> WAKEUP packet
mov ax, WOWStackNP
mov WOWStack._off, ax
mov WOWStack._sel, bx
cmp fInitTime, 0
je Sim32SendSim16_Init
les bx, WOWStack ; ES:BX -> SS:SP of WOW VDM task
mov ax, es:[bx]._off ; get SP
mov [si].MEM_OFF, ax
mov ax, es:[bx]._sel ; get SS
mov [si].MEM_SEL, ax
call Xceive
Sim32SendSim16_Ret:
les bx, WOWStack ; ES:BX -> SS:SP of WOW VDM task
mov di, OFFSET ReceivePkt
mov ax, [di].ToWOW32_OFF
mov es:[bx]._off, ax
mov ax, [di].ToWOW32_SEL
mov es:[bx]._sel, ax
pop es ; temps...
pop ds ; temps...
popa ; temps...
mov sp, bp
pop bp
ret 2
Sim32SendSim16_Init:
call Receive
inc fInitTime
call Initialize
jmp SHORT Sim32SendSim16_Ret
Sim32SendSim16 ENDP
;*****************************************************************************
;
; Sim32GetVDMMemory
;
;*****************************************************************************
;***************
PROCEDURE Sim32GetVDMMemory PUBLIC, FAR
push bp ; save stack frame
mov bp, sp
pusha ; temps...
push ds ; temps...
push es ; temps...
mov bx, ds
mov ax, SEG MAIN_DATA
mov ds, ax
mov si, OFFSET GetMemPkt ; DS:SI -> ToWOW32 packet
mov ax, WOW32_Buffer ; get buffer's address
mov WOW32Buffer._off, ax
mov ax, bx
mov WOW32Buffer._sel, ax
mov ax, WOW32_Off
mov [si].MEM_OFF, ax
mov ax, WOW32_Sel
mov [si].MEM_SEL, ax
mov cx, WOW32_Size ; get the length
cmp cx, 3B6h
jg Sim32GetMem_Error
mov [si].MEM_LENGTH, cx
call Xceive ; send GetMem packet and pickup
; the response
mov cx, WOW32_Size
les di, WOW32Buffer ; ES:DI -> WOW32 buffer
mov si, OFFSET ReceivePkt+4
rep movsb
pop es ; temps...
pop ds ; temps...
popa ; temps...
mov sp, bp
pop bp
ret 8
Sim32GetMem_Error:
int 3
Sim32GetVDMMemory ENDP
;*****************************************************************************
;
; Sim32SetVDMMemory
;
;*****************************************************************************
;***************
PROCEDURE Sim32SetVDMMemory PUBLIC, FAR
push bp ; save stack frame
mov bp, sp
pusha ; temps...
push ds ; temps...
push es ; temps...
mov bx, ds
mov ax, SEG MAIN_DATA
mov ds, ax
mov di, OFFSET SetMemPkt ; DS:DI -> SetMem packet
mov ax, WOW32_Buffer ; get buffer's address
mov WOW32Buffer._off, ax
mov ax, bx
mov WOW32Buffer._sel, ax
mov ax, WOW32_Off
mov [di].MEM_OFF, ax
mov ax, WOW32_Sel
mov [di].MEM_SEL, ax
mov cx, WOW32_Size
cmp cx, 3B6h
jg Sim32SetMem_Error
mov [di].MEM_LENGTH, cx
mov bx, 11
add bx, cx
mov [di].Len, bx
add di, 0Ah
mov bx, ds
mov es, bx
lds si, WOW32Buffer ; DS:SI -> Buffer
rep movsb
mov BYTE PTR es:[di], EOT
mov ds, bx
mov si, OFFSET SetMemPkt ; DS:SI -> SetMem packet
call Xceive
pop es ; temps...
pop ds ; temps...
popa ; temps...
mov sp, bp
pop bp
ret 8
Sim32SetMem_Error:
int 3
Sim32SetVDMMemory ENDP
;*****************************************************************************
;
; Sim16SendSim32
;
;*****************************************************************************
PROCEDURE Sim16SendSim32 PUBLIC, FAR
push bp ; save stack frame
mov bp, sp
pusha ; temps...
push ds ; temps...
push es ; temps...
mov bx, ds
mov ax, SEG MAIN_DATA
mov ds, ax
mov si, OFFSET ToWOW32Pkt ; DS:SI -> ToWOW32 packet
cmp fInitDLL, 0
jne @f
pusha
call Initialize
popa
inc fInitDLL
@@:
; prepare ToWOW32 packet
mov ax, WOWStackOff
mov [si].ToWOW32_OFF, ax ;
mov ax, WOWStackSel
mov [si].ToWOW32_SEL, ax ;
; send it
call Xceive ; send ToWOW32 packet and pick up
; the response
Sim16SendSim32_Loop:
mov di, OFFSET Receivepkt
mov ax, [di].MEM_OFF ; get sel:off and length from
mov VDMAddress._off, ax ; packet
mov ax, [di].MEM_SEL
mov VDMAddress._sel, ax
mov ax, [di].MEM_LENGTH
mov VDMLength, ax
Sim16SendSim32_GetMem:
cmp [di].Command, GETMEM
jne Sim16SendSim32_SetMem
call GetVDMMemory ; get vdm memory
call Xceive ; send response and get next packet
jmp SHORT Sim16SendSim32_Loop
Sim16SendSim32_SetMem:
cmp [di].Command, SETMEM
jne Sim16SendSim32_PszLen
call SetVDMMemory ; get vdm memory
call Xceive ; send response and get next packet
jmp SHORT Sim16SendSim32_Loop
Sim16SendSim32_PszLen:
cmp [di].Command, PSZ
jne Sim16SendSim32_WakeUp
call PszLen
call Xceive ; send response and get next packet
jmp SHORT Sim16SendSim32_Loop
Sim16SendSim32_WakeUp:
cmp [di].Command, WAKEUP
jne Sim16SendSim32_Error
Sim16SendSim32_Done:
pop es ; temps...
pop ds ; temps...
popa ; temps...
IFDEF STACKSWITCH
cli
mov sp, VDMAddress._off
mov ss, VDMAddress._sel ; could be a task switch !
sub sp, 8
sti
ENDIF
pop bp
ret 4
Sim16SendSim32_Error:
int 3
mov si, OFFSET NAKPkt
call Xceive
jmp SHORT Sim16SendSim32_Loop
Sim16SendSim32 ENDP
;*****************************************************************************
;
; GetVDMMemory
;
;*****************************************************************************
PROCEDURE GetVDMMemory, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
push di
push es
push ds
mov ax, ds
mov es, ax
mov di, OFFSET RespPkt+4 ; ES:DI -> Response Packet
mov cx, VDMLength
lds si, VDMAddress ; DS:SI -> memory to get
rep movsb
pop ds
pop es
pop di
mov si, OFFSET RespPkt ; DS:SI -> Resp packet
mov ax, si
mov cx, VDMLength
add cx, 5
mov [si].Len, cx
add si, cx
dec si
mov [si], BYTE PTR EOT
mov si, ax ; DS:SI -> Resp packet
ret
GetVDMMemory ENDP
;*****************************************************************************
;
; SetVDMMemory
;
;*****************************************************************************
PROCEDURE SetVDMMemory, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
push di
push es
lea si, ReceivePkt.DataM ; DS:SI -> Data to set
mov cx, VDMLength
les di, VDMAddress ; DS:SI -> memory to set
rep movsb
mov si, OFFSET RespPkt ; DS:DI -> Response Packet
mov [si].Len, 7
mov [si].MEM_OFF, 0AAh
mov BYTE PTR [si].MEM_SEL, EOT
pop es
pop di
ret
SetVDMMemory ENDP
;*****************************************************************************
;
; PszLen
;
; This routine returns the length of the null terminated string
; address specified by VDMAddress.
;
;*****************************************************************************
PROCEDURE PszLen, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
push di
push es
les di, VDMAddress ; ES:DI -> String
mov cx, 0FFFFh
sub ax, ax ; look for null
repne scasb
jnz PszLen_Notfound
xor cx, 0FFFFh ; CX = length of string
mov si, OFFSET RespPkt ; DS:DI -> Response Packet
mov [si].Len, 7
mov [si].MEM_OFF, cx
mov BYTE PTR [si].MEM_SEL, EOT
pop es
pop di
ret
PszLen_Notfound:
int 3
pop es
pop di
ret
PszLen ENDP
;*****************************************************************************
; T R A N S P O R T L A Y E R
;*****************************************************************************
;*****************************************************************************
;
; Xceive - TransCeive
;
; DS:SI -> Packet to be transmitted
;
;*****************************************************************************
PROCEDURE Xceive, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
mov RxPktLen, -1
mov ReceivePktPtr, 0
mov fReceive, 0
mov fRxCount, 0
mov fRxError, 0
call StartTransmitter
Xceive_Loop:
cmp fReceive, 0
je Xceive_Loop
mov fReceive, 0
cmp fRxError, 0
jne Xceive_NAK
cmp ReceivePkt, SOH
jne Xceive_NAK
mov bx, ReceivePkt.Len
dec bx
cmp ReceivePkt.[bx], EOT
jne Xceive_NAK
xor ax, ax
ret
Xceive_NAK:
cmp fRxCount, MAXCOUNT
jg Xceive_Error
inc fRxCount
mov si, OFFSET NAKPkt
jmp SHORT Xceive_Loop
Xceive_Error:
int 3
mov ax, 1
ret
Xceive ENDP
;*****************************************************************************
;
; Receive
;
;*****************************************************************************
PROCEDURE Receive, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
mov RxPktLen, -1
mov ReceivePktPtr, 0
mov fReceive, 0
mov fRxCount, 0
Receive_Loop:
cmp fReceive, 0
je Receive_Loop
mov fReceive, 0
cmp fRxError, 0
jne Receive_NAK
xor ax, ax
ret
Receive_NAK:
cmp fRxCount, MAXCOUNT
jg Receive_Error
inc fRxCount
mov si, OFFSET NAKPkt
call StartTransmitter
jmp SHORT Receive
Receive_Error:
int 3
mov ax, 1
ret
Receive ENDP
;*****************************************************************************
; S E R I A L D R I V E R
;*****************************************************************************
;*****************************************************************************
;
; Start Transmitter
;
;*****************************************************************************
PROCEDURE StartTransmitter, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
StartTransmitter_Loop:
cmp fTransmitting, 1
je StartTransmitter_Loop
mov TransmitPkt._sel, ds
mov TransmitPkt._off, si
mov ax, [si].Len ; get packet length
mov TransmitPktLen, ax
mov TransmitPktPtr, 0
mov fTransmitting, 1
cmp TransmitPktLen, 0
je StartTransmitter_Ret
mov dx, SERIALPORT ; COM1 or COM2
mov dl, IER ; turn on interrupts on 8250
in al, dx
DELAY
or al, TxInt
out dx, al
DELAY
StartTransmitter_Ret:
ret
StartTransmitter ENDP
;*****************************************************************************
;
; Interrupt Routine
;
;*****************************************************************************
PUBLIC COMISR, COMISR_LSR, COMISR_Receive, COMISR_Transmit, COMISR_MSR
COMISR:
push ax
push ds
mov ax, SEG DGROUP
mov ds, ax
DISABLE
call NewStack
pusha
push es
COMISR_More:
mov dx, SERIALPORT
mov dl, IIR
in al, dx
test al, IntPending ; is int pending ?
jnz COMISR_Ret ; no int is pending
xor ah, ah
mov di, ax
shr di, 1
add di, di
jmp [di].IntRoutines ; service int
COMISR_LSR:
INT3
mov fRxError, 1
mov dx, SERIALPORT
mov dl, LSR
in al, dx
DELAY
jmp SHORT COMISR_More
COMISR_Receive:
mov dx, SERIALPORT
in al, dx
DELAY
mov bx, ReceivePktPtr
mov [bx].ReceivePkt, al
inc ReceivePktPtr
cmp bx, 03
jne COMISR_ReceiveNext
mov ax, WORD PTR ReceivePkt+2
dec ax
mov RxPktLen, ax
COMISR_ReceiveNext:
cmp bx, RxPktLen
jne @f
mov fReceive, 1 ; receive Done !
@@:
jmp SHORT COMISR_More
COMISR_Transmit:
cmp TransmitPktLen, 0
jne COMISR_Send
mov dx, SERIALPORT
mov dl, IER ; turn off interrupts on 8250
in al, dx
DELAY
and al, NOT TxInt
out dx, al
DELAY
mov fTransmitting, 0
jmp SHORT COMISR_More
COMISR_Send:
les bx, DWORD PTR TransmitPkt
mov di, TransmitPktPtr
mov al, BYTE PTR es:[bx][di]
mov dx, SERIALPORT
out dx, al
DELAY
inc TransmitPktPtr
dec TransmitPktLen
jmp COMISR_More
COMISR_MSR:
INT3
mov fRxError, 1
mov dx, SERIALPORT
mov dl, MSR
in al, dx
DELAY
jmp COMISR_More
COMISR_Ret:
DELAY
pop es
popa
call OldStack
DISABLE
mov al, EOI
out PIC, al
pop ds
pop ax
iret
;*****************************************************************************
;
; New Stack
;
;*****************************************************************************
PROCEDURE NewStack, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
inc fStackUse
jnz NewStack_Ret
pop Scratch
mov OldSS, ss
mov OldSP, sp
push ds
pop ss
mov sp, OFFSET StackTop
push Scratch
NewStack_Ret:
ret
NewStack ENDP
;*****************************************************************************
;
; Old Stack
;
;*****************************************************************************
PROCEDURE OldStack, PUBLIC
ASSUME CS:MAIN_CODE, DS:DGROUP
DISABLE
cmp fStackUse, 0
jne OldStack_Ret
pop Scratch
mov ss, OldSS
mov sp, OldSP
push Scratch
OldStack_Ret:
dec fStackUse
ENABLE
ret
OldStack ENDP
MAIN_CODE ENDS
END