;****************************************************************************** ; ; 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