home *** CD-ROM | disk | FTP | other *** search
- PAGE 62,132
- TITLE BYE-PC Version 3.00 - Resident Modem Driver
- ;-----------------------------------------------------------------------
- ; * * * BYE-PC Resident Modem Driver * * *
- ;
- ; (c) Copyright 1986, 1987 MCODE Software
- ; by
- ; R. E. Starr, Jr.
- ; 3444 Dresden Dr.
- ; Montgomery Al. 36111
- ; (205)244-7230
- ;-----------------------------------------------------------------------
- ;
- ; Many thanks to the following people for
- ; making this project possible:
- ;
- ; - William C. Bryan -
- ;
- ; Special thanks to Bill for the hardware timing functions
- ; and guidance during initial project development.
- ;
- ; - Greg Gross -
- ;
- ; Special thanks to Greg for the endless hours of online de-
- ; bugging. Almost all of the online debugging was performed by
- ; Greg.
- ;
- ;-----------------------------------------------------------------------
- ;-------------------- General Equates Section --------------------------
- ;-----------------------------------------------------------------------
- ;
- PGM_VER equ 3 ;BYE-PC version number
- PGM_REV equ 0 ;BYE-PC revision level
- ;
- ; -- general purpose equates --
- ;
- YES equ 1 ;boolean defines
- NO equ 0
- ON equ 1
- OFF equ 0
-
- EOF equ -1 ;end of file
- NULL equ 0 ;zero value
- CR equ 0Dh ;carriage return
- LF equ 0Ah ;line feed
- ESK equ 1Bh ;escape (ESC is an instruction)
- BKSPC equ 08h
- BELL equ 7 ;ring bell through tty print
- CTRL_C equ 03h ;remote break control key
- CTRL_S equ 13h ;remote pause key
- ;
- ; -- keyboard scan codes --
- ;
- ALT_Q equ 16 ;top row keys
- ALT_W equ 17
- ALT_E equ 18
- ALT_R equ 19
- ALT_T equ 20
- ALT_Y equ 21
- ALT_U equ 22
- ALT_I equ 23
- ALT_O equ 24
- ALT_P equ 25
-
- ALT_A equ 30 ;middle row keys
- ALT_S equ 31
- ALT_D equ 32
- ALT_F equ 33
- ALT_G equ 34
- ALT_H equ 35
- ALT_J equ 36
- ALT_K equ 37
- ALT_L equ 38
-
- ALT_Z equ 44 ;bottom row keys
- ALT_X equ 45
- ALT_C equ 46
- ALT_V equ 47
- ALT_B equ 48
- ALT_N equ 49
- ALT_M equ 50
- ;
- ; -- baud rate initialization for 8255 --
- ;
- BPS300 equ 0180h ;port initialize (300 bps)
- BPS600 equ 00C0h ;port initialize (600 bps)
- BPS1200 equ 0060h ;port initialize (1200 bps)
- BPS2400 equ 0030h ;port initialize (2400 bps)
- BPS3600 equ 0020h ;port initialize (3600 bps)
- BPS4800 equ 0018h ;port initialize (4800 bps)
- BPS7200 equ 0010h ;port initialize (7200 bps)
- BPS9600 equ 000Ch ;port initialize (9600 bps)
-
- INT_RX equ 0 ;Set the Rx-Interrupt mode
- INT_TX equ 1 ;Set the Tx-Interrupt mode
- INT_STAT equ 2 ;Set the Status Interrupt mode
- ;
- ; -- system hardware addresses --
- ;
- EOI equ 20h ;end of interrupt command
- IO_8259 equ 20h ;8259 PIC interrupt controller port
- PORT_TM equ 40h ;8253 timer i/o port
- PORT_PA equ 60h ;8255 PPI keyboard input port
- PORT_PB equ PORT_PA+1 ;8255 PPI in/out keyboard & cassette
- PORT_PC equ PORT_PA+2 ;8255 PPI input from planer switches
- ; (COM1=03F8h, COM2=02F8h)
- WBOOT_OFF equ 0E05Bh ;IBM-PC Warm boot offset
- WBOOT_SEG equ 0F000h ;IBM-PC Warm boot segment
- ;
- ;***********************************************************************
- ;******************** PROGRAM CONFIGURATION SECTION ********************
- ;***********************************************************************
- ;
- ; COMM Port selection equates, all three of these must be changed in
- ; order to change the COMM port used for the modem.
- ;
- ;
- RS232_INT equ 0Ch ;rs232 vector (0Ch=COM1, 0Bh=COM2)
- IRQ_BASE equ 10h ;(IRQ4=10h:COM1, IRQ3=08h:COM2)
- PORT_BASE equ 03F8h ;8255 rs232 i/o base port address
- ;03F8h=COM1, 02F8h=COM2
- ;
- ; Receive buffer queue size. This is the actual size of the ring
- ; buffer in bytes used by the rs-232 interrupt routines.
- ;
- RX_BUFF equ 256 ;rx-data interrupt queue size
- ;
- ; YES if you are using a Hayes compatable command set modem. If NO, then
- ; use the CD line to wait for carrier and sync to baud by checking for
- ; a carriage return to appear at the port (remote must send CR's). This
- ; is for dumb modems, such as the Universal Data Systems 212b with auto-
- ; answer capability only.
- ;
- SMART_MDM equ YES ;yes, if you are using a smart modem
- ;
- ; Select ONLY ONE of these baud rates for your modems highest baud rate!
- ;
- BPS_300 equ NO ;max baud rate 300bps?
- BPS_1200 equ YES ;max baud rate 1200bps?
- BPS_2400 equ NO ;max baud rate 2400bps?
- TELEBIT equ NO ;Telebit Trailblazer 9600 only!
- ;
- ; Set to YES for the Telebit Trailblazer, If the rx-queue becomes full,
- ; the RTS line is asserted false to tell the modem to halt sending data.
- ;
- USE_RTS equ NO ;yes, ask nulls question
- ;
- ; Yes for nulls, you may need to ask for nulls if you have 2400ps mdm.
- ;
- USE_NULLS equ YES ;yes, ask nulls question
- ;
- ; Yes to run a COM/EXE file upon receiveing a valid carrier.
- ;
- LOGON_EXE equ YES ;yes, execute XBBS during logon
- ;
- ; If YES, re-boot after running 'COM/EXE' file locally.
- ;
- REBOOT equ NO ;no, exit to dos after 'run local'
- ;
- ; Initial time allowed on system. This can be read and set via INT66
- ; function numbers 17 & 18. Normally set/reset by XBBS after log on.
- ;
- TIME equ 60 ;initial time on system limit
- ;
- ; Ctrl-S timeout, after timeout is reached Ctrl-S pause if reset.
- ;
- TIMEOUT equ 30 ;30 seconds during Ctrl-S pause
- ;
- ; This sets the limit for remote type ahead during 'stdin' operations.
- ; If the limit is exceeded (noise), the rx queue is flushed and reset.
- ;
- KEYLIM equ 32 ;up to 32 chars at once
- ;
- ; Allows optional call to old interrupt 1C service routine. This will
- ; be an 'iret' instruction if no other resident programs loaded.
- ;
- CHAIN_INT1C equ YES ;call old interrupt 1C
- ;
- ; Local keyboard control key mapping. These keys become active
- ; when the caller makes connection.
- ;
- K_END equ 79 ;[End] key to exit msg from sys/op
- K_REMOTE equ ALT_B ;toggle remote on off key
- K_LOGOFF equ ALT_O ;send log off message
- K_HANGUP equ ALT_H ;hangup on caller and re-boot
- K_CHAT equ ALT_Q ;message from sysop key
- K_BELL equ ALT_G ;toggle bell on/off
- K_CLS equ ALT_Z ;clear the screen locally
- K_TIME equ ALT_U ;unlimited time on key
- K_SYSOP equ ALT_S ;sys/op status level
- K_CALLER equ ALT_C ;display caller on line
- ;
- ;***********************************************************************
- ;****************** END PROGRAM CONFIGURATION SECTION ******************
- ;***********************************************************************
- ;
- rom_bios_data SEGMENT at 40h ;ROM Bios data area SEGMENT
- ORG 72h
- reset_flag dw ? ;ALT-CTRL-DEL pressed flag
- rom_bios_data ENDS
- ;
- ; -- set up the segment and begin exection --
- ;
- code SEGMENT para public 'code'
- ASSUME cs:code, ds:code, es:code, ss:code
- ORG 100h
-
- start: jmp initialize ;goto loader routine.
- ;
- PAGE
- ;-----------------------------------------------------------------------
- ;----------------------- PROGRAM DATA AREA -----------------------------
- ;-----------------------------------------------------------------------
- ;
- ; NOTE: Do not remove copyright as "byexface.c" uses this to
- ; determine if BYE-PC is resident in memory.
- ;
- ;-----------------------------------------------------------------------
- ;
- copyrite db "BYE-PC (c) Copyright 1986, 1987 MCODE Software"
- db 01Ah ;Do not alter this string!!!
- bye_sign dw 1234h ;BYE-PC signiture when installed
- ;
- ; -- Terminal Configuration Data --
- ; (Televideo 910/912/920/925/950)
- ;
- cls_cnt db 2 ;#bytes to send cls
- cls_bytes db ESK,':',0,0,0,0 ;clear screen data
-
- loc_cnt db 2 ;#bytes to locate cursor
- loc_bytes db ESK,'=',0,0,0,0 ;locate cursor prefix data
-
- namebuf db 64 dup(0) ;caller name buffer.
- ;
- ; -- System Messages and Strings --
- ;
- lost_msg db 0Dh,0Ah,0Dh,0Ah
- db "[Carrier Lost]",0Dh,0Ah,"$"
- timeup_msg db 0Dh,0Ah,0Dh,0Ah
- db "[Time Limit Expired]",0Dh,0Ah,0Dh,0Ah,"$"
- off_msg db ": Off]$"
- on_msg db ": On]$"
- remote_msg db "[Remote$"
- bell_msg db "[Bell$"
- utime_msg db "[Unlimited Time]$"
- logoff_msg db "[System Going down in 2 Mins!]$"
- chat_msg db "Message from Sys/Op: $"
- sysop_msg db "[Sys/Op Privledges]$"
- caller_msg db "[Caller on line: $"
- ;
- ;-----------------------------------------------------------------------
- ;------------------- Program Flags & Varibles Area----------------------
- ;-----------------------------------------------------------------------
- ;
- baud db 0 ;call baud rate (0=300,1=1200,3=2400)
- nulls db 0 ;# of nulls to send
- time_on db TIME ;minutes allowed online
- cd_lost db NO ;carrier lost detect flag
- bell_flg db ON ;local bell state
- brk_flg db ON ;Ctrl-Break enable from remote on
- trap_flg db OFF ;^S & ^C trap enable flag
- tout_flg db ON ;timeout during pause flag on
- cstat dw 0FFFFh ;caller status byte (0-255)
- ;
- ; --Interrupt Data Storage Areas --
- ;
- old_int09 dd ? ;storage for old keybd service int
- old_int10 dd ? ;storage for old video int
- old_int13 dd ? ;storage for old disk interrupt
- old_int16 dd ? ;storage for old keybd access int
- old_int1C dd ? ;storage for old timer interrupt
- ;
- ; -- Program status and system flags --
- ;
- timer_tick dw 0 ;timer tick counter
- timer_min db 0 ;timer tick minutes counter
- int10_merge db ON ;merge characters 'to' screen & mdm
- int16_merge db ON ;merge characters 'from' screen & mdm
- cd_check db ON ;checking carrier detect status
- scan_key db EOF ;scan code key storage.
- local_flg db 0 ;program already active flag.
- disk_flg db 0 ;disk int 13h busy flag
- pause_req db 0 ;Ctrl-S pressed flag
- pause_flg db 0 ;Ctrl-S pressed flag
- recur_flg db 0 ;int10 re-entrance flag
- IF USE_RTS
- rts_flg db ON ;rts on/off state flag
- ENDIF
- ;
- ; -- Receive interrupt data storage --
- ;
- rx_head dw 0 ;queue starting ptr
- rx_tail dw 0 ;queue ending ptr
- rx_cnt dw 0 ;# of chars in rx-queue
- rx_buf db RX_BUFF+1 dup(0) ;rx-queue buffer
- ;
- ;
- PAGE
- SUBTTL *** Keyboard Service Interrupt ***
- ;---INT-09--------------------------------------------------------------
- ;Keyboard service interrupt to load all characters from the keyboard.
- ;This routine traps all keyboard interrupts from the BIOS and checks
- ;for the 'hot keys' to enable local control options.
- ;-----------------------------------------------------------------------
- ;
- int09_main PROC far
-
- sti ;re-enable interrupts
- push ds ;save registers
- push ax
-
- push cs ;DS=CS
- pop ds
-
- in al,PORT_PA ;get scan code.
- mov scan_key,al ;save key pressed.
- call lkey_ndx ;key a local ctrl function?
- cmp al,EOF ;no, exit
- je kb0
- mov ah,2 ;check shift key status
- int 16h
- test al,8 ;is the Alt key pressed?
- jne kb2 ;no, then exit
-
- kb0: pop ax ;restore registers
- pop ds
- jmp cs:[old_int09] ;jump to Bios routine
-
- ;
- ; Reset the keyboard controler and issue an EOI to 8259 controller.
- ;
- kb2: in al,PORT_PB ;get current control value
- mov ah,al ;save it in AH
- or al,80h ;set the high bit
- out PORT_PB,al ;send it to the control port
- mov al,ah ;recover original value
- out PORT_PB,al ;send it out
- cli ;suspend interrupts
- mov al,EOI ;load EOI value
- out IO_8259,al ;send it to the 8259
- sti ;restore interrupts
-
- cmp local_flg,NULL ;local routine already active?
- jne kb1 ; yes, then exit
- cmp disk_flg,NULL ;any disk i/o pending?
- jne kb1 ; yes, then exit
- call local_ctrl ;call local key routine
-
- kb1: pop ax
- pop ds ;end interrupt routine
- iret
-
- int09_main ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; LOCAL CONTROL -- This sets up for a call to the local control key
- ; functions. After one of the correct hot keys are pressed, control is
- ; transferred here to perform the actual function call.
- ;-----------------------------------------------------------------------
- ;
- local_ctrl PROC near
-
- mov local_flg,YES ;set program active flag
- push ax ;save all registers
- push bx
- push cx
- push dx
- push si
- push di
-
- mov al,scan_key ;get scan code stored
- call lkey_ndx ;key a local ctrl function?
- cmp al,EOF ;no, exit
- je alt_key_end
- xor bx,bx ;clear the word
- mov bl,al ;load the function number
- shl bx,1 ;table offset x 2
- call cs:alt_jtbl[bx] ;call subroutine function#
- alt_key_end:
- mov local_flg,NULL ;reset status flag
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- ;
- ; --- Call table of hot key functions to call ---
- ;
- alt_jtbl dw OFFSET loc_remote ;0 = toggle remote
- dw OFFSET loc_logoff ;1 = tell user to logoff
- dw OFFSET boot_sys ;2 = hangup on caller
- dw OFFSET loc_chat ;3 = enter chat
- dw OFFSET loc_bell ;4 = toggle bell on/off
- dw OFFSET loc_scrn ;5 = clear screen
- dw OFFSET loc_utime ;6 = unlimited time
- dw OFFSET loc_sysop ;7 = sys/op status
- dw OFFSET loc_caller ;8 = caller on line
-
- local_ctrl ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; LOCAL KEY INDEX -- This function returns the index of the local keybd
- ; Alt control keys. If an EOF is returned, the key does not exsists.
- ;
- ; Entry AL = Scan Code of Alt key to check
- ;
- ; Return: AL = EOF if not a local control key option
- ;
- ;-----------------------------------------------------------------------
- ;
- lkey_ndx PROC near
-
- push bx
- xor bl,bl
-
- cmp al,K_REMOTE ;toggle remote on off key
- je lkey_exit ;BL = 0
- inc bl
- cmp al,K_LOGOFF ;send log off message
- je lkey_exit ;BL = 1
- inc bl
- cmp al,K_HANGUP ;hangup on caller and re-boot
- je lkey_exit ;BL = 2
- inc bl
- cmp al,K_CHAT ;message from sysop
- je lkey_exit ;BL = 3
- inc bl
- cmp al,K_BELL ;toggle bell on/off
- je lkey_exit ;BL = 4
- inc bl
- cmp al,K_CLS ;clear the screen locally
- je lkey_exit ;BL = 5
- inc bl
- cmp al,K_TIME ;unlimited time on key
- je lkey_exit ;BL = 6
- inc bl
- cmp al,K_SYSOP ;sys/op status
- je lkey_exit ;BL = 7
- inc bl
- cmp al,K_CALLER ;display caller on line
- je lkey_exit ;BL = 8
- mov bl,EOF ;else, invalid key
-
- lkey_exit: mov al,bl
- pop bx
- ret
-
- lkey_ndx ENDP
- ;
- ;
- PAGE
- SUBTTL *** Video BIOS Interrupt ***
- ;---INT-10--------------------------------------------------------------
- ; All video writes to the BIOS are translated here and passed to the
- ; modem and the screen. This routine directs all the character video
- ; writes to the modem and then to the screen. Presently this function
- ; traps TTY and write character/attribute calls.
- ;-----------------------------------------------------------------------
- ;
- int10_main PROC far
-
- sti ;re-enable interrupts
- push ds ;save DS on the stack
- push cs ;DS=CS
- pop ds
- cmp int10_merge,NULL ;exit if ignoring mdm
- je int10_end
- cmp recur_flg,0 ;exit if recursive call
- je int10_entry ; from old int10 routine
- int10_end: pop ds
- jmp cs:[old_int10] ;go back to old routine
- ;
- ; Redirect BIOS video writes to go to the modem first.
- ;
- int10_entry: push ax ;save function register
- cmp ah,14 ;write tty?
- je vid_tty ; yes, send it out
- cmp ah,10 ;write char at pstn?
- je vid_con ; yes, send it out
- cmp ah,9 ;write char/attr at pstn?
- je vid_con ; yes, send it out
- cmp ah,7 ;scroll down?
- je vid_cls ; yes, process it
- cmp ah,6 ;scroll up?
- je vid_cls ; yes, process it
- cmp ah,2 ;position cursor?
- jne int10_exit ; no, exit
-
- vid_loc: push cx ;send locate csr prefix
- push si
- mov cl,loc_cnt
- mov si,OFFSET loc_bytes
- call tx_puts
- pop si
- pop cx
- mov al,dh ;send the cursor row#.
- add al,020h ;make it ascii
- call tx_putc
- mov al,dl ;send the cursor col#.
- add al,020h ;make it ascii
- call tx_putc
- jmp SHORT int10_exit ;exit to old int10
-
- vid_cls: cmp al,0 ;is it a clear window?
- jne int10_exit ;no, skip sending cls
- cmp cx,0 ;upper left corner 0,0
- jne int10_exit
- cmp dl,79 ;column 79 or greater?
- jl int10_exit
- cmp dh,24 ;row 24 or greater?
- jl int10_exit
- push cx ;send clear screen data
- push si
- mov cl,cls_cnt
- mov si,OFFSET cls_bytes
- call tx_puts
- pop si
- pop cx
- jmp SHORT int10_exit ;exit to old int10
-
- vid_tty: call tx_putc ;char to tx in AL now
- cmp al,BELL ;was it a bell?
- jne int10_exit ; no, then send it out
- cmp bell_flg,NULL ;ok to ring locally?
- jne int10_exit ; yes, the ring it.
- pop ax ;get char off stack
- jmp SHORT int10_exit1 ;exit without bell
-
- vid_con: call tx_char ;print char with nulls
- ;
- ; Restore registers, call the old int10 to service the video display,
- ; and then reset the recursion flag before exiting.
- ;
- int10_exit: pop ax ;restore function register
- mov recur_flg,1
- pushf ;save the flags
- call old_int10 ;call old bios routine
- mov recur_flg,0 ;clear recursion flag
- int10_exit1: pop ds ;one last pop for the DS
- iret
-
- int10_main ENDP
- ;
- ;
- PAGE
- SUBTTL *** Disk BIOS Interrupt ***
- ;---INT-13--------------------------------------------------------------
- ; Disk i/o interrupt. This routine sets a flag any time disk i/o is
- ; pending. This is used to prevent any local console hot keys from
- ; doing anything if any disk i/o is being performed.
- ;------------------------------------------------------------------------------
- ;
- int13_main PROC far
-
- mov cs:disk_flg,1 ;set disk 'busy' flag
- pushf ;save the flags
- call cs:[old_int13] ;call old disk int
- mov cs:disk_flg,0 ;reset disk 'busy' flag
- ret 2 ;exit with new flags
-
- int13_main ENDP
- ;
- ;
- PAGE
- SUBTTL *** Keyboard BIOS Interrupt ***
- ;---INT-16--------------------------------------------------------------
- ; All keyboard requests to the BIOS are intercepted here. Keyboard BIOS
- ; functions #0-(keyboard get character) and #1-(keyboard data availble)
- ; are interrcepted here. If the modem rx-queue has data, it is merged
- ; before the local keyboard data received. Otherwise, the original BIOS
- ; routines are called to service the local keyboard. Note that we could
- ; simply stuff the characters in the queue within the rx-data interrupt,
- ; but this would prevent us from having more than 15 character type
- ; ahead. This method allows the int16 to keep getting chars up to the
- ; the maximum rx-queue size.
- ;-----------------------------------------------------------------------
- ;
- int16_main PROC far
-
- sti ;re-enable interrupts
- push ds
- push ax
-
- push cs ;DS=CS
- pop ds
-
- cmp cd_check,NULL ;checking cd status?
- je int16_main1 ;no, skip time check
- call chk_timeon ;time online is up?
- int16_main1: cmp int16_merge,NULL ;ignoring modem input?
- je skip_int16 ; yes, then jump
- ;
- ; -- Check for input overflow. If buffer is full ring bell & flush --
- ;
- push ax ;save ax
- flush_all: call rx_size ;check remote input limit
- cmp ax,KEYLIM
- jl int16_main2 ;if limit reached, reset it
- call rx_flush ;reset the rx buffer
- cmp bell_flg,NULL ;ok to ring bell?
- je flush_all ; no, skip it.
- push bx
- mov bl,2 ; yes, beep on overflow
- call beep
- pop bx
- jmp SHORT flush_all ;flush it out again
-
- int16_main2: pop ax ;restore ax
- or ah,ah ;0 = get-a-key
- jz getkey
- dec ah ;1 = get-keybd-status
- jz kbhit
-
- skip_int16: pop ax ;recover function#
- pop ds ;recover DS
- jmp cs:[old_int16] ;skip shift status, jmp to bios
- ;
- ; --- check for char waiting at modem, else goto BIOS keybd routine ---
- ;
- kbhit: call rx_ready ;character in the queue?
- jz skip_int16 ; no, exit through BIOS
- pop ax ;recover function call#
- pop ds ;recover DS
- or al,1 ;char ready at keybd bit.
- ret 2 ;return from interrupt with
- ; flags popped off stack.
- ;
- ; --- get a character from modem or keyboard ---
- ;
- getkey: call rx_ready ;character in queue?
- jz skip_int16 ;jump if no character rdy
- pop ax ;discard int function#
- gotkey: call rx_getc ;get character from mdm
- and al,7Fh ;strip off parity bit 7
- xor ah,ah ;clear scan code return
- pop ds ;recover DS
- iret
-
- int16_main ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; CHECK TIME ONLINE -- Check to see if timeon has expired, if not exit
- ; else tell the caller time is up, hangup, and re-boot. This function
- ; is called before each keyboard get data/status interrupt is processed.
- ;-----------------------------------------------------------------------
- ;
- chk_timeon PROC near
-
- push ax
- mov ah,time_on ;get time limit
- or ah,0
- jz check_end ; no, exit
- cmp timer_min,ah ;compare to time passed
- jg time_up ;time on < time expired?
- check_end: pop ax
- ret
-
- time_up: pop ax
- mov si,OFFSET timeup_msg ;tell caller time is up
- call con_puts
- mov ax,2 ;wait 2 seconds
- call delay ;fall through and wboot
- jmp NEAR PTR boot_sys ;reboot system
-
- chk_timeon ENDP
- ;
- PAGE
- SUBTTL *** Timer Tick Service Interrupt ***
- ;---INT-1C--------------------------------------------------------------
- ; This routine is called approximatly 18.2 times/second to service the
- ; system timer that counts minutes passed since logon. Also, if the
- ; keyboard 'request_flg' is set, the alt_key routine is called to serv-
- ; ice local keyboard control functions.
- ;-----------------------------------------------------------------------
- ;
- int1C_main PROC far
-
- sti
- push ds ;save DS
-
- push cs ;DS=CS
- pop ds
- IF CHAIN_INT1C
- pushf ;save the flags
- call old_int1C ;call old timer rtn
- ENDIF
- ;
- ; Check to see if the RTS is off, and if we can turn it on yet.
- ; The RTS line is used to control data flows from high speed modems.
- ;
- IF USE_RTS
- push ax
- cmp rts_flg,NULL ;exit if RTS is on
- jne skip_rts
- call rx_size ;get queue size
- cmp ax,(RX_BUFF/4) ;3/4 empty yet?
- jg skip_rts ;no, leave it off
- mov rts_flg,ON
- mov ax,ON ;turn RTS back on now
- call port_rts
- skip_rts: pop ax
- ENDIF
- ;
- ; Increment the time on system clock ticker used to check time-on limit.
- ;
- inc timer_tick
- cmp timer_tick,1092 ;ticked 1092 times yet?
- jl int1C_end ;jmp if not > 1080
- inc timer_min ;else, inc minutes...
- mov timer_tick,0 ;reset the ticker
-
- int1C_end: pop ds
- iret
-
- int1C_main ENDP
- ;
- PAGE
- SUBTTL *** Applications Program Interface (API) ***
- ;-----------------------------------------------------------------------
- ;INT66 APPLICATIONS PROGRAM INTERFACE (API) -- This interrupt provides
- ; modem i/o for applications which need direct control of the modem.
- ;
- ; Altered registers : AX, BX, CX, DX
- ; ES (only when funct 21 called)
- ;
- ; Preserved registers: CS, DS, SS, DI, SI, SP, BP
- ;
- ;-----------------------------------------------------------------------
- ; Functions Provided:
- ;
- ; AH=0 Get character from modem in AL.
- ; AL=character returned
- ; AH=0 null (no keybd scan codes)
- ; AX = EOF if no data.
- ;
- ; AH=1 Put character in AL to modem.
- ; AL=character to send.
- ;
- ; AH=2 Hang up the modem (DTR off):
- ; AL=0 turn off dtr
- ; AL=1 turn on dtr
- ;
- ; AH=3 Get carrier detect status in AX:
- ; AX=0 no carrier detect found
- ; AX=1 carrier detect found
- ;
- ; AH=4 Set carrier detect check status:
- ; AX=0 ignore carrier detect status
- ; AX=1 check carrier detect status
- ;
- ; AH=5 Flush the rx queue of all data.
- ;
- ; AH=6 Get # of chars in rx queue:
- ; AX=0 rx queue size
- ;
- ; AH=7 Get Baud rate of this call in AX:
- ; (0=300bps, 1=1200bps, 3=2400bps)
- ;
- ; AH=8 Set Control Break/Pause (CTRL-C/CTRL-S) flag state:
- ; AL=0 CTRL_NOBRK - disable remote ^C & ^S breaks
- ; AL=1 CTRL_BRK - enable remote breaks
- ; AL=2 CTRL_NOTOUT - disable ^S pause timeout
- ; AL=3 CTRL_TOUT - enable ^S timeout
- ; AL=4 CTRL_NOTRAP - dont trap ^C & ^S characters
- ; AL=5 CTRL_TRAP - allow ^C & ^S to be trapped out
- ;
- ; AH=9 Set <stdout> merged with modem:
- ; AL=0 disable output modem
- ; AL=1 enable output to modem
- ;
- ; AH=10 Set <stdin> merged with modem:
- ; AL=0 disable input from modem (rx-queue active)
- ; AL=1 enable input from modem (rx-queue active)
- ;
- ; AH=11 Get BYE-PC version/revison level in AX:
- ; AL=Current Revision level
- ; AH=Current Version level
- ;
- ; AH=12 Get number of nulls requested in AX:
- ; AX=Number of nulls requested
- ;
- ; AH=13 Set number of nulls to AX:
- ; AL=Number of nulls to send
- ;
- ; AH=14 Warm Boot the system through bios Ctrl-Alt-Del.
- ;
- ; AH=15 Get the user caller status
- ; AX=Status level (0-FFFFh).
- ;
- ; AH=16 Set the user caller status
- ; CX=Status level (0-FFFFh).
- ;
- ; AH=17 Set the time limit caller is allowed on line.
- ; AL=number of minutes (0-255, 0=Unlimited).
- ;
- ; AH=18 Get the time caller has been on line
- ; AX=number of minutes online (0-255).
- ;
- ; AH=19 Set the receive data interrupt mode
- ; AL=Mode (0=Off, 1=On)
- ;
- ; AH=20 Get the time limit caller is allowed on line.
- ; AX=number of minutes allowed online (0-255).
- ;
- ; AH=21 Get far pointer to caller name buffer.
- ; ES:BX -> far ptr to name buffer
- ;
- ; AH=22 Get far pointer to terminal configuration buffer
- ; ES:BX -> far ptr to terminal config buffer
- ;
- ;-----------------------------------------------------------------------
- ;
- int66_main PROC far
-
- sti ;re-enable interrupts
- push si
- push ds ;save DS
- push cs
- pop ds ;DS=CS for data items
-
- cmp ah,22 ;check function range
- jg int66_end
- xor bh,bh ;clear the msb of word
- mov bl,ah ;load function# in lsb
- shl bx,1 ;table OFFSET x 2
- call cs:int66_jtbl[bx] ;call subroutine function#
-
- int66_end: pop ds ;restore DS
- pop si
- iret
- ;
- ; --- Call table for function # to call ---
- ;
- int66_jtbl dw OFFSET rx_getc ; 0 = mdm get character
- dw OFFSET iputc ; 1 = mdm put character
- dw OFFSET dtr_state ; 2 = dtr on/off
- dw OFFSET cd_status ; 3 = CD status
- dw OFFSET cd_flag ; 4 = ignore CD state
- dw OFFSET rx_flush ; 5 = flush Rx queue
- dw OFFSET rx_size ; 6 = get Rx-size
- dw OFFSET get_bps ; 7 = get baud rate
- dw OFFSET set_break ; 8 = set break
- dw OFFSET halt_send ; 9 = halt loc sending
- dw OFFSET halt_get ; 10 = halt loc receiving
- dw OFFSET get_vers ; 11 = get rev level
- dw OFFSET get_nulls ; 12 = get # of nulls
- dw OFFSET set_nulls ; 13 = set # of nulls
- dw OFFSET boot_sys ; 14 = re-boot system
- dw OFFSET get_stat ; 15 = set status
- dw OFFSET set_stat ; 16 = get status
- dw OFFSET set_timer ; 17 = set max time online
- dw OFFSET get_timeon ; 18 = get time online
- dw OFFSET set_rxint ; 19 = set rx interrupt
- dw OFFSET get_timer ; 20 = get max time online
- dw OFFSET get_nameptr ; 21 = ptr to name buffer
- dw OFFSET get_termptr ; 22 = ptr to term buffer
-
- int66_main ENDP
- ;
- PAGE
- ;-----------------------------------------------------------------------
- ; INT66 subroutine functions. These are called via software interrupts.
- ;-----------------------------------------------------------------------
- ;
- ; Put character to modem in AL.
- ;
- iputc PROC near
-
- call tx_putc ;char in AL
- xor ax,ax ;signal ok
- iputc1: ret
-
- iputc ENDP
- ;
- ; Return the current status of the carrier detect line.
- ;
- cd_status PROC near
-
- call port_cd ;check CD line
- mov ax,YES
- jc cd_stat1 ;jump if CD found
- mov ax,NULL ;flag no carrier
- cd_stat1: ret
-
- cd_status ENDP
- ;
- ; Set/Reset the flag that ignores carrier detect status.
- ;
- cd_flag PROC near
-
- or al,al ;carrier chk on or off?
- jz cd_flag1
- mov cd_check,ON ;carrier checking on
- cmp cd_lost,NULL ;has carrier been lost?
- je cd_flag2 ; jump if not lost
- jmp NEAR PTR boot_sys ; else, re-boot system.
- cd_flag1: mov cd_check,NULL ;carrier checking off
- cd_flag2: ret
-
- cd_flag ENDP
- ;
- ; Toggle the dtr/cts line to the modem to force a hangup.
- ;
- dtr_state PROC near
-
- or al,al
- jz dtr_state1
- mov ax,ON
- jmp SHORT dtr_state2
- dtr_state1: mov ax,NULL ;turn OFF the dtr/rts
- dtr_state2: call port_dtr
- ret
-
- dtr_state ENDP
- ;
- ; Get the baud rate of this call in AX.
- ;
- get_bps PROC near
-
- xor ah,ah ;clear the msb
- mov al,baud ;return baud rate
- ret
-
- get_bps ENDP
- ;
- ; Set the ctrl-break flag on/off.
- ;
- set_break PROC near
-
- or al,al
- jz set_brk_off ;AH=0 - Break/Pause Off
- dec al
- jz set_brk_on ;AH=1 - Break/Pause On
- dec al
- jz set_tim_off ;AH=2 - Pause Timeout Off
- dec al
- jz set_tim_on ;AH=3 - Pause Timeout On
- dec al
- jz filter_off ;AH=4 - Filter/Trap off
- dec al
- jz filter_on ;AH=5 - Filter/Trap On
- jmp SHORT set_brk_end
-
- set_brk_off: mov brk_flg,OFF ;^C break off
- jmp SHORT set_brk_end
- set_brk_on: mov brk_flg,ON ;^C break on
- jmp SHORT set_brk_end
- set_tim_off: mov tout_flg,OFF ;^S time-out off
- jmp SHORT set_brk_end
- set_tim_on: mov tout_flg,ON ;^S time-out on
- jmp SHORT set_brk_end
- filter_off: mov trap_flg,OFF ;^C & ^S trap off
- mov pause_req,OFF ;clear ^S pause flag
- jmp SHORT set_brk_end
- filter_on: mov trap_flg,ON ;^C & ^S trap mdm on
-
- set_brk_end: ret
-
- set_break ENDP
- ;
- ; Set/Reset the flag that ignores chars sent to modem.
- ;
- halt_send PROC near
-
- or al,al
- jz halt_send1
- mov int10_merge,ON ;chars 'to' mdm on
- jmp SHORT halts_exit
- halt_send1: mov int10_merge,NULL ;chars 'to' mdm off
- halts_exit: ret
-
- halt_send ENDP
- ;
- ; Set/Reset the flag that ignores chars received from modem.
- ;
- halt_get PROC near
-
- or al,al
- jz halt_get1
- mov int16_merge,ON ;chars 'from' mdm on
- jmp SHORT haltg_exit
- halt_get1: mov int16_merge,NULL ;chars 'from' mdm off
- haltg_exit: ret
-
- halt_get ENDP
- ;
- ; Return the version/revision level in AX.
- ;
- get_vers PROC near
-
- mov al,PGM_REV ;get rev level
- mov ah,PGM_VER ;get vers number
- ret
-
- get_vers ENDP
- ;
- ; Get the number of nulls currently used.
- ;
- get_nulls PROC near
-
- xor ah,ah ;clear msb
- mov al,nulls ;return nulls
- ret
-
- get_nulls ENDP
- ;
- ; Set the number of nulls currently used.
- ;
- set_nulls PROC near
-
- cmp al,9
- jle set_nulls1
- mov al,0
- set_nulls1: mov nulls,al
- ret
-
- set_nulls ENDP
- ;
- ; Re-Boot the system function.
- ;
- boot_sys PROC near
-
- mov ax,OFF
- call port_dtr ;hang up modem
- ASSUME ds:rom_bios_data
- mov ax,rom_bios_data ;set DS to rom bios data
- mov ds,ax ; area.
- mov reset_flag, 1234h ;set the alt-ctrl-del flag.
- db 0EAH ;jmp to ROM warm boot at:
- dw WBOOT_OFF ; 0E05B OFFSET
- dw WBOOT_SEG ; 0F000 segment
- ASSUME ds:code
-
- boot_sys ENDP
- ;
- ; Get the caller status level.
- ;
- get_stat PROC near
-
- mov ax,cstat ;get status level
- ret
-
- get_stat ENDP
- ;
- ; Set the caller status level.
- ;
- set_stat PROC near
-
- mov cstat,cx ;set status level
- ret
-
- set_stat ENDP
- ;
- ; Set the callers time limit online allowed.
- ;
- set_timer PROC near
-
- mov time_on,al ;save time on allowed
- mov timer_tick,0 ;reset timer counter
- mov timer_min,0
- ret
-
- set_timer ENDP
- ;
- ; Get the callers time online.
- ;
- get_timeon PROC near
-
- xor ah,ah
- mov al,timer_min ;return it in AL
- ret
-
- get_timeon ENDP
- ;
- ; Set the receive interrupt mode
- ;
- set_rxint PROC near
-
- and al,ON ;toggle for int state
- mov ah,INT_RX ;set rx-interrupt mode
- call port_imode ;change interrupt mode
- call rx_flush ;clear rx queue
- ret
-
- set_rxint ENDP
- ;
- ; Get the callers time limit online allowed.
- ;
- get_timer PROC near
-
- xor ah,ah
- mov al,time_on ;save time on allowed
- ret
-
- get_timer ENDP
- ;
- ; Get far ptr to caller name buffer within BYE-PC.
- ;
- get_nameptr PROC near
-
- mov ax,cs ;ES=CS
- mov es,ax
- lea bx,namebuf ;ES:BX points to name buff
- ret
-
- get_nameptr ENDP
- ;
- ; Get far ptr to terminal type buffer within BYE-PC.
- ;
- get_termptr PROC near
-
- mov ax,cs ;ES=CS
- mov es,ax
- lea bx,cls_cnt ;ES:BX points to term'buff
- ret
-
- get_termptr ENDP
- ;
- ;-----------------------------------------------------------------------
- ; Local keyboard control key subroutines called from INT09 interrupts.
- ;-----------------------------------------------------------------------
- ;
- ; Toggle the remote on/off from 'stdin' and 'stdout'
- ;
- loc_remote PROC near
-
- mov bl,int10_merge ;save int10 trap state
- push bx ;save bx reg
- mov int10_merge,NULL ;dont send chars to mdm
- mov si,OFFSET remote_msg ;show header
- call con_puts
- pop bx ;restore bx
- mov al,bl
- xor al,ON ;now toggle int10 state
- or al,al ;is it off?
- mov si,OFFSET off_msg
- jz loc_remote1 ;show 'on'/'off' msg
- mov si,OFFSET on_msg
- loc_remote1: call con_puts
- call rx_flush ;reset rx-queue
- mov int10_merge,al ;set chars 'to' mdm
- mov int16_merge,al ;set chars 'from' mdm
- ;--> mov ah,INT_RX ;set rx-interrupt mode
- ;--> call port_imode ;change interrupt mode
- ret
-
- loc_remote ENDP
- ;
- ; Teller caller to logoff.
- ;
- loc_logoff PROC near
-
- mov si,OFFSET logoff_msg
- call con_puts
- ret
-
- loc_logoff ENDP
- ;
- ; Give caller unlimted time.
- ;
- loc_utime PROC near
-
- mov si,OFFSET utime_msg
- call con_puts
- mov time_on,0 ;disable online timer
- ret
-
- loc_utime ENDP
- ;
- ; Perform local sys/op message
- ;
- loc_chat PROC near
-
- mov si,OFFSET chat_msg ;tell'em were breaking in
- call con_puts
- mov al,OFF ;cut off rx-interrupts
- mov ah,INT_RX ;set rx-interrupt
- call port_imode ;change interrupt mode
- call rx_flush
- loc_chat1: mov ah,1 ;see if local keyboard
- pushf ; has char ready.
- call old_int16
- jnz loc_chat1 ;jmp if no character ready
- mov ah,0 ;check key press state.
- pushf
- call old_int16 ;read the key pressed.
- cmp al,0 ;was it a scan code key?
- jne loc_chat4 ; no, display the key
- cmp ah,K_END ;[End] key exits chat
- je loc_chat_end
- jp SHORT loc_chat1 ;continue, wrong scan key
- loc_chat4: cmp al,ESK ;<ESK> key exits chat
- je loc_chat_end
- call con_putc ;display key received
- cmp al,CR
- jne loc_chat1 ;if carriage return,
- mov al,LF ; send a line feed also.
- call con_putc
- jp SHORT loc_chat1
- loc_chat_end: mov al,ON ;toggle for int state
- mov ah,INT_RX ;set rx-interrupt mode
- call port_imode ;change interrupt mode
- call rx_flush
- mov al,CR ;send a new line on exit.
- call con_putc
- mov al,LF
- call con_putc
- ret
-
- loc_chat ENDP
- ;
- ; Toggle the system bell enable flag
- ;
- loc_bell PROC near
-
- mov bl,int10_merge
- push bx
- mov int10_merge,NULL
- mov si,OFFSET bell_msg
- call con_puts
- mov al,bell_flg ;get current bell state
- xor al,YES ;now toggle it.
- cmp al,NULL ;is it on?
- mov si,OFFSET on_msg
- jne loc_bell1
- mov si,OFFSET off_msg
- loc_bell1: call con_puts
- mov bell_flg,al ;set new bell state
- pop bx
- mov int10_merge,bl
- ret
-
- loc_bell ENDP
- ;
- ; Perform local clear screen function.
- ;
- loc_scrn PROC near
-
- mov cx,0
- mov ax,0700h ;clear the screen
- mov dx,184fh
- mov bx,0700h
- pushf
- call old_int10
- mov ah,2 ;home the cursor
- mov dx,0
- mov bx,0
- pushf
- call old_int10
- ret
-
- loc_scrn ENDP
- ;
- ; Give caller online sys/op privledges.
- ;
- loc_sysop PROC near
-
- mov si,OFFSET sysop_msg
- call con_puts
- mov cstat,0FFFFh ;caller status byte
- ret
-
- loc_sysop ENDP
- ;
- ; Display caller name buffer locally.
- ;
- loc_caller PROC near
-
- mov bl,int10_merge
- mov int10_merge,NULL
- mov si,OFFSET caller_msg
- call con_puts
- mov si,OFFSET namebuf
- call con_puts
- mov al,']'
- call con_putc
- mov int10_merge,bl
- ret
-
- loc_caller ENDP
- ;
- ;
- PAGE
- SUBTTL *** RS232 Service Routines ***
- ;---RS232-INTERRUPT-SERVICE-ROUTINES------------------------------------
- ; This is the interrupt main service routine for the serial port.
- ; This routine is called due to one of the following occurances:
- ;
- ; Priority: (1) Received Data register has character.
- ; (2) Transmitter Holding register empty (Not Used Yet!).
- ; (3) Change in modem CD status (Carrier Detect).
- ;
- ; When the interrupt occurs the interrupt identification register is
- ; read to check for which class of interrupt occured and call the
- ; appropriate function to handle the request. Note that more than one
- ; interrupt may have occured at once and the interrupt id register
- ; must be checked for any pending interrupts before exiting.
- ;-----------------------------------------------------------------------
- ;
- rs232_serv PROC far
-
- sti ;restart interrupts first!
- push ax ;save registers
- push bx
- push cx
- push dx
- push di
- push si
- push ds
-
- mov ax,cs ;DS=CS
- mov ds,ax
- ;
- ; Check the 8259 interrupt controller for any other interrupts that
- ; may be pending. More than one may have occured at same time!
- ;
- rs232_serv0: mov dx,PORT_BASE+2 ;interrupt id register
- in al,dx ;read interrupt id code
- test al,1 ;test for interrupts pending
- jnz rs232_exit ;no more to service, exit!
- mov bl,al ;set table index in lsb
- xor bh,bh ;clear the msb
- call cs:rs232_jmp[bx] ;call appropriate service rtn
- jmp SHORT rs232_serv0 ;check for other pending ints
- ;
- ; Signal the 8259 interrupt controller that we are done.
- ;
- rs232_exit: cli ;halt interrupts temporarily
- mov al,EOI ;send EOI command to the
- out IO_8259,al ; 8259 interrupt controller.
- sti ;now re-enable interrupts
- cmp pause_req,NULL ;Ctrl-S pause requested?
- je rs232_exit1 ; no, exit from interrupt.
- cmp pause_flg,NULL ;Is pause already in effect?
- jne rs232_exit1 ; yes, exit from interrupt.
- call pause_rtn ;fall into pause loop until
- ;another rx interrupt occurs.
- rs232_exit1: pop ds
- pop si
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
- iret
-
- rs232_serv ENDP
- ;
- ; Jump table of routines to call on interrupt request
- ;
- rs232_jmp dw OFFSET stat_serv ;service modem status change
- dw OFFSET tx_serv ;service tx-routine
- dw OFFSET rx_serv ;service rx-routine
- ;
- ;
- ;---PAUSE-ROUTINE-------------------------------------------------------
- ; This routine handles the pause routines, generated by a Ctrl-S being
- ; received at the serial port, if control key trapping is enabled.
- ;-----------------------------------------------------------------------
- ;
- pause_rtn PROC near
-
- mov pause_flg,ON ;signal pause in effect
- mov ah,15
- int 10h ;get video mode
- cmp al,2 ;if CGA is found make sure
- je vmode2 ; its enabled before pause
- cmp al,3
- je vmode3
- jmp SHORT pause0 ;else, no re-enable needed.
- vmode2: mov al,2Dh ;re-enable value mode 2
- jmp SHORT pause0
- vmode3: mov al,29h ;re-enable value mode 3
- mov dx,3D8h ;cga control register
- out dx,al ;send it to the cga
- ;
- ; Now wait in a loop for another receive interrupt to occur or
- ; for the timer to timeout and return control.
- ;
- pause0: mov cx,TIMEOUT*8 ;set up time out delay
- pause1: cmp pause_req,NULL ;has another interrupt occured
- je pause_end ; to cut off pause?
- pause2: cmp tout_flg,NULL ;any timeout?
- je pause1 ; no,loop back
- mov ax,2 ;else
- call timer ; wait 1/9th sec
- loop pause1 ;loop if no timeout yet
- pause_end: mov pause_req,NULL ;reset pause request
- mov pause_flg,NULL ;pause no longer active
- ret
-
- pause_rtn ENDP
- ;
- ;
- ;---RX-SERVICE-ROUTINE--------------------------------------------------
- ; This routine is called every time a character arrives at the serial
- ; port. The data is placed in the circular rx-queue and the buffer
- ; pointers are incremented.
- ;-----------------------------------------------------------------------
- ;
- rx_serv PROC near
-
- mov dx,PORT_BASE ;rx-data register
- in al,dx ;get data from port
- mov dx,PORT_BASE+5 ;line status register
- mov bl,al ;save character in BL
- in al,dx ;read line status register
- test ah,00011110b ;receive error?
- jnz rx_nerr ;jmp if no rx-error
- mov bl,0FBh ;force error to 'check' char
- rx_nerr: mov al,bl ;restore char from BL
- ;
- ; The character is in the AL reg now, check for special characters.
- ;
- cmp pause_req,NULL ;if pause is off, skip
- je rx_serva ; pause reset,
- mov pause_req,NULL ;else, reset pause and
- ret ; exit.
- rx_serva: cmp trap_flg,NULL ;dont trap any ctrl-chars if
- je rx_serv0 ; trap is off.
-
- rx_servb: cmp al,CTRL_C ;check for ^C break.
- jne rx_servc
- cmp brk_flg,NULL ;skip if break off
- je rx_servd
- int 1Bh ;issue a break program interrupt
- rx_reset: mov rx_head,0 ;reset the rx queue
- mov rx_tail,0
- mov rx_cnt,0
- ret ; and exit
-
- rx_servc: cmp al,CTRL_S ;check for ^S pause.
- jne rx_serv0
- mov pause_req,ON ;set the pause request flag on
- rx_servd: ret ; and exit
- ;
- ; Put the character in the rx-queue and adjust the queue pointers.
- ;
- rx_serv0: mov bx,rx_tail ;get the end pointer
- mov [rx_buf+bx],al ;put char in the queue
- inc rx_cnt ;inc cnt for char added
- inc bx ;advance the pointer
- cmp bx,RX_BUFF ;wrapped around yet?
- jl rx_serv1
- mov bx,0 ;yes, wrap around
- rx_serv1: cmp bx,rx_head ;is the buffer full?
- je rx_serv3 ;yes, next char overwrites
- mov rx_tail,bx ;new end of queue
- ret
- rx_serv3:
- IF USE_RTS
- mov rts_flg,OFF ;set flg signaling RTS is off
- mov ax,OFF
- call port_rts ;now drop the RTS line
- ELSE
- jmp SHORT rx_reset
- ENDIF
- rx_serv_end: ret
-
- rx_serv ENDP
- ;
- ;
- ;---TX-SERVICE-ROUTINE--------------------------------------------------
- ; DUMMY FUNCTION -- Tx-interrupts are not implemented yet!
- ;-----------------------------------------------------------------------
- ;
- tx_serv PROC near
-
- ret
-
- tx_serv ENDP
- ;
- ;
- ;---STATUS-SERVICE-ROUTINE----------------------------------------------
- ; This routine is called every time a change in modem status is found.
- ; This routine checks for loss of carrier and resets if carrier is lost.
- ;-----------------------------------------------------------------------
- ;
- stat_serv PROC near
-
- call port_cd ;CD pin pulled high?
- jc stat_exit ;jmp if CD found
- mov cd_lost,YES ;set carrier lost flg
- cmp cd_check,NULL ;checking CD status?
- je stat_exit ;no, exit
- mov int10_merge,NULL ;skip the modem
- mov int16_merge,NULL ;skip the keyboard
- mov si,OFFSET lost_msg ;show carrier lost message
- call con_puts
- mov ax,OFF ;turn off dtr/rts, hang up
- call port_dtr
- mov ax,2 ;wait a second
- call delay ;fall through and wboot
- call boot_sys ;re-boot the system!
- stat_exit: ret
-
- stat_serv ENDP
- ;
- ;-----------------------------------------------------------------------
- ; *** END OF INTERRUPT SERVICE ROUTINES ***
- ;-----------------------------------------------------------------------
- ;
- ;
- PAGE
- SUBTTL *** Receive Data Routines ***
- ;-RX-READY--------------------------------------------------------------
- ; Set the zero flag if the rx-queue is empty, else clear the zero
- ; flag to indicate that data is available in the queue.
- ;
- ; Return: Zero Flag set = NO data in queue.
- ; Zero Flag reset = data waiting in queue.
- ;
- ;-----------------------------------------------------------------------
- ;
- rx_ready PROC near
-
- cli ;halt all interrupts
- push bx
- or bl,bl ;clear zero flag
- mov bx,rx_head ;fetch the pointers
- cmp bx,rx_tail ;if head=tail, no data!
- pop bx
- sti ;restart interrupts
- ret
-
- rx_ready ENDP
- ;
- ;
- ;-RX-GET-CHARACTER------------------------------------------------------
- ; Get a character from the rx-queue. If the character is not available
- ; return an EOF to signal an error. (All other registers preserved)
- ;
- ; Return: AX = EOF if error.
- ; AL = Character received
- ; AH = NULL (scan codes not supported)
- ;
- ;-----------------------------------------------------------------------
- ;
- rx_getc PROC near
-
- cli ;halt all interrupts
- push bx
- mov ax,EOF ;assume error
- mov bx,rx_head ;fetch the pointers
- cmp bx,rx_tail ;if head=tail, no data!
- je rx_getc3 ;no, exit with eof
- mov al,[rx_buf+bx] ;get data from head ptr
- xor ah,ah ;clear the msb scan code
- dec rx_cnt ;dec cnt after removal
- inc bx ;advance head ptr
- cmp bx,RX_BUFF ;wrapped around?
- jl rx_getc2 ; no, update head ptr
- mov bx,0 ; yes, wrap ptr around
- rx_getc2: mov rx_head,bx ;update the ptr
- rx_getc3: pop bx ;restart interrupts
- sti
- ret
-
- rx_getc ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; RX FLUSH -- Empty all characters from the mdm receive port
- ;-----------------------------------------------------------------------
- ;
- rx_flush PROC near
-
- cli
- mov rx_head,0 ;reset head pointer
- mov rx_tail,0 ;reset tail pointer
- mov rx_cnt,0 ;reset counter
- sti
- ret
-
- rx_flush ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; RX SIZE -- Return the number of characters in the rx-queue.
- ;
- ; Return: AX = Characters in rx-queue.
- ;
- ;-----------------------------------------------------------------------
- ;
- rx_size PROC near
-
- cli
- mov ax,rx_cnt ;get the count
- sti
- ret
-
- rx_size ENDP
- ;
- ;
- PAGE
- SUBTTL *** Transmit Data Routines ***
- ;-----------------------------------------------------------------------
- ; TX PUTS - This function transmits the buffer pointed to by the AX
- ; register for CL bytes. AL & CL register destroyed, all others are
- ; preserved. This function does not use nulls translation.
- ;
- ; Entry: DS:SI -- buffer to transmit
- ; CL -- count of bytes to transmit
- ;
- ;-----------------------------------------------------------------------
- ;
- tx_puts PROC near
-
- xor ch,ch ;clear the msb
- cld ;clear direction flag
- tx_puts1: lodsb ;get a byte from string
- call tx_putc ;send the data
- loop tx_puts1
- ret
-
- tx_puts ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; MODEM TX CHARACTER -- Send a character to modem through com port.
- ; If the character sent was a line feed (LF) and 'nulls' greater that 0,
- ; then nulls are sent after the line feed. (All registers preserved)
- ;
- ; Entry: AL - Character to send
- ;
- ;-----------------------------------------------------------------------
- ;
- tx_char PROC near
-
- call tx_putc ;now send the character
- IF USE_NULLS
- push cx
- mov cl,nulls ;get # of nulls to send
- xor ch,ch ;clear the msb
- or cx,cx ;check if for any nulls to tx
- jz tx_char2 ;exit if nulls not in effect
- cmp al,LF ;send nulls if a line feed
- jne tx_char2 ;no, skip over if not a LF
- push ax ;save the data
- tx_char1: mov al,0
- call tx_putc ;send a null out
- loop tx_char1 ;loop until CX=0
- pop ax
- tx_char2: pop cx
- ENDIF
- ret
-
- tx_char ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; TRANSMIT CHARACTER -- Send a character to modem through com port.
- ; All registers used are saved before sending the char. Note that in
- ; order to transmit a byte, that DSR and CTS must be active.
- ;
- ; Entry: AL - Character to send
- ;
- ;-----------------------------------------------------------------------
- ;
- tx_putc PROC near
-
- push dx
- push ax
-
- mov dx,PORT_BASE+6 ;modem status register
- tx_putc1: in al,dx ;read port status
- and al,030h ;check DSR & CTS
- jz tx_putc1 ;loop until DSR & CTS
- dec dx ;line status register
- tx_putc2: in al,dx ;read port status
- and al,20h ;check tx hold reg empty
- jz tx_putc2 ;loop until tx complete
- sub dx,5 ;data port register
-
- pop ax ;recover data to send
- out dx,al ;send the character
- pop dx ;restore dx
- ret
-
- tx_putc ENDP
- ;
- ;
- PAGE
- SUBTTL *** RS232 Port Control Routines ***
- ;-----------------------------------------------------------------------
- ; PORT CARRIER DETECT -- Read the modem CD pin from COM status port
- ;
- ; Exit: CARRY FLAG SET = Carrier Detect (CD) found
- ;
- ;-----------------------------------------------------------------------
- ;
- port_cd PROC near
-
- push dx
- push ax
-
- cli
- mov dx,PORT_BASE+6 ;mdm status register
- or al,al ;clear the carry flag
- in al,dx ;get the port status
- rcl al,1 ;rotate left through carry
- sti
-
- pop ax
- pop dx
- ret
-
- port_cd ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; PORT DTR -- Toggle the DTR/RTS line to the modem
- ;
- ; Entry: AX == 0 DTR/RTS off
- ; AX <> 0 DTR/RTS on
- ;
- ;-----------------------------------------------------------------------
- ;
- port_dtr PROC near
-
- push bx
- push dx
-
- cli
- mov bx,ax ;save state flag
- mov dx,PORT_BASE+4 ;modem control register
- in al,dx
- or bx,0 ;turn on or off?
- jz port_dtr0
- or al,00000011b ;DTR/RTS bits on
- jmp SHORT port_dtr1
- port_dtr0: and al,11111100b ;DTR/RTS bits off
- port_dtr1: mov dx,PORT_BASE+4 ;modem control register
- out dx,al
- sti
-
- pop dx
- pop bx
- ret
-
- port_dtr ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; PORT RTS -- Toggle only the RTS line to the modem
- ;
- ; Entry: AX == 0 RTS off
- ; AX <> RTS on
- ;
- ;-----------------------------------------------------------------------
- ;
- IF USE_RTS
- port_rts PROC near
-
- push bx
- push dx
-
- cli
- mov bx,ax ;save state flag
- mov dx,PORT_BASE+4 ;modem control register
- in al,dx
- or bx,0 ;turn on or off?
- jz port_rts0
- or al,00000010b ;RTS bits on
- jmp SHORT port_rts1
- port_rts0: and al,11111101b ;RTS bits off
- port_rts1: mov dx,PORT_BASE+4 ;modem control register
- out dx,al
- sti
-
- pop dx
- pop bx
- ret
-
- port_rts ENDP
- ENDIF
- ;
- ;
- ;-----------------------------------------------------------------------
- ; ASYNC PORT BAUD RATE SET -- Set the baud rate of the 8250.
- ;
- ; Entry: AX = Baud rate baud rate initialization value.
- ;
- ;-----------------------------------------------------------------------
- ;
- port_baud PROC near
-
- push dx
-
- cli
- push ax
- mov dx,PORT_BASE+3 ;line control register
- in al,dx
- or al,10000000b ;set DLAB = 1
- out dx,al
- pop ax
- mov dx,PORT_BASE
- out dx,al ;send the lsb
- inc dx
- mov al,ah
- out dx,al ;send the msb
-
- mov dx,PORT_BASE+3 ;line control register
- in al,dx
- and al,not 10000000b ;set DLAB = 0
- out dx,al
- mov al,00000011b ;no parity, 8 bits, 1 stop bit
- out dx,al
- sti
-
- pop dx
- ret
-
- port_baud ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; ASYNC PORT INTERRUPT START -- Starts the interrupts from the 8250.
- ; This routine sets up all the interrupt registers on the 8250 and
- ; on the 8259 interrupt controller for interrupts. The default start
- ; mode is for Rx/Tx interrupts only, modem status is enabled after
- ; a caller is online to check for carrier detect lost.
- ;-----------------------------------------------------------------------
- ;
- port_start PROC near
-
- mov dx,PORT_BASE+3 ;line control register
- in al,dx
- and al,not 10000000b ;set DLAB = 0
- out dx,al
- mov dx,PORT_BASE ;data holding register
- in al,dx ;flush any Rx-data out
- ;
- ; 1) Set the correct bit in the 8259 interrupt controller to enable
- ; the IRQ4 interrupts from the serial port.
- ;
- pushf ;save interrupt status
- cli ;stop interrupts temporarily
- mov cl,not IRQ_BASE ;set the IRQ4 bit ON to 8259
- in al,21h ;read 8259 status
- and al,cl ;set bit to zero to enable
- out 21h,al ;update new interrupt status
- ;
- ; 2) At base+3 cut off the DLAB bit to allow access to the
- ; interrupt enable register (EIR).
- ;
- mov dx,PORT_BASE+3
- in al,dx ;read current status
- and al,not 10000000b
- out dx,al ;turn off DLAB
- ;
- ; 3) At base base+1 (IER), enable interrupts to the 8250
- ;
- mov dx,PORT_BASE+1 ;8250 interrupt enable register
- mov al,00000000b ;enable rx interrupts to start
- out dx,al
- ;
- ; 4) At base base+4 (mdm control), enable OUT2 signal
- ;
- mov dx,PORT_BASE+4 ;modem control register
- in al,dx
- or al,00001000b ;set the out2 bit
- out dx,al ;send update
- popf ;restore interrupt status
- ;
- ; Interrupts are enabled and will load the first character ready
- ;
- call clear_pints ;clear any pending interrupts
- ret
-
- port_start ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; ASYNC PORT INTERRUPT STOP -- Stops the interrupts from the 8250.
- ; This routine resets all the interrupt registers on the 8250 and
- ; on the 8259 interrupt controller.
- ;-----------------------------------------------------------------------
- ;
- port_stop PROC near
-
- ;
- ; 1) Set the correct bit in the 8259 interrupt controller to disable
- ; the IRQ4 interrupts from the serial port.
- ;
- pushf ;save interrupt status
- cli ;stop interrupts temporarily
- mov cl,00010000b ;set the IRQ4 bit OFF to 8259
- in al,21h ;read 8259 status
- or al,cl ;set bit to 'one' to disable
- out 21h,al ;update new interrupt status
- ;
- ; 2) At base+3 cut off the DLAB bit to allow access to the
- ; interrupt enable register (EIR).
- ;
- mov dx,PORT_BASE+3
- in al,dx ;read current status
- and al,not 10000000b
- out dx,al ;turn off DLAB
- ;
- ; 3) At base base+1 (IER), disable interrupts to the 8250
- ;
- mov dx,PORT_BASE+1 ;8250 interrupt enable register
- mov al,00000000b ;disable all interrupts
- out dx,al
- ;
- ; 4) At base base+4 (mdm control), disable OUT2 signal
- ;
- mov dx,PORT_BASE+4 ;modem control register
- in al,dx
- and al,not IRQ_BASE ;reset the out2 bit
- out dx,al ;send update
- popf ;restore interrupt status
- ret
-
- port_stop ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; ASYNC INTERRUPT MODE -- This routine sets the interrupts modes for
- ; the comm port either on or off.
- ;
- ; Entry:
- ;
- ; AL = Mode (0=OFF, 1=ON)
- ;
- ; AH = 0 -- Set the Rx-Interrupt mode
- ; AH = 1 -- Set the Tx-Interrupt mode
- ; AH = 2 -- Set the Modem Status Interrupt mode
- ;
- ;-----------------------------------------------------------------------
- ;
- port_imode PROC near
-
- push ax
- push bx
- push cx
- pushf ;save interrupt status
- cli ;stop interrupts temporarily
-
- mov bl,al
- or ah,ah
- mov bh,00000001b
- jz imode0 ;rx-interrupts?
- dec ah
- mov bh,00000010b
- jz imode0 ;tx-interrupt?
- dec ah
- mov bh,00001000b
- jz imode0 ;modem status interrupts?
- jmp SHORT imode_end
- ;
- ; 1) At base+3 cut off the DLAB bit to allow access to the
- ; interrupt enable register (EIR).
- ;
- imode0: mov dx,PORT_BASE+3
- in al,dx ;read current status
- and al,not 10000000b
- out dx,al ;turn off DLAB
- ;
- ; 2) At base base+1 (IER), set interrupts to the 8250
- ;
- mov dx,PORT_BASE+1 ;8250 interrupt enable register
- in al,dx ;read current interrupt state
- or bl,bl ;test for on/off flag
- jnz imode1
- not bh ;set the bit off
- and al,bh
- jmp SHORT imode2
- imode1: or al,bh ;set the bit on
- imode2: out dx,al ;send new interrupt mode
-
- imode_end: popf ;restart interrupts
- pop cx
- pop bx
- pop ax
- ret
-
- port_imode ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; CLEAR PENDING INTERRUPTS -- Clear any pending interrupts from the
- ; 8250 and the 8259 interrupt controller.
- ;-----------------------------------------------------------------------
- ;
- clear_pints PROC near
-
- mov dx,PORT_BASE+2 ;(IIR) interrupt id register
- in al,dx
- test al,1
- jnz clear_exit ;exit if none pending
- xor bh,bh
- mov bl,al
- call cs:clr_jmp[bx] ;clear the interrupt
- jmp SHORT clear_pints
- clear_exit: ret
- ;
- ; Jump table of routines to call clear interrupts
- ;
- clr_jmp dw OFFSET clr_stat ;clear modem status
- dw OFFSET clr_tx ;clear tx-routine
- dw OFFSET clr_rx ;clear rx-routine
- ;
- ; Clear the interrupt based on the interrupt id code
- ;
- clr_stat: mov dx,PORT_BASE+6 ;cleared by reading
- in al,dx ; modem status reg.
- ret
-
- clr_tx: ret ;cleared from reading IIR
-
- clr_rx: mov dx,PORT_BASE ;cleared by reading rx-data
- in al,dx ; register.
- ret
-
- clear_pints ENDP
- ;
- ;
- PAGE
- SUBTTL *** Utility Routines ***
- ;----------------------------------------------------------------------
- ; *** These routines compliments of William C. Bryan ***
- ;
- ; This routine has two entry points. One entry point allows timing
- ; in 18ths of seconds, and the other entry point allows in seconds.
- ;----------------------------------------------------------------------
- ;
- ; TIMER -- provides a hardware delay timing in 18ths of a second
- ;
- ; Entry: AX = # of 1/18th seconds to delay (65535 Max)
- ;
- ;----------------------------------------------------------------------
- ;
- ; DELAY -- provides a hardware delay timing in seconds
- ;
- ; Entry: AX = # of seconds to delay. (60 Minutes Max)
- ;
- ;----------------------------------------------------------------------
- ;
- timer PROC near
-
- push ax ;save all registers changed
- push bx
- push cx
- push dx
-
- begin: call getticks ;read present time into DX
- add dx,ax
- adc cx,0
- cmp cx,018h ;check for 24 hour rollover
- jl timer0
- cmp dx,0B0h
- jl timer0
- sub dx,0B0h ;correct for rollover
- sbb cx,018h
- timer0: mov bx,dx ;AX:BX = Match time
- mov ax,cx
- timer1: call getticks
- cmp dx,bx ;compare match time to current time
- jne timer1 ; as a long value
- cmp cx,ax
- jne timer1
-
- pop dx ;restore altered registers
- pop cx
- pop bx
- pop ax
- ret
-
- delay LABEL near
-
- push ax ;save all registers changed
- push bx
- push cx
- push dx
-
- mov cx,ax ;provide correction for 18.2 ms timing
- mov ax,182 ;TICKRATE = 18.2 times per second / 10
- mul cx ;multiply CX * TICKRATE
- mov cx,10
- div cx ;now divide by ten, final value in AX
- jmp SHORT begin
-
- timer ENDP
- ;
- ;
- ;----------------------------------------------------------------------
- ; GETTICKS -- get the current BIOS clock ticks value and return
- ; long value in the DX:CX register.
- ;----------------------------------------------------------------------
- ;
- getticks PROC near
-
- push ax ;save ax reg
- xor ah,ah
- int 1Ah ;read time of day
- pop ax ;restore ax
- ret
-
- getticks ENDP
- ;
- ;
- ;----------------------------------------------------------------------
- ; BEEP -- Emit a tone for 'BL' durations of ~500ms each.
- ;----------------------------------------------------------------------
- ;
- beep PROC near
-
- push ax
- push cx
- mov al,10110110B ;timer mode2, lsb,msb,bin
- out PORT_TM+3,al ;write to timer mode reg
- mov ax,533h ;divisor for 1000hz
- out PORT_TM+2,al ;write timer 2 cnt, lsb.
- mov al,ah
- out PORT_TM+2,al ;write timer 2 cnt, msb.
- in al,PORT_PB ;read port setting
- mov ah,al ;save port register
- or al,3 ;turn on the speaker
- out PORT_PB,al
- sub cx,cx
- beep1:
- loop beep1 ;delay loop
- dec bl
- jnz beep1 ;loop until BL = 0
- mov al,ah ;recover port state
- out PORT_PB,al ;restore port state
- pop cx
- pop ax
- ret
-
- beep ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; CONSOLE PUT CHARACTER -- Print a character on the console and remote.
- ;
- ; Entry: AL - Character to Print locally and remote
- ;
- ;-----------------------------------------------------------------------
- ;
- con_putc PROC near
-
- mov ah,0Eh ;write tty function
- int 10h ;video bios int
- ret
-
- con_putc ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; CONSOLE PUT STRING -- Send the console a string at DS:DI. The string
- ; must contain a "$" or null character to signal the end of the string.
- ; If 'int10_skip' is non-zero, characters will not be sent to the modem.
- ;
- ; Entry: DS:SI - Points to the string of chars to send
- ;
- ;-----------------------------------------------------------------------
- ;
- con_puts PROC near
-
- push ax
- cld
- con_puts1: lodsb ;get a byte from string
- cmp al,'$' ;if '$', end of string
- je con_puts2
- cmp al,0 ;if null, end of string
- je con_puts2
- mov ah,0Eh ;write tty function
- int 10h ;video bios int
- jmp SHORT con_puts1 ;continue looping
- con_puts2: pop ax
- ret
-
- con_puts ENDP
- ;
- ;
- ; -- All code after this point is trashed after loading --
- ;
- end_resident:
- ;
- PAGE
- SUBTTL *** Initialization and Loader Routines ***
- ;
- ;-----------------------------------------------------------------------
- ;--------------------- Start of Loader Code ----------------------------
- ;-----------------------------------------------------------------------
- ;
- ; NOTE: All code after this point is trashed after the connection
- ; to remote station is established.
- ;
- ;-----------------------------------------------------------------------
- ;
- init_msg db 0Dh,0Ah
- db "BYE-PC for the IBM Personal Computer - Version "
- db PGM_VER+'0',".0",PGM_REV+'0',0Dh,0Ah
- db "Copyright (C) MCODE Software 1986, 1987. All rights reserved", 0Dh,0Ah
- db "[Local Control use Ctrl-C]"
- IFE SMART_MDM
- db 0Dh,0Ah,0Dh,0Ah,"Waiting for call...$"
- ELSE
- db 0Dh,0Ah,0Dh,0Ah,"$"
- ENDIF
-
- halt_msg db 0Dh,0Ah
- IFE SMART_MDM
- db 0Dh,0Ah
- ENDIF
- IF LOGON_EXE
- db "PRESS: <E>xecute locally",0Dh,0Ah
- db " <R>esume Call Wait",0Dh,0Ah
- ELSE
- db "PRESS: <R>esume Call Wait",0Dh,0Ah
- ENDIF
- db " Return",17,196,217," exit to DOS$"
-
- exit_msg db 0Dh,0Ah,0Dh,0Ah
- db "Exiting BYE-PC...."
- db 0Dh,0Ah, "$"
-
- bye_msg db 0Dh,0Ah
- db " Goodbye, call again...."
- db 0Dh,0Ah,0Dh,0Ah, "$"
-
- crlf db 0Dh,0Ah,"$"
-
- mdm_nulls db 0Dh,0Ah
- db "Nulls, if needed, (0-9)? ","$"
-
- mdm_flunk db 0Dh,0Ah,0Dh,0Ah
- db "You flunked the (0-9) IQ test...Bye!"
- db 0Dh,0Ah,0Dh,0Ah, "$"
-
- IF SMART_MDM
- error_msg1 db 0Dh,0Ah
- db "[ERROR: Modem Initialization!]",0Dh,0Ah
- db "$"
- ENDIF
-
- IF LOGON_EXE
- free_err_msg db 0Dh,0Ah
- db "[ERROR: Releasing Memory!]",0Dh,0Ah
- db 0Dh,0Ah,0Dh,0Ah, "$"
-
- exec_err_msg db 0Dh,0Ah
- db "[ERROR: Executing .COM or .EXE file!]",0Dh,0Ah
- db 0Dh,0Ah,0Dh,0Ah, "$"
- ENDIF
-
- IF SMART_MDM
- mdm_init db "ATE0F1Q0V0M0"
- IF BPS_2400
- db "X2"
- ELSE
- db "X1"
- ENDIF
- db "S0=0S2=3S10=25"
- ENDIF
- IF TELEBIT
- db "S50=0S51=4S52=1S53=1S55=2S58=2S66=1S68=2"
- ENDIF
- db 0Dh,0Ah,"$"
-
- IF SMART_MDM
- mdm_reset db "ATZ",0Dh,0Ah,"$"
- mdm_atten db "AT",0Dh,0Ah,"$"
- mdm_answer db "ATA",0Dh,0Ah,"$"
- mdm_noanswer db "ATS0=0",0Dh,0Ah,"$"
- ENDIF
-
- msg_nocd db 0Dh,0Ah
- db "[No Carrier]"
- db 0Dh,0Ah,"$"
-
- msg_300 db "[300 bps]",0Dh,"$"
-
- IF BPS_1200 OR BPS_2400 OR TELEBIT
- msg_1200 db "[1200bps]",0Dh,"$"
- ENDIF
-
- IF BPS_2400 OR TELEBIT
- msg_2400 db "[2400bps]",0Dh,"$"
- ENDIF
-
- IF TELEBIT
- msg_tbit db "[Highspeed PEP]",0Dh,"$"
- ENDIF
- ;
- locl_flg db NO ;local control flag
- res_buf db 16 dup(0) ;modem results code buffer
- ;
- ;
- PAGE
- ;-----------------------------------------------------------------------
- ; Load and Initialize the Program
- ;-----------------------------------------------------------------------
- ; INITIALIZE check to see if BYE-PC is already installed. If it is,
- ; hangup the modem and re-boot for the next call. Otherwise, store all
- ; of the interrupts present locations, setup rs232 interrupt vector and
- ; intialize the modem and wait for a call.
- ;
- ; NOTE: All subroutines after this point may not be called from
- ; above this point, as they are discarded after loading.
- ;
- ;-----------------------------------------------------------------------
- ;
- initialize PROC near
-
- mov ax,cs ;DS = CS
- mov ds,ax
- ;
- ; check for BYE already active.
- ;
- mov ax,3516h ;get vector
- int 21h
- cmp es:bye_sign,1234h ;bye signiture
- jne load_bye ;bye not present, load it
- ;
- ; Bye is already loaded, say goodby, hangup, and re-boot system
- ;
- mov ah,INT_STAT ;mdm status interrupts.
- mov al,OFF ;turn off status ints
- call port_imode ; for loss of carrier.
- mov si,OFFSET bye_msg ;send goodbye message
- call con_puts ; to console and mdm.
- mov ax,OFF ;hang up the modem.
- call port_dtr
- mov ax,2 ;wait a sec or two
- call delay
- mov ax,ON ;turn dtr back on
- call port_dtr
- IF SMART_MDM
- mov si,OFFSET mdm_noanswer ;tell the mdm to not
- call mdm_puts ; answer any calls
- ENDIF
- mov ax,2 ;wait a sec or two
- call delay
-
- ASSUME ds:rom_bios_data ;boot the system
- wboot_sys: mov ax,rom_bios_data ;set DS to rom bios data
- mov ds,ax ; area.
- mov reset_flag, 1234h ;set the alt-ctrl-del flag.
- db 0EAH ;jmp to the specified:
- dw WBOOT_OFF ; OFFSET
- dw WBOOT_SEG ; segment
- ASSUME ds:code
- ;
- ; Wait for call re-vector interrupts to BYE intercept routines
- ;
- load_bye: mov ah,25h ;set rs232 vector
- mov al,RS232_INT
- mov dx, OFFSET rs232_serv ;set new rs232 int
- int 21h ;make dos call
-
- mov ax,3509h ;dos get vector function
- int 21h ;make dos call
- mov WORD PTR [old_int09],bx ;set asside old vector to
- mov WORD PTR [old_int09 + 2],es ; allow pass to Bios L
-
- mov ax,3510h ;dos get vector function
- int 21h ;make dos call
- mov WORD PTR [old_int10],bx ;set asside old vector to
- mov WORD PTR [old_int10 + 2],es ; allow pass to Bios
-
- mov ax,3513h ;dos get vector function
- int 21h ;make dos call
- mov WORD PTR [old_int13],bx ;set asside old vector to
- mov WORD PTR [old_int13 + 2],es ; allow pass to Bios
-
- mov ax,3516h ;dos get vector function
- int 21h ;make dos call
- mov WORD PTR [old_int16],bx ;set asside old vector to
- mov WORD PTR [old_int16 + 2],es ; allow pass to Bios
-
- mov ax,351Ch ;dos get vector function
- int 21h ;make dos call
- mov WORD PTR [old_int1C],bx ;set asside old vector to
- mov WORD PTR [old_int1C + 2],es ; allow pass to Bios
- ;
- ; Wait for a call, then replace the interrupt vectors with the new ones.
- ;
- call call_wait ;wait for a call
-
- mov ax,2509h ;dos set vector function
- mov dx, OFFSET int09_main ;set new keybd int
- int 21h ;make dos call
-
- mov ax,2510h ;dos set vector function
- mov dx, OFFSET int10_main ;set new video int
- int 21h ;make dos call
-
- mov ax,2513h ;dos set vector function
- mov dx, OFFSET int13_main ;set new disk int
- int 21h ;make dos call
-
- mov ax,2516h ;dos set vector function
- mov dx, OFFSET int16_main ;set new keyboard int
- int 21h ;make dos call
-
- mov ax,251Ch ;dos set vector function
- mov dx, OFFSET int1C_main ;set up timer tick int
- int 21h ;make dos call
-
- mov ax,2566h ;dos set vector function
- mov dx, OFFSET int66_main ;set BYE control int
- int 21h ;make dos call
- ;
- ; Execute .EXE/.COM file upon after modem is logged on
- ;
- mov trap_flg,ON ;enable ^S & ^C trapping
- IF LOGON_EXE
- cmp locl_flg,NULL ;if local, cut of mdm
- je run_local ; to screen & keybd.
- mov int10_merge,NULL ;data 'to' mdm off
- mov int16_merge,NULL ;data 'from' mdm off
- run_local: mov brk_flg,NULL ;disable remote Ctrl-C
- call free_mem ;free memory after loader
- call exec_pgm ;run external program
- ENDIF
- ;
- ; Calculate the size of the program and load resident portion.
- ;
- IF REBOOT
- cmp locl_flg,NULL ;if local re-boot
- je run_local1
- mov ax,2 ;wait a couple secs
- call delay
- jmp wboot_sys
- ENDIF
-
- run_local1: mov dx,OFFSET end_resident ;get end of program area.
- mov cl,4 ;resident cant do with an
- shr dx,cl ; expression because assembler
- inc dx ; can't calc w/relocatable label.
- mov ax,3100h ;dos make resident function.
- int 21h ;terminate be stay resident.
-
- initialize ENDP
- ;
- ;
- PAGE
- ;-----------------------------------------------------------------------
- ; CALL WAIT -- clears the screen, re-initializes the modem and watches
- ; the modem for any calls. When a call is detected, the modem answers
- ; and the program determines the baud rate of the call. If nulls are
- ; enabled, the caller is prompted for the number of nulls before comp-
- ; leting the connection.
- ;-----------------------------------------------------------------------
- ;
- call_wait PROC near
- ;
- ; Initialize baud rate, turn on DTR/RTS, and start interrupts
- ;
- IF BPS_300
- mov ax,BPS300 ;start at 300 bps
- ENDIF
- IF BPS_1200
- mov ax,BPS1200 ;start at 1200 bps
- ENDIF
- IF BPS_2400
- mov ax,BPS2400 ;start at 2400 bps
- ENDIF
- IF TELEBIT
- mov ax,BPS9600 ;start at 9600 bps
- ENDIF
- call port_baud ;initialize com port
- mov ax,ON ;turn on dtr/rts
- call port_dtr ; and IRQ line.
- call port_start ;enable interrupts
- mov al,ON
- mov ah,INT_RX ;start Rx-interrupts
- call port_imode
-
- call_restart: mov cx,0
- mov ax,0700h ;clear the screen
- mov dx,184fh
- mov bx,0700h
- int 10h
- mov ah,2 ;home the cursor
- mov dx,0
- mov bx,0
- int 10h
- mov si,OFFSET init_msg ;show sign on message
- call con_puts
- ;
- ; Reset and initialize the modem for a phone call.
- ;
- IF SMART_MDM
- mov si,OFFSET mdm_reset ;reset the modem
- call mcon_puts ;send the 'ATZ'
- mov ax,2 ;wait for 2 seconds
- call delay ;wait for delay time
- call rx_flush ;empty trash from Rx buf
- mov si,OFFSET mdm_init ;initialization string
- call mcon_puts
- mov ax,1 ;wait for 1 second
- call delay
- call rx_flush ;empty trash from Rx buf
- mov si,OFFSET mdm_atten ;try to get mdm's attention
- call mdm_puts
-
- reset0: call rx_ready ;any data ready?
- jz reset0 ;no char waiting
- call rx_getc ;is the modem setup ok
- cmp al,'0'
- je reset1
- mov si,OFFSET error_msg1 ;did'nt get back an Ok
- call con_puts ; result code of 0.
- mov al,BELL ;ring the bell
- call con_putc
- mov ax,2 ;wait 2 seconds
- call delay
- jmp call_restart ;try again...
-
- reset1: call con_putc ;show init complete ok
- mov si,OFFSET crlf
- call con_puts
- call rx_flush ;empty trash from Rx buf
- ENDIF
- ;
- ; Wait for modem to ring or a Ctrl-C at the local console.
- ;
- wloop: mov ah,1 ;check for console keys
- int 16h
- jz wloop1 ;jmp if no key
- mov ah,0
- int 16h ;get the key pressed
- cmp al,CTRL_C
- jne wloop1 ;ctrl-c pressed?
- mov si,OFFSET halt_msg ;ask user what to do
- call con_puts
- ;
- ; Ctrl-C was pressed ask the user what he wants to do.
- ;
- wloop0: mov ah,1 ;check for con key press
- int 16h
- jz wloop0 ;jmp if no key
- mov ah,0
- int 16h ;get the key pressed
- cmp al,61h ;check for upper case
- jl wloop2
- cmp al,7Ah
- jg wloop2
- and al,0DFh ;make upper case
-
- wloop2: cmp al,'R' ;'R' to resume call wait
- jne loc_ctrl
- jmp call_restart
- loc_ctrl:
- IF LOGON_EXE
- cmp al,'E' ;'E' execute BYE locally
- jne loc_ctrl1
- mov locl_flg,YES
- jmp getnulls
- ENDIF
-
- loc_ctrl1: cmp al,CR ;CR to exit BYE to DOS
- jne wloop0
- loc_ctrl3: mov si,OFFSET exit_msg
- call con_puts
- mov ax,OFF ;turn off dtr.
- call port_dtr
- call port_stop ;turn off interrupts
- int 20h ;exit to dos
- ;
- ; Check the modem to see if its ringing. If it is not a ring ignore
- ;the data and jump to see if local keyboard has anything.
- ;
- IF SMART_MDM
- wloop1: call rx_ready
- jz wloop ;no char waiting
- call rx_getc ;get char from mdm.
- cmp al,'2' ;mdm sent ringing code?
- jne wloop1 ; no, try again!
- call con_putc ;show character rx-ed
- ELSE
- wloop1: call port_cd ;cd pin active?
- jnc wloop ;jmp if cd not found
- ENDIF
- ring: mov si,OFFSET crlf ;send a crlf
- call con_puts
- mov ax,2 ;wait a sec for modem to
- call delay ; settle.
- IF SMART_MDM
- call rx_flush
- mov si,OFFSET mdm_answer ;answer the phone call
- call mcon_puts ;send the 'ATA' to modem
- ENDIF
- ;
- ; Get the status of the modem answer request. If no carrier was found
- ; hang up the modem and recycle for the next call.
- ;
- IF SMART_MDM
- mov ax,2 ;wait about 1/2 sec
- call delay
-
- mov cx,4 ;up to 4 chars at max
- mov di,OFFSET res_buf ;ptr to input buffer
- call mdm_gets ;get a string from mdm
- mov si,OFFSET res_buf
- call con_puts ;display result code
-
- mov ax, WORD PTR res_buf ;read first 2 bytes
- mov baud,0
- mov bl, '1' ;code "1" = 300bps
- mov bh,0 ;Bell 103 compatable
- cmp bx,ax
- je answer1
-
- IF BPS_1200 OR BPS_2400 OR TELEBIT
- mov baud,1
- mov bl, '5' ;code "5" = 1200bps
- mov bh,0 ;Bell 212A or V.22
- cmp bx,ax
- je answer1
- ENDIF
-
- IF BPS_2400 OR TELEBIT
- mov baud,2
- mov bl, '1' ;code "10" = 2400bps
- mov bh, '0' ;V.22 compatable
- cmp bx,ax
- je answer1
- ENDIF
-
- IF TELEBIT
- mov baud,3
- mov bl, '5' ;code "50" = 9600bps
- mov bh, '0' ;PEP Protocol
- cmp bx,ax
- je answer1
- ENDIF
-
- no_answer: mov si,OFFSET msg_nocd ;show no carrier msg
- call con_puts
- mov ax,1 ;now wait and recycle
- call delay
- jmp abort_call
- ENDIF
- ;
- ; The modem is now locked on to the remote carrier. We must now make
- ; sure the port is set to the correct baud if not at 1200 buad.
- ;
- answer1:
- mov si,OFFSET crlf ;send a cr/lf to console
- call con_puts
- IF SMART_MDM
- mov ax,2 ;let the modem settle
- ELSE
- mov ax,1 ;let the modem settle
- ENDIF ; after carrier lock!
- call delay
- call rx_flush ;emtpy out rx-buffer
- ;
- ; Check for a CR to sync the baud rate on and to determine buad rate.
- ;
- IF SMART_MDM
- call set_baud ;set from mdm result code
- ELSE
- call sync_baud ;set by sync'ing to cr
- jnc abort_call ;was baud rate set ok?
- ENDIF
- ;
- ; Caller is on-line, baud rate is set; start mdm status interrupts
- ; that check for loss of carrier. Program will re-boot if lost now.
- ;
- mov al,ON ;turn on modem status
- mov ah,INT_STAT ; interrupts to test
- call port_imode ; for loss of carrier.
- ;
- ; Ask the user how many nulls. May need nulls at 2400bps.
- ;
- getnulls:
- IF USE_NULLS
- call ask_nulls ;ask caller for nulls
- jc call_online ;go on if ok
- ELSE
- jmp call_online
- ENDIF
- ;
- ; Caller flunked the nulls test or rx-trash on baud sync. Start all over
- ;
- abort_call: mov ah,INT_STAT ;mdm status interrupts off
- mov al,OFF ;status int's testing
- call port_imode ; for carrier loss.
- mov ax,OFF ;hang up the modem.
- call port_dtr
- mov ax,2 ;let mdm settle after
- call delay ; hanging up.
- IF BPS_300
- mov ax,BPS300 ;start at 300 bps
- ENDIF
- IF BPS_1200
- mov ax,BPS1200 ;start at 1200 bps
- ENDIF
- IF BPS_2400
- mov ax,BPS2400 ;start at 2400 bps
- ENDIF
- IF TELEBIT
- mov ax,BPS9600 ;start at 9600 bps
- ENDIF
- call port_baud ;initialize com port
- call rx_flush ;clear out any trash
- mov ax,ON ;DTR/RTS back on
- call port_dtr
- jmp call_restart ;start all over,
-
- call_online: mov si,OFFSET crlf ;send crlf
- call con_puts
- ret ;call online rtn completed...
-
- call_wait ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; ASK NULLS --- Ask the caller for how many nulls to needed.
- ;
- ; Exit: Carry Set - Error getting Nulls Response from caller
- ; Carry Clr - Caller Answered Nulls Question ok
- ;
- ;-----------------------------------------------------------------------
- ;
- IF USE_NULLS
- ask_nulls PROC near
-
- mov si,OFFSET crlf
- call mcon_puts
- mov bx,9 ;only 8 tries allowed
- getnulls1: dec bx
- cmp bx,0
- je flunked ;screwed up the iq test?
- mov si,OFFSET mdm_nulls
- call mcon_puts ;ask nulls question.
- getnulls2: call rx_ready
- jnz getnulls3
- mov ah,1 ;check for console keys
- int 16h
- jz getnulls2 ;jmp if no key
- mov ah,0
- int 16h ;get the key pressed
- jmp SHORT getnulls4
- getnulls3: call rx_getc ;get a response.
- getnulls4: call mcon_putc ;show character rx-ed.
- cmp al,'0'
- jl getnulls1
- cmp al,'9'
- jg getnulls1
- sub al,30h ;convert to 0-9 base
- mov nulls,al ;store # of nulls to send
- jmp SHORT ask_ok
- flunked: mov si,OFFSET mdm_flunk
- call mcon_puts ;fall through to abort
- ask_err: clc ;clear the carry flag
- jmp SHORT ask_ok1
- ask_ok: mov si,OFFSET crlf
- call mcon_puts
- stc ;set carry flag
- ask_ok1: ret
-
- ask_nulls ENDP
- ;
- ENDIF
- ;
- ;-----------------------------------------------------------------------
- ; SET BAUD RATE -- Sets the baud rate of caller according to the baud
- ; rate flag that was set by the modem result code sent on answer.
- ;
- ; baud = 0 300bps
- ; = 1 1200bps
- ; = 2 2400bps
- ; = 3 9600bps (Telebit Modem already set to 9600)
- ;
- ;-----------------------------------------------------------------------
- ;
- IF SMART_MDM
- ;
- set_baud PROC near
-
- mov al,baud
- or al,al
- jz set_300 ;0 = 300bps
- IF BPS_1200 OR BPS_2400 OR TELEBIT
- dec al
- jz set_1200 ;1 = 1200bps
- ENDIF
- IF BPS_2400 OR TELEBIT
- dec al
- jz set_2400 ;2 = 2400bps
- ENDIF
- IF TELEBIT
- dec al
- jz set_9600 ;3 = 9600bps
- ENDIF
- jmp SHORT set_1200 ;error!, reset to 1200bps
-
- set_300: mov ax,BPS300 ;reset port to 300 bps
- mov si,OFFSET msg_300
- jmp SHORT set_end
-
- IF BPS_1200 OR BPS_2400 OR TELEBIT
- set_1200: mov ax,BPS1200 ;reset port to 1200 bps
- mov si,OFFSET msg_1200
- jmp SHORT set_end
- ENDIF
-
- IF BPS_2400 OR TELEBIT
- set_2400: mov ax,BPS2400 ;reset port to 2400 bps
- mov si,OFFSET msg_2400
- jmp SHORT set_end
- ENDIF
-
- IF TELEBIT
- set_9600: mov ax,BPS9600 ;reset port to 9600 bps
- mov si,OFFSET msg_tbit
- ENDIF
- set_end:
- IFE TELEBIT
- call port_baud ;set the baud rate
- ENDIF
- call con_puts ;show baud rate setting
- mov si,OFFSET crlf ; and send a new line
- call con_puts
- mov ax,2 ;wait a second...
- call delay
- call rx_flush ;clear any trash
- ret
-
- set_baud ENDP
- ;
- ELSE ; Its not a smart modem....
- ;
- ;-----------------------------------------------------------------------
- ; SYNC BAUD RATE -- Look for a CR to determine what baud rate the call
- ; is at. If unable to lock on to the baud rate then return with the
- ; carry flag set, else clear the carry flag.
- ;
- ; Exit: Carry Set - Baud rate determined and set
- ; Carry Clr - Error during baud rate sync
- ;
- ;-----------------------------------------------------------------------
- ;
- sync_baud PROC near
-
- mov cx, 15 ;try 15 times
-
- sync_baud1: mov ax,BPS300 ;try 300 bps
- call port_baud
- call rx_flush
- mov baud,0
- mov si,OFFSET msg_300
- call con_puts
- call sync_cr
- jc sync_ok
-
- IF BPS_1200 OR BPS_2400
- mov ax,BPS1200 ;try 1200 bps
- call port_baud
- call rx_flush
- mov baud,1
- mov si,OFFSET msg_1200
- call con_puts
- call sync_cr
- jc sync_ok
- ENDIF
-
- IF BPS_2400
- mov ax,BPS2400 ;try 2400bps
- call port_baud
- call rx_flush
- mov baud,2
- mov si,OFFSET msg_2400
- call con_puts
- call sync_cr
- jc sync_ok
- ENDIF
-
- loop sync_baud1 ;jmp not enough trash yet.
- sync_err: clc ;clear the carry flag
- jmp SHORT sync_ok1
- sync_ok: stc ;set the carry flag
- sync_ok1: ret
-
- sync_baud ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; SYNC TO <CR> -- Look for a CR/Ctrl-C to determine what baud rate.
- ;
- ; Exit: Carry Set - Found a CR or Ctrl-C ok
- ; Carry Clr - Error getting CR or Ctrl-C
- ;
- ;-----------------------------------------------------------------------
- ;
- sync_cr PROC near
-
- push cx
- mov cx,20 ;try 20 times
- sync_cr0: call rx_getc ;get a character
- cmp al,CR
- je sync_cr1 ;jump if CR found
- cmp al,CTRL_C
- je sync_cr1 ;jump if ^C, else
- mov ax,1 ; delay for a sec
- call timer ; and try again...
- loop sync_cr0
- clc ;clear carry, error
- jmp SHORT sync_cr2
- sync_cr1: stc ;set carry, its sync'ed
- sync_cr2: pop cx
- ret
-
- sync_cr ENDP
- ;
- ENDIF
- ;
- ;
- ;-----------------------------------------------------------------------
- ; MODEM GET STRING -- Get a string from the modem and place the results
- ; in the buffer pointed to by DS:SI. This function will input up to 'n'
- ; characters in the CX register or until a CR or LF is received. Any
- ; CR or LF received is replaced by a null terminating character.
- ;
- ;
- ; Entry: DS:DI - Buffer to place data in
- ; CX - Maximum characters to input
- ;
- ;-----------------------------------------------------------------------
- ;
- mdm_gets PROC near
-
- cld ;set 'fwd' direction
- gets1: call rx_getc ;get the character
- cmp ax,EOF ;skip error.
- je gets1 ;error reading char?
- cmp al, CR ;break on CR
- je gets_end
- cmp al, LF ;break on LF
- je gets_end
- mov [di],al ;store it in buffer
- inc di
- loop gets1
-
- gets_end: mov al,0 ;null terminate string
- mov [di],al ;store it in buffer
- ret
-
- mdm_gets ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; MODEM PUT STRING -- Send the modem a string at DS:DI. The string must
- ; contain a "$" character to signal the end of the string.
- ;
- ; Entry: DS:SI - Points to the string of chars to send
- ;
- ;-----------------------------------------------------------------------
- ;
- mdm_puts PROC near
-
- push ax
- cld
- mdmputs1: lodsb ;get a byte from string
- cmp al,'$' ;if '$', end of string
- je mdmputs2
- cmp al,0 ;if null, end of string
- je mdmputs2
- call tx_putc ;send char to modem
- jmp SHORT mdmputs1 ;continue looping
- mdmputs2: pop ax
- ret
-
- mdm_puts ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; MODEM & CONSOLE PUT STRING -- Send the modem a string at DS:DI.
- ; The string must contain a "$" character to signal the end of string.
- ;
- ; Entry: DS:SI - Points to the string of chars to send
- ;
- ;-----------------------------------------------------------------------
- ;
- mcon_puts PROC near
-
- push ax
- cld
- cputs1: lodsb ;get a byte from string
- cmp al,'$' ;if '$', end of string
- je cputs2
- cmp al,0 ;if null, end of string
- je cputs2
- call mcon_putc ;send char to modem & screen
- jmp SHORT cputs1 ;continue looping
- cputs2: pop ax
- ret
-
- mcon_puts ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; MODEM & CONSOLE PUT CHAR -- Send a character to the local console
- ; and the modem.
- ;-----------------------------------------------------------------------
- ;
- mcon_putc PROC near
-
- cmp locl_flg,0 ;local mode?
- jne mcon_putc1 ;yes, skip modem
- call tx_putc ;send char to modem
- mcon_putc1: mov ah,0Eh ;write tty function
- int 10h ;video bios call
- ret
-
- mcon_putc ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; FREE MEMORY -- This routine releases the memory used after BYE is
- ; loaded so that other programs will have memory to execute.
- ;-----------------------------------------------------------------------
- ;
- IF LOGON_EXE
- free_mem PROC near
-
- mov ax,cs ;ES=CS
- mov es,ax
- mov bx,OFFSET eom ;get end of memory
- mov cl,4
- shr bx,cl ;BX divided by 16
- inc bx ;case not multiple of 16
- mov ah,4Ah ;code for memory release
- int 21h
- jnc free_ok ;memory free ok?
- mov al,BELL ;ring the bell
- call con_putc
- mov si,OFFSET free_err_msg ; no, print error msg
- call con_puts ; and abort execute.
- free_ok: ret
-
- free_mem ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; EXECUTE A CHILD PROCESS -- This function will execute either a .COM
- ; or an .EXE file and return control to the caller.
- ;-----------------------------------------------------------------------
- ;
- exec_pgm PROC near
-
- mov ax,cs ;ES=CS
- mov es,ax
-
- mov dx,OFFSET child_name ;file to execute
- mov bx,OFFSET child_parms ;es:bx -> paramater block
- mov cx,cs:[2Ch] ;set SEGMENT addrs of
- mov environ_seg,cx ; environment blk passed.
- mov command_off,80h
- mov command_seg,cs
- mov fcb1_off,5Ch
- mov fcb1_seg,cs
- mov fcb2_off,6Ch
- mov fcb2_seg,cs
- cli
- mov stk_ptr,sp ;get stack pointer
- mov stk_seg,ss
- sti
- ;
- ; -- now execute the child process and return control
- ;
- mov ax,4B00h ;execute a child process
- int 21h
- jnc exec_ok ;exec ok?
- mov al,BELL ;ring the bell
- call con_putc
- mov si,OFFSET exec_err_msg ;no, print error msg
- call con_puts ;and abort execute.
-
- exec_ok: mov ax,cs ;set SEGMENTs back up
- mov es,ax
- mov ds,ax
- cli ;halt int's temoporarily
- mov ss,stk_seg ;restore stack segment
- mov sp,stk_ptr ;restore stack ptr
- sti
- ret
-
- exec_pgm ENDP
- ;
- ;
- ;-----------------------------------------------------------------------
- ; --- Data area for executable programs ---
- ;-----------------------------------------------------------------------
- ;
- child_name db "C:\SYSTEM\XBBS\XBBS.EXE"
- db 0
- child_parms equ $ ;passed to calling module
- environ_seg dw ?
- command_off dw ?
- command_seg dw ?
- fcb1_off dw ?
- fcb1_seg dw ?
- fcb2_off dw ?
- fcb2_seg dw ?
- stk_ptr dw ?
- stk_seg dw ?
- ENDIF
-
- eom equ $ ;end of pgm memory marker
- ;
- ;-----------------------------------------------------------------------
- ; End of Program Code
- ;-----------------------------------------------------------------------
- ;
- code ENDS ;end of segment
- END start ;end of program from start
-