diff --git a/WEGA/contrib/wdos/src/bios.asm b/WEGA/contrib/wdos/src/bios.asm new file mode 100644 index 0000000..510843c --- /dev/null +++ b/WEGA/contrib/wdos/src/bios.asm @@ -0,0 +1,863 @@ +;************************************************************************** +;************************************************************************** +; +; 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 diff --git a/WEGA/contrib/wdos/src/orgs.asm b/WEGA/contrib/wdos/src/orgs.asm new file mode 100644 index 0000000..4a15b8b --- /dev/null +++ b/WEGA/contrib/wdos/src/orgs.asm @@ -0,0 +1,321 @@ +;************************************************************************** +;************************************************************************** +; +; WDOS-BIOS - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988 +; Programm: orgs.asm +; +; Bearbeiter : P. Hoge +; Datum : 24.1.89 +; Version : 1.1 +; +;************************************************************************** +; +; System-Einspruenge und Vereinbarungen +; +;************************************************************************** +;************************************************************************** + + +.EXTERNAL DISK_SETUP;NEAR +.EXTERNAL SEEK;NEAR +.EXTERNAL START;NEAR +.EXTERNAL NMIINT;NEAR +.EXTERNAL BOOT;NEAR +.EXTERNAL KBOARD;NEAR +.EXTERNAL KBINT;NEAR +.EXTERNAL DISK;NEAR +.EXTERNAL DISKINT;NEAR +.EXTERNAL PRINTER;NEAR +.EXTERNAL VIDEO;NEAR +.EXTERNAL MEMSIZE;NEAR +.EXTERNAL EQUIP;NEAR +.EXTERNAL CASSETTE;NEAR +.EXTERNAL TOFDAY;NEAR +.EXTERNAL TIMERINT;NEAR +.EXTERNAL RS232;NEAR +.EXTERNAL PRSCREEN;NEAR + +.public connect +.public reset +.public intin +.public ttyin +.public clkin +.public diskin +.public intout +.public ttyout +.public lpout +.public diskout +.public hdtyp +.public date +.public ttybuf +.public lpbuf +.public diskrq +.PUBLIC VECTOR_TABLE +.PUBLIC DUMMY_RET +.PUBLIC FD_TBL +.PUBLIC FD1_TBL +.PUBLIC FD2_TBL +.PUBLIC DISK_BASE + + + ORG 0D000H +connect: ;---- Uebergabe-Bereich +reset: db -1 ;reset +intin: db 0 ;intin + db 0 ;dummy in + db 0 + db 0 + db 0 +ttyin: db 9 ;vector Tastatur + db 0 ;instop + db 0 ;inbyte + db 0 ;dummy +clkin: db 8 ;vector Timer + db 0 ;instop + db 0 ;inbyte + db 0 ;dummy +diskin: db 0eh ;vector Disk + db 0 ;instop + db 0 ;inbyte + db 0 ;dummy +intout: db 0 ;intout + db 0 ;dummy + db 0 ;dummy out + db 0 + db 0 + db 0 +ttyout: db 0 ;outstop TTY + db 0 ;dummy + dw 0 ;noutb +lpout: db 0 ;outstop LP + db 0 ;dummy + dw 0 ;noutb +diskout db 0 ;outstop Disk + db 0 ;dummy + dw 0 ;noutb +hdtyp: db 0 ;Harddisk 0 Typ + db 0 ;Harddisk 1 Typ +date: db 0 ;sec Date/Time + db 0 ;min + db 0 ;hour + db 0 ;day + db 0 ;mon + db 0 ;year +ttybuf: blkb 800h +lpbuf: blkb 100h +diskrq: blkb 10h + + + ORG 0E05BH +RESET: JMP START + + ORG 0E2C3H ;----- NMI ENTRY +NMI_INT: + JMP NMIINT + +;------ FIXED DISK PARAMETER TABLE + +FD_TBL: ;Drive 5 MByte + DW 500 ;CYLINDERS + DB 2 ;HEADS + DW 0 ;nicht benutzt + DW -1 ;(WRITE PRE-COMPENSATION CYL) + DB 0 ;nicht benutzt + DB 0 ;(CONTROL BYTE) + DB 0,0,0 ;nicht benutzt + DW 0 ;(LANDING ZONE) nicht benutzt + DB 10 ;SECTORS/TRACK + DB 0 ;nicht benutzt + +FD1_TBL: ;Drive 10 MByte + DW 500 ;CYLINDERS + DB 4 ;HEADS + DW 0 ;nicht benutzt + DW -1 ;(WRITE PRE-COMPENSATION CYL) + DB 0 ;nicht benutzt + DB 0 ;(CONTROL BYTE) + DB 0,0,0 ;nicht benutzt + DW 0 ;(LANDING ZONE) nicht benutzt + DB 10 ;SECTORS/TRACK + DB 0 ;nicht benutzt + +FD2_TBL: ;Drive 20 MByte + DW 500 ;CYLINDERS + DB 8 ;HEADS + DW 0 ;nicht benutzt + DW -1 ;(WRITE PRE-COMPENSATION CYL) + DB 0 ;nicht benutzt + DB 0 ;(CONTROL BYTE) + DB 0,0,0 ;nicht benutzt + DW 0 ;(LANDING ZONE) nicht benutzt + DB 10 ;SECTORS/TRACK + DB 0 ;nicht benutzt + + ORG 0E6F2H ;------ BOOT LOADER INTERRUPT +BOOTSTRAP: + JMP BOOT + + ORG 0E739H ;----- RS232 +RS232_IO: + JMP RS232 + + ORG 0E82EH ;------ KEYBOARD +KBOARD_IO: + JMP KBOARD + + ORG 0E987H ;------ KEYBOARD INT +KB_INT: + JMP KBINT + + ORG 0EC59H ;------ DISKETTE I/O +DKETTE_IO: + JMP DISK + + ORG 0EF57H ;------ DISKETTE INT +DISK_INT: + JMP DISKINT + + ORG 0EFC7H ;------ DISK BASE +DISK_BASE: + DB 0 + DB 0 + DB 0 + DB 2 ;512 Byte/Sector + DB 9 ;letzter Sector + DB 1BH ;GPL + DB 0FFH + DB 54H ;GPL fuer Format + DB 0F6H ;Datenbyte fuer Format + DB 0 + DB 0 + + ORG 0EFD2H ;------ PRINTER IO +PRINTR_IO: + JMP PRINTER + + ORG 0F045H ;------ VIDEO IO + +.EXTERNAL SET_MODE;NEAR +.EXTERNAL SET_CTYPE;NEAR +.EXTERNAL SET_CPOS;NEAR +.EXTERNAL READ_CURSOR;NEAR +.EXTERNAL READ_LPEN;NEAR +.EXTERNAL ACT_DISP_PAGE;NEAR +.EXTERNAL SCROLL_UP;NEAR +.EXTERNAL SCROLL_DOWN;NEAR +.EXTERNAL READ_AC_CURRENT;NEAR +.EXTERNAL WRITE_AC_CURRENT;NEAR +.EXTERNAL WRITE_C_CURRENT;NEAR +.EXTERNAL SET_COLOR;NEAR +.EXTERNAL WRITE_DOT;NEAR +.EXTERNAL READ_DOT;NEAR +.EXTERNAL WRITE_TTY;NEAR +.EXTERNAL VIDEO_STATE;NEAR + +M1: DW SET_MODE ;TABLE OF ROUTINES WITHIN VIDEO I/O + DW SET_CTYPE + DW SET_CPOS + DW READ_CURSOR + DW READ_LPEN + DW ACT_DISP_PAGE + DW SCROLL_UP + DW SCROLL_DOWN + DW READ_AC_CURRENT + DW WRITE_AC_CURRENT + DW WRITE_C_CURRENT + DW SET_COLOR + DW WRITE_DOT + DW READ_DOT + DW WRITE_TTY + DW VIDEO_STATE +M1L EQU $-M1 + + ORG 0F065H +VIDEO_IO: + JMP VIDEO + + ORG 0F0A4H +VIDEO_PARMS: + DB 0 + + + ORG 0F841H ;------ MEMORY SIZE +MEMSIZE_D: + JMP MEMSIZE + + ORG 0F84DH ;------ EQUIPMENT DETERMINE +EQUIPMENT: + JMP EQUIP + + ORG 0F859H ;------ CASSETTE (NO BIOS SUPPORT) +CASSET_IO: + JMP CASSETTE + + ORG 0FE6EH ;------ TIME OF DAY +T_OF_DAY: + JMP TOFDAY + + ORG 0FEA5H ;------ TIMER INTERRUPT +TIMER_INT: + JMP TIMERINT + + ORG 0FEE3H ;------ VECTOR TABLE +VECTOR_TABLE: + DW DUMMY_RET ;INT 0 + DW DUMMY_RET ;INT 1 + DW NMI_INT ;INT 2 + DW DUMMY_RET ;INT 3 + DW DUMMY_RET ;INT 4 + DW PR_SCREEN ;INT 5 + DW DUMMY_RET ;INT 6 + DW DUMMY_RET ;INT 7 + DW TIMER_INT ;INT 8 + DW KB_INT ;INT 9 + DW DUMMY_RET ;INT A + DW DUMMY_RET ;INT B + DW DUMMY_RET ;INT C + DW DUMMY_RET ;INT D + DW DISK_INT ;INT E + DW DUMMY_RET ;INT F + +;------ SOFTWARE INTERRUPTS + + DW VIDEO_IO ;INT 10H + DW EQUIPMENT ;INT 11H + DW MEMSIZE_D ;INT 12H + DW DKETTE_IO ;INT 13H + DW RS232_IO ;INT 14H + DW CASSET_IO ;INT 15H + DW KBOARD_IO ;INT 16H + DW PRINTR_IO ;INT 17H + DW DUMMY_RET ;INT 18H + DW BOOTSTRAP ;INT 19H + DW T_OF_DAY ;INT 1AH + DW DUMMY_RET ;INT 1BH -- KEYBOARD BREAK ADDR + DW DUMMY_RET ;INT 1CH -- TIMER BREAK ADDR + DW VIDEO_PARMS ;INT 1DH -- VIDEO PARAMETERS + DW DISK_BASE ;INT 1EH -- DISK PARMS + DW 0 ;INT 1FH -- POINTER TO VIDEO EXT + + ORG 0FF53H ;------ DUMMY INT HANDLER +DUMMY_RET: + IRET + + ORG 0FF54H ;------ PRINT SCREEN +PR_SCREEN: + JMP PRSCREEN + + ORG 0FFF0H ;------ POWER ON RESET + +P_O_R: DB 0EAH ;HARD CODE JUMP + DW RESET ;OFFSET + DW 0F000H ;SEGMENT + + db '01/10/88' ;RELEASE MARKER + ;bei 01/10/84 (Original) wird Harddisk- + ;Treiber im Disketten-BIOS benutzt + + ORG 0FFFEH + DB 0FCH ;THIS PC'S ID + + END diff --git a/WEGA/contrib/wdos/src/termp8.asm b/WEGA/contrib/wdos/src/termp8.asm new file mode 100644 index 0000000..db4e679 --- /dev/null +++ b/WEGA/contrib/wdos/src/termp8.asm @@ -0,0 +1,864 @@ +;************************************************************************** +;************************************************************************** +; +; WDOS-BIOS - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1988 +; +; Programm: termp8.asm +; +; Bearbeiter : P. Hoge +; Datum : 24.1.89 +; Version : 1.1 +; +;************************************************************************** +; +; normales P8000-Terminal (ADM31) ohne Bildwiederholspeicher +; +;************************************************************************** +;************************************************************************** + + +.EXTERNAL DDS ;NEAR +.EXTERNAL BYTE KB_FLAG +.EXTERNAL WORD BUFFER_START +.EXTERNAL WORD BUFFER_END +.EXTERNAL WORD BUFFER_HEAD +.EXTERNAL WORD BUFFER_TAIL +.EXTERNAL WORD CURSOR_POSN +.EXTERNAL WORD CURSOR_MODE +.EXTERNAL BYTE CRT_MODE +.EXTERNAL WORD CRT_COLS +.EXTERNAL WORD CRT_LEN +.external byte intin +.external byte intout +.external byte ttyin +.external byte ttyout +.external byte lpout +.external byte ttybuf +.external byte lpbuf + +.PUBLIC PUTA +.PUBLIC KBOARD +.PUBLIC KBINT +.PUBLIC VIDEO +.PUBLIC PRINTER +.PUBLIC RS232 + +;---- INT 16 ------------------------------------------------------------------ +;KEYBOARD I/O +; THESE ROUTINES PROVIDE KEYBOARD SUPPORT +;INPUT +; (AH)=0 READ THE NEXT ASCII CHARACTER STRUCK FROM THE KEYBOARD +; RETURN THE RESULT IN (AL), SCAN CODE IN (AH) +; (AH)=1 SET THE Z FLAG TO INDICATE IF AN ASCII CHARACTER IS AVAILABLE +; (ZF)=1 -- NO CODE AVAILABLE +; (ZF)=0 -- CODE IS AVAILABLE +; IF ZF = 0, THE NEXT CHARACTER IN THE BUFFER TO BE READ IS +; IN AX, AND THE ENTRY REMAINS IN THE BUFFER +; (AH)=2 RETURN THE CURRENT SHIFT STATUS IN AL REGISTER +; THE BIT SETTINGS FOR THIS CODE ARE INDICATED IN THE +; THE EQUATES FOR KB_FLAG +;OUTPUT +; AS NOTED ABOVE, ONLY AX AND FLAGS CHANGED +; ALL REGISTERS RETAINED +;------------------------------------------------------------------------------ +KBOARD ;PROC FAR ;>>> ENTRY POINT FOR ORG 0E82EH + STI ;INTERRUPTS BACK ON + PUSH DS ;SAVE CURRENT DS + PUSH BX ;SAVE BX TEMPORARILY + CALL DDS ;ESTABLISH POINTER TO DATA REGION + call CURSOR_OUT + OR AH,AH ;AH=0 + JZ K0 ;ASCII_READ + DEC AH ;AH=1 + JZ K1 ;ASCII_STATUS + DEC AH ;AH=2 + JZ K2 ;SHIFT_STATUS + POP BX ;RECOVER REGISTER + POP DS + IRET ;INVALID COMMAND + +;------ READ THE KEY TO FIGURE OUT WHAT TO DO + +K0: +; MOV BX,BUFFER_HEAD ;GET POINTER TO HEAD OF BUFFER +; CMP BX,BUFFER_TAIL ;TEST END OF BUFFER +; JNE K0B ;IF ANYTHING IN BUFFER DONT DO INTERRUPT +; MOV AX,09002H ;MOVE IN WAIT CODE & TYPE +; INT 15H ;PERFORM OTHER FUNCTION + +K0A: ;ASCII READ + STI ;INTERRUPTS BACK ON DURING LOOP + NOP ;ALLOW AN INTERRUPT TO OCCUR +K0B: CLI ;INTERRUPTS BACK OFF + MOV BX,BUFFER_HEAD ;GET POINTER TO HEAD OF BUFFER + CMP BX,BUFFER_TAIL ;TEST END OF BUFFER + JZ K0A ;LOOP UNTIL SOMETHING IN BUFFER + + MOV AX,[BX] ;GET SCAN CODE AND ASCII CODE + CALL K3 ;MOVE POINTER TO NEXT POSITION + MOV BUFFER_HEAD,BX ;STORE VALUE IN VARIABLE + POP BX ;RECOVER REGISTER + POP DS ;RECOVER SEGMENT/ + IRET ;RETURN TO CALLER + +;------ ASCII STATUS + +K1: CLI ;INTERRUPTS OFF + MOV BX,BUFFER_HEAD ;GET HEAD POINTER + CMP BX,BUFFER_TAIL ;IF EQUAL (Z=1) THEN NOTHING THERE + MOV AX,[BX] + POP BX ;RECOVER REGISTER + POP DS ;RECOVER SEGMENT + STI ;INTERRUPTS BACK ON + RET FAR 2 ;THROW AWAY FLAGS + +;------ SHIFT STATUS + +K2: MOV AL,KB_FLAG ;GET THE SHIFT STATUS FLAGS + POP BX ;RECOVER REGISTER + POP DS ;RECOVER REGISTERS + IRET ;RETURN TO CALLER + +;------ INCREMENT A BUFFER POINTER + +K3 ;PROC NEAR + INC BX ;MOVE TO NEXT WORD IN LIST + INC BX + CMP BX,BUFFER_END ;AT END OF BUFFER? + JNE K3A ;NO, CONTINUE + MOV BX,BUFFER_START ;YES, RESET TO BUFFER BEGINNING +K3A: RET + +;------ KEYBOARD INTERRUPT ROUTINE + +KBINT ;PROC FAR + STI + PUSH AX + PUSH BX + PUSH SI + PUSH DS + CALL DDS ;SET UP ADDRESSING + mov cs:intin,0 ;naechsten Int freigeben + mov al,cs:ttyin+2 + and al,7fh + xor ah,ah + +;------ PUT CHARACTER INTO BUFFER + + MOV BX,BUFFER_TAIL ;GET THE END POINTER TO THE BUFFER + MOV SI,BX ;SAVE THE VALUE + CALL K3 ;ADVANCE THE TAIL + CMP BX,BUFFER_HEAD ;HAS THE BUFFER WRAPPED AROUND + JE K4B ;BUFFER_FULL_BEEP + MOV [SI],AX ;STORE THE VALUE + MOV BUFFER_TAIL,BX ;MOVE THE POINTER UP + +K4A: POP DS + POP SI + POP BX + POP AX + mov cs:ttyin+1,0 + IRET ;RETURN, INTERRUPTS BACK ON WITH FLAG CHANGE + +K4B: mov al,07h ;BUFFER FULL BEEP + call PUTA + JMP SHORT K4A + + +;--- INT 10 -------------------------------------------------------------- +;VIDEO_IO +; THESE ROUTINES PROVIDE THE CRT INTERFACE +; THE FOLLOWING FUNCTIONS ARE PROVIDED: +; (AH)=0 SET MODE - nur Mode 7 moeglich +; (AH)=1 SET CURSOR TYPE - nicht moeglich +; (AH)=2 SET CURSOR POSITION +; (AH)=3 READ CURSOR POSITION +; (AH)=4 READ LIGHT PEN POSITION - nicht moeglich +; (AH)=5 SELECT ACTIVE DISPLAY PAGE - nur Page 0 +; (AH)=6 SCROLL ACTIVE PAGE UP - nur Loeschen (al = 0) +; (AH)=7 SCROLL ACTIVE PAGE DOWN - nur Loeschen (al = 0) +;CHARAKTER HANDLING ROUTINES +; (AH)=8 READ ATTRIBUTE/CHARAKTER AT CURRENT CURSOR POSITION +; (AH)=9 WRITE ATTRIBUTE/CHARAKTER AT CURRENT CURSOR POSITION +; (AH)=10 WRITE CHARACTER ONLY AT CURRENT CURSOR POSITION +;GRAPHICS INTERFACE +; (AH)=11 SET COLOR PALETTE - nicht moeglich +; (AH)=12 WRITE DOT - nicht moeglich +; (AH)=13 READ DOT - nicht moeglich +;ASCII TELETYPE ROUTINE FOR OUTPUT +; (AH)=14 WRITE TELETYPE TO ACTIVE PAGE +; (AH)=15 CURRENT VIDEO STATE +; (AH)=16 RESERVED +; (AH)=17 RESERVED +; (AH)=18 RESERVED +; (AH)=19 WRITE STRING +; (AL) = 0 +; BL - ATTRIBUTE +; STRING IS [CHAR,CHAR, ... ,CHAR] +; CURSOR NOT MOVED +; (AL) = 1 +; BL - ATTRIBUTE +; STRING IS [CHAR,CHAR, ... ,CHAR] +; CURSOR IS MOVED +; (AL) = 2 +; STRING IS [CHAR,ATTR,CHAR,ATTR, ... ,CHAR,ATTR] +; CURSOR IS NOT MOVED +; (AL) = 3 +; STRING IS [CHAR,ATTR,CHAR,ATTR, ... ,CHAR,ATTR] +; CURSOR IS MOVED +; NOTE: CARRIAGE RETURN, LINE FEED, BACKSPACE, AND BELL ARE +; TREATED AS COMMANDS RATHER THEN PRINTABLE CHARACTERS. +; +; SS,SP,ES,DS,DX,CX,BX,SI,DI,BP PRESERVED DURING CALL +; ALL OTHERS DESTROYED. +;------------------------------------------------------------------------- + +.PUBLIC SET_MODE +.PUBLIC SET_CTYPE +.PUBLIC SET_CPOS +.PUBLIC READ_CURSOR +.PUBLIC READ_LPEN +.PUBLIC ACT_DISP_PAGE +.PUBLIC SCROLL_UP +.PUBLIC SCROLL_DOWN +.PUBLIC READ_AC_CURRENT +.PUBLIC WRITE_AC_CURRENT +.PUBLIC WRITE_C_CURRENT +.PUBLIC SET_COLOR +.PUBLIC WRITE_DOT +.PUBLIC READ_DOT +.PUBLIC WRITE_TTY +.PUBLIC VIDEO_STATE + +V1 DW SET_MODE + DW SET_CTYPE + DW SET_CPOS + DW READ_CURSOR + DW READ_LPEN + DW ACT_DISP_PAGE + DW SCROLL_UP + DW SCROLL_DOWN + DW READ_AC_CURRENT + DW WRITE_AC_CURRENT + DW WRITE_C_CURRENT + DW SET_COLOR + DW WRITE_DOT + DW READ_DOT + DW WRITE_TTY + DW VIDEO_STATE + DW VIDEO_RETURN ;Reserved + DW VIDEO_RETURN ;Reserved + DW VIDEO_RETURN ;Reserved + DW WRITE_STRING ;CASE 19h, Write string +V1L EQU $-V1 + +VIDEO ;PROC NEAR ;ENTRY POINT FOR ORG 0F065H + STI ;INTERRUPTS BACK ON + CLD ;SET DIRECTION FORWARD + PUSH ES + PUSH DS ;SAVE SEGMENT REGISTERS + PUSH DX + PUSH CX + PUSH BX + PUSH SI + PUSH DI + PUSH BP + PUSH AX ;SAVE AX VALUE + MOV AL,AH ;GET INTO LOW BYTE + XOR AH,AH ;ZERO TO HIGH BYTE + SAL AX,1 ;*2 FOR TABLE LOOKUP + MOV SI,AX ;PUT INTO SI FOR BRANCH + CMP AX,V1L ;TEST FOR WITHIN RANGE + JB V2 ;BRANCH AROUND BRANCH + POP AX ;THROW AWAY THE PARAMETER + JMP short VIDEO_RETURN + +V2: CALL DDS + POP AX ;RECOVER VALUE + CMP AH,13H ;TEST FOR WRITE STRING OP + JNE V3 + PUSH BP ;IF IT'S WRITE STRING THEN GET THE + MOV BP,SP ;STRINGS SEGMENT,SINCE IT GET CLOBBERED + MOV ES,[BP]+10H ;MOV ES,[BP].ES_POS ???? + POP BP + +V3: JMP CS:[SI]+V1 + +;--------------------------------------------------------------- +;LIGHT PEN Implementation nicht moeglich +;ACT_DISP_PAGE +;SET_COLOR +;READ DOT -- WRITE DOT +;--------------------------------------------------------------- +READ_LPEN: ;AH = 0 = nicht verfuegbar + mov ah,0 ;nicht verfuegbar + jmp short VIDEO_RETURN +READ_DOT: ;AL = DOT VALUE + sub al,al +ACT_DISP_PAGE: +SET_COLOR: +WRITE_DOT: + +;------ NORMAL RETURN FROM ALL VIDEO RETURNS +VIDEO_RETURN: + POP BP + POP DI + POP SI + POP BX + POP CX + POP DX + POP DS + POP ES + IRET + +;----------------------------------------------------- +;SET_MODE +;Mode setzen und Bildschirm loeschen +;----------------------------------------------------- +CURSOR_TTY: + defw -1 + +SET_MODE ;PROC NEAR + mov CRT_MODE,7 + mov CRT_COLS,80 + mov CRT_LEN,2*25*80 + call CLR_TTY ;Bildschirm loeschen + mov CURSOR_POSN,0 ;Cursor Home setzen + jmp short VIDEO_RETURN + +CLR_TTY: +;------ ADM 31 Escape-Folge Bildschirm loeschen + push ax + mov al,1bh + call PUTA + mov al,'*' + call PUTA + + mov ax,-1 + mov cs:CURSOR_TTY,ax ;Cursor synchronisieren + call CURSOR_OUT + pop ax + ret + +;--------------------------------------------------------- +;SET_CTYPE +;--------------------------------------------------------- +SET_CTYPE ;PROC NEAR ;**** nicht moeglich + mov CURSOR_MODE,cx + jmp short VIDEO_RETURN + +;--------------------------------------------------------------- +;SET_CPOS +; THIS ROUTINE SETS THE CURRENT CURSOR POSITION TO THE +; NEW X-Y VALUES PASSED +;INPUT +; DX - ROW, COLUMN OF NEW CURSOR +;OUTPUT +; CURSOR IS SET +;--------------------------------------------------------------- +SET_CPOS ;PROC NEAR ;nur 1 Page moeglich + mov CURSOR_POSN,dx + jmp short VIDEO_RETURN + +;--------------------------------------------------------------- +;READ_CURSOR +; THIS ROUTINE READS THE CURRENT CURSOR VALUE +;OUTPUT +; DX - ROW, COLUMN OF THE CURRENT CURSOR POSITION +; CX - CURRENT CURSOR MODE +;--------------------------------------------------------------- +READ_CURSOR ;PROC NEAR ;nur 1 Page + mov dx,CURSOR_POSN + mov cx,CURSOR_MODE + POP BP + POP DI + POP SI + POP BX + POP AX ;DISCARD SAVED CX AND DX + POP AX + POP DS + POP ES + IRET + +;--------------------------------------------------------------- +;VIDEO_STATE +; RETURNS THE CURRENT VIDEO STATE IN AX +; AH = NUMBER OF COLUMNS ON THE SCREEN +; AL = CURRENT VIDEO MODE +; BH = CURRENT ACTIVE PAGE +;--------------------------------------------------------------- +VIDEO_STATE ;PROC NEAR + mov ah,80 ;GET NUMBER OF COLUMNS + mov al,7 ;CURRENT MODE + mov bh,0 ;GET CURRENT ACTIVE PAGE + POP BP + POP DI + POP SI + POP CX ;DISCARD SAVED BX + POP CX + POP DX + POP DS + POP ES + IRET + +;--------------------------------------------------------------- +;SCROLL_UP / SCROLL_DOWN +; realisiert nur Bildschirmloeschen +;INPUT +; (AL) = 0 = Loeschen Bildschirm +;--------------------------------------------------------------- +SCROLL_UP ;PROC NEAR +SCROLL_DOWN ;PROC NEAR + or al,al ;Loeschen + jnz SUP0 + call CLR_TTY + jmp VIDEO_RETURN + +SUP0: push ax ;Rollen durch LF realisieren + mov ax,0e0ah ;Write TTY: LF ausgeben + int 10h + pop ax + dec al + jnz SUP0 + jmp VIDEO_RETURN + +;--------------------------------------------------------------- +;READ_AC_CURRENT +; nicht moeglich, Return mit 0720h +;OUTPUT +; (AL) = 20h (Space) +; (AH) = 07h (Attribut) +;---------------------------------------------------------------- +READ_AC_CURRENT ;PROC NEAR + mov ax,0720h + JMP VIDEO_RETURN + +;--------------------------------------------------------------- +;WRITE_AC_CURRENT +; nicht moeglich, Funktion wie WRITE_C_CURRENT +;--------------------------------------------------------------- +WRITE_AC_CURRENT ;PROC NEAR + +;--------------------------------------------------------------- +;WRITE_C_CURRENT +; THIS ROUTINE WRITES THE CHARACTER AT +; THE CURRENT CURSOR POSITION, ATTRIBUTE UNCHANGED +;INPUT +; (CX) = COUNT OF CHARACTERS TO WRITE +; (AL) = CHAR TO WRITE +; (DS) = DATA SEGMENT +;OUTPUT +; NONE +;--------------------------------------------------------------- +WRITE_C_CURRENT ;PROC NEAR + call CURSOR_OUT +WCC0: ;WRITE_LOOP + inc word ptr cs:CURSOR_TTY + cmp al,07h ;Diese Zeichen haben hier + jz WCC1 ;keine Sonderbedeutung + cmp al,08h + jz WCC1 + cmp al,0ah + jz WCC1 + cmp al,0dh + jnz WCC2 +WCC1: mov al,20h +WCC2: call PUTA + LOOP WCC0 ;AS MANY TIMES AS REQUESTED + JMP VIDEO_RETURN +;WRITE_AC_CURRENT + +;--------------------------------------------------------------- +;WRITE_TTY +; THIS INTERFACE PROVIDES A TELETYPE LIKE INTERFACE. +;ENTRY -- +; (AL) = CHARACTER TO BE WRITTEN +; NOTE THAT BACK SPACE, CR, BELL AND LINE FEED ARE HANDLED +; AS COMMANDS RATHER THAN AS DISPLAYABLE GRAPHICS +;EXIT -- +; ALL REGISTERS SAVED +;--------------------------------------------------------------- +WRITE_TTY ;PROC NEAR + call CURSOR_OUT + call PUTA + mov dx,CURSOR_POSN ;READ CURSOR POSITION + +;------ DX NOW HAS THE CURRENT CURSOR POSITION + + CMP AL,8 ;IS IT A BACKSPACE + JE U5 ;BACK_SPACE + CMP AL,0DH ;IS IT CARRIAGE RETURN + JE U6 ;CAR_RET + CMP AL,0AH ;IS IT A LINE FEED + JE U7 ;LINE_FEED + CMP AL,07H ;IS IT A BELL + JE U4 ;Return + +;------ POSITION THE CURSOR FOR NEXT CHAR + + INC DL + CMP DL,80 ;TEST FOR COLUMN OVERFLOW + JNZ U3 ;SET_CURSOR + MOV DL,0 ;COLUMN FOR CURSOR + CMP DH,24 + JNZ U2 ;SET_CURSOR_INC + +;------ SCROLL REQUIRED + +U1: jmp short U3 + +U2: inc dh ;SET-CURSOR-INC NEXT ROW +U3: mov CURSOR_POSN,dx ;SET-CURSOR + mov cs:CURSOR_TTY,dx + +U4: JMP VIDEO_RETURN + +;------ BACK SPACE FOUND +U5: CMP DL,0 ;ALREADY AT END OF LINE + JE U3 ;SET_CURSOR + DEC DL ;NO -- JUST MOVE IT BACK + JMP short U3 ;SET_CURSOR + +;------ CARRIAGE RETURN FOUND +U6: MOV DL,0 ;MOVE TO FIRST COLUMN + JMP short U3 ;SET_CURSOR + +;------ LINE FEED FOUND +U7: CMP DH,24 ;BOTTOM OF SCREEN + JNE U2 ;YES, SCROLL THE SCREEN + JMP short U1 ;NO, JUST SET THE CURSOR + +;--------------------------------------------------------------- +;WRITE STRING +; This routine writes a string of characters to the crt. +;INPUT +; (AL) = WRITE STRING COMMAND 0 - 3 +; (CX) = COUNT OF CHARACTERS TO WRITE. IF CX == 0 THEN RETURN +; (DX) = CURSOR POSITION +; (BL) = ATTRIBUTE OF CHAR TO WRITE IF AL == 0 | AL == 1 +; (ES) = STRING SEGMENT +; (BP) = STRING OFFSET +;OUTPUT +; N/A +;---------------------------------------------------------------- +WRITE_STRING ;PROC NEAR + CMP AL,04 ;TEST FOR INVALID WRITE STRING OPTION + JB W0 ;IF OPTION INVALID THEN RETURN + JMP DONE +W0: OR CX,CX ;TEST FOR ZERO LENGTH STRING + JNZ W1 + JMP short DONE ;IF ZERO LENGTH STRING THEN RETURN +W1: MOV SI,CURSOR_POSN + PUSH SI ;SAVE CURRENT CURSOR POSITION + mov CURSOR_POSN,dx ;SET NEW CURSOR POSITION + +WRITE_CHAR: + PUSH CX + PUSH BX + PUSH AX + PUSH ES + XCHG AH,AL ;PUT THE WRITE STRING OPTION INTO AH + MOV AL,ES:[BP] ;GET CHARACTER FROM INPUT STRING + INC BP ;BUMP POINTER TO CHARACTER + +;------ TEST FOR SPECIAL CHARACTER'S + + CMP AL,8 ;IS IT A BACKSPACE + JE DO_TTY ;BACK_SPACE + CMP AL,0DH ;IS IT CARRIAGE RETURN + JE DO_TTY ;CAR_RET + CMP AL,0AH ;IS IT A LINE FEED + JE DO_TTY ;LINE_FEED + CMP AL,07H ;IS IT A BELL + JNE GET_ATTRIBUTE ;IF NOT THEN DO WRITE CHARACTER +DO_TTY: + MOV AH,14 ;WRITE TTY CHARACTER TO THE CRT + INT 10H + MOV DX,CURSOR_POSN ;GET CURRENT CURSOR POSITION + POP ES + POP AX ;RESTORE REGISTERS + POP BX + POP CX + JMP short ROWS_SET + +GET_ATTRIBUTE: + MOV CX,1 ;SET CHARACTER WRITE AMOUNT TO ONE + CMP AH,2 ;IS THE ATTRIBUTE IN THE STRING + JB GOT_IT ;IF NOT THEN JUMP + MOV BL,ES:[BP] ;ELSE GET IT + INC BP ;BUMP STRING POINTER + +GOT_IT: MOV AH,09 ;WRITE CHARACTER TO THE CRT + INT 10H + POP ES + POP AX ;RESTORE REGISTERS + POP BX + POP CX + INC DL ;INCREMENT COLUMN COUNTER + CMP DL,80 ;IF COLS ARE WITHIN RANGE FOR THIS MODE + JB COLUMNS_SET ;THEN GOTO COLS SET + INC DH ;BUMP ROW COUNTER BY ONE + SUB DL,DL ;SET COLUMN COUNTER TO ZERO + CMP DH,25 ;IF ROWS ARE < 25 THEN + JB ROWS_SET ;GOTO ROWS_SET + ;SAVE WRITE STRING PARAMETER REGS + PUSH ES ;SAVE REG'S THAT GET CLOBBERED + PUSH AX + MOV AX,0E0AH ;DO SCROLL ONE LINE + INT 10H ;RESET ROW COUNTER TO 24 + DEC DH + POP AX ;RESTORE REG'S + POP ES + +ROWS_SET: +COLUMNS_SET: + mov CURSOR_POSN,dx + LOOP WRITE_CHAR ;DO IT ONCE MORE UNTIL CX = ZERO + POP DX ;RESTORE OLD CURSOR COORDINATES + CMP AL,1 ;IF CURSOR WAS TO BE MOVED THEN + JE DONE ;WE'RE DONE + CMP AL,3 + JE DONE + mov CURSOR_POSN,dx ;ELSE RESTORE OLD CURSOR POSITION +DONE: + JMP VIDEO_RETURN ;RETURN TO CALLER + +;--------------------------------------------------------------- +; Cursor-Stand vergleichen und Differenzen ausgeben +;--------------------------------------------------------------- +CURSOR_OUT: ;CURSOR-Stand vergleichen und Cursor setzen + push ax + push dx + mov dx,CURSOR_POSN + cmp dx,cs:CURSOR_TTY + jz COUT2 ;Cursor steht auf Bildschirm richtig + + mov al,1bh ;ADM 31 ESC-Folge + call PUTA + mov cs:CURSOR_TTY,dx + mov al,'=' + call PUTA + mov al,dh + cmp al,24 ;Terminal hat nur 24 Zeilen + jnz COUT1 + dec al ;25 = 24 Zeile, da 24 Zeilen-Terminal +COUT1: add al,20h + call PUTA + mov al,dl + add al,20h + call PUTA + +COUT2: pop dx + pop ax + ret + +;--------------------------------------------------------------- +;PUTA +;--------------------------------------------------------------- +PUTA: push ax + push bx + push di + mov di,offset ttybuf +PU1: mov bx, word ptr cs:ttyout+2 + xchg bh,bl + cmp bx,800h + jnc PU1 ;warten, da Puffer voll + cmp al,80h + jc PU2 + mov al,20h +PU2: sti + nop + cli + mov ah,cs:ttyout+0 ;outstop + or ah,ah + jnz PU2 + mov bx, word ptr cs:ttyout+2 + xchg bh,bl + mov cs:[bx+di],al + inc bx + xchg bh,bl + mov word ptr cs:ttyout+2,bx ;noutb + cmp bx,0100h + jnz PU4 +PU3: sti ;beim 1.Zeichen INT geben + nop + cli + mov ah,cs:intout ;kann INT gegeben werden ? + or ah,ah + jnz PU3 + mov cs:intout,1 ;tty + out 0,al ;INT geben +PU4: sti + pop di + pop bx + pop ax + ret + + +;--- INT 17 -------------------------------------------------------------- +;PRINTER_IO +; THIS ROUTINE PROVIDES COMMUNICATION WITH THE PRINTER +;INPUT +; (AH)=0 PRINT THE CHARACTER IN (AL) +; ON RETURN, (AH) BITS SET AS ON NORMAL STATUS CALL +; (AH)=1 INITIALIZE THE PRINTER PORT +; RETURNS WITH (AH) SET WITH PRINTER STATUS +; (AH)=2 READ THE PRINTER STATUS INTO (AH) +; +; (DX) = PRINTER TO BE USED (0,1,2) - nur ein Printer moeglich +; +;REGISTERS AH IS MODIFIED +; ALL OTHERS UNCHANGED +;------------------------------------------------------------------------- +PRINTER ;PROC FAR ;ENTRY POINT FOR ORG 0EFD2H + STI ;INTERRUPTS BACK ON + OR AH,AH ;TEST FOR (AH)=0 + JZ P0 ;PRINT_AL + DEC AH ;TEST FOR (AH)=1 + JZ P1 ;INIT_PRT - nicht implementiert + DEC AH ;TEST FOR (AH)=2 + JZ P1 ;PRINTER STATUS + JMP SHORT P3 + +;------ PRINT THE CHARACTER IN (AL) + +P0: push bx + push di + mov di,offset lpbuf +P0A: mov bx, word ptr cs:lpout+2 + xchg bh,bl + cmp bx,100h + jnc P0A ;warten Uebergabepuffer voll +P0B: sti + nop + cli + mov ah,cs:lpout+0 ;outstop + or ah,ah + jnz P0A + mov bx, word ptr cs:lpout+2 + xchg bh,bl + mov cs:[bx+di],al + inc bx + xchg bh,bl + mov word ptr cs:lpout+2,bx ;noutb + cmp bx,0100h + jnz P0D +P0C: sti ;beim 1.Zeichen INT geben + nop + cli + mov ah,cs:intout ;kann INT gegeben werden ? + or ah,ah + jnz P0C + mov cs:intout,2 ;lp + out 0,al ;INT geben +P0D: sti + pop di + pop bx + +;------ PRINTER STATUS + +P1: push bx + mov bx,word ptr cs:lpout+2 + xchg bh,bl + cmp bx,100h ;Puffer voll ? + jnc P2 + mov bh,cs:lpout+0 ;outstop + or bh,bh + jnz P2 + mov ah,0d0h ;bereit fuer naechstes Zeichen + pop bx + iret +P2: mov ah,50h ;nicht bereit fuer naechstes Zeichen + pop bx +P3: iret + + +;------- INT_14 ----------------------------------------------------- +;RS232_IO +; THIS ROUTINE PROVIDES BYTE STREAM I/O TO THE COMMUNICATIONS +; PORT ACCORDING TO THE PARAMETERS: +; (AH)=0 INITIALIZE THE COMMUNICATIONS PORT +; (AL) HAS PARMS FOR INITIALIZATION +; +; 7 6 5 4 3 2 1 0 +; ----- BAUD RATE -- -PARITY-- STOPBIT --WORD LENGTH-- +; +; 000 - 110 XO - NONE 0 - 1 10 - 7 BITS +; 001 - 150 01 - ODD 1 - 2 11 - 8 BITS +; 010 - 300 11 - EVEN +; 011 - 600 +; 100 - 1200 +; 101 - 2400 +; 110 - 4800 +; 111 - 9600 +; ON RETURN, CONDITIONS SET AS IN CALL TO COMMO STATUS (AH=3) +; (AH)=1 SEND THE CHARACTER IN (AL) OVER THE COMMO LINE +; (AL) REGISTER IS PRESERVED. +; ON EXIT, BIT 7 OF AH IS SET IF THE ROUTINE HAS UNABLE TO +; TO TRNASMIT THE BYTE OF DATA OVER THE LINE. +; IF BIT 7 OF AH IS NOT SET, THE +; REMAINDER OF AH IS SET AS IN A STATUS REQUEST, +; REFLECTING THE CURRENT STATUS OF THE LINE. +; (AH)=2 RECEIVE A CHARACTER IN (AL) FROM COMMO LINE BEFORE +; RETURNIND TO CALLER +; ON EXIT, AH HAS THE CURRENT LINE STATUS, AS SET BY THE +; THE STATUS ROUTINE, EXCEPT THAT THE ONLY BITS +; LEFT ON ARE THE ERROR BITS (7,4,3,2,1) +; IF AH HAS BIT 7 ON (TIME OUT) THE REMAINING +; BITS ARE NOT PREDICTABLE. +; THUS, AH IS NON ZERO ONLY WHEN AH ERROR OCCURRED. +; (AH)=3 RETURN THE COMMO PORT STATUS IN (AX) +; AH CONTAINS THE LINE CONTROL STATUS +; BIT 7 = TIME OUT +; BIT 6 = TRANS HOLDING REGISTER EMPTY +; BIT 5 = TRAN HOLDING REGISTER EMPTY +; BIT 4 = BREAK DETECT +; BIT 3 = FRANING ERROR +; BIT 2 = PARITY ERROR +; BIT 1 = OVERRUN ERROR +; BIT 0 = DATA READY +; AL CONTAINS THE MODEM STATUS +; BIT 7 = RECEVED LINE SIGNAL DETECT +; BIT 6 = RING INDICATOR +; BIT 5 = DATA SET READY +; BIT 4 = CLEAR TO SEND +; BIT 3 = DELTA RECEIVE LINE SIGNAL DETECT +; BIT 2 = TRAILING EDCE RING DETECTOR +; BIT 1 = DELTA DATA SET READY +; BIT 0 = DELTA CLEAR TO SEND +; +; (DX) = PARAMETER INDICATING WHICH RS232 CARD (0,1 ALLOWED) +; +;OUTPUT +; AX MODIFIED ACCORDING TO PARMS OF CALL +; ALL OTHERS UNCHANCED: +;---------------------------------------------------------------------- +RS232 ;PROC FAR + +;------ VECTOR TO APPROPRIATE ROUTINE + + STI ;INTERRUPTS BACK ON + OR AH,AH ;TEST FOR (AH)=0 + JZ RS0 ;COMMUN INIT + DEC AH ;TEST FOR (AH)=1 + JZ RS1 ;SEND AL + DEC AH ;TEST FOR (AH)=2 + JZ RS2 ;RECEIVE INTO AL + DEC AH ;TEST FOR (AH)=3 + JZ RS3 ;COMMUNICATION STATUS + JMP SHORT RS4 + +;------ INITIALIZE THE COMMUNICATIONS PORT +RS0: + +;------ RECEIVE CHARACTER FROM COMMO LINE +RS2: + +;------ COMMO PORT STATUS ROUTINE +RS3: MOV AL,0 + +;------ SEND CHARACTER IN (AL) OVER COMMO LINE +RS1: MOV AH,80H ;INDICATE TIME OUT +RS4: IRET + + END diff --git a/WEGA/contrib/wdos/src/test.asm b/WEGA/contrib/wdos/src/test.asm new file mode 100644 index 0000000..d0df0ed --- /dev/null +++ b/WEGA/contrib/wdos/src/test.asm @@ -0,0 +1,864 @@ +;************************************************************************** +;************************************************************************** +; +; 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