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