P8000/WEGA/contrib/wdos/src/bios.asm

864 lines
21 KiB
NASM

;**************************************************************************
;**************************************************************************
;
; WDOS-BIOS - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988
; Programm: bios.asm
;
; Bearbeiter : P. Hoge
; Datum : 24.1.89
; Version : 1.1
;
;**************************************************************************
;
; 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 byte KB_FLAG
.external byte KB_EXT
.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 ;MEMORY SIZE SETZEN in KByte
MOV EQUIP_FLAG,4071H ;EQUIPMENT FLAG SETZEN
;80*25 VIDEO BW, 2 FD, 1 LP, 0 RS232
;kein 287
mov KB_EXT,10h ;extended Keyboard
; mov KB_FLAG,20h ;NUM-Lock aktiv
;------ 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
;---------------------------------------------------------------
MSGRUN: defb '(running)',0dh,0ah
MSGBER: defb 'Boot Error',0dh,0ah
BOOT: sti
mov al,cs:reset
or al,al
jz BOOT0 ;Ausschrift unterdruecken
mov SI,OFFSET MSGRUN
call P_MSG
BOOT0: sub ax,ax
mov cs:reset,al ;Reset verhindern
mov es,ax ;Segment 0
mov ah,2 ;Read Boot Sector
mov al,1 ;Count of Sectors
sub ch,ch ;Track 0
mov cl,al ;Sector 0
mov dh,ch ;Head 0
mov dl,ch ;FD Drive 0
mov bx,offset BOOT_LOCN
int 13h
jnc BOOT1 ;Fehler
mov ax,0201h ;Read Boot Sector HD
mov dl,80h ;HD Drive 0
int 13h
jnc BOOT2
mov si,offset MSGBER ;Fehler
call P_MSG
ret
BOOT1: mov al,es:BOOT_LOCN+24 ;Anzahl Sektoren/Track
mov es:BOOT_LOCN+2fh,al ;Wert im Urlader korrigieren
mov cs:DISK_BASE+4,al
BOOT2: jmp far 0:7c00h
;--- 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