|
|
;****************************************************************************** ; ; Copyright (c) 1992 Insignia Solutions Ltd. ; ; Program: ; ; Purpose: ; ; Version: ; ; Author: Dave Bartlett ; Modifications: ; 1) Tim June 92. Changes to get DEC PC working. Take over ; IVT entries 6h (illegal instruction), 11h (equipment ; check), 16h (keyboard BIOS), 17h (printer), ; 42h (default video). ; 2) Tim June 92. Changed version to 1.11 ; 3) Tim June 92. Avoid accesses to host ROM as far as ; possible. Take over lots of IVT entries and continue to ; point them at this driver. ; 4) Tim July 92. Version num 1.12, put pseudo ROM stuff back in. ; 5) Tim July 92. v 1.13, use SoftPC video BIOS when windowed. ; ; 6) 12-Sep-1992 Jonle, Merged with ntio.sys ; cleanup usage of assumes espcially with ES ; optimized loading of IVT ; other general cleanup ; ; This obj module is intially loaded in a temporary memory location ; along with ntio.sys. Ntio.sys will copy the resident code (marked by ; SpcKbdBeg, SpcKbdEnd) into the permanent memory location which resides ; just below the normal device drivers loaded by config.sys. ; ; The nonresident intialization code is run with CS= temp seg ; and DS= final seg. ; ;******************************************************************************
.286
;================================================================ ; Macros and includes ;================================================================
include vint.inc include bop.inc include syscall.inc include msequ.inc
BIOS_CPU_QUIT equ 0FEh BIOS_KB_INT equ 9 BIOS_INT15 equ 15h BIOS_PRINTER_IO equ 17h UNEXP_BOP equ 2 RTC_WAIT_FLAG equ 0a0h ; offset of rtc_wait_flag in bios data seg VERSIONID equ 0BEEFh
FULLSCREEN equ 1 STREAM_IO equ 2 MAX_VIDEO_FUNC equ 1Ch GET_FONT_FUNC equ 11h
VID_MODECHANGE equ 0 VID_VESA_BIOS equ 4fh MOUSE_LIGHT_PEN equ 4 MIN_MOUSE_FUNC equ 0F0H MAX_MOUSE_FUNC equ 0F7H XTRA_MOUSE_FUNC equ 0FAH MS_VIDEO_STRING equ 13FFH
MOUSE_VID_BOP equ 0BEh EGA_VIDEO_BOP equ 42h
PRT_NOTBUSY equ 80h PRT_NUM_PORTS equ 3 PRT_STATE_READY equ 0 PRT_IRQ equ 10h PRT_LPT_BUSY equ 1
TIMER_LOW equ 6ch TIMER_HIGH equ 6eh TIMER_OVFL equ 70h MOTOR_STATUS equ 3fh MOTOR_COUNT equ 40h
; Keyboard buf ptrs BUFFER_HEAD equ 1ah BUFFER_TAIL equ 1ch BUFFER_START equ 80h BUFFER_END equ 82h
; kb_flag and LED bits KB_FLAG equ 17h CAPS_STATE equ 40h NUM_STATE equ 20h SCROLL_STATE equ 10h
KB_FLAG_1 equ 18h
KB_FLAG_2 equ 97h KB_LEDS equ 07h ; Keyboard LED state bits KB_PR_LED equ 40h ; Mode indicator update
KB_FLAG_3 equ 96h KBF3_ALT_CTRL equ 0ch
;..............................................keyboard constants
; bits in kb_flag RIGHT_SHIFT = 1 LEFT_SHIFT = 2 CTL_SHIFT = 4 ALT_SHIFT = 8
; bit in kb_flag_1 HOLD_STATE = 8 SCROLL_SHIFT = 10h NUM_SHIFT = 20h CAPS_SHIFT = 40h INS_SHIFT = 80h SYS_SHIFT = 04h
; IBM scan codes CTL_KEY = 29 LEFT_SHIFTKEY = 42 RIGHT_SHIFTKEY = 54 ALT_KEY = 56 CAPS_KEY = 58 NUM_KEY = 69 SCROLL_KEY = 70 INS_KEY = 82
; ; Segment definitions for ntio.sys, ; include biosseg.inc
SpcKbdSeg segment
assume cs:SpcKbdSeg,ds:nothing,es:nothing
; ; SpcKbdBeg - SpcKbdEnd ; ; Marks the resident code, anything outside of these markers ; is discarded after intialization ; 13-Sep-1992 Jonle ; public SpcKbdBeg
SpcKbdBeg label byte
; ; Reduced data table for Video 7 modes 0 and 2. ; This table is extracted from our video7 ROM. Only text modes are ; required, mode 0 and 1 are identical as are modes 2 and 3. ; ega_parm_setup:
;--40x25-- DB 40,24,16 ; width,height,character height DW 00800H ; Page size in bytes
DB 008H, 003H, 000H, 002H ; Sequencer Parameters
DB 067H ;Misc Reg
; CRTC Parameters DB 02dH, 027H, 028H, 090H, 02bH DB 0a0H, 0bfH, 01fH, 000H, 04fH DB 00dH, 00eH, 000H, 000H, 000H DB 000H, 09cH, 0aeH, 08fH, 014H DB 01fH, 096H, 0b9H, 0a3H, 0ffH
; Attribute parameters DB 000H, 001H, 002H, 003H, 004H DB 005H, 014H, 007H, 038H, 039H DB 03aH, 03bH, 03cH, 03dH, 03eH DB 03fH, 00cH, 000H, 00fH, 008H
; Graph parameters DB 000H, 000H, 000H, 000H, 000H DB 010H, 00eH, 000H, 0ffH
;--80x25-- DB 80,24,16 ; width,height,character height DW 01000H ; Page size in bytes
DB 000H, 003H, 000H, 002H ; Sequencer Parameters
DB 067H ;Misc Reg
; CRTC Parameters DB 05fH, 04fH, 050H, 082H, 055H DB 081H, 0bfH, 01fH, 000H, 04fH DB 00dH, 00eH, 000H, 000H, 000H DB 000H, 09cH, 08eH, 08fH, 028H DB 01fH, 096H, 0b9H, 0a3H, 0ffH
; Attribute parameters DB 000H, 001H, 002H, 003H, 004H DB 005H, 014H, 007H, 038H, 039H DB 03aH, 03bH, 03cH, 03dH, 03eH DB 03fH, 00cH, 000H, 00fH, 008H
; Graph parameters DB 000H, 000H, 000H, 000H, 000H DB 010H, 00eH, 000H, 0ffH
;--80x25 mono-- DB 80,24,16 ; width,height,character height DW 01000H ; Page size in bytes
DB 000H, 003H, 000H, 003H ; Sequencer Parameters
DB 0a6H ;Misc Reg
; CRTC Parameters DB 05fH, 04fH, 050H, 082H, 055H DB 081H, 0bfH, 01fH, 000H, 04dH DB 00bH, 00cH, 000H, 000H, 000H DB 000H, 083H, 0a5H, 05dH, 028H DB 00dH, 063H, 0baH, 0a3H, 0ffH
; Attribute parameters DB 000H, 008H, 008H, 008H, 008H DB 008H, 008H, 008H, 010H, 018H DB 018H, 018H, 018H, 018H, 018H DB 018H, 00eH, 000H, 00fH, 008H
; Graph parameters DB 000H, 000H, 000H, 000H, 000H DB 010H, 00aH, 000H, 0ffH
; Mode b (font load)
DB 5eh,32H,8 ; width,height,character height DW 09700H ; Page size in bytes
DB 001H, 00fH, 000H, 006H ; Sequencer Parameters
DB 0e7H ;Misc Reg
; CRTC Parameters DB 06dH, 05dH, 05eH, 090H, 061H DB 08fH, 0bfH, 01fH, 000H, 040H DB 000H, 000H, 000H, 000H, 000H DB 000H, 0a2H, 08eH, 099H, 02fH DB 000H, 0a1H, 0b9H, 0e3H, 0ffH
; Attribute parameters DB 000H, 001H, 002H, 003H, 004H DB 005H, 014H, 007H, 038H, 039H DB 03aH, 03bH, 03cH, 03dH, 03eH DB 03fH, 001H, 000H, 00fH, 000H
; Graph parameters DB 000H, 000H, 000H, 000H, 000H DB 000H, 005H, 00fH, 0ffH
;--350 scanline 40x25 DB 40,24,14 ; width,height,character height DW 00800H ; Page size in bytes
DB 009H, 003H, 000H, 002H ; Sequencer Parameters
DB 0a3H ;Misc Reg
; CRTC Parameters DB 02dH, 027H, 028H, 090H, 02bH DB 0a0H, 0bfH, 01fH, 000H, 04dH DB 00bH, 00cH, 000H, 000H, 000H DB 000H, 083H, 0a5H, 05dH, 014H DB 01fH, 063H, 0baH, 0a3H, 0ffH
; Attribute parameters DB 000H, 001H, 002H, 003H, 004H DB 005H, 014H, 007H, 038H, 039H DB 03aH, 03bH, 03cH, 03dH, 03eH DB 03fH, 008H, 000H, 00fH, 000H
; Graph parameters DB 000H, 000H, 000H, 000H, 000H DB 010H, 00eH, 000H, 0ffH
;--350 scanline 80x25 DB 80,24,14 ; width,height,character height DW 01000H ; Page size in bytes
DB 001H, 003H, 000H, 002H ; Sequencer Parameters
DB 0a3H ;Misc Reg
; CRTC Parameters DB 05fH, 04fH, 050H, 082H, 055H DB 081H, 0bfH, 01fH, 000H, 04dH DB 00bH, 00cH, 000H, 000H, 000H DB 000H, 083H, 0a5H, 05dH, 028H DB 01fH, 063H, 0baH, 0a3H, 0ffH
; Attribute parameters DB 000H, 001H, 002H, 003H, 004H DB 005H, 014H, 007H, 038H, 039H DB 03aH, 03bH, 03cH, 03dH, 03eH DB 03fH, 008H, 000H, 00fH, 000H
; Graph parameters DB 000H, 000H, 000H, 000H, 000H DB 010H, 00eH, 000H, 0ffH
; ; End of baby mode table. ; ; Table of VGA bios 'capability' info for func 1b to point at. vga_1b_table db 07fh, 060h, 00fh, 000h, 000h, 000h, 000h, 007h db 002h, 008h, 0ffh, 00eh, 000h, 000h, 03fh, 000h
; Configuration table for INT 15 Func C0 to point at. conf_table dw 008h ;; db 0fch, 002h, 000h, 070h, 000h, 000h, 000h, 000h db 0fch, 002h, 074h, 070h, 000h, 000h, 000h, 000h
PRT_BUF_SIZE equ 255
;================================================================ ; Printer status table ;================================================================ prt_status db PRT_NUM_PORTS dup (?) prt_state db PRT_NUM_PORTS dup (?) prt_control db PRT_NUM_PORTS dup (?) prt_lpt_stat db PRT_NUM_PORTS dup (?) cur_buf_size dw PRT_BUF_SIZE prt_data_buf db PRT_BUF_SIZE dup (?) ; buffer in the 16bit side for perf. cur_lpt db 0ffh ; buffer is not being used cur_count dw ? cur_busy db 0 ; initially not busy
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; Keyboard tables ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
shift_keys: ;K6 DB INS_KEY,CAPS_KEY,NUM_KEY,SCROLL_KEY DB ALT_KEY,CTL_KEY,LEFT_SHIFTKEY,RIGHT_SHIFTKEY
shift_masks: ;K7 DB INS_SHIFT,CAPS_SHIFT,NUM_SHIFT,SCROLL_SHIFT DB ALT_SHIFT,CTL_SHIFT,LEFT_SHIFT,RIGHT_SHIFT
ctl_n_table: ;K8 DB 27, -1, 0, -1, -1, -1, 30, -1 DB -1, -1, -1, 31, -1, 127, 148, 17 DB 23, 5, 18, 20, 25, 21, 9, 15 DB 16, 27, 29, 10, -1, 1, 19, 4 DB 6, 7, 8, 10, 11, 12, -1, -1 DB -1, -1, 28, 26, 24, 3, 22, 2 DB 14, 13, -1, -1, -1, -1, 150, -1 DB ' ', -1
ctl_f_table: ;K9 DB 94, 95, 96, 97, 98, 99, 100, 101 DB 102, 103, -1, -1, 119, 141, 132, 142 DB 115, 143, 116, 144, 117, 145, 118, 146 DB 147, -1, -1, -1, 137, 138
lowercase: DB 27, '1', '2', '3', '4', '5', '6', '7', '8', '9' ;K10 DB '0', '-', '=', 8, 9, 'q', 'w', 'e', 'r', 't' DB 'y', 'u', 'i', 'o', 'p', '[', ']', 13, -1, 'a' DB 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', 39 DB 96, -1, 92, 'z', 'x', 'c', 'v', 'b', 'n', 'm' DB ',', '.', '/', -1, '*', -1, ' ', -1
lc_tbl_scan: DB 59, 60, 61, 62, 63, 64, 65, 66, 67, 68 DB -1, -1
base_case: DB 71, 72, 73, -1, 75, -1, 77, -1, 79, 80 DB 81, 82, 83, -1, -1, 92, 133, 134 ;K15
uppercase: ;K11 DB 27, '!', '@', '#', '$', '%', '^', '&', '*', '(' DB ')', '_', '+', 8, 0, 'Q', 'W', 'E', 'R', 'T' DB 'Y', 'U', 'I', 'O', 'P', '{', '}', 13, -1, 'A' DB 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"' DB 126, -1, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M' DB '<', '>', '?', -1, 0, -1, ' ', -1;
ucase_scan: DB 84, 85, 86, 87, 88, 89, 90, 91, 92, 93 DB -1, -1
numb_state: DB '7', '8', '9', '-', '4', '5', '6', '+', '1', '2' ;K14 DB '3', '0', '.' , -1, -1, 124, 135, 136
alt_table: DB 82, 79, 80, 81, 75, 76, 77, 71, 72, 73 ;K30 DB 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 DB 30, 31, 32, 33, 34, 35, 36, 37, 38, 44 DB 45, 46, 47, 48, 49, 50
;================================================================ ; Keyboard break caller ;================================================================
keyboard_break_caller: int 1bh ;keyboard break bop %BIOS_CPU_QUIT
;================================================================ ; Print screen caller ;================================================================
print_screen_caller: int 5h ;print screen bop %BIOS_CPU_QUIT
;================================================================ ; Int 15 caller ;================================================================ ; Tim modified int 15 caller. Copied from BIOS2. It gives CPU ; a chance to take other interrupts. Suspect the extra jumps are ; now harmless with IRET hooking. ;int15h_caller: ;int 15h ;bop %BIOS_CPU_QUIT int15h_caller: int 15h ; Cassette I/O. jmp k1 k1: jmp k2 k2: jmp k3 k3: BOP %BIOS_CPU_QUIT
;================================================================ ; Unexpected interrupt handler ;================================================================
unexp_int: bop %UNEXP_BOP jmp iret_com
;================================================================ ;Int 13 caller ;================================================================ int13h_caller: int 13h bop %BIOS_CPU_QUIT
ifdef JAPAN ;================================================================ ;int 16 caller ;================================================================ int16h_caller: int 16h bop %BIOS_CPU_QUIT endif ; JAPAN
;================================================================ ; New interrupt 9h handler ;================================================================
int09h_vector: push ax xor ax, ax bop %BIOS_KB_INT pop ax jmp iret_com
; CarbonCopy traces int 9 in order to gain control ; over where the kbd data is coming from (the physical kbd ; or the serial link) The kbd_inb instruction must be visible ; in the 16 bit code via int 1 tracing, for CarbonCopy to work. ; Softpc assumes the exact location of the first nop ; relative to the bop just above. nop nop in al, 60h ; keyba_io_buffers nop nop BOP %BIOS_CPU_QUIT
;================================================================= ; IRET hooks bop table ;=================================================================
IRET_HOOK = 5dh ;IRET hook BOP
iret_bop_table: bop %IRET_HOOK db 0 iret_end_first_entry: bop %IRET_HOOK db 1 bop %IRET_HOOK db 2 bop %IRET_HOOK db 3 bop %IRET_HOOK db 4 bop %IRET_HOOK db 5 bop %IRET_HOOK db 6 bop %IRET_HOOK db 7 bop %IRET_HOOK db 8 bop %IRET_HOOK db 9 bop %IRET_HOOK db 10 bop %IRET_HOOK db 11 bop %IRET_HOOK db 12 bop %IRET_HOOK db 13 bop %IRET_HOOK db 14 bop %IRET_HOOK db 15
;================================================================ ; New interrupt 13h handler ;================================================================
int13h_vector: cmp dl,80h ; 0 - 7f are floppy commands jb int40h_vector
cmp ah,2 ; we fail the direct access commands jb diskcmd ; read/write/seek/verify/format cmp ah,5 ; but let others go through (disk tables etc) jbe faildisk cmp ah,0ah jb diskcmd cmp ah,0ch ja diskcmd faildisk: push ax mov ax,1 ; direct access error panel bop 59h pop ax ; preserve AL for safety sake mov ah, 80h ; error - timeout stc retf 2
diskcmd: bop 13h retf 2
;================================================================ ; New interrupt 40h handler ;================================================================
int40h_vector: ; cmp ah,2 ; we fail the direct access commands ; jb flopcmd ; read/write/seek/verify/format ; cmp ah,5 ; but let others go through (disk tables etc) ; jbe failflop ; cmp ah,0ah ; jb flopcmd ; cmp ah,0ch ; ja flopcmd failflop: ; push ax ; mov ax,0 ; direct access error panel ; bop 59h ; pop ax ; mov ah, 80h ; error - timeout ; stc ; retf 2
flopcmd: bop 40h retf 2
;; waiting for diskette interrupt wait_int: push ds push ax push cx mov ax, 40h mov ds, ax mov cx, 10h wait_int_loop: mov al, [3Eh] test al, 80h loopz wait_int_loop pop cx pop ax pop ds bop %BIOS_CPU_QUIT
;; floppy parameters table floppy_table label byte
DB 01 ;; 360KB in 360KB DW OFFSET md_tbl1 DB 82H ;; 360KB in 1,2MB DW OFFSET md_tbl2 DB 02 ;; 1.2MB in 1.2MB DW OFFSET md_tbl3 DB 03 ;; 720KB in 720KB DW OFFSET md_tbl4 DB 84H ;; 720KB in 1.44MB DW OFFSET md_tbl5 DB 04 ;; 1.44MB in 1.44MB DW OFFSET md_tbl6 DB 85h ;; 720KB in 2.88MB DW OFFSET md_tbl7 DB 85h ;; 1.44MB in 2.88MB DW OFFSET md_tbl8 DB 5 ;; 2.88MB in 2.88MB DW OFFSET md_tbl9
md_tbl1: ; MEDIA = 40 track low data rate; DRIVE = 40 track low data rate DB 0DFh ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 9 ; sectors/track DB 02Ah ; gap length DB 0FFh ; data length DB 050h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time DB 39 ; maximum track number DB 80H ; transfer rate
md_tbl2: ; MEDIA = 40 track low data rate; DRIVE = 80 track high data rate DB 0DFh ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 9 ; sectors/track DB 02Ah ; gap length DB 0FFh ; data length DB 050h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time DB 39 ; maximum track number DB 40H ; transfer rate
md_tbl3: ; MEDIA = 80 track high data rate; DRIVE = 80 track high data rate DB 0DFh ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 15 ; sectors/track DB 01Bh ; gap length DB 0FFh ; data length DB 054h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time DB 79 ; maximum track number DB 0 ; transfer rate
md_tbl4: ; MEDIA = 80 track low data rate; DRIVE = 80 track low data rate DB 0DFh ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 9 ; sectors/track DB 02Ah ; gap length DB 0FFh ; data length DB 050h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start ime DB 79 ; maximum track number DB 80H ; transfer rate
md_tbl5: ; MEDIA = 80 track low data rate; DRIVE = 80 track high data rate DB 0DFh ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 9 ; sectors/track DB 02Ah ; gap length DB 0FFh ; data length DB 050h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time DB 79 ; maximum track number DB 80H ; transfer rate
md_tbl6: ; MEDIA = 80 track high data rate; DRIVE = 80 track high data rate DB 0AFh ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 18 ; sectors/track DB 01Bh ; gap length DB 0FFh ; data length DB 06Ch ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time DB 79 ; maximum track number DB 0 ; transfer rate
md_tbl7: ;MEDIA = 80 tracks, 9 sectors/track; DRIVE = 80 tracks, 36 sectotrs per track
DB 0E1h ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 9 ; sectors/track DB 02Ah ; gap length DB 0FFh ; data length DB 050h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start ime DB 79 ; maximum track number DB 80H ; transfer rate md_tbl8: ;MEDIA = 80 tracks, 18 sectors/track; DRIVE = 80 tracks, 36 sectotrs per track
DB 0D1h ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 18 ; sectors/track DB 01Bh ; gap length DB 0FFh ; data length DB 065h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time DB 79 ; maximum track number DB 0 ; transfer rate
md_tbl9: ;MEDIA = 80 tracks, 36 sectors/track; DRIVE = 80 tracks, 36 sectotrs per track
DB 0A1h ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 36 ; sectors/track DB 038h ; gap length DB 0FFh ; data length DB 053h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time DB 79 ; maximum track number DB 0C0h ; transfer rate
floppy_table_len equ $ - floppy_table
bios_floppy_table label byte DB 0DFh ; 1st specify byte DB 2 ; 2nd specify byte DB 25H ; motor off wait time DB 2 ; ie 2 bytes/sector DB 18 ; sectors/track DB 01Bh ; gap length DB 0FFh ; data length DB 054h ; gap length for format DB 0F6h ; fill byte for format DB 15 ; head settle time/ms DB 8 ; ie 1s motor start time bios_floppy_table_len equ $ - bios_floppy_table
;=============================================================== ; New interrupt 15h handler ;================================================================ ; Tim, modified this to be like a "normal" SoftPC ROM. ; Copied from BIOS2, but rtc_wait_flag is now referenced via ES not ; DS. ; ; 17-Sep-1992 Jonle , ES ref to rtc_wait was change from assume ES ; to seg overides to prevent accidents in assuming. ;
;int15h_vector: ;bop %BIOS_INT15 ;iret ;;;;;;;;;STF hide this int15h_vector: int15h_vector: call DOSTI cmp ah, 88h je lbl1 cmp ah, 91h je lbl1 cmp ah, 86h je lbl2 BOP 15h RETF 2 lbl1: BOP 15h jmp iret_com lbl2: BOP 15h jc lbl5 push cx push dx push es ; Tim, save ES not DS. mov ax, 40h ; point es to biosdata mov es, ax xchg dx, cx lbl3: test byte ptr es:[RTC_WAIT_FLAG], 080h ; check for end of wait loopz lbl3 ; dec timeout delay jnz lbl4 ; exit if wait ended sub dx, 1 ; dec error timeout counter jnc lbl3 ; loop till counters timeout lbl4: mov byte ptr es:[RTC_WAIT_FLAG], 0 ; set function inactive pop es ; Kipper, restore ES not DS. pop dx pop cx clc lbl5: RETF 2
;================================================================= ; Regular SoftPC int 17 handler (especially important for DEC PCs) ;=================================================================
int17h_vector: ; ; Do a get status purely in 16-bit code but only if the printer is ready and ;we don't have interrupts turned on. Otherwise we must do a BOP and let 32-bit ;code handle it. ; push si push dx push ax mov ax, dx ; dx = adapter no., ensure it is no xor dx, dx ; greater than PRT_NUM_PORTS. mov si, PRT_NUM_PORTS div si mov si, dx pop ax cmp ah, 2 je do_prt_status or ah,ah je do_write jmp do_print_bop
do_prt_status: cmp byte ptr cs:[si + prt_state], PRT_STATE_READY jne do_print_bop test byte ptr cs:[si + prt_control], PRT_IRQ je get_status jmp short do_print_bop
do_write: cmp byte ptr cs:[cur_lpt],0ffh jne check_lpti mov byte ptr cs:[cur_lpt],dl mov word ptr cs:[cur_count],0 mov byte ptr cs:[cur_busy],0ffh jmp short do_print_bop check_lpti: cmp byte ptr cs:[cur_lpt],dl je buf_ok push si xor si,si bop %BIOS_PRINTER_IO pop si mov word ptr cs:[cur_count],0 mov byte ptr cs:[cur_lpt],dl jmp short do_print_bop buf_ok: mov dx,word ptr cs:[cur_count] mov si,dx mov byte ptr cs:[si + prt_data_buf],al inc word ptr cs:[cur_count] cmp word ptr cs:[cur_count],PRT_BUF_SIZE jne no_flushing xor si,si ; sub-function 0 for this bop bop %BIOS_PRINTER_IO test ah,08h jz flush_ok dec word ptr cs:[cur_count] jmp short int17h_end flush_ok: mov word ptr cs:[cur_count],0 no_flushing: mov ah,90h jmp short int17h_end
; ; Risc int17 entry point, provided to cope with si subfunctions ; int17h_RiscVector:
push si push dx
do_print_bop: mov si,0ffffh ; sub-function 1 bop %BIOS_PRINTER_IO jmp int17h_end
get_status: test byte ptr cs:[si + prt_lpt_stat], PRT_LPT_BUSY jne noset or byte ptr cs:[si + prt_status], PRT_NOTBUSY noset: mov ah, cs:[si + prt_status] and ah, 0f8h xor ah, 48h int17h_end: pop dx pop si iret_com: FIRET
;================================================================= ; Pseudo-ROM vectuz, copied from BIOS2.ASM ;=================================================================
dummy_vector: ; Copied from BIOS2.ASM jmp iret_com illegal_bop_vector: bop 72h jmp iret_com intD11_vector: bop 72h jmp iret_com
int05h_vector: ; Print Screen func. copied from BIOS2.ASM call DOSTI PUSH AX PUSH BX PUSH CX PUSH DX PUSH DS ;::::::::::::::::::::::::::::::::: Setup DS to point to BIOS data area MOV AX,40H MOV DS,AX ;::::::::::::::::::::::::::::::: Print screen already in progress ???? CMP BYTE PTR DS:[100H],1 JE end_print ;::::::::::::::::::::::::::::::::::::::::::::::: Set print screen busy MOV BYTE PTR DS:[100h],1
;::::: fetch no rows, columns, curr page from bios data area mov ch, byte ptr ds:[4ah] ; cols mov cl, byte ptr ds:[84h] ; rows mov bh, byte ptr ds:[62h] ; curr page num
;::::::::::::::::::::::::::::::::::: Print line feed / carriage return CALL print_crlf ;:::::::::::::::::::::::::::::::::::::::::: Get current cursor postion PUSH CX MOV AH,3 INT 10H POP CX ;::::::::::::::::::::::::::::::::::::::::::::::::: Save cursor postion PUSH DX ;save current cursor postion XOR DH,DH ;current row being processed start_print_col: XOR DL,DL ;current column being processed ;::::::::::::::::::::::::::::::::::::::::::::::: Start printing screen start_print_row: ;:::::::::::::::::::::::::::::::::::::::::::::::::: Set cursor postion PUSH DX ;save current row,column MOV AH,2 INT 10H ;::::::::::::::::::::::::::::::::::: Read character at current postion MOV AH,8 INT 10H ;::::::::::::::::::::::::::::::::::::::::::::::::::::: Print character OR al,al JNZ print_char MOV AL,20H print_char: XOR DX,DX XOR AH,AH INT 17H ;:::::::::::::::::::::::::::::::::::::::::::: Check for printer errors POP DX ;Restore current row,column AND AH,25H JZ cont2 MOV BYTE PTR DS:[100H],0FFH JMP short exit_print ;::::::::::::::::::::::::::::::::::::::::::: Move to mext print column cont2: INC DL ;Inc current column CMP DL,CH ;Current col compared to no. of cols JB start_print_row ;:::::::::::::::::::::::::::::::::::::::::: End of column, print CR/LF CALL print_crlf ;:::::::::::::::::::::::::::::::::::::::::::::::::: More rows to print INC DH ;Inc current row CMP DH,CL ;Current row compared to no. of rows JBE start_print_col MOV BYTE PTR DS:[0100H],0 ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Exit print exit_print: ;:::::::::::::::::::::::::::::::::::::; Restore orginal cursor postion POP DX MOV AH,2 INT 10H ;:::::::::::::::::::::::::::::::::::::::::::::::::::: Tidy up and exit end_print: POP DS POP DX POP CX POP BX POP AX jmp iret_com
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Print CR/LF print_crlf: PUSH DX XOR DX,DX MOV AX,0DH INT 17H XOR DX,DX MOV AX,0AH INT 17H POP DX RET ; End of int05_vector (print screen).
int06h_vector: bop 06h jmp iret_com
; IVT 7 is set to unexpected interrupt.
int08h_vector: ; The usual int8 handler modified for optimum performance. ; - stays in 16 bit code (no BOP) ; - keeps interrupts off when not needed ; - calls int 1c directly ; call DOCLI ; make sure interrupts stay off until iret
push es push ds ; save some registers push ax push dx
mov ax, 40h ; set ds to bios data area mov ds, ax xor ax, ax mov es, ax ; set es to IVT seg for i1c callout
inc word ptr ds:[TIMER_LOW] ; inc time counters jnz i8v1 inc word ptr ds:[TIMER_HIGH] i8v1: cmp word ptr ds:[TIMER_HIGH], 018h ; check for 24 hours, wrap point jnz i8v2 cmp word ptr ds:[TIMER_LOW], 0b0h jnz i8v2
mov word ptr ds:[TIMER_HIGH], ax ; 24 hour wrap, set OVFL bit mov word ptr ds:[TIMER_LOW], ax mov byte ptr ds:[TIMER_OVFL], 1 or al, 8 ; set Overflow bit for fake flags
;--- ; skip floppy motor stuff
i8v2: ; handle the floppy motor stuff push ax dec byte ptr ds:[MOTOR_COUNT] jnz i8v3 and byte ptr ds:[MOTOR_STATUS], 0f0h mov al, 0ch mov dx, 03f2h ; costly outb happens 1/256 timer tics... out dx, al
i8v3: pop ax
; if a dpmi app has interrupts hooked in PM, then we have to do a real ; INT 1C so that the dpmi host has a chance to switch to PM test word ptr ds:[FIXED_NTVDMSTATE_REL40], VDM_INTS_HOOKED_IN_PM jnz i8v4 ; call int1c user routine directly lahf ; get lobyte of flags for fake flags xchg ah,al push ax ; put fake flags on the stack call dword ptr es:[1ch*4] ; do it! jmp i8v5
i8v4: int 1ch ; do real int1C i8v5:
call DOCLI ; make sure interrupts stay off until iret
mov al, 20h ; send eoi out 20h, al
pop dx ;restore the stack pop ax pop ds pop es
jmp iret_com
int0e_vector: bop 0eh jmp iret_com
DOCLI: FCLI ret
DOSTI: FSTI ret
;----------------------------------------------------------------------- ;function: sw_video_io ; ;description: ; int10 ah=0e and ax=13ffh handler for "well-behaved" applications which ; do their video i/o through dos/file or WriteTTy call ; Since the output won't go to the video hardware, it was called software ; video. ; ;input: whatever to int10 ; ;output: carry flag = 1 if we have done the function ; carry flag = 0 if we have not done anything, the caller has ; to carry on the operation ; ;modified: none ;-----------------------------------------------------------------------
sw_temp db 0 SW_VIDEO_BUFFER_SEGMENT = 0B000h SW_VIDEO_BUFFER_SIZE = 82 * 2 ;; make sure we are in word boundary because they are accessed from ;; 32bits code EVEN sw_video_dirty_count dw 0 sw_video_busy dw 0 sw_video_io proc near ;stop 32bits code from accessing shared variables. ;We do not bop to 32bits at all unless our buffer doesn't have ;enough space for the new data. The 32 bits code would refresh ;our buffer contents to the console periodically. ; inc cs:sw_video_busy ;indicate we are busy ;this is the basic sync mechanism ;with 32bits stream_io update code cmp ax,13ffh ;secret write string? jne sw_check_write_tty ;no, check for write tty cmp cx, 1 je sw_video_string_1
push si mov si, SW_VIDEO_BUFFER_SIZE sub si, cs:sw_video_dirty_count cmp cx, si jae sw_video_overflow
push di push cx push dx push ds push es mov dx, es ;ds:di ptr to the string mov ds, dx mov dx, SW_VIDEO_BUFFER_SEGMENT mov es, dx mov dx, cx mov si, di mov di, cs:sw_video_dirty_count cld ;ds:si ptr to the string shr cx, 1 ;cs has the byte count rep movsw adc cl, 0 rep movsb add cs:sw_video_dirty_count, dx pop es pop ds pop dx pop cx pop di pop si stc ;tell the caller we've done it dec cs:sw_video_busy ret
sw_video_string_1: push ax mov ah, 0eh mov al, es:[di] call sw_video_write_tty pop ax ret ;; this should be a rare case as we have a big buffer ;; we go directly to 32bits and we will take care of it there sw_video_overflow: pop si dec cs:sw_video_busy bop EGA_VIDEO_BOP ;not free buffer space stc ;do it on 32bits ret
sw_check_write_tty: cmp ah, 0eh jne sw_mode_change ;we have to enable video h/w
sw_video_write_tty: push si mov si, cs:sw_video_dirty_count ;the current count(index) cmp si, SW_VIDEO_BUFFER_SIZE jae sw_video_overflow push ds mov si, SW_VIDEO_BUFFER_SEGMENT mov ds, si mov si, cs:sw_video_dirty_count mov ds:[si], al ;put it in the buffer inc si mov cs:sw_video_dirty_count, si ;new count, new index pop ds pop si sw_video_done: stc dec cs:sw_video_busy ret
sw_mode_change: push ax mov ax, 013FEh ;tell 32bits to initialize bop EGA_VIDEO_BOP ;video hardware for us pop ax clc ;tell caller we didn't do any dec cs:sw_video_busy ret sw_video_io endp
; ; Tim August 92. Video BIOS grabber. ; Call SPC BIOS when in windowed mode and the host BIOS when in full-screen. ; Controled by value of 'use_host_int10'. ; Try to limit bops by validating calling values. Mouse has to get first shot ; and then video bios. ;
use_host_int10 db 01h ; native/softpc bios flag changing_mode db 01h ; delay handshake if in bios mode change
PUBLIC int10h_vector
int10h_vector: cmp use_host_int10, STREAM_IO jne hw_video_io call sw_video_io jc viddone hw_video_io: cmp use_host_int10, FULLSCREEN je nativebios
cmp ah,VID_MODECHANGE ; mode change?? je modechange cmp ah,MAX_VIDEO_FUNC ; range check ja mousecheck ; not a vid func but mouse has higher cmp ah,MOUSE_LIGHT_PEN ; light pen special case je mousebios spcbios: bop EGA_VIDEO_BOP ; regular windowed Int 10 jmp viddone
mousecheck: cmp ah,VID_VESA_BIOS ; Is VESA bios call? jne short @f ; ne, no, proceed normally
bop MOUSE_VID_BOP ; yes, will go fullscreen jmp jmp_native ; and handle the int10 by native bios
@@: cmp ah,MIN_MOUSE_FUNC ; range check mouse fn f0-f7 + fa. jb badvid cmp ah,MAX_MOUSE_FUNC jbe mousebios cmp ah,XTRA_MOUSE_FUNC jne badvid
mousebios: ; call softpc mouse video entrypoint bop MOUSE_VID_BOP jmp viddone
modechange: ; windowed modechange. Mouse gets a look mov changing_mode,1 ; then softpc video bios. If gfx mode then bop MOUSE_VID_BOP ; will go fullscreen ;;;nop ;;;nop ; nops aid debugging ;;;bop EGA_VIDEO_BOP ; will go fullscreen here nop nop push ax ; save video mode which may have top bit set and ax,7fh cmp al,3 jbe endmode ; if graphics mode, repeat modechange to setup cmp al,7 ; video card, else fall through je endmode pop ax jmp nativebios endmode: pop ax mov changing_mode,0 ; Clear 'mode changing' flag.
viddone: jmp iret_com
badvid: ; unrecognised video func stc jmp viddone
nativebios: mov changing_mode,0 ; Clear 'mode changing' flag. cmp ax,MS_VIDEO_STRING ; ensure not MS special video string fn je ms_wrt_string
cmp ah,MIN_MOUSE_FUNC ; could be a mouse call jb chk_mse_vid cmp ah,MAX_MOUSE_FUNC ; range check mouse fn f0-f7 + fa. jbe mousebios cmp ah,XTRA_MOUSE_FUNC je mousebios jmp jmp_native ; probably bad func but...
chk_mse_vid: cmp ah,MOUSE_LIGHT_PEN ; mouse handles light pen je mousebios cmp ah,VID_MODECHANGE jne chk_font_change bop MOUSE_VID_BOP ; mouse wants first sniff at mode changes jmp jmp_native ; then fall through chk_font_change: cmp ah,GET_FONT_FUNC jne jmp_native bop MOUSE_VID_BOP ; select mouse buffer for new no. of lines ; then fall through
jmp_native:
db 0EAh ; far jump host_int10 dd ? ; to native int 10 vector
ms_wrt_string: push si push di push bp go_loop1: mov dx,46h ; looks a good value for flags push dx ; make an iret frame push cs mov bx, offset go_cont push bx mov bx,7 ; set foreground color mov ah,0eh ; set command to write a character mov al,es:[di] ; get char inc di jmp jmp_native ; make far jmp to int 10 vector
go_cont: loop go_loop1 ;repeat until all through pop bp pop di pop si mov ax,1 ; return success goto_viddone: jmp viddone ; ; int 42 - 'old' video bios entry point. Use same windowed/fullscreen ; redirection as Int 10 above. ; int42h_vector: cmp use_host_int10, STREAM_IO jne hw_video_io_42 call sw_video_io jc goto_viddone
hw_video_io_42: cmp use_host_int10, FULLSCREEN jz maybe_host_42_bios
bop 10h ; old video bop jmp iret_com
; If it's the special BIOS print string function, don't call the ; host video BIOS cos it won't know what we are talking about. ; It's only in our video BIOS. maybe_host_42_bios: cmp AH, 013h jnz gogo_host_42_bios cmp AL, 0ffh jz ms_wrt_string ; reuse path from Int 10
gogo_host_42_bios: db 0EAh ; far jump host_int42 dd ? ; to native int 42 vector
int10h_caller: int 10h ; Re-entrant video entry point. bop 0feh
int11h_vector: ; Equipment check. bop 11h jmp iret_com int12h_vector: ; Get memory size, copied from BIOS2.ASM bop 12h jmp iret_com
; IVT 13 is floppy io, grabbed above to fake error status.
int14h_vector: ; RS-232 serial comms, copied from BIOS2 bop 14h jmp iret_com
; Int 15 cassette io, is done above.
; Idle indicators- All word sized, and dword aligned ; Int 16 keyboard vector
align 4 public Icounter,CharsPerTick,MinTicks
Icounter dw 0 dw 0 CharsPerTick dw 0 dw 0 MinTicks dw 50 dw 0
int16h_vector: push ds push bx mov bx, 40h ; bios data adressable mov ds, bx cmp ah, 10h call DOCLI ; make sure interrupts are off jb i16vStdFns jmp i16vExtFns
; The dispatch code must preserve the jz,dec,dec pattern ; to return the same ah value as is returned by the ; standard bios (0 for supported unless otherwise documented ; and nonzero for unsupported). This is because some apps look ; at the ret value of ah even tho it is a side effect of the ; original dispatch code in the rom bios.
i16vStdFns: or ah, ah jz i16v00h ; read key, wait dec ah jz i16v01h ; read key no wait dec ah jz i16v02h ; get shift state dec ah jz i16viret ; we don't support ah=3, set kbd rate dec ah jz i16viret ; undefined function dec ah jz i16v05h ; push char into kbd buffer ; the rest are undefined\unsupported
; normal iret exit i16viret: pop bx pop ds jmp iret_com
; return shift state in al i16v02h: mov al, ds:[KB_FLAG] jmp i16viret
i16v05h: push si mov bx, word ptr ds:[BUFFER_TAIL] mov si, bx call IncrBuffPtr cmp bx, word ptr ds:[BUFFER_HEAD] je i16v05h1 mov word ptr ds:[si], cx mov word ptr ds:[BUFFER_TAIL], bx mov al, 0 pop si jmp i16viret
i16v05h1: mov al, 1 pop si jmp i16viret
; read a character, wait if none available i16v00h: mov bx, word ptr ds:[BUFFER_HEAD] cmp bx, word ptr ds:[BUFFER_TAIL] jne i16v00h1 call DOSTI mov ax, 09002h int 15h ; wait device
i16v00h0: call DOCLI mov bx, word ptr ds:[BUFFER_HEAD] cmp bx, word ptr ds:[BUFFER_TAIL]
i16v00h1: call UpdateLed jne i16v00h2 call IdlePoll jmp i16v00h0
i16v00h2: ; translate..... mov ax, [bx] call IncrBuffPtr mov word ptr ds:[BUFFER_HEAD], bx call TranslateStd jc i16v00h0 call IdleInit jmp i16viret
; read a character, nowait if none available i16v01h: mov bx, word ptr ds:[BUFFER_HEAD] ;;maybe should turn IF on ?? cmp bx, word ptr ds:[BUFFER_TAIL] mov ax, [bx] call UpdateLed je i16vretf1
call IdleInit call TranslateStd call DOSTI jnc i16vretf5 ; got a key, all done! call IncrBuffPtr ; throw away key mov word ptr ds:[BUFFER_HEAD], bx jmp i16v01h ; go for the next one
; ExtKbd read a character, nowait if none available i16v11h: mov bx, word ptr ds:[BUFFER_HEAD] ;;maybe should turn IF on ?? cmp bx, word ptr ds:[BUFFER_TAIL] mov ax, [bx] call UpdateLed je i16vretf1 ; common retf stuff for nowait
call IdleInit call TranslateExt call DOSTI jmp i16vretf5
; retf2 exit preserving flags i16vretf1: call DOSTI push ax lahf push ax
mov ax, cs:Icounter cmp ax, cs:MinTicks jb i16vretf2
mov ah, 1 ; polling kbd, idle now BOP 16h jmp i16vretf4
i16vretf2: inc cs:CharsPerTick
i16vretf4: pop ax sahf pop ax
i16vretf5: pop bx pop ds retf 2
i16vExtFns: sub ah, 10h jz i16v10h ; extended read key, wait dec ah jz i16v11h ; extended read key, nowait dec ah jz i16v12h ; extended shift status jmp i16viret ; undefined
; return extended shift state i16v12h: mov al, ds:[KB_FLAG_1] mov ah, al and al, SYS_SHIFT push cx mov cl, 5 shl al, cl pop cx and ah, NOT (SYS_SHIFT+HOLD_STATE+INS_SHIFT) or al, ah mov ah, ds:[KB_FLAG_3] and ah, KBF3_ALT_CTRL or ah, al mov al, ds:[KB_FLAG] jmp i16viret
; ExtKbd read a character, wait if none available i16v10h: mov bx, word ptr ds:[BUFFER_HEAD] cmp bx, word ptr ds:[BUFFER_TAIL] jne i16v10h1 call DOSTI mov ax, 09002h int 15h ; wait device
i16v10h0: call DOCLI mov bx, word ptr ds:[BUFFER_HEAD] cmp bx, word ptr ds:[BUFFER_TAIL]
i16v10h1: call UpdateLed jne i16v10h2 call IdlePoll jmp i16v10h0
i16v10h2: ; translate..... mov ax, [bx] call IncrBuffPtr mov word ptr ds:[BUFFER_HEAD], bx call TranslateExt call IdleInit jmp i16viret
; IdlePoll - Spins waiting for a key, doing idle callouts as needed ; flags trashed, all registers preserved ; interrupts are left on upon exit ; IdlePoll proc near push ax
call DOSTI mov ah, 2 ; Idle_waitio BOP 16h IPoll1: mov bx, word ptr ds:[BUFFER_HEAD] cmp bx, word ptr ds:[BUFFER_TAIL] ; interrupts are off only jne IPoll3 ; safe to peek for change
mov ax, cs:Icounter cmp ax, cs:MinTicks jae IPoll2 inc cs:CharsPerTick jmp IPoll1 IPoll2: mov ah, 1 ; idle now BOP 16h IPoll3: pop ax ret IdlePoll endp
; IdleInit - reinits the idle indicators, dups functionality ; of IDLE_init() ; IdleInit proc near
mov cs:Icounter, 0 mov cs:CharsPerTick, 0
ret IdleInit endp
; TranslateExt - Retrieves and translates next scan code ; pair for extended kbd ; ; input: ax - raw scan code pair ; output: ax - translated scan code pair ; ; all other flags,registers preserved
TranslateExt proc near
push bx push ax lahf mov bx, ax pop ax push bx
cmp al, 0f0h jne TExt1 or ah, ah jz TExt1 xor al, al TExt1: mov bx, ax pop ax sahf mov ax, bx pop bx ret
TranslateExt endp
; TranslateStd - Retrieves and translates next scan code ; pair for standard kbd ; ; input: ax - raw scan code pair ; output: ax - translated scan code pair ; returns carry for throw away ; all other flags,registers preserved
TranslateStd proc near
push bx push ax lahf mov bx, ax pop ax push bx
cmp ah, 0e0h jne TStd1
; keypad enter or '/' mov ah, 1ch ; assume enter key cmp al, 0dh je TStdNoCarry cmp al, 0ah je TStdNoCarry mov ah, 35h ; oops it was key pad! jmp TStdNoCarry
TStd1: cmp ah, 84h ja TStdCarry ; extended key ?
cmp al, 0f0h ; fill in key ? jne TStd2 or ah, ah ; ah = 0 is special jz TStdNoCarry jmp TStdCarry
TStd2: cmp al, 0e0h ; convert to compatible output jne TStdNoCarry or ah, ah jz TStdNoCarry xor al, al
TStdNoCarry: mov bx, ax pop ax sahf mov ax, bx pop bx clc ret
TStdCarry: mov bx, ax pop ax sahf mov ax, bx pop bx stc ret TranslateStd endp
; IncrBuffPtr - increments the buffer pointer ; ; input: ds:bx - curr buf ptr ; output: ds:bx - new buf ptr ; does not update the bios buf ptr
IncrBuffPtr proc near inc bx inc bx cmp bx, word ptr ds:[BUFFER_END] jne ibpExit mov bx, word ptr ds:[BUFFER_START] ibpExit: ret IncrBuffPtr endp
; UpdateLed - forms the data byte for the mode indicators ; updates the led bits (MAKE_LED,SEND_LED) ; ; input: none ; output: led bits updated ; ; Caveats: all low flags,registers preserved ; MUST be called with interrupts off ; does not update the kbd hardware (send_led) ; UpdateLed proc near
push bx push cx push ax lahf push ax
; make_led mov al, byte ptr ds:[KB_FLAG] ; get led bits and al, CAPS_STATE+NUM_STATE+SCROLL_STATE mov cl, 4 shr al, cl ; shift for kb_flag_2 and al, KB_LEDS ; only led mode bits
mov bl, byte ptr ds:[KB_FLAG_2] xor bl, al ; see if different and bl, KB_LEDS ; only led mode bits jz UledExit
test byte ptr ds:[KB_FLAG_2], KB_PR_LED ;if update under way jnz ULedExit ; skip update or byte ptr ds:[KB_FLAG_2], KB_PR_LED ;else upd in progress
shl bl, cl ; add in changebits or al, bl ; to hi nibble of al mov ah, 3 ; inform softpc to set lights BOP 16h
and byte ptr ds:[KB_FLAG_2], NOT KB_LEDS ; clear led bits and al, 0fh ; remove change bits or byte ptr ds:[KB_FLAG_2], al ; stick in new led bits
and byte ptr ds:[KB_FLAG_2], NOT KB_PR_LED ; clear upd bit
ULedExit: pop ax sahf pop ax pop cx pop bx
ret UpdateLed endp
; IVT 17 is printer IO, done above.
int18h_vector: ; ROM BASIC, copied from BIOS2.ASM bop 18h jmp iret_com int19h_vector: ; reboot vector, we terminate vdm! bop 19h jmp iret_com
IdleTicLo dw 0 IdleTicHi dw 0 IdleTicNum db 0
int1Ah_vector: ; Time of day. call DOSTI cmp ah, 2 jb i1aTic1
bop 1ah jmp iret_com
i1aTic1: push ds ; bios data adressable push bx push ax mov ax, 40h mov ds, ax pop ax call DOCLI
or ah, ah ; fn 0 or fn 1 ? jnz i1aTic5
i1aTic2: mov al, byte ptr ds:[TIMER_OVFL] ; GetTickCount mov cx, word ptr ds:[TIMER_HIGH] mov dx, word ptr ds:[TIMER_LOW]
; If time stamp is within 1 tic of curr tic count ; do idle polling managment
cmp cs:IdleTicHi, cx ; check TIMER_HIGH jnz i1aTic8
mov bx, cs:IdleTicLo ; check TIMER_LOW cmp bx, dx jz i1aTic3 inc bx cmp bx, dx jnz i1aTic8
i1aTic3: inc cs:IdleTicNum ; Yes, inc poll count cmp cs:IdleTicNum, 16 ; Is poll count too hi ? jb i1aTic9
call DOSTI xor ax,ax ; Yes, do idle BOP dec cs:IdleTicLo ; make sure only bop once BOP 5ah call DOCLI jmp short i1aTic2
i1aTic5: mov word ptr ds:[TIMER_LOW], dx ; SetTickCount mov word ptr ds:[TIMER_HIGH], cx
i1aTic8: mov cs:IdleTicNum, 0 ; reset idle indicators
i1aTic9: mov cs:IdleTicLo, dx ; store time stamp mov cs:IdleTicHi, cx mov byte ptr ds:[TIMER_OVFL], 0 ; common TicCount exit pop bx pop ds jmp iret_com
; IVT 1B is keyboard break, set to dummy.
int1Eh_vector: bop 1eh jmp iret_com
int70h_vector: ; Real time clock, copied from BIOS1.ASM bop 70h ; rtc_bios.c:rtc_int() jmp iret_com
int4Ah_caller: call DOSTI ; Called from base\bios\rtc_bios.c:rtc_int() int 4ah ; User installed alarm. jmp r1 r1: jmp r2 r2: jmp r3 r3: call DOCLI bop 0feh
int71h_vector: ; redirect, copied from BIOS1.ASM bop 71h int 0Ah jmp iret_com int75h_vector: ; NPX 287. bop 75h int 02h jmp iret_com ;================================================================= ; End of pseudo-ROM vectuz. ;=================================================================
;================================================================ ; Wait for interrupts ;================================================================
cpu_nop_code: call DOSTI jmp short nxt1 nxt1: jmp short nxt2 nxt2: jmp short nxt3 nxt3: bop %BIOS_CPU_QUIT
public SpcKbdEnd SpcKbdEnd label byte
align 4 ;; makes MIPS happy
; offset table for redirected functions ifdef JAPAN kio_table dw 34 dup(?) else ; !JAPAN kio_table dw 33 dup(?) endif ; !JAPAN
public InstSpcKbd
; ; InstSpcKbd - Installs the softpc custom interrupt hooks ; ; Inputs: ds == Resident location of SysInitSeg ; Outputs: None ; InstSpcKbd proc near
pusha call DOCLI
; The following vectors are used for both x86\mips ; The dos interrupts Int 25\Int26 are handled by the dos kerenl xor ax, ax mov es, ax mov word ptr es:[08h*4], offset int08h_vector mov word ptr es:[(08h*4)+2], ds mov word ptr es:[09h*4], offset int09h_vector mov word ptr es:[(09h*4)+2], ds mov word ptr es:[13h*4], offset int13h_vector mov word ptr es:[(13h*4)+2], ds mov word ptr es:[16h*4], offset int16h_vector mov word ptr es:[(16h*4)+2], ds mov word ptr es:[40h*4], offset int40h_vector mov word ptr es:[(40h*4)+2], ds mov word ptr es:[19h*4], offset int19h_vector mov word ptr es:[(19h*4)+2], ds mov word ptr es:[1ah*4], offset int1Ah_vector mov word ptr es:[(1ah*4)+2], ds
; BOP 5F - send interesting addresses to softpc C BIOS ; CS seg of kio_table ; DS seg of resident keyboard code ; DI offset of bop table ; CX size of bop table entry ; SI offset of kio_table mov si,offset sysinitgrp:kio_table push ds push cs pop ds mov word ptr [si], offset shift_keys ;K6 mov word ptr [si+2], offset shift_masks ;K7 mov word ptr [si+4], offset ctl_n_table ;K8 mov word ptr [si+6], offset ctl_f_table ;K9 mov word ptr [si+8], offset lowercase ;K10 mov word ptr [si+10], offset uppercase ;K11 mov word ptr [si+12], offset alt_table ;K30 mov word ptr [si+14], offset dummy_vector mov word ptr [si+16], offset print_screen_caller mov word ptr [si+18], offset int15h_caller mov word ptr [si+20], offset cpu_nop_code mov word ptr [si+22], offset int15h_vector mov word ptr [si+24], offset Icounter mov word ptr [si+26], offset int4Ah_caller mov word ptr [si+28], offset keyboard_break_caller mov word ptr [si+30], offset int10h_caller mov word ptr [si+32], offset int10h_vector mov word ptr [si+34], offset use_host_int10 mov word ptr [si+36], offset ega_parm_setup mov word ptr [si+38], offset changing_mode mov word ptr [si+40], offset prt_status mov word ptr [si+42], offset wait_int mov word ptr [si+44], offset floppy_table mov word ptr [si+46], offset vga_1b_table mov word ptr [si+48], offset conf_table mov word ptr [si+50], offset int08h_vector mov word ptr [si+52], offset int13h_vector mov word ptr [si+54], offset int13h_caller mov word ptr [si+56], SW_VIDEO_BUFFER_SIZE mov word ptr [si+58], SW_VIDEO_BUFFER_SEGMENT mov word ptr [si+60], offset sw_video_dirty_count mov word ptr [si+62], offset sw_video_busy ifdef JAPAN mov word ptr [si+64], offset int16h_caller endif ; JAPAN
; Pass DOS_FLAG to 32 bit side
push es push bx mov ah, GET_IN_VARS int 21h mov ax, es pop bx pop es
; The last entry is reserved for assertion checking ifdef JAPAN mov word ptr [si+66], ax mov word ptr [si+68], DOS_FLAG_OFFSET mov word ptr [si+70], VERSIONID else ; !JAPAN mov word ptr [si+64], ax mov word ptr [si+66], DOS_FLAG_OFFSET mov word ptr [si+68], VERSIONID endif ; !JAPAN pop ds
; mov si, offset kio_table mov di, offset iret_bop_table mov cx, offset iret_end_first_entry - offset iret_bop_table mov ax, VERSIONID bop BOP_UNIMPINT jc isk_int9
; ; Risc only ;
xor ax, ax mov es, ax mov word ptr es:[17h*4], offset int17h_RiscVector mov word ptr es:[(17h*4)+2], ds
; ; End Risc only ; jmp isk_Exit
isk_int9:
; ; X86 only ;
; save old video int xor ax, ax mov es, ax mov bx, es:[40h] mov si, offset host_int10 mov word ptr ds:[si], bx mov bx, es:[42h] mov word ptr ds:[si+2], bx
; save old secondary video int (42h) mov bx, es:[108h] mov si, offset host_int42 mov word ptr ds:[si], bx mov bx, es:[10ah] mov word ptr ds:[si+2], bx
;----------------------------------------------------------- ; ; Crazy vector grabber ; ; Works OK on DEC PC when grab INT's 6, 11, 16, 17, 42. ; Now try and avoid all accesses to host ROM. ; ; At this point we assume ES=0 ;-----------------------------------------------------------
; Grab some prominent vectors for pseudo-ROM routines. ; start at Int 0h and work our way up as needed cld
mov di, 20 mov ax, offset int05h_vector ; INT 05h stosw ; Print screen mov ax, ds stosw mov ax, offset int06h_vector ; INT 06h stosw ; Illegal instruction. mov ax, ds stosw mov ax, offset unexp_int ; INT 07h stosw mov ax, ds stosw
; int 8h Timer hardware vector already done for both x86\mips ; int 9h kbd hardware vector already done for both x86\mips add di, 8
mov ax, offset unexp_int ; INT 0ah stosw mov ax, ds stosw mov ax, offset unexp_int ; INT 0bh stosw mov ax, ds stosw mov ax, offset unexp_int ; INT 0ch stosw mov ax, ds stosw mov ax, offset unexp_int ; INT 0dh stosw mov ax, ds stosw mov ax, offset int0e_vector ; INT 0eh stosw ; Floppy hardware int. mov ax, ds stosw mov ax, offset unexp_int ; INT 0fh stosw mov ax, ds stosw mov ax, offset int10h_vector ; INT 10h stosw mov ax, ds stosw mov ax, offset int11h_vector ; INT 11h stosw ; Equipment check. mov ax, ds stosw mov ax, offset int12h_vector ; INT 12h stosw ; Get memory size. mov ax, ds stosw
; int 13h already done (see above) for both mips\x86
mov di, 14h*4 ; Communications. mov ax, offset int14h_vector stosw mov ax, ds stosw mov ax, offset int15h_vector ; INT 15h stosw mov ax, ds stosw
; int 16h kbd hardware vector already done for both x86\mips add di, 4
mov ax, offset int17h_vector ; INT 17h stosw mov ax, ds stosw mov ax, offset int18h_vector ; INT 18h stosw ; ROM BASIC. mov ax, ds stosw
; int 19h (reboot vector) already done for both x86\mips
; int 1ah, time of day, already done for both x86\mips
mov di, 1Bh*4 mov ax, offset dummy_vector ; INT 1Bh stosw ; Keyboard break. mov ax, ds stosw mov ax, offset dummy_vector ; INT 1Ch stosw ; Timer tick. mov ax, ds stosw
mov di, 1Eh*4 ; Floppy parameters. mov ax, offset bios_floppy_table stosw mov ax, ds stosw
; int 40h already done (see above) for both mips\x86
mov di, 41h*4 mov ax, offset unexp_int ; INT 41h stosw ; Hard disk parameters. mov ax, ds stosw mov ax, offset int42h_vector ; INT 42h stosw ; Default video. mov ax, ds stosw
mov di, 70h*4 ; Real time clock init. mov ax, offset int70h_vector stosw mov ax, ds stosw mov ax, offset int71h_vector ; INT 71h Redirect. stosw mov ax, ds stosw mov ax, offset intD11_vector ; INT 72h D11 int stosw mov ax, ds stosw mov ax, offset intD11_vector ; INT 73h D11 int stosw mov ax, ds stosw mov ax, offset intD11_vector ; INT 74h D11 int stosw mov ax, ds stosw mov ax, offset int75h_vector ; INT 75h 287 int stosw mov ax, ds stosw mov ax, offset intD11_vector ; INT 76h D11 int stosw mov ax, ds stosw mov ax, offset intD11_vector ; INT 77h D11 int stosw mov ax, ds stosw
isk_Exit: ;; ;; williamh, May 16, 1996 ;; Photostyler blindly calls EMS function without even checking ;; if EMS driver ever exists at all. On most x86 machines, we are fine because ;; the ROM BIOS sets the vector to a valid address. On certain x86 machines ;; and all RISC machines, the vector is 0:0. This hack is to repoint ;; the vector to our dummy iret routine if it is not initialized. Windows 3.1 ;; Windows 95 ALWAYS redirect this vector to their own, so they don't have ;; the problem as we do. ;; Also note that the application may skip the EMS calls if the system has ;; big memory(more than 16MB, maybe). In this case, the problem won't get hit ;; at all. ;; ;; ds = segment of ntio.sys resident portion. It is the segment of our ;; iret_com rountine ;; xor di, di mov es, di mov di, 067h * 4 ; the EMS vector mov ax, es:[di] or ax, es:[di + 2] ;; anything set for the vector? jnz i67_patch_done mov word ptr es:[di], offset iret_com mov es:[di + 2], ds
i67_patch_done: call DOSTI popa ret
InstSpcKbd endp
SpcKbdSeg ends end
|