865 lines
21 KiB
NASM
865 lines
21 KiB
NASM
;**************************************************************************
|
|
;**************************************************************************
|
|
;
|
|
; WDOS-BIOS - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988
|
|
; Programm: test.asm
|
|
;
|
|
; Bearbeiter : P. Hoge
|
|
; Datum : 24.1.89
|
|
; Version : 1.1
|
|
;
|
|
;**************************************************************************
|
|
;
|
|
; BIOS Testversion fuer Erweiterungsmodule
|
|
;
|
|
;**************************************************************************
|
|
;**************************************************************************
|
|
|
|
|
|
;--------------------------------------------------------------------
|
|
;
|
|
;BIOS I/O INTERFACE
|
|
;
|
|
;--------------------------------------------------------------------
|
|
|
|
STACK: EQU 0030H
|
|
DATA: EQU 0040H
|
|
XXDATA: EQU 0050H
|
|
|
|
.EXTERNAL VECTOR_TABLE ;NEAR
|
|
.EXTERNAL WORD MEMORY_SIZE
|
|
.EXTERNAL WORD EQUIP_FLAG
|
|
.EXTERNAL WORD TIMER_LOW
|
|
.EXTERNAL WORD TIMER_HIGH
|
|
.EXTERNAL BYTE TIMER_OFL
|
|
.EXTERNAL BYTE STATUS_BYTE
|
|
.EXTERNAL WORD IO_ROM_INIT
|
|
.EXTERNAL WORD KB_BUFFER
|
|
.EXTERNAL WORD BUFFER_HEAD
|
|
.EXTERNAL WORD BUFFER_TAIL
|
|
.EXTERNAL WORD BUFFER_START
|
|
.EXTERNAL WORD BUFFER_END
|
|
.EXTERNAL BYTE PRINT_TIM_OUT
|
|
.EXTERNAL TOS
|
|
.EXTERNAL DUMMY_RET ;NEAR
|
|
.EXTERNAL DISK_SETUP ;NEAR
|
|
.EXTERNAL byte BOOT_LOCN
|
|
.external byte DISK_BASE
|
|
.external byte reset
|
|
.external byte intin
|
|
.external byte clkin
|
|
.external byte date
|
|
|
|
.PUBLIC START
|
|
.PUBLIC DDS
|
|
.PUBLIC XPC_BYTE
|
|
.PUBLIC PRT_HEX
|
|
.PUBLIC XLAT_PR
|
|
.PUBLIC P_MSG
|
|
.PUBLIC PRT_SEG
|
|
.PUBLIC BOOT
|
|
.PUBLIC MEMSIZE
|
|
.PUBLIC EQUIP
|
|
.PUBLIC NMIINT
|
|
.PUBLIC CASSETTE
|
|
.PUBLIC TOFDAY
|
|
.PUBLIC TIMERINT
|
|
.PUBLIC PRSCREEN
|
|
|
|
X287 EQU 0F0H ;MATH PROCESSOR
|
|
|
|
;----------------------------------------
|
|
;TIMER DATA AREA
|
|
;----------------------------------------
|
|
COUNTS_SEC EQU 18
|
|
COUNTS_MIN EQU 1092
|
|
COUNTS_HOUR EQU 65543
|
|
COUNTS_DAY EQU 1573040 = 1800B0H
|
|
|
|
;----------------------------------------
|
|
;TEST
|
|
; x286 PROCESSOR TEST (REAL MODE)
|
|
;DESCRIPTION
|
|
; VERIFY FLAGS, REGISTERS
|
|
; AND CONDITIONAL JUMPS
|
|
;----------------------------------------
|
|
START: ;NEAR
|
|
CLI ;DISABLE INTERRUPTS
|
|
MOV AH,0D5H ;SET SF, CF, ZF, AND AF FLAGS ON
|
|
SAHF
|
|
JNC ERR01 ;GO TO ERR ROUTINE IF CF NOT SET
|
|
JNZ ERR01 ;GO TO ERR ROUTINE IF ZF NOT SET
|
|
JNP ERR01 ;GO TO ERR ROUTINE IF PF NOT SET
|
|
JNS ERR01 ;GO TO ERR ROUTINE IF SF NOT SET
|
|
LAHF ;LOAD FLAG IMAGE TO AH
|
|
|
|
MOV CL,5 ;LOAD CNT REG WITH SHIFT CNT
|
|
SHR AH,CL ;SHIFT AF INTO CARRY BIT POS
|
|
JNC ERR01 ;GO TO ERR ROUTINE IF AF NOT SET
|
|
MOV AL,40H ;SET THE OF FLAG ON
|
|
SHL AL,1 ;SETUP FOR TESTING
|
|
JNO ERR01 ;GO TO ERR ROUTINE IF OF NOT SET
|
|
XOR AH,AH ;SET AH = 0
|
|
SAHF ;CLEAR SF, CF, ZF, AND PF
|
|
JBE ERR01 ;GO TO ERR ROUTINE IF CF ON
|
|
;GO TO ERR ROUTINE IF ZF ON
|
|
JS ERR01 ;GO TO ERR ROUTINE IF SF ON
|
|
JP ERR01 ;GO TO ERR ROUTINE IF PF ON
|
|
LAHF ;LOAD FLAG IMAGE TO AH
|
|
MOV CL,5 ;LOAD CNT REG WITH SHIFT CNT
|
|
SHR AH,CL ;SHIFT 'AF' INTO CARRY BIT POS
|
|
JC ERR01 ;GO TO ERR ROUTINE IF ON
|
|
SHL AH,1 ;CHECK THAT 'OF' IS CLEAR
|
|
JO ERR01 ;GO TO ERR ROUTINE IF ON
|
|
|
|
;------ READ/WRITE THE X286 GENERAL AND SEGMENTATION REGISTERS
|
|
; WITH ALL ONE'S AND ZEROES'S.
|
|
|
|
MOV AX,0FFFFH ;SETUP ONE'S PATTERN IN AX
|
|
STC ;SET CARRY FLAG
|
|
JNC ERR01 ;GO IF NO CARRY
|
|
T1: MOV DS,AX ;WRITE PATTERN TO ALL REGS
|
|
MOV BX,DS
|
|
MOV ES,BX
|
|
MOV CX,ES
|
|
MOV SS,CX
|
|
MOV DX,SS
|
|
MOV SP,DX
|
|
MOV BP,SP
|
|
MOV SI,BP
|
|
MOV DI,SI
|
|
JNC T2
|
|
XOR AX,DI ;PATTERN MAKE IT THRU ALL REGS
|
|
JNZ ERR01 ;NO - GO TO ERR ROUTINE
|
|
CLC ;CLEAR CARRY FLAG
|
|
JMP SHORT T1
|
|
T2:
|
|
OR AX,DI ;ZERO PATTERN MAKE IT THRU?
|
|
JZ I1 ;YES - GO TO NEXT TEST
|
|
ERR01: HLT ;HALT SYSTEM
|
|
|
|
;----------------------------------------
|
|
; INIT BIOS
|
|
;----------------------------------------
|
|
|
|
;------ CLEAR RAM
|
|
|
|
I1: MOV CX,1024 ;CLEAR 2K
|
|
SUB AX,AX
|
|
MOV DI,AX
|
|
MOV DS,AX
|
|
I2: MOV [DI],AX ;CLEAR
|
|
INC DI
|
|
INC DI ;POINT TO NEXT LOCATION
|
|
LOOP I2
|
|
|
|
;------ SETUP STACK SEG AND SP
|
|
|
|
MOV SP,STACK ;SET REAL MODE STACK
|
|
MOV SS,SP
|
|
MOV SP, OFFSET TOS
|
|
|
|
SUB AL,AL ;RESET MATH PROCESSOR
|
|
OUT X287+1,AL
|
|
|
|
;------ SET UP THE INTERRUPT VECTORS
|
|
|
|
MOV CX,78H ;FILL ALL INTERRUPT LOCATIONS
|
|
SUB DI,DI ;FIRST INTERRUPT LOCATION
|
|
MOV ES,DI ;SET ES ALSO
|
|
I3: MOV AX,OFFSET DUMMY_RET ;MOVE ADDRESS OF INT OFFSET
|
|
STOSW
|
|
MOV AX,CS ;GET THE SEGMENT
|
|
STOSW
|
|
LOOP I3
|
|
|
|
;------ ESTABLISH BIOS INTERRUPT VECTORS
|
|
|
|
SUB DI,DI ;FIRST INTERRUPT LOCATION
|
|
PUSH CS
|
|
POP DS ;SET UP ADDRESS OF VECTOR TABLE
|
|
MOV SI,OFFSET VECTOR_TABLE
|
|
MOV CX,32
|
|
I4: MOVSW ;MOVE VECTOR TABLE TO RAM
|
|
INC DI
|
|
INC DI ;SKIP SEGMENT POINTER
|
|
LOOP I4
|
|
|
|
;------ ZERO RESERVED VECTORS
|
|
|
|
SUB AX,AX
|
|
MOV DS,AX
|
|
MOV DI,60H*4 ;INT 60 THRU 67 FILL WITH ZERO
|
|
MOV CX,14 ;CLEAR 14 WORDS
|
|
I5: MOV WORD PTR [DI],0
|
|
INC DI ;POINT TO NEXT LOCATION
|
|
INC DI
|
|
LOOP I5
|
|
|
|
CALL DDS
|
|
MOV MEMORY_SIZE,704-64 ;MEMORY SIZE SETZEN in KByte
|
|
MOV EQUIP_FLAG,4071H ;EQUIPMENT FLAG SETZEN
|
|
;80*25 VIDEO BW, 2 FD, 1 LP, 0 RS232
|
|
;kein 287
|
|
|
|
;------ SETUP KEYBOARD PARAMETERS
|
|
|
|
MOV SI, OFFSET KB_BUFFER ;SETUP KEYBOARD PARAMETERS
|
|
MOV BUFFER_HEAD,SI
|
|
MOV BUFFER_TAIL,SI
|
|
MOV BUFFER_START,SI
|
|
ADD SI,32 ;DEFAULT BUFFER OF 32 BYTES
|
|
MOV BUFFER_END,SI
|
|
|
|
STI ;ALLOW INTERRUPTS
|
|
|
|
;------ INIT VIDEO
|
|
|
|
MOV AX,0002H ;SET MODE 80*25 B/W
|
|
INT 10H ;SEND INIT TO B/W CARD
|
|
|
|
;------- SET TIME OF DAY
|
|
|
|
CALL SET_TOD
|
|
call DISK_SETUP
|
|
|
|
;------ ENABLE HARDWARE INTERRUPT IF MATH PROCESSOR (X287)
|
|
|
|
; SUB AX,AX ;CLEAR IO_ROM_INIT
|
|
; MOV IO_ROM_INIT,AX
|
|
; ESC 28,BX
|
|
; XOR AX,AX
|
|
; ESC 15,IO_ROM_INIT
|
|
; PUSHA ;TIME FOR 287 TO RESPOND
|
|
; POPA
|
|
; AND IO_ROM_INIT,01F3FH ;CLEAR UNUSED 287 BITS
|
|
; CMP IO_ROM_INIT,0033FH ;IS IF 287 INSTALLED?
|
|
; JNZ NO_287 ;GO IF MATH PROCESSOR IS NOT INSTALLED
|
|
|
|
; WAIT
|
|
; ESC 02FH,IO_ROM_INIT ;STORE THE STATUS WORD
|
|
; PUSHA ;TIME FOR 287 TO RESPOND
|
|
; POPA
|
|
; TEST IO_ROM_INIT,0D8BFH ;ALL BITS SHOULD BE OFF
|
|
; JNZ NO_287 ;GO IF NOT INSTALLED
|
|
|
|
; OR BYTE PTR EQUI_FLAG,02H ;SET 287 BIT ON
|
|
|
|
;NO_287:
|
|
; MOV IO_ROM_INIT,0
|
|
|
|
;------ LOAD SYSTEM
|
|
INT 19H ;GO TO BOOT LOADER
|
|
CLI
|
|
HLT ;HALT CPU
|
|
|
|
DDS ;PROC NEAR
|
|
push ax
|
|
mov ax,DATA
|
|
mov ds,ax
|
|
pop ax
|
|
ret
|
|
|
|
;---------------------------------------------------------------------
|
|
;CONVERT AND PRINT ASCII CODE
|
|
;
|
|
; AL MUST CONTAIN NUMBER TO BE CONVERTED.
|
|
;---------------------------------------------------------------------
|
|
XPC_BYTE ;PROC NEAR
|
|
PUSH AX ;SAVE FOR LOW NIBBLE DISPLAY
|
|
MOV CL,4 ;SHIFT COUNT
|
|
SHR AL,CL ;NIBBLE SWAP
|
|
CALL XLAT_PR ;DO THE HIGH NIBBLE DISPLAY
|
|
POP AX ;RECOVER THE NIBBLE
|
|
AND AL,0FH ;ISOLATE TO LOW NIBBLE
|
|
;FALL INTO LOW NIBBLE CONVERSION
|
|
XLAT_PR ;PROC NEAR ;CONVERT 00-0F TO ASCII CHARAKTER
|
|
ADD AL,090H ;ADD FIRST CONVERSION FACTOR
|
|
DAA ;ADJUST FOR NUMERIC AND ALPHA RANGE
|
|
ADC AL,040H ;ADD CONVERSION AND ADJUST LOW NIBBLE
|
|
DAA ;ADJUST HIGH NIBBLE TO ASCHI RANGE
|
|
|
|
PRT_HEX ;PROC NEAR
|
|
MOV AH,14 ;DISPLAY CHARAKTER IN AL
|
|
MOV BH,0
|
|
INT 10H ;CALL VIDIO_IO
|
|
RET
|
|
|
|
;----------------------------------------------------------------------
|
|
;THIS SUBROUTINE WILL PRINT A MESSAGE ON THE DISPLAY
|
|
;
|
|
;ENTRY REQUIREMENTS:
|
|
; SI = OFFSET(ADDRESS) OF MESSAGE BUFFER
|
|
;----------------------------------------------------------------------
|
|
P_MSG ;PROC NEAR
|
|
PM1: MOV AL,CS:[SI] ;PUT CHAR IN AL
|
|
INC SI ;POINT TO NEXT CHAR
|
|
PUSH AX ;SAVE PRINT CHAR
|
|
CALL PRT_HEX ;CALL VIDIO IO
|
|
POP AX ;RECOVER PRINT CHAR
|
|
CMP AL,10 ;WAS IT LINE FEED?
|
|
JNE PM1 ;NO, KEEP PRINTING STRING
|
|
RET
|
|
|
|
;-----------------------------------------------------------
|
|
; PRINT A SEGMENT VALUE TO LOOK LIKE A 21 BIT ADDRESS
|
|
; DX MUST CONTAIN SEGMENT VALUE TO BE PRINTED
|
|
;-----------------------------------------------------------
|
|
PRT_SEG ;PROC NEAR
|
|
MOV AL,DH ;GET MSB
|
|
CALL XPC_BYTE
|
|
MOV AL,DL ;LSB
|
|
CALL XPC_BYTE
|
|
MOV AL,'0' ;PRINT A '0'
|
|
CALL PRT_HEX
|
|
MOV AL,' ' ;SPACE
|
|
CALL PRT_HEX
|
|
RET
|
|
|
|
;--- INT 19 ----------------------------------------------------
|
|
;BOOT DOS (hier ersetzt durch MP600-Test)
|
|
;---------------------------------------------------------------
|
|
MSGRUN: defb 'test running',0dh,0ah
|
|
|
|
BOOT: sti
|
|
BOOT0: mov SI,OFFSET MSGRUN
|
|
call P_MSG
|
|
mov cx,-1
|
|
sub ax,ax
|
|
mov ds,ax
|
|
mov bx,1000h
|
|
BOOT1: mov al,[bx] ;Byte gerade Adresse
|
|
mov dl,cs:[bx]
|
|
mov [bx],al
|
|
mov cs:[bx],bl
|
|
inc bx
|
|
mov al,[bx] ;Byte ungerade Adresse
|
|
mov dl,cs:[bx]
|
|
mov [bx],al
|
|
mov [bx],dl
|
|
dec bx
|
|
mov ax,[bx] ;Wort gerade Adresse
|
|
mov dx,cs:[bx]
|
|
mov [bx],ax
|
|
mov cs:[bx],dx
|
|
inc bx
|
|
mov ax,[bx] ;Wort ungerade Adresse
|
|
mov dx,cs:[bx]
|
|
mov [bx],ax
|
|
mov cs:[bx],dx
|
|
dec bx
|
|
loopnz BOOT1
|
|
jmp short BOOT0
|
|
|
|
|
|
;--- INT 12 ----------------------------------------------------
|
|
;MEMORY_SIZE_DETERMINE
|
|
;
|
|
;OUTPUT
|
|
; (AX) = NUMBER OF CONTICUOUS 1K BLOCKS OF MEMORY
|
|
;---------------------------------------------------------------
|
|
MEMSIZE ;PROC FAR
|
|
PUSH DS ;SAVE SEGMENT
|
|
CALL DDS ;ESTABLISH ADDRESSING
|
|
MOV AX,MEMORY_SIZE ;GET VALUE
|
|
POP DS ;RECOVER SEGMENT
|
|
IRET ;RETURN TO CALLER
|
|
|
|
;--- INT 11 ----------------------------------------------------
|
|
;EQUIPMENT DETERMINATION
|
|
; THIS ROUTINE ATTEMPTS TO DETERMINE WHAT OPTIONAL
|
|
; DEVICES ARE ATTACHED TO THE SYSTEM.
|
|
;OUTPUT
|
|
; (AX) IS SET, BIT SIGNIFICANT, TO INDICATE ATTACHED I/O
|
|
; BIT 1 = MATH COPROCESSOR
|
|
;---------------------------------------------------------------
|
|
EQUIP ;PROC FAR ;>>> ENTRY POINT FOR ORG 0F84DH
|
|
PUSH DS ;SAVE SEGMENT REGISTER
|
|
CALL DDS ;ESTABLISH ADDRESSING
|
|
MOV AX,EQUIP_FLAG ;GET THE CURRENT SETTINGS
|
|
POP DS ;RECOVER SEGMENT
|
|
IRET ;RETURN TO CALLER
|
|
|
|
;-- INT 2 -----------------------------------------------------
|
|
;NON-MASKABLE INTERRUPT ROUTINE (REAL MODE)
|
|
;SERVICE X287 INTERRUPTS
|
|
; THIS ROUTINE FIELDS X287 INTERRUPTS
|
|
;--------------------------------------------------------------
|
|
NMIINT ;PROC NEAR
|
|
PUSH AX
|
|
XOR AL,AL
|
|
OUT X287,AL ;REMOVE THE INT.REQUEST
|
|
POP AX
|
|
IRET
|
|
|
|
;- - INT 5 -----------------------------------------------------
|
|
; THIS LOGIC WILL BE INVOKED BY INTERRUPT 05H TO PRINT
|
|
; THE SCREEN. THE CURSOR POSITION AT THE TIME THIS ROUTINE
|
|
; IS INVOKED WILL BE SEVED AND RESTORED UPON COMPETION. THE
|
|
; ROUTINT IS INTENDED TO RUN WITH INTERRUPTS ENABLED.
|
|
; IF A SUBSEQUENT PRINT SGREEN KEY IS DEPRESSED DURING THE
|
|
; TIME THIS ROUTINE IS PRINTING IT WILL BE IGNORED.
|
|
; ADDRESS 50:0 CONTAINS THE STATUS OF THE PRINT SCREEN:
|
|
;
|
|
; 50:0 =0 EITHER PRINT SCREEN HAS NOT BEEN CALLED
|
|
; OR UPON RETURN FROM A CALL THIS INDI-
|
|
; CATES A SUCCESSFUL OPERATION.
|
|
;
|
|
; =1 PRINT SCREEN IS IN PROGRESS
|
|
;
|
|
; =255 ERROR ENCOUNTERED DURING PRINTING
|
|
;---------------------------------------------------------------
|
|
PRSCREEN ;PROC FAR
|
|
STI ;MUST RUN WITH INTERRUPTS ENABLED
|
|
PUSH DS ;MUST USE 50:0 FOR DATA ARE STORAGE
|
|
PUSH AX
|
|
PUSH BX
|
|
PUSH CX ;WILL USE THIS LATER FOR CURSOR LIMITS
|
|
PUSH DX ;WILL HOLD CURRENT CURSOR POSITION
|
|
MOV AX,XXDATA ;HEX 50
|
|
MOV DS,AX
|
|
CMP STATUS_BYTE,1 ;SEE IF PRINT ALREADY IN PROGRESS
|
|
JZ EXIT ;JUNP IF PRINT ALREADY IN PROGRESS
|
|
MOV STATUS_BYTE,1 ;INDICATE PRINT NOW IN PROGRESS
|
|
MOV AH,15 ;WILL REQUEST THE CURRENT SCEEN MODE
|
|
INT 10H ; [AL] = MODE
|
|
; [AH] = NUMBER COLUMNS/LINE
|
|
; [BH] = VISUAL PAGE
|
|
|
|
MOV CL,AH ;WILL MAKE USE OF [CX] REGISTER TO
|
|
MOV CH,25 ;CONTROL ROW & COLUMNS
|
|
CALL CRLF ;CARRIAGE RETURN LINE FEED ROUTINE
|
|
PUSH CX ;SAVE SCREEN BOUNDS
|
|
MOV AH,3 ;WILL NOW READ THE CURSOR
|
|
INT 10H ;AND PRESERVE THE POSITION
|
|
POP CX ;RECALL SCREEN BOUNDS
|
|
PUSH DX ;RECALL [BH]=VISUAL PAGE
|
|
XOR DX,DX ;WILL SET CURSOR POSITION TO [0,0]
|
|
|
|
;---------------------------------------------------------------------------
|
|
; THE LOOP FROM PRI10 TO THE INSTRUCTION PRIOR TO PRI20
|
|
; IS THE LOOP TO READ EACH CURSOR POSITION FROM THE SCREEN
|
|
; AND PRINT.
|
|
;---------------------------------------------------------------------------
|
|
|
|
PRI10: MOV AH,2 ;TO INDICATE CURSOR SET REQUEST
|
|
INT 10H ;NEW CURSOR POSITION ESTABLISHED
|
|
MOV AH,8 ;TO INDICATE READ CHARACTER
|
|
INT 10H ;CHARACTER NOW IN [AL]
|
|
OR AL,AL ;SEE IF VALID CHAR
|
|
JNZ PRI15 ;JUMP IF VALID CHAR
|
|
MOV AL,' ' ;MAKE A BLANK
|
|
PRI15:
|
|
PUSH DX ;SAVE CURSOR POSITION
|
|
XOR DX,DX ;INDICATE PRINTER 1
|
|
XOR AH,AH ;TO INDICATE PRINT CHAR IN [AL]
|
|
INT 17H ;PRINT THE CHARACTER
|
|
POP DX ;RACALL CURSOR POSITION
|
|
TEST AH,29H ;TEST FOR PRINTER ERROR
|
|
JNZ ERR10 ;JUMP IF ERROR DETECTED
|
|
INC DL ;ADVANCE TO NEXT COLUMN
|
|
CMP CL,DL ;SEE IF AT END OF LINE
|
|
JNZ PRI10 ;IF NOT PROCEED
|
|
XOR DL,DL ;BACK TO COLUMN 0
|
|
MOV AH,DL ;[AH]=0
|
|
PUSH DX ;SAVE NEW CURSOR POSITION
|
|
CALL CRLF ;LINE FEED CARRIAGE RETURN
|
|
POP DX ;RECALL CURSOR POSITION
|
|
INC DH ;ADVANCE TO NEXT LINE
|
|
CMP CH,DH ;FINISHED?
|
|
JNZ PRI10 ;IF NOT CONTINUE
|
|
PRI20: POP DX ;RECALL CURSOR POSITION
|
|
MOV AH,2 ;TO INDICATE CURSOR SET REQUEST
|
|
INT 10H ;CURSOR POSITION RESTORED
|
|
MOV STATUS_BYTE,0 ;INDICATE FINISHED
|
|
JMP SHORT EXIT ;EXIT THE ROUTINE
|
|
ERR10: POP DX ;GET CURSOR POSITION
|
|
MOV AH,2 ;TO REQUEST CURSOR SET
|
|
INT 10H ;CURSOR POSITION RESTORED
|
|
ERR20: MOV STATUS_BYTE,0FFH ;INDICATE ERROR
|
|
|
|
EXIT: POP DX ;RESTORE ALL THE REGISTERS USED
|
|
POP CX
|
|
POP BX
|
|
POP AX
|
|
POP DS
|
|
IRET
|
|
|
|
;------ CARRIAGE RETURN, LINE FEED SUBROUTINE
|
|
|
|
CRLF ;PROC NEAR
|
|
XOR DX,DX ;PRINTER 0
|
|
XOR AH,AH
|
|
MOV AL,0dh
|
|
INT 17H
|
|
XOR AH,AH
|
|
MOV AL,0ah
|
|
INT 17H ;SEND THE CARRIAGE RETURN
|
|
RET
|
|
|
|
;---------------------------------------------------------------
|
|
; THIS ROUTINE INITIALIZES THE TIMER DATA AREA IN THE
|
|
; ROM BIOS DATD AREA. IT IS CALLED BY THE POWER ON
|
|
; ROUTINES. IT CONVERTS HR:MIN:SEC TO TIMER
|
|
; TICS.
|
|
;---------------------------------------------------------------
|
|
;
|
|
;OUTPUT
|
|
; TIMER_LOW
|
|
; TIMER_HIGH
|
|
; TIMER_OFL
|
|
; ALL REGISTER UNCHANGEND
|
|
;--------------------------------------------------------------
|
|
COUNTS_DHOUR EQU 7 ;65543 - 65536
|
|
|
|
SET_TOD ;PROC NEAR
|
|
CLI
|
|
PUSH DS
|
|
CALL DDS
|
|
|
|
mov al,cs:date+0 ;Sekunden
|
|
sub ah,ah
|
|
MOV BL,COUNTS_SEC
|
|
MUL BL ;COUNT FOR SECONDS
|
|
MOV CX,AX
|
|
|
|
mov al,cs:date+1 ;Minuten
|
|
sub ah,ah
|
|
MOV BX,COUNTS_MIN
|
|
MUL BX ;COUNT FOR MINUTES
|
|
ADD AX,CX
|
|
MOV CX,AX
|
|
|
|
mov al,cs:date+2 ;Stunden
|
|
sub ah,ah
|
|
MOV DX,AX
|
|
MOV BL,COUNTS_DHOUR
|
|
MUL BL ;COUNT FOR HOURS
|
|
ADD AX,CX
|
|
ADC DX,0000H
|
|
MOV TIMER_HIGH,DX
|
|
MOV TIMER_LOW,AX
|
|
SUB AX,AX
|
|
MOV TIMER_OFL,AL ;RESET TIMER ROLL OVER INDICATOR
|
|
POP DS
|
|
STI
|
|
RET
|
|
|
|
|
|
;--- INT 1A -------------------------------------------------------------
|
|
;TIME_OF DAY
|
|
; THIS ROUTINE ALLOWS THE CLOCK TO BE SET/READ
|
|
;
|
|
;INPUT
|
|
; (AH) = 0 READ THE CURRENT CLOCK SETTING
|
|
; (AH) = 1 SET THE CURRENT CLOCK
|
|
; (AH) = 2 READ THE REAL TIME CLOCK
|
|
; (AH) = 3 SET THE REAL TIME CLOCK - nicht moeglich
|
|
; (AH) = 4 READ THE DATE FROM THE REAL TIME CLOCK
|
|
; (AH) = 5 SET THE DATE INTO THE REAL TIME CLOCK - nicht moeglich
|
|
; (AH) = 6 SET THE ALARM - nicht moeglich
|
|
; (AH) = 7 RESET THE ALARM - nicht moeglich
|
|
;
|
|
;NOTE: FOR AH = 6 - CY FLAG SET for not possible
|
|
;------------------------------------------------------------------------
|
|
TOFDAY ;PROC FAR
|
|
PUSH DS ;SAVE SEGMENT
|
|
CALL DDS ;SET DATA SEGMENT
|
|
OR AH,AH ;AH=0
|
|
JZ TD0 ;READ_TIME
|
|
DEC AH ;AH=1
|
|
JZ TD1 ;SET_TIME
|
|
DEC AH ;AH=2
|
|
JZ TD2 ;Read Real Time
|
|
DEC AH
|
|
DEC AH ;AH=4
|
|
JZ TD4
|
|
STC ;SET ERROR RETURN
|
|
POP DS
|
|
STI
|
|
RET FAR 2
|
|
|
|
TD0: MOV AL,TIMER_OFL
|
|
MOV TIMER_OFL,0 ;GET OVERFLOW, AND RESET THE FLAG
|
|
MOV CX,TIMER_HIGH
|
|
MOV DX,TIMER_LOW
|
|
POP DS ;RECOVER SEGMENT
|
|
IRET ;RETURN TO CALLER
|
|
|
|
TD1: MOV TIMER_LOW,DX
|
|
MOV TIMER_HIGH,CX ;SET THE TIME
|
|
MOV TIMER_OFL,0 ;RESET OVERFLOW
|
|
POP DS
|
|
IRET
|
|
|
|
TD2: mov al,cs:date+0 ;Sekunde
|
|
call CVT_BCD
|
|
mov dh,al
|
|
mov al,cs:date+1 ;Minute
|
|
inc al
|
|
call CVT_BCD
|
|
mov cl,al
|
|
mov al,cs:date+2 ;Stunde
|
|
call CVT_BCD
|
|
mov ch,al
|
|
pop ds
|
|
iret
|
|
|
|
TD4: mov al,cs:date+3 ;Tag
|
|
call CVT_BCD
|
|
mov dl,al
|
|
mov al,cs:date+4 ;Monat
|
|
inc al
|
|
call CVT_BCD
|
|
mov dh,al
|
|
mov al,cs:date+5 ;Jahr
|
|
call CVT_BCD
|
|
mov cl,al
|
|
mov ch,19h ;Jahrhundert
|
|
pop ds
|
|
iret
|
|
|
|
CVT_BCD ;PROC NEAR
|
|
aam
|
|
shl ah,1
|
|
shl ah,1
|
|
shl ah,1
|
|
shl ah,1
|
|
or al,ah
|
|
ret
|
|
|
|
|
|
;- - INT 8 -----------------------------------------------------
|
|
;THIS ROUTINE HANDLES THE TIMER INTERRUPTS
|
|
;THE INTERRUPT HANDLER MAINTAINS A COUNT OF INTERRUPTS SINCE
|
|
;POWER ON TIME, WHICH MAY BE USED TO ESTABLISH TIME OF DAY.
|
|
;THE INTERRUPT HANDLER WILL ALSO INVOKE A USER ROUTINE THROUGH
|
|
;INTERRUPT 1CH AT EVERY TIME TICK. THE USER MUST CODE A
|
|
;ROUTINE AND PLACE THE CORRECT ADDRESS IN THE VECTOR TABLE.
|
|
;---------------------------------------------------------------
|
|
|
|
TIMERINT ;PROC FAIR
|
|
mov cs:intin,0 ;weitere Ints erlauben
|
|
sti
|
|
push ds
|
|
push ax
|
|
push cx
|
|
call DDS
|
|
sub ax,ax
|
|
mov cx,1
|
|
inc cs:TISEC
|
|
mov al,cs:TISEC
|
|
cmp al,10 ;Korrektur bei 1 Sekunde ?
|
|
jnz TI1
|
|
mov cs:TISEC,ah
|
|
mov cx,9
|
|
inc cs:TIMIN
|
|
mov al,cs:TIMIN
|
|
cmp al,60 ;Korrektur bei 1 Minute ?
|
|
jnz TI1
|
|
mov cs:TIMIN,ah
|
|
mov cx,21
|
|
inc cs:TIHOUR
|
|
mov al,cs:TIHOUR
|
|
cmp al,60 ;Korrektur bei 1 Stunde ?
|
|
jnz TI1
|
|
mov cs:TIHOUR,ah
|
|
mov cx,44
|
|
|
|
TI1: INC TIMER_LOW ;INCREMENT TIME
|
|
JNZ TI2 ;TEST_DAY
|
|
INC TIMER_HIGH ;INCERMENT HIGH WORD OF TIME
|
|
TI2: CMP TIMER_HIGH,18H ;TEST FOR COUNT EQUALLING 24 HOURS
|
|
JNZ TI3
|
|
CMP TIMER_LOW,00B0H
|
|
JNZ TI3
|
|
|
|
SUB AX,AX ;TIMER HAS GONE 24 HOURS
|
|
MOV TIMER_HIGH,AX
|
|
MOV TIMER_LOW,AX
|
|
MOV TIMER_OFL,1
|
|
TI3: loop TI1
|
|
|
|
INT 1CH ;TRANSFER CONTROL TO A USER ROUTINE
|
|
mov cs:clkin+1,0 ;weiteren Clock-Int erlauben
|
|
pop cx
|
|
pop ax
|
|
pop ds
|
|
iret
|
|
|
|
TISEC: defb 0
|
|
TIMIN: defb 0
|
|
TIHOUR: defb 0
|
|
|
|
;--- INT 15 ----------------------------------------------------
|
|
; INPUT - CASSETTE I/O FUNCTIONS
|
|
; (AH) = 00
|
|
; (AH) = 01
|
|
; (AH) = 02
|
|
; (AH) = 03
|
|
; RETURNS FOR THESE FUNCTIONS ALWAYS (AH) = 86H, CF = 1)
|
|
; IF CASSETTE PORT NOT PRESENT
|
|
;---------------------------------------------------------------
|
|
; INPUT - UNUSED FUNCTIONS
|
|
; (AH) = 04 THROUGH 7F
|
|
; RETURNS FOR THESE FUNCTIONS ALWAYS (AH) = 86H, CF = 1)
|
|
;---------------------------------------------------------------
|
|
;Extensions
|
|
; (AH) = 80H DEVICE OPEN
|
|
; (BX) = DEVICE ID
|
|
; (CX) = PROCESS ID
|
|
;
|
|
; (AH) = 81H DEVICE CLOSE
|
|
; (BX) = DEVICE ID
|
|
; (CX) = PROCESS ID
|
|
;
|
|
; (AH) = 82H PROGRAM TERMINATION
|
|
; (BX) = DEVICE ID
|
|
;
|
|
; (AH) = 83H EVENT WAIT
|
|
; (AL) = 0 SET INTERVAL
|
|
; (ES:BX) POINTER TO A BYTE IN CALLERS MEMORY
|
|
; THAT WILL HAVE THE HIGH ORDER BIT SET
|
|
; AS SOON AS POSSIBLE AFTER THE INTERVAL
|
|
; EXPIRES.
|
|
; (CX,DX) NUMBER OF MICROSECONDS TO ELAPSE BEFORE
|
|
; POSTING.
|
|
; (AL) = 1 CANCEL
|
|
;
|
|
; (AH) = 84H JOYSTICK SUPPORT
|
|
; (DX) = 0 - READ THE CURRENT SWITCH SETTINGS
|
|
; RETURNS AL = SWITCH SETTINGS (BITS 7-4)
|
|
; (DX) = 1 - READ THE RESISTIVE INPUTS
|
|
; RETURNS AX = A(x) VALUE
|
|
; BX = A(y) VALUE
|
|
; CX = B(x) VALUE
|
|
; DX = B(y) VALUE
|
|
;
|
|
; (AH) = 85H SYSTEM REQUEST KEY PRESSED
|
|
; (AL) = 00 MAKE OF KEY
|
|
; (AL) = 01 BREAK OF KEY
|
|
; (AH) = 86H WAIT
|
|
; (CX,DX) NUMBER OF MICROSECONDS TO ELPASE BEFORE
|
|
; RETURN TO CALLER
|
|
; (AH) = 87H MOVE BLOCK
|
|
; (CX) NUMBER OF WORDS TO MOVE
|
|
; (ES:SI) POINTER TO DESCRIPTOR TABLE
|
|
; (AH) = 88H EXTENDENT MEMORY SIZE DETERMINE
|
|
; (AH) = 89H PROCESSOR TO VIRTUAL MODE
|
|
;
|
|
; (AH) = 90H DEVICE BUSY LOOP
|
|
; (AL) SEE TYPE CODE
|
|
;
|
|
; (AH) = 91H INTERRUPT COMPLETE FLAG SET
|
|
; (AL) TYPE CODE
|
|
; 00H -> 7FH
|
|
; SERIALLY REUSABLE DEVICES
|
|
; OPERATING SYSTEM MUST SERIALIZE
|
|
; ACCESS
|
|
; 80H -> BFH
|
|
; REENTRANT DEVICES;ES:BX IS
|
|
; USED TO DISTINGUISH DIFFERENT
|
|
; CALLS (MULTIPLE I/O CALLS ARE
|
|
; ALLOWED SIMULTANEUSLY)
|
|
; C0H -> FFH
|
|
; WAIT ONLY CALLS; THERE IS NO
|
|
; COMPLEMENTARY `POST` FOR THESE
|
|
; WAITS - - THESE ARE TIMEOUT
|
|
; ONLY. TIMES ARE FUNCTION NUMBER
|
|
; DEPENDENT
|
|
;
|
|
; TYPE DESCRIPTION TIMEOUT
|
|
;
|
|
; 00H = DISK YES
|
|
; 01H = DISKETTE YES
|
|
; 02H = KEYBOARD NO
|
|
; 80H = NETWORK NO
|
|
; ES:BX --> NCB
|
|
; FDH = DISKETTE MOTOR START YES
|
|
; FEH = PRINTER YES
|
|
;---------------------------------------------------------------
|
|
CASSETTE ;PROC FAR
|
|
STI
|
|
CMP AH,80H ;CHECK FOR RANGE
|
|
JB C1 ;RETURN IF 00-7FH
|
|
SUB AH,80H ;BASE ON 0
|
|
OR AH,AH
|
|
JZ DEV_OPEN ;DEVICE OPEN
|
|
DEC AH
|
|
JZ DEV_CLOSE ;DEVICE CLOSE
|
|
DEC AH
|
|
JZ PROG_TERM ;PROGRAM TERMINATION
|
|
DEC AH
|
|
JZ EVENT_WAIT ;EVENT WAIT
|
|
DEC AH
|
|
JZ JOY_STICK ;JOYSTICK BIOS
|
|
DEC AH
|
|
JZ SYS_REQ ;SYSTEM REQUEST KEY
|
|
DEC AH
|
|
JZ C1_A ;WAIT
|
|
DEC AH
|
|
JNZ C1_B
|
|
JMP BLOCKMOVE ;MOVE BLOCK
|
|
|
|
C1_A: JMP WAIT ;WAIT
|
|
|
|
C1_B: DEC AH
|
|
JNZ C1_C
|
|
JMP EXT_MEMORY ;GO GET THE EXTENDED MEMORY
|
|
|
|
C1_C: DEC AH ;CHECK FOR FUNCTION 89
|
|
JNZ C1_D
|
|
JMP SET_VMODE ;SWAP TO VIRTUAL MODE
|
|
|
|
C1_D: SUB AH,7 ;CHECK FOR FUNCTION 90
|
|
JNZ C1_E ;GO IF NOT
|
|
JMP DEVICE_BUSY
|
|
|
|
C1_E: DEC AH ;CHECK FOR FUNCTION 91
|
|
JNZ C1 ;GO IF NOT
|
|
JMP INT_COMPLETE
|
|
|
|
C1: MOV AH,86H ;SET BAD COMMAND
|
|
C2: STC ;SET CARRY FLAG ON
|
|
DEV_OPEN:
|
|
DEV_CLOSE:
|
|
PROG_TERM:
|
|
SYS_REQ:
|
|
C1_F:
|
|
RET FAR 2
|
|
|
|
EVENT_WAIT:
|
|
WAIT:
|
|
JMP SHORT C2 ;SET ERROR - keine CMOS-Uhr
|
|
|
|
JOY_STICK: ;nicht vorhanden
|
|
JMP SHORT C1 ;GO TO ERROR RETURN
|
|
|
|
BLOCKMOVE: ;nicht implementiert
|
|
MOV AH,1 ;Fehler setzen
|
|
JMP SHORT C2
|
|
|
|
EXT_MEMORY:
|
|
MOV AX,0 ;kein Speicher ueber 1 MByte
|
|
IRET ;RETURN TO USER
|
|
|
|
SET_VMODE: ;nicht implementiert
|
|
MOV AH,0FFH ;SET THE ERROR FLAG
|
|
JMP SHORT C2
|
|
|
|
;--- DEVICS BUSY AND INTERRUPT COMPLETE ------------------------
|
|
; THIS ROUTINE IS A TEMPORY HANDLER FOR DEVICE BUSY
|
|
; AND INTERRUPT COMPLETE
|
|
;
|
|
; INPUT
|
|
; SEE PROLOG
|
|
;---------------------------------------------------------------
|
|
DEVICE_BUSY ;PROC NEAR
|
|
CLC ;TURN CARRY OFF
|
|
JMP short C1_F ;RETURN WITH CARRY FLAG
|
|
|
|
INT_COMPLETE ;PROC NEAR
|
|
IRET ;RETURN
|
|
|
|
END
|