Category : BASIC Source Code
Archive   : RBBS-ASM.ZIP
Filename : BDRIVEC2.ASM
;
; --- CORVUS/IBM DRIVE INTERFACE UNIT FOR MICROSOFT ---
; PASCAL AND BASIC COMPILERS
; CONST ][ VERSION FOR DOS 1.10 & 2.0
;
; VERSION 1.41 BY BRK
; (MICROSOFT ASSEMBLER VERSION )
;
;
; NOTE: THIS INTERFACE UNIT NOW SUPPORTS BOTH PASCAL AND BASIC
; COMPILERS BUT IT MUST BE RE-ASSEMBLED WITH THE APPROPRIATE
; SETTING OF THE "LTYPE" EQUATE TO DO THIS FOR EACH LANGUAGE.
;
;
;
; THIS UNIT IMPLEMENTS 9 PROCEDURES:
;
; INITIO
; BIOPTR - CONST. ][
; SETSRVR - CONST. ][
; FINDSRVR - CONST. ][
; NETCMD - CONST. ][
; CDRECV = DRVRECV
; CDSEND = DRVSEND
;
; THE CALLING PROCEDURE IN PASCAL IS :
;
; CDSEND (VAR st : longstring )
;
; THE FIRST TWO BYTES OF THE STRING ARE THE LENGTH
; OF THE STRING TO BE SENT OR THE LENGTH OF THE
; STRING RECEIVED.
;
; function INITIO : INTEGER
;
; THE FUNCTION RETURNS A VALUE TO INDICATE THE STATUS OF
; THE INITIALIZATION OPERATION. A VALUE OF ZERO INDICATES
; THAT THE INITIALIZATION WAS SUCCESSFUL. A NON-ZERO VALUE
; INDICATES THE I/O WAS NOT SETUP AND THE CALLING PROGRAM
; SHOULD NOT ATTEMPT TO USE THE CORVUS DRIVERS.
;
; function BIOPTR : INTEGER
;
; THE FUNCTION RETURNS A 16 BIT POINTER TO THE "CORTAB"
; BIOS TABLE IN THE CORVUS "BIOS" DRIVERS. THIS ROUTINE
; SHOULD NOT BE EXECUTED BEFORE A SUCCESSFUL USE OF THE
; "INITIO" ROUTINE (ABOVE). NOTE: THE RETURNED VALUE IS
; RELATIVE TO "SEGMENT" ZERO, AND A RETURNED VALUE OF ZERO
; INDICATES THAT THE "CORTAB" TABLE COULD NOT BE FOUND.
;
; function SETSRVR ( srvr : integer): INTEGER
;
; THE FUNCTION RETURNS THE "BOOT SERVER" NETWORK ADDRESS.
; IF THE INPUT PARAMETER IS LESS THAN 255 ( BUT NOT NEGATIVE ),
; IT WILL BE TAKEN AS A RESET OF THE DEFAULT SERVER # WHEN
; USING THE SEND & RECIEVE ROUTINES. IF IT IS GREATER THAN 255
; OR NEGATIVE, NO CHANGE OF THE DEFAULT SERVER # WILL BE MADE.
; NOTE: THE DEFAULT SERVER # IS AUTOMATICALLY SET TO THE
; BOOT SERVER # WHEN THE "INITIO" FUNCTION IS EXECUTED.
;
; function FINDSRVR : INTEGER
;
; THE FUNCTION RETURNS THE NETWORK ADDRESS OF A VALID DISK SERVER.
; IF THE RETURNED VALUE IS GREATER THAN 63 OR NEGATIVE, THE COMMAND
; FAILED TO FIND A SERVER ( THE FLAT CABLE CARDS WOULD DO THIS ).
;
; function CARDID : INTEGER
;
; THE FUNCTION RETURNS THE CORVUS INTERFACE CARD TYPE ( 0 - OMNINET,
; 1 - FLAT CABLE ).
;
; function NETCMD ( VAR inp, VAR out: longstring) : INTEGER
;
; THE FUNCTION IS USED TO SEND/RECIEVE DATA TO A NETWORK SERVER.
; STRING inp SPECIFIES THE COMMAND TO SEND TO THE SERVER,
; AND STRING out IS WHERE ANY RETURNED DATA WILL BE PLACED
; ( THE STRING LENGTH OF out WILL NOT BE CHANGED BY THIS
; OPERATION UNLESS THE COMMAND FAILED- IN WHICH CASE THE LENGTH
; WILL BE SET TO ZERO). THE VALUE OF THE FUNCTION WILL BE
; RETURNED AS ZERO IF THE OPERATION WAS SUCCESSFUL, AND
; NON-ZERO IF IT FAILED.
; NOTE: THE SERVER # USED WILL BE THE "BOOT SERVER" # UNLESS
; THE DEFAULT IS CHANGED BY THE "SETSRVR" CMD.
;
;
;
;
; THE CALLING PROCEDURE BASIC IS :
;
; CALL CDSEND (B$ )
;
; THE FIRST TWO BYTES OF THE STRING ARE THE LENGTH
; OF THE STRING TO BE SENT OR THE LENGTH OF THE
; STRING RECEIVED ( I.E. LEFT$(B$,2) ).
;
; CALL INITIO (A%)
;
; THE FUNCTION RETURNS A VALUE TO INDICATE THE STATUS OF
; THE INITIALIZATION OPERATION. A VALUE OF ZERO INDICATES
; THAT THE INITIALIZATION WAS SUCCESSFUL. A NON-ZERO VALUE
; INDICATES THE I/O WAS NOT SETUP AND THE CALLING PROGRAM
; SHOULD NOT ATTEMPT TO USE THE CORVUS DRIVERS.
;
; CALL BIOPTR (A%)
;
; THE FUNCTION RETURNS A 16 BIT POINTER TO THE "CORTAB"
; BIOS TABLE IN THE CORVUS "BIOS" DRIVERS. THIS ROUTINE
; SHOULD NOT BE EXECUTED BEFORE A SUCCESSFUL USE OF THE
; "INITIO" ROUTINE (ABOVE). NOTE: THE RETURNED VALUE IS
; RELATIVE TO "SEGMENT" ZERO, AND A RETURNED VALUE OF ZERO
; INDICATES THAT THE "CORTAB" TABLE COULD NOT BE FOUND.
;
; CALL SETSRVR (A%) here A% is used for input and output
;
; THE FUNCTION RETURNS THE "BOOT SERVER" NETWORK ADDRESS.
; IF THE INPUT PARAMETER IS LESS THAN 255 ( BUT NOT NEGATIVE ),
; IT WILL BE TAKEN AS A RESET OF THE DEFAULT SERVER # WHEN
; USING THE SEND & RECIEVE ROUTINES. IF IT IS GREATER THAN 255
; OR NEGATIVE, NO CHANGE OF THE DEFAULT SERVER # WILL BE MADE.
; NOTE: THE DEFAULT SERVER # IS AUTOMATICALLY SET TO THE
; BOOT SERVER # WHEN THE "INITIO" FUNCTION IS EXECUTED.
;
; CALL FINDSRVR (A%)
;
; THE FUNCTION RETURNS THE NETWORK ADDRESS OF A VALID DISK SERVER.
; IF THE RETURNED VALUE IS GREATER THAN 63 OR NEGATIVE, THE COMMAND
; FAILED TO FIND A SERVER ( THE FLAT CABLE CARDS WOULD DO THIS ).
;
; CALL CARDID (A%)
;
; THE FUNCTION RETURNS THE CORVUS INTERFACE CARD TYPE ( 0 - OMNINET,
; 1 - FLAT CABLE ).
;
; CALL NETCMD ( A$,B$,C%)
;
; THE FUNCTION IS USED TO SEND/RECIEVE DATA TO A NETWORK SERVER.
; STRING A$ SPECIFIES THE COMMAND TO SEND TO THE SERVER,
; AND STRING B$ IS WHERE ANY RETURNED DATA WILL BE PLACED
; ( THE STRING LENGTH OF out WILL NOT BE CHANGED BY THIS
; OPERATION UNLESS THE COMMAND FAILED- IN WHICH CASE THE LENGTH
; WILL BE SET TO ZERO). THE VALUE OF THE FUNCTION WILL BE
; RETURNED ( IN C% ) AS ZERO IF THE OPERATION WAS SUCCESSFUL, AND
; NON-ZERO IF IT FAILED.
; NOTE: THE SERVER # USED WILL BE THE "BOOT SERVER" # UNLESS
; THE DEFAULT IS CHANGED BY THE "SETSRVR" CMD.
;
;=============================================================
; REVISION HISTORY
;
; FIRST VERSION : 10-05-82 BY BRK
; : 11-01-82 improved turn around delay for mirror
; : 02-16-83 CONST. ][ version
; : 05-16-83 added support for Basic
; : 07-06-83 fixed bug in FINDSRVR routine
; V1.40 : 07-29-83 updated for DOS 2.0
; V1.41 : 08-04-83 set timeout to zero to avoid ROM bug
;
;=============================================================
;
TRUE EQU 0FFFFH
FALSE EQU 0
;
PASCAL EQU 1 ; LANGUAGE TYPE DESCRIPTOR
BASIC EQU 2 ; LANGUAGE TYPE DESCRIPTOR
;
LTYPE EQU PASCAL ; SET TO LANGUAGE TYPE TO BE USED WITH
INTDVR EQU FALSE ; SET TO FALSE TO DISABLE INTERNAL FLAT CABLE DRIVER
;
;
; ----- CORVUS EQUATES -----
;
DATA EQU 2EEH ; DISC I/O PORT #
STAT EQU 2EFH ; DISC STATUS PORT
DRDY EQU 1 ; MASK FOR DRIVE READY BIT
DIFAC EQU 2 ; MASK FOR BUS DIRECTION BIT
ROMSEG EQU 0DF00H ; LOCATION OF CORVUS ROM
BIOSSEG EQU 60H ; STD IBM BIOS SEGMENT ADDRESS
ABTCTR EQU 0A00H ; VALUE TO SET TIMEOUT AND # OF RETRYS
; ; v1.41 timeouts=0
;
FCALL EQU 9AH ; OPCODE FOR FAR CALL
FJMP EQU 0EAH ; OPCODE FOR FAR JUMP
;
; --- MSDOS EQUATES ( V2.0 ) ---
;
VERCMD EQU 30H ; BDOS COMMAND TO GET VERSION #
HOPEN EQU 3DH ; BDOS COMMAND TO "OPEN" A FILE HANDLE
HCLOSE EQU 3EH ; BDOS COMMAND TO "CLOSE" A FILE HANDLE
HREAD EQU 3FH ; BDOS COMMAND TO "READ" FROM A FILE
HWRITE EQU 40H ; BDOS COMMAND TO "WRITE" TO A FILE
;
PGSEG SEGMENT 'CODE'
ASSUME CS:PGSEG
;
;
IF LTYPE EQ PASCAL
DB 'CORVUS/IBM PC CONST. ][ PASCAL DRIVER AS OF 08-04-83'
ENDIF
;
IF LTYPE EQ BASIC
DB 'CORVUS/IBM PC CONST. ][ BASIC DRIVER AS OF 08-04-83'
ENDIF
;
; --- COPY OF "ROM" FAR JUMP TABLE ---
;
ROMTAB PROC NEAR
DB FJMP
DW 0,ROMSEG ; FAR JUMP TO COLD BOOT ROM ENTRY
DB FJMP
DW 3,ROMSEG ; FAR JUMP TO WARM START ROM ENTRY
DB FJMP
DW 6,ROMSEG ; FAR JUMP TO I/O ROM ENTRY
DB FJMP
DW 9,ROMSEG ; FAR JUMP TO DUMMY "IRET" ENTRY
LENTAB EQU offset $-offset ROMTAB ; LENGTH OF TABLE
ROMTAB ENDP
;
; --- COPY OF CORVUS TABLE IDENTIER ---
;
CORTAB DB 'CORTAb' ; VERSION FOR CONST. ][
;
; --- COPY OF UTILITY "HOOK" DRIVER NAME ---
;
UTILPTR DB 'UTILHOOK',0
;
;
; --- THESE DATA POINTERS MUST BE KEPT IN THE SAME RELATIVE ORDER
;
SNDPTR DW 0 ; BUFFER TO SAVE POINTER TO 'SEND' STRING
SNDSEG DW 0 ; BUFFER TO SAVE 'SEND' STRING SEGMENT #
;
CORVEC DW 0,0 ; BUF TO SAVE DOUBLE WORD POINTER TO "CORTAB"
;
; --- MISC DATA AND BUFFERS ----
;
CORPTR DW 0 ; BUFFER FOR "CORTAB" POINTER
; ; INITIALIZE INITIALLY TO ZERO
CRDTYPE DB 1 ; BUFFER TO SAVE "CARD TYPE" BYTE
BOOTSRVR DB 0FFH ; BUFFER FOR "BOOT SERVER"
SRVR DB 0FFH ; BUFFER FOR "DEFAULT SERVER"
;
;
; === INITIALIZE CORVUS I/O DRIVERS ===
;
; THIS ROUTINE MUST BE CALLED
; ONCE TO SETUP THE DRIVERS BEFORE
; THEY ARE USED. IF THE ROUTINE DOES
; ANYTHING THAT CAN ONLY BE DONE ONCE,
; IT MUST DISABLE THIS SECTION SO THAT
; AND ACCIDENTAL SECOND CALL WILL NOT
; LOCK UP THE HARDWARE.
;
PUBLIC INITIO
;
INITIO PROC FAR
PUSH DS
PUSH ES
PUSH CS
POP ES ; SET ES=CS
CLD
;
MOV AH,VERCMD ; MSDOS VERSION CHECK COMMAND
INT 21H ; GET VERSION # OF DOS
OR AL,AL ; IS IT V 1.1 OR 1.0?
JZ IV11 ; YES, SO TRY FINDING "CORTAb"
;
PUSH CS
POP DS ; SET TO LOCAL SEGMENT FOR TESTING
;
MOV AH,HOPEN ; SET MSDOS 2.X, OPEN HANDLE COMMAND
MOV AL,2 ; OPEN FOR R/W
MOV DX,offset UTILPTR ; POINT TO "HOOK" DRIVER NAME
INT 21H ; DO IT
JC IV12 ; IF ERROR, TRY FOR IBM ROM
;
MOV BX,AX ; GET "HANDLE" IN (BX)
MOV AH,HWRITE ; GET WRITE CMD
MOV CX,2 ; SET TO WRITE 2 CHARS
MOV DX,offset UTILPTR ; USE NAME FOR SOURCE OF CHARACTERS
INT 21H ; THIS SHOULD RESET "POINTER" IN DRIVER
;
MOV AH,HREAD ; SET READ CMD
MOV CX,4 ; SET TO READ DOUBLE WORD
MOV DX,offset CORVEC ; POINT TO DESTINATION OF READ
INT 21H ; DO IT
;
MOV AH,HCLOSE ; GET CLOSE CMD
INT 21H ; CLOSE HANDLE
;
LDS BX,dword ptr CORVEC ; GET POSSIBLE POINTER TO "CORTAb"
CALL BIOT1 ; TEST FOR "CORTAb"
JNC OKEXIT ; IF OK, EXIT
JMP IV12 ; OTHERWISE PROCEED
;
IV11: MOV AX,BIOSSEG ; SET TO TEST STD IBM SEGMENT ADD
CALL BIOTST ; TEST BIOS AND LINK TO IT IF OK
JNC OKEXIT ; IF OK, EXIT
MOV AX,BIOSSEG-20H ; TRY MICROSOFT STD LOCATION (40H)
CALL BIOTST
JNC OKEXIT ; IF OK, EXIT
;
IV12: MOV AX,ROMSEG
MOV DS,AX ; SET DS=ROM SEGMENT
XOR AX,AX ; GET A ZERO
MOV BX,AX ; POINT TO START OF ROM
MOV DI,AX ; INIT CHECKSUM COUNTER
MOV CX,4 ; CHECK FOR 4 JUMPS AT START OF ROM
;
CKROM: MOV AL,[BX] ; READ POSSIBLE OPCODE BYTE
ADD DI,AX ; SUM THE TEST BYTES
ADD BX,3 ; POINT TO POSSIBLE NEXT OPCODE
LOOP CKROM ; SUM THE OPCODES
;
CMP DI,4*(0E9H) ; SHOULD BE 4 0E9H OPCODES (JMP)
;
IF INTDVR
JNZ OKEXIT ; NO, SO LEAVE DEFAULT DRIVERS
ENDIF
;
IF NOT INTDVR
JNZ BDEXIT ; NO, SO LEAVE WITH ERROR CONDITION
ENDIF
;
PUSH CS
POP DS ; DS=ES=CS
;
MOV SI,offset ROMTAB ; POINT TO SOURCE (ROM CALL TABLE COPY)
CALL CPYTAB ; COPY TABLES
;
DB FCALL
DW 3,ROMSEG ; FAR CALL TO ROM "INIT" ROUTINE
;
MOV AH,0 ; COMMAND FOR CARD TYPE IDENTIFY
;
DB FCALL
DW 6,ROMSEG ; FAR CALL TO DRIVE I/O ROM ENTRY
;
MOV CS:CRDTYPE,AL ; SAVE CARD TYPE []
;
OR AL,AL ; TEST FOR OMNINET
JNZ OKEXIT ; IF FLAT, EXIT
MOV AH,4 ; SET TO FIND SERVER ADDRESS
MOV BX,ABTCTR ; SET ABORT TIME AND RETRYS
;
DB FCALL
DW 6,ROMSEG ; FAR CALL TO DRIVE I/O ROM ENTRY
;
MOV CS:BOOTSRVR,AH ; SAVE SERVER #
MOV CS:SRVR,AH
OR AL,AL ; WAS SERVER # ACTUALLY FOUND
BDEXIT: MOV AX,1 ; SET FOR ERROR CONDITION
JNZ INEXIT ; NO, SO SHOW ERROR AND EXIT
;
OKEXIT: MOV AX,0 ; RETURN A ZERO
INEXIT: POP ES
POP DS
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN ERROR CONDITION BYTE
POP BP
RET 2
ENDIF
;
INITIO ENDP
;
; --- COPY ADDRESS INFORMATION FROM SOURCE POINTED TO BY DS:SI ---
;
CPYTAB PROC NEAR
MOV DI,offset LNKTAB ; POINT TO ROUTINE LINKAGE TABLE
MOV CX,LENTAB ; SET TO COPY
REP MOVSB ; DO COPY
RET
CPYTAB ENDP
;
; --- TEST FOR "CORVUS" CONST ][ BIOS ---
;
BIOTST PROC NEAR
MOV DS,AX ; SET DATA SEGMENT TO THAT OF "BIOS"
MOV BX,1 ; POINT TO "INIT" ADDRESS FIELD OF JUMP
MOV BX,[BX] ; GET THIS ADDRESS IN BX
ADD BX,1 ; OFFSET FOR INSTRUCTION SIZE
MOV BX,[BX] ; GET POSSIBLE POINTER TO "CORTAb" STRING
;
BIOT1 PROC NEAR
MOV SI,BX ; SAVE IT
MOV DI,offset CORTAB ; POINT TO LOCAL COPY OF STRING
MOV CX,6 ; LENGTH OF STRING
REPZ CMPSB ; COMPARE STRINGS
STC ; SET CARRY TO INDICATE POSSIBLE MISMATCH
JNZ BIOE ; EXIT IF MISMATCH
;
MOV AX,DS ; GET "BIOS" SEGMENT
MOV CL,4 ; SET TO MULTIPLY BY 16
SHL AX,CL ; CONVERT SEGMENT # TO ADDRESS
ADD AX,BX ; FIND "CORTAb" ADDRESS RELATIVE TO SEG. 0
MOV CS:CORPTR,AX ; SAVE FOR POSSIBLE USE []
;
MOV AL,35 [BX] ; GET "BOOT SERVER" # FROM BIOS
MOV CS:BOOTSRVR,AL ; SAVE IT []
MOV CS:SRVR,AL ; INIT "DEFAULT SERVER" AS "BOOT SERVER" []
;
ADD BX,23 ; OFFSET TO ROM FUNCTION TABLE POINTER
MOV SI,[BX] ; GET IT
CALL CPYTAB ; COPY TABLE INTO THIS DRIVER
MOV AH,0 ; ID COMMAND
CALL far ptr CRVIO ; DO IT
MOV CS:CRDTYPE,AL ; SAVE CARD TYPE
CLC ; CLEAR CARRY TO INDICATE SUCCESS
BIOE: RET
;
BIOT1 ENDP
BIOTST ENDP
;
;
; === RETURN POINTER TO "CORTAb" IN CORVUS BIOS ===
;
PUBLIC BIOPTR
;
BIOPTR PROC FAR
MOV AX,CS:CORPTR ; GET POINTER []
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN POINTER
POP BP
RET 2
ENDIF
;
BIOPTR ENDP
;
; ==== SET SERVER # AND READ BOOT SERVER # ====
;
PUBLIC SETSRVR
;
SETSRVR PROC FAR
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV CX,6 [BP] ; GET PASSED VALUE
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET POINTER TO VALUE
MOV CX,[BX] ; GET ITS VALUE
ENDIF
;
OR CH,CH ; IS IT TOO BIG?
JNZ SETS1 ; YES, SO DO NOT CHANGE PRESENT VALUE
MOV CS:SRVR,CL ; NO, SO SET NEW DEFAULT SERVER #
SETS1: XOR AX,AX ; GET A ZERO
MOV AL,CS:BOOTSRVR ; GET "BOOT SERVER" # AS RETURN VALUE
;
IF LTYPE EQ BASIC
MOV [BX],AX ; SET RETURNED VALUE
ENDIF
;
POP BP ; RESTORE FRAME
RET 2
SETSRVR ENDP
;
; === FIND A VALID NETWORK SERVER ADDRESS ===
;
PUBLIC FINDSRVR
;
FINDSRVR PROC FAR
MOV AH,4 ; FIND SERVER COMMAND ( 1.31 bug fix )
MOV BX,ABTCTR ; SET MAX RETRY COUNT AND ABORT TIME
CALL far ptr CRVIO ; CALL I/O DRIVER
XCHG AL,AH ; GET SERVER # IN LSB
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN SERVER #
POP BP
RET 2
ENDIF
;
FINDSRVR ENDP
;
; === IDENTIFY CORVUS I/O CARD TYPE ===
;
PUBLIC CARDID
;
CARDID PROC FAR
MOV AH,0 ; ZERO MSB
MOV AL,CS:CRDTYPE ; GET CARD IDENTIFIER
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN CARD TYPE
POP BP
RET 2
ENDIF
;
CARDID ENDP
;
; === SEND/RECEIVE A COMMAND TO A NETWORK SERVER ===
;
PUBLIC NETCMD
;
NETCMD PROC FAR
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV SI,6 [BP] ; GET ADDRESS OF INPUT STRING
MOV DI,8 [BP] ; GET ADDRESS OF OUTPUT STRING
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
MOV SI,[BX] ; GET ADDRESS OF INPUT STRING
MOV BX,8 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
MOV DI,[BX] ; GET ADDRESS OF OUTPUT STRING
ENDIF
;
PUSH DS
POP ES ; SET ES=DS (SAVE SEGMENT)
;
MOV CX,[SI] ; LOOK AT LENGTH
MOV AL,CL ; SAVE FOR RETURN STATUS
JCXZ NETE ; IF ZERO, SET RET LENGTH TO ZERO AND RET
;
PUSH DI
INC SI
INC SI ; POINT TO SEND DATA ( DS:SI )
;
INC DI
INC DI ; POINT TO PLACE TO SAVE RETURNED DATA ( ES:DI)
;
MOV DX,530 ; SET MAX # OF RETURNED BYTES
;
MOV AH,3 ; SET FOR SERVER CMD
MOV AL,CS:SRVR ; SET DISK SERVER #
MOV BX,ABTCTR ; SET ABORT TIME AND # OF RETRYS
CALL far ptr CRVIO ; DO DISK I/O
;
POP DI ; GET POINTER BACK TO LENGTH
MOV CX,[DI] ; GET LENGTH PREVIOUSLY SET
NETE: MOV [DI],CX ; SET LENGTH OF RETURNED STRING
MOV AH,0 ; CLEAR MSB OF RETURNED VALUE
;
IF LTYPE EQ PASCAL
POP BP ; GET FRAME POINTER BACK
RET 4 ; CLEAR RETURN STACK
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,10 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN ERROR CONDITION BYTE
POP BP
RET 6
ENDIF
;
NETCMD ENDP
;
; === RECEIVE A STRING OF BYTES FROM THE DRIVE ===
;
PUBLIC CDRECV, DRVRECV
;
CDRECV PROC FAR
DRVRECV:
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV DI,6 [BP] ; GET ADDRESS OF STRING TO SAVE DATA IN
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
INC BX
INC BX ; POINT TO STRING POINTER
MOV DI,[BX] ; GET ADDRESS OF STRING TO SAVE DATA IN
ENDIF
;
PUSH DS
POP ES ; SET ES=DS (SAVE SEGMENT)
;
PUSH DI
PUSH DS
;
LDS SI,CS:dword ptr SNDPTR ; GET POINTER TO SOURCE STRING
MOV CX,[SI] ; LOOK AT LENGTH
MOV AL,CL ; SAVE FOR RETURN STATUS
JCXZ RLPE ; IF ZERO, SET RET LENGTH TO ZERO AND RET
;
INC SI
INC SI ; POINT TO SEND DATA ( DS:SI )
;
INC DI
INC DI
INC DI ; POINT TO PLACE TO SAVE RETURNED DATA ( ES:DI)
;
MOV DX,530 ; SET MAX # OF RETURNED BYTES
;
MOV AH,1 ; SET FOR "BCI" LIKE COMMAND
MOV AL,CS:SRVR ; SET DISK SERVER #
MOV BX,ABTCTR ; SET ABORT TIME AND # OF RETRYS
CALL far ptr CRVIO ; DO DISK I/O
;
RLPE: POP DS
POP DI ; GET POINTER BACK TO LENGTH
MOV [DI],CX ; SET LENGTH OF RETURNED STRING
MOV 2 [DI],AL ; SAVE RETURN STATUS
POP BP ; GET FRAME POINTER BACK
RET 2 ; CLEAR RETURN STACK
CDRECV ENDP
;
; === SEND STRING OF BYTES TO DRIVE ===
;
; THIS CONSTELLATION VERSION
; JUST SAVES TWO POINTERS TO
; THE DATA STRING TO SEND. THE
; CDRECV ROUTINE ACTUALLY SENDS
; THE DATA AND RECEIVES THE
; RETURN STATUS
;
PUBLIC CDSEND, DRVSEND
;
CDSEND PROC FAR
DRVSEND:
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV AX,6 [BP] ; GET ADDRESS OF STRING TO SEND
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
INC BX
INC BX ; POINT TO STRING POINTER
MOV AX,[BX] ; GET ADDRESS OF STRING TO SAVE DATA IN
ENDIF
;
MOV CS:SNDPTR,AX ; SAVE IT []
;
MOV AX,DS ; GET DATA SEGMENT
MOV CS:SNDSEG,AX ; SAVE IT []
;
POP BP ; GET FRAME POINTER BACK
RET 2 ; CLEAR RETURN STACK
CDSEND ENDP
;
;
;
;
; ============ FLAT CABLE R/W ROUTINES ==============
;
; THESE ROUTINES ARE ESSENTIALLY THE SAME AS THE FLAT CABLE
; DRIVERS IN THE "ROM". THEY ARE REPRODUCED HERE SO THAT
; SYSTEMS WITH FLAT CABLE INTERFACES NEED NOT HAVE A "ROM"
; TO WORK WITH CONSTELLATION ][ SOFTWARE.
;
; --- BUFFERS USED BY "ROM" DRIVER ROUTINES ---
;
CLICKS DB 0 ; BUFFER FOR SAVING # OF CLOCK TICKS
STOPTM DW 0 ; BUFFER FOR SAVING STOP TIME
RMCMD DB 0 ; BUFFER FOR SAVING PASSED "ROM" CMD
BLKLEN DW 512 ; BUFFER FOR SAVING # OF BYTES TO XFER
CMDLEN DW 4 ; BUFFER FOR SAVING LENGTH OF CMD
RTNCODE DB 0 ; BUFFER FOR SAVING DISK RETURN CODE
;
; --- SET TIMER ---
;
STIME PROC NEAR
XOR AH,AH ; READ TIME OF DAY CLOCK
INT 1AH
JMP STIME1
;
; --- CHECK FOR TIMOUT ---
;
CKTIME: CMP CS:CLICKS,0 ; WAS A WAIT REQUESTED? []
CLC
JZ CKRET ; NO, SO RETURN WITH CARRY CLEAR
XOR AH,AH ; TIME OF DAY CALL
INT 1AH
OR AL,AL ; HAS CLOCK WRAPPED AROUND TO ZERO?
JZ CKT1 ; NO
;
; IF CLOCK HAS PASSED 24 HOURS, RECALCULATE STOP TIME
;
STIME1: MOV AL,CS:CLICKS ; GET # OF CLOCK TICKS OF DELAY []
XOR AH,AH
MOV CL,4 ; SET TO MULTIPLY BY 16
SHL AX,CL ; DO IT BY SHIFTING
ADD DX,AX
MOV CS:STOPTM,DX ; SAVE STOP TIME []
CHKOK: CLC ; CLEAR CARRY ( TIME CHECK IS OK )
RET
;
CKT1: CMP DX,CS:STOPTM ; TIMEOUT? []
JB CHKOK
;
STC ; SET CARRY IF TIMEOUT
CKRET: RET
STIME ENDP
;
; ---- MAIN DRIVER ENTRY POINT ---
;
DRVIO PROC FAR
CLD ; SET FOR "INCREMENT"
MOV CS:RMCMD,AH ; SAVE COMMAND []
CMP AH,1 ; IS IT A "BCI" COMMAND?
JZ RW15 ; YES, SO DO IT
CMP AH,5 ; IS IT A "WRITE" COMMAND?
JZ RW15 ; YES, SO DO IT
CMP AH,0 ; IS IT AN "IDENTIFY" COMMAND
JZ RW00 ; YES, SO DO IT
MOV AL,0FFH ; IF ANY OTHER, INDICATE "ABORT" OR ERROR
MOV CX,0
RET ; LONG RET
;
RW00: MOV AL,1 ; INDICATE FLAT CABLE
RET ; LONG RET
;
;
RW15: PUSH DS ; SAVE REGISTERS THAT MAY BE CHANGED
PUSH SI
PUSH DI
PUSH BX
PUSH DX
;
MOV CS:CLICKS,BL ; SAVE # OF TIMER CLICKS []
MOV CS:BLKLEN,DX ; SAVE BLOCK LENGTH []
MOV CS:CMDLEN,CX ; SAVE CMD LENGTH []
CALL ROMIO ; DO DISK I/O
POP DX
POP BX
POP DI
POP SI
POP DS
MOV AL,CS:RTNCODE ; GET RETURN CODE []
;
DMYLRET LABEL FAR
RET ; LONG RET
;
DMYIRET LABEL FAR
IRET ; DUMMY "IRET"
;
DRVIO ENDP
;
ROMIO PROC NEAR
CALL STIME ; SETUP TIMER COUNT
;
RO1: MOV DX,STAT ; POINT TO STATUS PORT
CLI ; DISABLE INTERRUPTS FOR TEST
IN AL,DX ; READ DRIVE STATUS BYTE
TEST AL,DRDY ; IS IT READY?
JZ RO2 ; YES, SO PROCEED
STI ; NO, SO RE-ENABLE INTERRUPTS
CALL CKTIME ; CHECK IF TIMED OUT
JNC RO1 ; IF NOT, TRY AGAIN
ARET: MOV CS:RTNCODE,0FFH ; IF TIMED OUT, SET ERROR []
MOV CX,0 ; INDICATE NO DATA RETURNED
RET
;
RO2: MOV CX,CS:CMDLEN ; GET CMD LENGTH []
CALL SNDBLK ; SEND BLOCK OF DATA TO DRIVE
CMP CS:RMCMD,5 ; WAS CMD A "WRITE" CMD? []
JNZ RCVBLK ; NO, SO GO RECEIVE DATA
;
MOV SI,DI ; YES, POINT TO SECTOR DATA
MOV AX,ES
MOV DS,AX
MOV CX,CS:BLKLEN ; GET LENGTH OF DATA BLOCK []
CALL SNDBLK ; SEND SECTOR DATA
;
RCVBLK: CALL STIME ; SET TIMER
;
CALL DELAY1 ; DELAY
;
RCV1: CALL CKTIME ; TIMED OUT YET?
JC ARET ; YES, SO RETURN WITH ERROR
;
RCV2: MOV DX,STAT ; POINT TO STATUS PORT
IN AL,DX ; READ DRIVE STATUS BYTE
TEST AL,DIFAC ; TEST BUS DIRECTION
JNZ RCV1 ; WAIT FOR "HOST TO DRIVE"
TEST AL,DRDY ; TEST IF ALSO READY
JNZ RCV1
;
CALL DELAY1 ; WAIT TO BE SURE
;
IN AL,DX ; TEST STATUS AGAIN
TEST AL,DIFAC
JNZ RCV1 ; IF FALSE ALARM, TRY AGAIN
TEST AL,DRDY
JNZ RCV1 ; IF NOT READY, TRY AGAIN
;
DEC DX ; POINT TO DATA PORT
IN AL,DX ; GET RETURN CODE
INC DX ; POINT BACK TO STATUS PORT
;
MOV CX,1 ; INDICATE 1 BYTE WAS RETURNED
MOV CS:RTNCODE,AL ; SAVE IT []
CMP CS:RMCMD,5 ; WAS CMD A "WRITE" CMD []
JZ RCRET ; YES, SO RETURN
;
MOV BX,CX ; OTHERWISE SET COUNTER
MOV CX,CS:BLKLEN ; GET LENGTH OF EXPECTED DATA
;
RCV3: IN AL,DX ; GET STATUS AGAIN
TEST AL,DRDY ; IS DRIVE READY?
JNZ RCV3 ; NO, SO WAIT
TEST AL,DIFAC ; ARE WE DONE?
JNZ RCV4 ; POSSIBLY, ...
;
DEC DX ; POINT TO DATA PORT
IN AL,DX ; GET DATA FROM DRIVE
INC DX ; POINT BACK TO STATUS PORT
;
JCXZ RCVS ; IF DATA NOT WANTED
STOSB ; SAVE DATA IN BUFFER
DEC CX ; COUNT DOWN # TO SAVE
;
RCVS: INC BX ; COUNT UP # RECEIVED
JMP RCV3 ; LOOP UNTIL EXIT
;
RCV4: IN AL,DX ; GET STATUS BYTE
TEST AL,DRDY ; IS DRIVE READY
JNZ RCV3 ; NO, SO PREVIOUS RESULT MAY BE FALSE
TEST AL,DIFAC ; IS IT STILL "HOST TO DRIVE"?
JZ RCV3 ; NO, SO TRY AGAIN
;
MOV CX,BX ; GET # OF BYTES RECEIVED
RCRET: RET
;
DELAY1: MOV BL,15 ; SET DELAY
DELAY: DEC BL
JNZ DELAY ; LOOP UNTIL DONE
RET
;
; --- SEND BLOCK OF DATA TO DRIVE ---
;
SNDBLK: MOV DX,STAT ; POINT TO STATUS PORT
;
SND1: IN AL,DX ; GET STATUS BYTE
TEST AL,DRDY ; IS DRIVE READY?
JNZ SND1 ; NO, SO LOOP
;
DEC DX ; POINT TO DATA PORT
LODSB ; GET DATA FROM MEMORY
OUT DX,AL ; SEND DATA TO DRIVE
INC DX ; POINT BACK TO STATUS PORT
;
STI ; RE-ENABLE INTERRUPTS
LOOP SND1 ; CONTINUE UNTIL DONE
RET
;
ROMIO ENDP
;
;
; ---- INTERFACE "FAR" CALL TABLE ---
; THIS TABLE GETS PATCHED
; TO EITHER "BIOS" CALLS OR
; "ROM" CALLS IF THE APPROPRIATE
; LINK IS FOUND
;
LNKTAB PROC NEAR
JMP DMYLRET ;
JMP DMYLRET ;
;
CRVIO LABEL FAR
JMP DRVIO ; THIS SHOULD BE A FAR CALL
;
JMP DMYIRET ; THIS SHOULD BE A FAR JUMP
LNKTAB ENDP
;
; =========================================================
;
PGSEG ENDS
;
;
END
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/