URL
https://opencores.org/ocsvn/next186mp3/next186mp3/trunk
Subversion Repositories next186mp3
[/] [next186mp3/] [trunk/] [SW/] [BIOS/] [BIOS_Next186.asm] - Rev 3
Compare with Previous | Blame | View Log
; This file is part of the Next186 SoC PC project
; http://opencores.org/project,next186
; Filename: BIOS_Next186.asm
; Description: Part of the Next186 SoC PC project, ROM BIOS code
; Version 1.0
; Creation date: Feb-Jun 2013
; Author: Nicolae Dumitrache
; e-mail: ndumitrache@opencores.org
; -------------------------------------------------------------------------------------
; Copyright (C) 2013 Nicolae Dumitrache
; This source file may be used and distributed without
; restriction provided that this copyright statement is not
; removed from the file and that any derivative work contains
; the original copyright notice and the associated disclaimer.
; This source file is free software; you can redistribute it
; and/or modify it under the terms of the GNU Lesser General
; Public License as published by the Free Software Foundation;
; either version 2.1 of the License, or (at your option) any
; later version.
; This source is distributed in the hope that it will be
; useful, but WITHOUT ANY WARRANTY; without even the implied
; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
; PURPOSE. See the GNU Lesser General Public License for more
; details.
; You should have received a copy of the GNU Lesser General
; Public License along with this source; if not, download it
; from http://www.opencores.org/lgpl.shtml
; -----------------------------------------------------------------------
; Additional Comments:
; Assembled with MASM v6.14.8444
; Next186 SoC PC have no ROM, only RAM. The bootstrap code is the initial value of cache
; (last half 1K = 4 lines of 256bytes each), initially marked as "dirty", in order to
; be saved in RAM at first flush
; The bootstrap code may load the BIOS from SD, or from RS232, and place it at F000:E000
.186
.model tiny
.code
SCANCODE1 equ 1
;-------------------------- BIOS data area (BDA) -----------------
;40:0000 2 Base port address of first RS-232 adapter (COM1) See COM Ports
;40:0002 2 Port of COM2
;40:0004 2 Port of COM3
;40:0006 2 Port of COM4
;40:0008 2 Base port addr of first parallel printer (LPT1) Printer Ports
;40:000A 2 Port of LPT2
;40:000C 2 Port of LPT3
;40:000E 2 Port of LPT4
;40:0010 2 Equipment/hardware installed/active; see Equipment List
;40:0012 1 Errors in PCjr infrared keyboard link
;40:0013 2 Total memory in K-bytes (same as obtained via INT 12H)
;40:0015 2 Scratch pad for manufacturing error tests
;
;40:0017 2 Keyboard status bits; see Keyboard Shift Status Flags
;40:0019 1 Current (accumulating) value of Alt+numpad pseudo-key input;
; normally 0. When [Alt] is released, value is stored in
; keyboard buffer at 001e.
;40:001a 2 Addr of keyboard buffer head (keystroke at that addr is next)
;40:001c 2 Address of keyboard buffer tail
;40:001e 32 Keyboard buffer. BIOS stores keystrokes here (head and tail
; point to addresses from 041eH to 043dH inclusive).
;
;40:003e 1 Diskette drive needs recalibration (bit 0=A, bit 1=B, etc.)
; bits 4-5 indicate which drive is currently selected
;40:003f 1 Diskette motor is running (bit 0=drive A, bit 1=B, etc.)
;40:0040 1 Time until motor off. INT 08H turns motor off when this is 0.
;40:0041 1 Diskette error status; same as status returned by INT 13H
;40:0042 7 Diskette controller status information area
;
;40:0049 1 Current active video mode. See Video Modes and INT 10H.
;40:004a 2 Screen width in text columns
;40:004c 2 Length (in bytes) of video area (regen size)
;40:004e 2 Offset from video segment of active video memory page
;40:0050 16 Cursor location (8 byte-pairs; low byte=clm, hi byte=row)
;40:0060 2 Cursor size/shape. Low byte=end scan line; hi byte=start line.
;40:0062 1 Current active video page number
;40:0063 2 Port address for 6845 video controller chip; see CGA I/O Ports
;40:0065 1 Current value of 6845 video ctrlr CRT_MODE (port 3x8H register)
;40:0066 1 Current value of 6845 video ctrlr CRT_PALETTE (port 3x9H reg)
;
;40:0067 5 Cassette data area or POST data area
; 40:0067: 1 byte mouse buffer counter (DataCounter)
; 40:0068: 1 byte mouse packet size (PacketSize): 0 for 3 bytes, 1 for 4 bytes (Intellimouse)
; 40:0069: 1 byte palette paging status
; 40:006a: 1 byte PalPagingCounter - guards pal paging re-entrance
;
;40:006c 4 Timer tick counter (count of 55ms ticks since CPU reset)
;40:0070 1 Timer overflow flag (timer has rolled over 24 hr)
;40:0071 1 Ctrl-Break flag. Bit 7=1 when break was pressed. This never
; gets reset unless you do it yourself.
;
;40:0072 2 1234H means Ctrl+Alt+Del reboot is in progress. BIOS checks
; this to avoid doing a "cold boot" with the time-consuming POST
; 4321H means reset, preserving memory
; 5678H, 9abcH, and abcdH (are internal PC Convertible codes)
;
;40:0074 4 PCjr diskette or AT hard disk control area
; (0074) 1 Status of last fixed-disk drive operation
; (0075) 1 Number of hard disk drives for AT
; (0077) 1 Hard disk port for XT. See XT Hard Disk Ports.
;40:0078 4 Printer time-out values (478H=Lpt1, 478H=Lpt2...)
;40:007c 4 RS-232 time-out values (47cH=Com1, 47dH=Com2...)
;
;40:0080 2 AT PS/2 keyboard buffer offset start address (usually 01eH)
;40:0082 2 end address (usually 003eH)
;
;40:0084 1 EGA text rows-1 (maximum valid row value)
;40:0085 2 EGA bytes per character (scan-lines/char used in active mode)
;40:0087 1 EGA flags; see EgaMiscInfoRec
;40:0088 1 EGA flags; see EgaMiscInfo2Rec
;40:0089 1 VGA flags; see VgaFlagsRec
; See also: EGA/VGA Data Areas
;
;40:008b 1 AT PS/2 Media control: data rate, step rate
;40:008c 1 AT PS/2 Hard disk drive controller status
;40:008d 1 AT PS/2 Hard disk drive error status
;40:008e 1 AT PS/2 Hard disk drive interrupt control
;
;40:0090 1 AT PS/2 Disk media state bits for drive 0
;40:0091 1 for drive 1
;40:0092 1 AT PS/2 Disk operation started flag for drive 0
;40:0093 1 for drive 1
;40:0094 1 AT PS/2 Present cylinder number for drive 0
;40:0095 1 for drive 1
; 2 - Number of 512bytes sectors of HD0
;
;40:0096 1 AT Keyboard flag bit 4=1 (10H) if 101-key keyboard is attached
;40:0097 1 AT Keyboard flag for LED 'key lock' display
; bits 0-2 are ScrollLock, NumLock, CapsLock
;
;40:0098 4 AT Pointer to 8-bit user wait flag; see INT 15H 86H
;40:009c 4 AT Microseconds before user wait is done
;40:00a0 1 AT User wait activity flag:
; 01H=busy, 80H=posted, 00H=acknowledged
;
;40:00a1 7 AT Reserved for network adapters
; 40:00a1: 4 bytes far pointer to mouse callback (HandlerPtr)
; 40:00a5: 3 bytes mouse buffer (DataBuffer)
;
;40:00a8 4 EGA Address of table of pointers; see EgaSavePtrRec
;40:00ac 68 Reserved
;40:00f0 16 (IAC) Inter-Aapplication Communication area. Programs may use
; this area to store status, etc. Might get overwritten by
; another program.
; http://www.ctyme.com/intr/int.htm
; video memory: 8 physical segments at 0a000h, 0b000h, 0c000h, 0d000h, 0e000h, 0f000h, 10000h, 11000h
; Memory segments mapping
; 1Mb virtual seg address physical seg address
; 0000h 0000h
; 1000h 1000h
; 2000h 2000h
; 3000h 3000h
; 4000h 4000h
; 5000h 5000h
; 6000h 6000h
; 7000h 7000h
; 8000h 8000h
; 9000h 9000h
; a000h a000h - video
; b000h b000h - video
; c000h 12000h
; d000h 13000h
; e000h 14000h
; f000h 15000h
RAMSize equ 80h ; 64KB segments
org 0e000h
bios:
biosmsg db 'Next186 PapilioPro SoC PC BIOS (C) 2014 Nicolae Dumitrache', 0
msgmb db 'MB SD Card', 13, 10, 0
msgkb db 'PS2 KB detected', 13, 10, 0
; Graphics character set
font8x8: ; TODO define and place font
font8x16: ; TODO define and place font
org 0e05bh
coldboot:
warmboot:
cli
cld
mov ax, 30h
mov ss, ax
mov sp, 100h
push 0
popf
mov al, 36h
out 43h, al
xor ax, ax
out 40h, al
out 40h, al ; 18Hz PIT CH0
out 61h, al ; speaker off
not al
out 21h, al ; disable all interrupts
; ------------------ MAP init
call flush
mov ax, 15h ; BIOS physical segment 15h mapped on virtual segment 0ch
out 8ch, ax
push 0c000h
pop es
push 0f000h
pop ds
xor si, si
xor di, di
mov cx, 8000h
rep movsw ; copy BIOS virtual segment 0fh over physical segment 15h
call flush
mov dx, 80h
xor ax, ax
mapi:
out dx, ax
inc ax
inc dx
cmp al, 0ch
jne short mapi1
add al, 6
mapi1:
cmp al, 16h
jne short mapi
; -------------------- Interrupt table init
push 0
pop ds
push ds
pop es
xor si, si
mov di, 4
mov word ptr [si], offset defint
mov word ptr [si+2], cs
mov cx, 256-2
rep movsw
mov word ptr ds:[7*4], offset int07
mov word ptr ds:[8*4], offset int08
mov word ptr ds:[9*4], offset int09
mov word ptr ds:[10h*4], offset int10
mov word ptr ds:[11h*4], offset int11
mov word ptr ds:[12h*4], offset int12
mov word ptr ds:[13h*4], offset int13
mov word ptr ds:[15h*4], offset int15
mov word ptr ds:[16h*4], offset int16
mov word ptr ds:[18h*4], offset int18
mov word ptr ds:[19h*4], offset int19
mov word ptr ds:[1ah*4], offset int1a
mov word ptr ds:[70h*4], offset int70
mov word ptr ds:[74h*4], offset int74
; ------------------- BDA init
push 40h
pop ds
push ds
pop es
xor di, di
xor si, si
xor ax, ax
mov cl, 80h
rep stosw
mov word ptr [si+08h], 378h ; LPT1 base port address
mov byte ptr [si+10h], 24h ; equipment word (color 80x25, PS2 mouse present)
mov word ptr [si+13h], 640 ; memory size in KB
add word ptr [si+1ah], 1eh ; next char pointer in kb buffer
add word ptr [si+1ch], 1eh ; last char pointer in kb buffer
mov word ptr [si+60h], 0e0fh ; cursor shape
mov word ptr [si+63h], 3d4h ; video port address
add word ptr [si+80h], 1eh ; start kb buffer
add word ptr [si+82h], 3eh ; end kb buffer
mov word ptr [si+87h], 0940h ; video adapter options (512Kb video)
mov word ptr [si+89h], 0b71h ; VGA video flags: 400 line text mode, default palette loading on (0), blinking on
mov byte ptr [si+96h], 10h ; 101 keyboard installed
; ------------------- Graph mode init
mov ax, 3
int 10h
; ------------------- KB init ----------------
mov al, 0aeh
out 64h, al ; enable kb
mov al, 0a7h
out 64h, al ; disable mouse
mov cx, 25
kbi1:
call getps2byte
loop short kbi1 ; wait for kb timeout
mov ah, 0ffh ; reset kb
clc ; kb command
call sendcmd
jc short nokb
mov cl, 25
kbi2:
dec cx
jcxz short nokb
call getps2byte
jc short kbi2 ; wait for BAT
cmp al, 0aah
jne short nokb
mov ah, 0f2h ; kb id
call sendcmd ; CF = 0
jc short nokb
call getps2byte
cmp al, 0abh
jne short nokb
call getps2byte
cmp al, 83h
; set scan code 1
IFDEF SCANCODE1
jne short nokb
mov ah, 0f0h ; kb scan set
call sendcmd
jc short nokb
mov ah, 1 ; scan set 1
call sendcmd
jnc short kbok
ELSE
je short kbok
ENDIF
nokb:
mov byte ptr KbdFlags3, 0 ; kb not present
kbok:
mov al, 0adh
out 64h, al ; disable kb interface
; ------------------- Mouse init ----------------
mov al, 0a8h
out 64h, al ; enable mouse
mousei0:
call getps2byte
jnc short mousei0
mov ah, 0ffh
call sendcmd ; reset mouse (CF = 1)
jc short nomouse
mov cl, 25
mousei1:
dec cx
jcxz short nomouse
call getps2byte
jc short mousei1
cmp al, 0aah ; BAT
jne short nomouse
call getps2byte
cmp al, 0 ; mouse ID
je short mouseok
nomouse:
mov al, 0a7h
out 64h, al ; disable mouse
and byte ptr EquipmentWord, not 4 ; ps2 mouse not present in equipement word
mouseok:
call enableKbIfPresent
mov al, 20h
out 64h, al
in al, 60h
or al, 3
mov ah, al
mov al, 60h
out 64h, al
mov al, ah
out 60h, al ; enable 8042 mouse and kb interrupts
mov ax,1000-1 ; 1ms
out 70h, ax ; set RTC frequency
mov al, 0e4h
out 21h, al ; enable all PIC interrupts (8h, 9h, 70h, 74h)
inc ax
out 1, ax ; enable auto flush on vblank
sti ; enable CPU interrupts
; --------------------- HDD init
call sdinit
mov HDSize, ax
push cs
pop es
mov si, offset biosmsg
call prts
mov si, offset bioscont
call prts
mov ax, HDSize
shr ax, 1
call dispAX
mov si, offset msgmb
call prts
test byte ptr KbdFlags3, 10h
jz nokbmsg
mov si, offset msgkb
call prts
nokbmsg:
test byte ptr EquipmentWord, 4
jz nomousemsg
mov si, offset msgmouse
call prts
nomousemsg:
;-------------- HD bootstrap
mov ax, 305h
xor bx, bx
int 16h ; set typematic rate and delay to fastest
int 19h
msgmouse db 'PS2 Mouse detected', 13, 10, 0
bioscont db 13, 10, 'CPU: 80186 40Mhz (40MIPS, 80Mhz 32bit bus)', 13, 10
db 'RAM: 8MB SDR 144Mhz', 13, 10
db 'Cache: 4-way, 64x256 bytes data/inst', 13, 10
db 'HD0: ', 0
; ---------------------------- INT 07 ---------------------
int07 proc near ; coprocessor ESC sequence
push ax
push bx
push ds
push bp
mov bp, sp
lds bx, [bp+8]
int07_pfx:
mov al, [bx]
inc bx
and al, 0f8h
cmp al, 0d8h ; ESC code
jne short int07_pfx
cmp byte ptr [bx], 0c0h ; mod reg r/m of ESC 8087 instruction
sbb al, al
and al, [bx]
and ax, 0c7h
cmp al, 6
jne int072
mov al, 80h
int072:
shr al, 6
inc ax
add ax, bx
mov [bp+8], ax
pop bp
pop ds
pop bx
pop ax
iret
int07 endp
; ---------------------------- INT 08 ---------------------
int08 proc near
push ds
push bx
push 40h
pop ds
mov bx, 6ch
add word ptr [bx], 1
adc word ptr [bx+2], 0
cmp word ptr [bx+2], 18h
jne short int081
cmp word ptr [bx], 0b0h
jne short int081
mov word ptr [bx], 0
mov word ptr [bx+2], 0
mov byte ptr [bx+4], 1
int081:
int 1ch
sti
push ax
mov ah, 4
kloop:
in al, 64h
test al, 1
jz short nokey
dec ah
jnz short kloop
test al, 20h
jz short kbdata
int 74h
jmp short nokey
kbdata:
int 9h
nokey:
pop ax
pop bx
pop ds
iret
int08 endp
; --------------------- INT 09 - keyboard ------------------
KbdFlags1 equ <ds:[17h]>
KbdFlags2 equ <ds:[18h]>
AltKpd equ <ds:[19h]>
CtrlBreak equ <ds:[71h]>
KbdFlags3 equ <ds:[96h]>
KbdFlags4 equ <ds:[97h]>
; Bits for the KbdFlags1
RShfDown equ 1
LShfDown equ 2
CtrlDown equ 4
AltDown equ 8
ScrLock equ 10h
NumLock equ 20h
CapsLock equ 40h
Insert equ 80h
; Bits for the KbdFlags2
LCtrDown equ 1
LAltDown equ 2
SysReqDown equ 4
Pause equ 8
ScrLockDown equ 10h
NumLockDown equ 20h
CapsLockDown equ 40h
InsDown equ 80h
; Bits for the KbdFlags3
LastE1 equ 1
LastE0 equ 2
RCtrDown equ 4
RAltDown equ 8
LastF0 equ 20h
; Bits for the KbdFlags4
ScrLockLED equ 1
NumLockLED equ 2
CapsLockLED equ 4
SetRepeat equ 8 ; Set auto repeat command in progress
AckReceived equ 10h
LEDUpdate equ 40h
IFDEF SCANCODE1
int09 proc near
pusha
push ds
push es
push 40h
pop ds
in al, 60h ; al contains the scan code
mov dx, KbdFlags1
mov cx, KbdFlags3
cmp al, 0fah ; ACK
jne short noACK
; ------------ manage ACK response
test ch, LEDUpdate
jz short ToggleACK ; no LED update
test ch, AckReceived
jnz short SecondACK ; second ACK received
mov ah, ch ; LED update command sent, ACK received, need to send second byte
and ah, ScrLockLED or NumLockLED or CapsLockLED
mov bl, 0
call sendps2byte
jmp short ToggleACK
SecondACK:
xor ch, LEDUpdate ; second ACK, clear LED update bit
ToggleACK:
xor ch, AckReceived ; toggle ACK bit
SetFlags1:
jmp SetFlags
; ------------ no ACK
noACK:
mov ah,4fh
stc
int 15h
jnc int09Exit
cmp al, 0e0h
jne short noE0
or cl, LastE0
jmp short SetFlags1
noE0:
cmp al, 0e1h
jne short noE1
or cl, LastE1
jmp short SetFlags1
noE1:
cmp al, 53h ; is DEL?
jne short noDEL
mov ah, dl
and ah, CtrlDown or AltDown
cmp ah, CtrlDown or AltDown
jne NormalKey ; is DEL, but no CTRL+ALt+DEL
mov word ptr ds:[72h], 1234h ; warm boot flag
db 0eah
dw 0, 0ffffh ; reboot
noDEL:
test cl, LastE0
jnz short noRSUp ; ignore fake shifts
cmp al, 2ah ; left shift
jne short noLSDown
or dl, LShfDown
jmp short SetFlagsKey2
noLSDown:
cmp al, 2ah or 80h
jne short noLSUp
and dl, not LShfDown
jmp short SetFlagsKey2
noLSUp:
cmp al, 36h ; right shift
jne short noRSDown
or dl, RShfDown
jmp short SetFlagsKey2
noRSDown:
cmp al, 36h or 80h
jne short noRSUP
and dl, not RShfDown
jmp short SetFlagsKey2
noRSUp:
cmp al, 38h ; ALT
jne short noALTDown
test cl, LastE0
jz short LALTDn
or cl, RAltDown
or dl, AltDown
jmp short SetFlagsKey2
LALTDn:
or dx, (LAltDown shl 8) or AltDown
jmp short SetFlagsKey2
noALTDown:
cmp al, 38h or 80h
jne short noALTUp
test cl, LastE0
jz short LALTUp
and cl, not RAltDown
and dl, not AltDown
jmp short ALTup
LALTUp:
and dx, not ((LAltDown shl 8) or AltDown)
ALTUp:
xor ax, ax
xchg al, AltKpd
test al, al
jz short SetFlagsKey2
jmp pushKey
noALTUp:
cmp al, 1dh ; CTL
jne short noCTLDown
test cl, lastE0
jz short LCTLDn
or cl, RCtrDown
or dl, CtrlDown
SetFlagsKey2:
jmp short SetFlagsKey1
LCTLDn:
or dx, (LCtrDown shl 8) or CtrlDown
jmp short SetFlagsKey1
noCTLDown:
cmp al, 1dh or 80h
jne short noCTLUp
test cl, LastE0
jz short LCTLUp
and cl, not RCtrDown
and dl, not CtrlDown
jmp short SetFlagsKey1
LCTLUp:
and dx, not ((LCtrDown shl 8) or CtrlDown)
jmp short SetFlagsKey1
noCTLUp:
mov bx, 3a00h + CapsLock
call KeyLock
jnc short SetFlagsKey1
mov bx, 4600h + ScrLock
push dx ; save ScrLock state bit (dl)
call KeyLock
pop bx ; restore ScrLock state bit (bl)
jc short noScrLock
test dl, CtrlDown
jz short SetFlagsKey1; no break, just ScollLock
mov dl, bl ; restore ScrLock flag
test bh, ScrLockDown
jnz short SetFlagsKey1
mov byte ptr CtrlBreak, 80h ; CTRL+BREAK flag
mov ax, Buffer
mov HeadPtr, ax
mov TailPtr, ax
int 1bh
xor ax, ax
jmp pushkey
noScrLock:
test cl, LastE0 ; INS
jnz short testINS
test dl, RShfDown or LShfDown
jnz short testINS
test dl, NumLock
jnz short NoIns
testINS:
mov bx, 5200h + Insert
call KeyLock
noIns:
mov bx, 4500h + NumLock
push dx ; save NumLock state bit (dl)
call KeyLock
pop bx ; restore NumLock state bit (bl)
jc short NormalKey ; CTRL+NumLock = Pause
test dl, CtrlDown
jz short SetFlagsKey1
mov dl, bl ; restore NumLock flag
or dh, Pause ; set Pause bit
SetFlagsKey1:
jmp SetFlagsKey
E0Key:
mov di, offset E0KeyList
push cx
mov cx, E0KeyIndex - E0KeyList
cld
push cs
pop es
repne scasb
pop cx
jne short SetFlagsKey
mov al, es:[di + E0KeyIndex - E0KeyList - 1]
jmp short KeyDown
NormalKey:
test al, 80h
jnz short SetFlagsKey ; key up
test cl, LastE0
jnz short E0Key
cmp al, 59h
sbb ah, ah
and al, ah
mov bx, offset KeyIndex
xlat cs:[bx]
KeyDown:
xor bx, bx
test dl, RShfDown or LShfDown
jz short noShift
mov bl, 2
noShift:
cmp al, 26
ja short noCaps
test dl, CapsLock
jz short noNum
xor bl, 2
jmp short noNum
noCaps:
cmp al, 37
ja short noNum
test dl, NumLock
jnz short NumDown
mov bl, 2
NumDown:
xor bl, 2
noNum:
test dl, CtrlDown
jz short noCtrl
mov bl, 4
noCtrl:
test dl, AltDown
jz short noAlt
mov bl, 6
noAlt:
cbw
shl ax, 3
add bx, ax
mov ax, cs:KeyCode[bx]
cmp ax, 000ah
ja short pushKey
dec ax
js short SetFlagsKey ; ax was 0
mov ah, AltKpd
aad
mov AltKpd, al
jmp short SetFlagsKey
pushKey:
push cx
mov cx, ax
mov ah, 5
int 16h
pop cx
and dh, not Pause ; clear Pause bit
SetFlagsKey:
and cl, not (LastE0 or LastE1) ; not prefix key code, clear all prefixes
SetFlags:
mov al, dl
shr al, 4
xor al, ch
and al, 7
jz short SF1 ; no LEDs to update
test ch, SetRepeat or AckReceived or LEDUpdate
jnz short SF1 ; can not update LEDS, so just write the flags and exit
or al, LEDUpdate
xor ch, al ; insert the LEDs in KbdFlags4
mov ah, 0edh ; set LED
mov bl, 0
call sendps2byte
SF1:
mov KbdFlags1, dx
mov KbdFlags3, cx
int09Exit:
pop es
pop ds
popa
iret
int09 endp
ELSE ; SCANCODE2
int09 proc near
pusha
push ds
push es
push 40h
pop ds
in al, 60h ; al contains the scan code
mov dx, KbdFlags1
mov cx, KbdFlags3
cmp al, 0fah ; ACK
jne short noACK
; ------------ manage ACK response
test ch, LEDUpdate
jz short ToggleACK ; no LED update
test ch, AckReceived
jnz short SecondACK ; second ACK received
mov ah, ch ; LED update command sent, ACK received, need to send second byte
and ah, ScrLockLED or NumLockLED or CapsLockLED
mov bl, 0
call sendps2byte
jmp short ToggleACK
SecondACK:
xor ch, LEDUpdate ; second ACK, clear LED update bit
ToggleACK:
xor ch, AckReceived ; toggle ACK bit
SetFlags1:
jmp SetFlags
; ------------ no ACK
noACK:
cmp al, 0e0h
jne short noE0
or cl, LastE0
jmp short SetFlags1
noE0:
cmp al, 0e1h
jne short noE1
or cl, LastE1
jmp short SetFlags1
noE1:
cmp al, 0f0h
jne short noF0
or cl, LastF0
jmp short SetFlags1
noF0:
cmp al, 71h ; is DEL?
jne short noDEL
mov ah, dl
and ah, CtrlDown or AltDown
cmp ah, CtrlDown or AltDown
je short noF01
NormalKey1:
jmp NormalKey
noF01:
mov word ptr ds:[72h], 1234h ; warm boot flag
db 0eah
dw 0, 0ffffh ; reboot
noDEL:
cmp al, 83h ; is F7
je short NormalKey1
ja short SetFlags1
test cl, LastF0 ; key up?
jz short noKeyUp
or al, 80h ; key up flag
noKeyUp:
test cl, LastE0
jnz short noRSUp ; ignore fake shifts
cmp al, 12h ; left shift
jne short noLSDown
or dl, LShfDown
jmp short SetFlagsKey2
noLSDown:
cmp al, 12h or 80h
jne short noLSUp
and dl, not LShfDown
jmp short SetFlagsKey2
noLSUp:
cmp al, 59h ; right shift
jne short noRSDown
or dl, RShfDown
jmp short SetFlagsKey2
noRSDown:
cmp al, 59h or 80h
jne short noRSUP
and dl, not RShfDown
jmp short SetFlagsKey2
noRSUp:
cmp al, 11h ; ALT
jne short noALTDown
test cl, LastE0
jz short LALTDn
or cl, RAltDown
or dl, AltDown
jmp short SetFlagsKey2
LALTDn:
or dx, (LAltDown shl 8) or AltDown
jmp short SetFlagsKey2
noALTDown:
cmp al, 11h or 80h
jne short noALTUp
test cl, LastE0
jz short LALTUp
and cl, not RAltDown
and dl, not AltDown
jmp short ALTup
LALTUp:
and dx, not ((LAltDown shl 8) or AltDown)
ALTUp:
xor ax, ax
xchg al, AltKpd
test al, al
jz short SetFlagsKey2
jmp pushKey
noALTUp:
cmp al, 14h ; CTL
jne short noCTLDown
test cl, lastE0
jz short LCTLDn
or cl, RCtrDown
or dl, CtrlDown
SetFlagsKey2:
jmp short SetFlagsKey1
LCTLDn:
or dx, (LCtrDown shl 8) or CtrlDown
jmp short SetFlagsKey1
noCTLDown:
cmp al, 14h or 80h
jne short noCTLUp
test cl, LastE0
jz short LCTLUp
and cl, not RCtrDown
and dl, not CtrlDown
jmp short SetFlagsKey1
LCTLUp:
and dx, not ((LCtrDown shl 8) or CtrlDown)
jmp short SetFlagsKey1
noCTLUp:
mov bx, 5800h + CapsLock
call KeyLock
jnc short SetFlagsKey1
mov bx, 7e00h + ScrLock
push dx ; save ScrLock state bit (dl)
call KeyLock
pop bx ; restore ScrLock state bit (bl)
jc short noScrLock
test dl, CtrlDown
jz short SetFlagsKey1; no break, just ScollLock
mov dl, bl ; restore ScrLock flag
test bh, ScrLockDown
jnz short SetFlagsKey1
mov byte ptr CtrlBreak, 80h ; CTRL+BREAK flag
mov ax, Buffer
mov HeadPtr, ax
mov TailPtr, ax
int 1bh
xor ax, ax
jmp pushkey
noScrLock:
test cl, LastE0 ; INS
jnz short testINS
test dl, RShfDown or LShfDown
jnz short testINS
test dl, NumLock
jnz short NoIns
testINS:
mov bx, 7000h + Insert
call KeyLock
noIns:
mov bx, 7700h + NumLock
push dx ; save NumLock state bit (dl)
call KeyLock
pop bx ; restore NumLock state bit (bl)
jc short noPause
test dl, CtrlDown
jz short SetFlagsKey1
mov dl, bl ; restore NumLock flag
or dh, Pause ; set Pause bit
SetFlagsKey1:
jmp SetFlagsKey
E0Key:
mov di, offset E0KeyList
push cx
mov cx, E0KeyIndex - E0KeyList
cld
push cs
pop es
repne scasb
pop cx
jne short SetFlagsKey
mov al, es:[di + E0KeyIndex - E0KeyList - 1]
jmp short KeyDown
noPause:
and al, 07fh ; delete up bit
NormalKey:
test cl, LastF0
jnz short SetFlagsKey ; key up
test cl, LastE0
jnz short E0Key
mov bx, offset KeyIndex
xlat cs:[bx]
KeyDown:
xor bx, bx
test dl, RShfDown or LShfDown
jz short noShift
mov bl, 2
noShift:
cmp al, 26
ja short noCaps
test dl, CapsLock
jz short noNum
xor bl, 2
jmp short noNum
noCaps:
cmp al, 37
ja short noNum
test dl, NumLock
jnz short NumDown
mov bl, 2
NumDown:
xor bl, 2
noNum:
test dl, CtrlDown
jz short noCtrl
mov bl, 4
noCtrl:
test dl, AltDown
jz short noAlt
mov bl, 6
noAlt:
cbw
shl ax, 3
add bx, ax
mov ax, cs:KeyCode[bx]
cmp ax, 000ah
ja short pushKey
dec ax
js short SetFlagsKey ; ax was 0
mov ah, AltKpd
aad
mov AltKpd, al
jmp short SetFlagsKey
pushKey:
push cx
mov cx, ax
mov al, ah ; scan code
mov ah,4fh
stc
int 15h
jnc nopush
mov ah, 5
int 16h
nopush:
pop cx
and dh, not Pause ; clear Pause bit
SetFlagsKey:
and cl, not (LastE0 or LastE1 or LastF0) ; not prefix key code, clear all prefixes
SetFlags:
mov al, dl
shr al, 4
xor al, ch
and al, 7
jz short SF1 ; no LEDs to update
test ch, SetRepeat or AckReceived or LEDUpdate
jnz short SF1 ; can not update LEDS, so just write the flags and exit
or al, LEDUpdate
xor ch, al ; insert the LEDs in KbdFlags4
mov ah, 0edh ; set LED
mov bl, 0
call sendps2byte
SF1:
mov KbdFlags1, dx
mov KbdFlags3, cx
int09Exit:
pop es
pop ds
popa
iret
int09 endp
ENDIF
KeyLock proc near ; input: BH = expected scan code, al = scan code, BL = key lock flag. Returns CF=1 to continue, CF=0 to exit
xor bh, al
jnz short s2
mov ah, dh
or dh, bl ; set flag
xor ah, dh ; get flag difference
xor dl, ah ; toggle only if key was not already down
ret
s2: cmp bh, 80h
stc
jne short exit
xor dh, bl ; key up
exit:
ret
KeyLock endp
; --------------------- INT 10h - Video ----------------
ActiveVideoMode equ <ds:[49h]> ; 1 byte
ScreenWidth equ <ds:[4ah]> ; 2 Screen width in text columns
RegenLength equ <ds:[4ch]> ; 2 Length (in bytes) of video area (regen size)
PageOffset equ <ds:[4eh]> ; 2 Offset from video segment of active video memory page
CursorPos equ <ds:[50h]> ; 16 Cursor location (8 byte-pairs; low byte=col, hi byte=row)
CursorShape equ <ds:[60h]> ; 2 Cursor size/shape. Low byte=end scan line; hi byte=start line.
ActivePage equ <ds:[62h]> ; 1 Current active video page number
PortAddress equ <ds:[63h]> ; 2 Port address for 6845 video controller chip; see CGA I/O Ports
CrtMode equ <ds:[65h]> ; 1 Current value of 6845 video ctrlr CRT_MODE (port 3x8H register)
CrtPalette equ <ds:[66h]> ; 1 Current value of 6845 video ctrlr CRT_PALETTE (port 3x9H reg)
ScreenRows equ <ds:[84h]> ; 1 EGA text rows-1 (maximum valid row value)
ScanLinesChar equ <ds:[85h]> ; 2 EGA bytes per character (scan-lines/char used in active mode)
EgaMiscInfo equ <ds:[87h]> ; 1 EGA flags; see EgaMiscInfoRec
EgaMiscInfo2 equ <ds:[88h]> ; 1 EGA flags; see EgaMiscInfo2Rec
VgaFlags equ <ds:[89h]> ; 1 VGA flags; see VgaFlagsRec
VgaFlags2 equ <ds:[8ah]> ; 1 VGA flags2
PalPaging equ <ds:[69h]> ; 1 Palette paging status: bit7=0 for 4x64, 1 for 16x16. bit3:0=active page
PalPagingCounter equ <ds:[6ah]> ; 1 Palette paging counter
int10 proc near
sti ; no interrupt reentrant
cld
push ds
push si
push 40h
pop ds
cmp ah, 4fh
je short svga
cmp ah, 1ch
ja short exit
mov si, ax
shr si, 7
and si, 1feh
call cs:vidtbl[si]
exit:
pop si
pop ds
iret
svga:
cmp al, 5
je short VESAMemControl
cmp al, 1
jb short VESAGetInfo
je short VESAGetModeInfo
cmp al, 3
jb short VESASetMode
je short VESAGetMode
mov ax, 100h
jmp short exit
; ---------------- VESA fn00
VESAGetInfo:
push cx
push di
mov si, offset VESAInfo
mov cx, 10
rep movsw es:[di], cs:[si]
mov cl, 118 ; 236 bytes 0
VESASupportedClear:
xor ax, ax
rep stosw
pop di
pop cx
VESASupported:
mov ah, 0 ; success
VESASupportedErr:
mov al, 4fh
jmp short exit
; ---------------- VESA fn01
VESAGetModeInfo:
cmp cx, 101h
VESAGetModeInfo1:
mov ah, 1 ; error
jne short VESASupportedErr
push cx
push di
mov cx, 9
mov si, offset VESAModeInfo
rep movsw es:[di], cs:[si]
mov cl, 119
jmp short VESASupportedClear
; ---------------- VESA fn02
VESASetMode:
imul ax, bx, 2
cmp ax, 101h*2
jne short VESASetMode1
lea ax, [bx+23ffh]
xchg ah, al
int 10h
jmp short VESASupported
VESASetMode1:
mov al, bl
mov ah, 0
int 10h
jmp short VESASupported
; ---------------- VESA fn03
VESAGetMode:
mov bh, EgaMiscInfo
and bh, 80h
mov bl, ActiveVideoMode
cmp bl, 25h
je short VESAGetMode1
or bl, bh
mov bh, 0
jmp short VESASupported
VESAGetMode1:
add bx, 257-25h
jmp short VESASupported
; ---------------- VESA fn05
VESAMemControl:
; test bx, not 101h ; BX validation
; jnz short VESAGetModeInfo1 ; error
push cs
push offset VESASupported
; call VESAMemControlCB
; jmp short VESASupported
VESAMemControlCB:
pushf
cli
push ax
push dx
mov ax, bx
and ax, 1
add al, 8ah
xchg ax, dx
and ax, 7
add al, 0ah
test bh, bh
jnz getpageinfo
call flush
out dx, ax
pop dx
pop ax
popf
retf
getpageinfo:
in ax, dx
sub al, 0ah
and ax, 7
xchg ax, dx
pop ax
pop ax
popf
retf
VESAInfo db 'VESA'
dw 100h, VESAOEM, 0f000h, 2, 0, VESAModes, 0f000h, 8
VESAOEM db 'Nicolae Dumitrache', 0
VESAModes dw 101h, 0ffffh
VESAModeInfo:
;Bit(s) Description - mode attributes
;0 mode supported by present hardware configuration
;1 optional information available (must be =1 for VBE v1.2+)
;2 BIOS output supported
;3 set if color, clear if monochrome
;4 set if graphics mode, clear if text mode
;---VBE v2.0+ ---
;5 mode is not VGA-compatible
;6 bank-switched mode not supported
;7 linear framebuffer mode supported
;8 double-scan mode available (e.g. 320x200 and 320x240)
;---VBE v3.0 ---
;9 interlaced mode available
;10 hardware supports triple buffering
;11 hardware supports stereoscopic display
;12 dual display start address support
;13-15 reserved
dw 0000000010011001b
;Bit(s) Description - window attributes
;0 exists
;1 readable
;2 writable
;3-7 reserved
db 00000111b, 00000111b
dw 64, 64, 0a000h, 0b000h, VESAMemControlCB, 0f000h, 640
; --------------- fn 00h, set video mode
setmode:
pusha
push es
add al, al ; CF = cls bit
rcl byte ptr EgaMiscInfo, 1
ror byte ptr EgaMiscInfo, 1
push ax
mov dx, 3c4h
mov ax, 0f02h
out dx, ax ; enable all write planes
mov ax, 0804h
out dx, ax ; clear planar mode
mov dl, 0ceh
mov ax, 0001h
out dx, ax ; disable set/reset
mov ax, 0003h
out dx, ax ; reset logical op and rotate count
mov ax, 0005h
out dx, ax ; set write mode to 00 (CPU access)
mov ax, 0ff08h
out dx, ax ; set bitmask to CPU access
pop ax
cmp al, 3*2
ja short setmode1
mov al, 0b6h ; reset sound generator
out 43h, al
mov al, 0
out 42h, al
out 42h, al
mov ax, 0806h ; text mode (80x25, 16 colors), flash enabled
mov word ptr ScreenWidth, 80
mov word ptr RegenLength, 1000h
mov byte ptr ScreenRows, 25-1
mov word ptr ScanLinesChar, 16
mov bx, 0b800h ; segment
mov cx, 4000h ; video len/2
mov si, 0720h ; clear value
mov di, 0bf14h ; 200lines, 14h offset
jmp short setmode2
setmode1:
cmp al, 0dh*2
jne short setmode12
mov di, 0bf14h ; 200 lines, 14h offset
mov ah, 11h ; graphic, 640x480, half
mov word ptr ScreenWidth, 40
mov word ptr RegenLength, 2000h
jmp short setmode121
setmode12:
cmp al, 12h*2
jne short setmode13
mov di, 0028h ; 240lines, 28h offset
mov ah, 1 ; graphic, 640x480
mov word ptr ScreenWidth, 80
mov word ptr RegenLength, 0a000h
setmode121:
push ax
mov dx, 3c4h
mov ax, 0ff02h
out dx, ax ; set write all planes
mov ax, 0004h
out dx, ax ; set planar mode
pop ax
jmp short setmode21
setmode13:
cmp al, 13h*2
jne short setmode3
mov ah, 41h ; graphic mode, 320x200, 256 colors
mov word ptr ScreenWidth, 40
mov word ptr RegenLength, 0000h
mov di, 0bf28h ; 200 lines, 28h offset
jmp short setmode21
setmode3:
cmp al, 25h*2
jne setmodeexit
mov di, 0050h ; 240 lines, 50h offset
mov ah, 1 ; graphic mode, 640x400, 256 colors
mov word ptr ScreenWidth, 80
mov word ptr RegenLength, 0000h
setmode21:
mov bx, 0a000h ; segment
mov cx, 8000h ; video len/2
xor si, si ; clear value
setmode2:
shr al, 1
mov ActiveVideoMode, al
push ax
push cx
push ds
pop es
mov dx, 3d4h
mov ax, di
mov al, 6
out dx, ax ; set scanlines
xchg ax, di
mov ah, al
mov al, 13h
out dx, ax ; set offset
xor ax, ax
mov di, offset CursorPos
mov cx, 8
rep stosw ; reset cursor position for all pages
mov ax, 0500h
int 10h ; set page0
pop cx
test byte ptr EgaMiscInfo, 80h
jnz short setmode4 ; no clear video memory
mov es, bx
clearnext:
xchg ax, si
xor di, di
push cx
rep stosw
pop cx
cmp bh, 0a0h
jnz short clearok
xchg ax, si
inc ax
int 10h
cmp al, 8
jnz short clearnext
clearok:
call palpageset
mov byte ptr PalPaging, cl ; reset paging
setmode4:
pop ax
mov dx, 3c0h
mov al, 10h
out dx, al
mov al, ah
out dx, al ; set video mode
mov al, 13h
out dx, al
mov al, 0
out dx, al ; 0 pan
mov ax, 1123h
int 10h ; set ROM 8x8 font for graphics mode
mov ah, 1
xor cx, cx
int 10h ; show cursor
test byte ptr VgaFlags, 8 ; test default palette loading
jnz short setmodeexit ; no default palette
mov ax, 1012h
xor bx, bx
mov cx, 100h
mov dx, offset default_pal
push cs
pop es
int 10h ; set default palette
setmodeexit:
pop es
popa
nullproc:
ret
; --------------- fn 01h, set cursor shape and visibility (shape is ignored, always lines 14&15 of text mode char)
cursor: ; CH bit 6 or 5 -> cursor off
push ax
push dx
mov dx, 3d4h
mov al, 0ah
out dx, al
mov al, ch
shr al, 1
or al, ch
inc dx
out dx, al
pop dx
pop ax
ret
;---------------- fn 02h, set cursor pos
curpos:
push ax
push bx
mov al, bh
shr bx, 7
and bx, 0eh
mov CursorPos[bx], dx
cmp byte ptr ActiveVideoMode, 3
jne short curpos1
cmp al, ActivePage
jne short curpos1
push dx
xor ax, ax
xchg al, dh
imul ax, 80
add ax, dx
mov dx, 3d4h
push ax
mov ah, al
mov al, 0fh
out dx, ax
pop ax
mov al, 0eh
out dx, ax
pop dx
curpos1:
pop bx
pop ax
ret
;---------------- fn 03h, get cursor pos
getcurpos:
push bx
shr bx, 7
and bx, 0eh
mov dx, CursorPos[bx]
mov cx, CursorShape
pop bx
ret
;---------------- fn 04h, light pen
lightpen:
mov ah, 0 ; not triggered
ret
;---------------- fn 05h, set active video page
apage:
pusha
call flush
and al, 7
mov bh, al
mov ActivePage, al
mov al, ActiveVideoMode
cmp al, 13h
jae short apage1
cmp al, 3
ja short apage2
mov ax, 0ah
out 8ah, ax
inc ax
out 8bh, ax
mov ah, 3
int 10h ; get cursor pos
mov ah, 2
int 10h ; set cursor pos
mov ax, 400h
jmp short apage4
apage1:
mov ax, 0ah ; mode 13h and 25h
add al, bh
out 8ah, ax
inc ax
cmp al, 12h
jne short apage3
mov al, 0ah
apage3:
out 8bh, ax
apage2:
mov ax, RegenLength
apage4:
shr bx, 8 ; page number
mul bx
mov bx, ax ; 1 means 4 bytes, or 2 characters
shl ax, 2 ; 1 means 1 byte
mov PageOffset, ax
mov dx, 3d4h
mov ah, bl
mov al, 0dh
out dx, ax
mov ah, bh
dec ax
out dx, ax
popa
ret
;---------------- fn 06h, scroll up / clr
scrollup:
pusha
push es
xchg cx, dx
sub cx, dx
inc cx
call scr_params
scrollup6:
push 0b800h ; segment
pop es
add dl, dl
add di, di
add di, PageOffset ; di = top left corner address
xchg ax, cx ; ah = 0
test bl, bl
jz short scrollup3 ; clear
sub ah, bl
jb short scrollup3 ; clear
add si, di
scrollup4:
mov cl, al
rep movsw es:[si], es:[di]
add si, dx
add di, dx
dec ah
jns short scrollup4 ; ch = lines - 1
scrollup3:
add ah, bl ; clear rectangle: DI=address, ah=lines, al=columns, bh=attribute
xchg ax, bx
mov al, ' '
scrollup5:
mov cl, bl
rep stosw
add di, dx
dec bh
jns short scrollup5 ; ch = lines - 1
scrollexit:
pop es
popa
ret
;---------------- fn 07h, scroll dn / clr
scrolldn:
std
pusha
push es
neg cx
add cx, dx
inc cx
call scr_params
neg dx
neg si
jmp short scrollup6
scr_params:
mov bl, al ; lines
xor ax, ax
xchg al, dh
imul di, ax, 80
add di, dx
mov dl, 80 ; dh = 0
sub dl, cl
mov al, bl
imul si, ax, 160
ret
;---------------- fn 08h, read char/attr
readchar:
push bx
call mode3chaddr
mov ax, [bx]
pop bx
ret
mode3chaddr: ; returns current char address in mode3 in ds:bx. Input: bh=page, ds=40h
push ax
and bx, 700h
lea ax, [bx+0b800h]
shr bx, 7
mov bx, CursorPos[bx]
mov ds, ax
xor ax, ax
xchg al, bh
imul ax, 80
add bx, ax
add bx, bx
pop ax
ret
;---------------- fn 09h, write char/attr
writecharattr:
push ax
push es
push bx
push cx
mov ah, bl
call mode3chaddr
push ds
pop es
xchg di, bx
rep stosw
xchg di, bx
pop cx
pop bx
pop es
pop ax
ret
;---------------- fn 0ah, write char
writechar:
jcxz short writecharskip
push bx
push cx
call mode3chaddr
writechar3:
mov [bx], al
add bx, 2
loop short writechar3
pop cx
pop bx
writecharskip:
ret
;---------------- fn 0eh, write char as TTY
writecharTTY:
push ax
push bx
push dx
mov bl, ActivePage
mov bh, 0
add bx, bx
mov dx, CursorPos[bx]
shl bx, 7
mov ah, 0ah
call tty
mov ah, 2 ; set cursor pos
int 10h
pop dx
pop bx
pop ax
ret
tty: ; dx=xy, bh=page, al=char, bl=attr, ah=0ah(no attr) or 09h(with attr)
test word ptr KbdFlags2, Pause
jnz short tty
push cx
cmp al, 7
je short bell
cmp al, 8
je short bs
cmp al, 0ah
je short cr
cmp al, 0dh
je short lf
mov cx, 1
int 10h ; write char at cursor
inc dx
cmp dl, ScreenWidth
jae short crlf
tty1:
pop cx
ret
bell:
; TODO bell code
jmp short tty1
bs:
sub dl, 1
adc dl, 0
jmp short tty1
lf:
mov dl, 0
jmp short tty1
crlf:
mov dl, 0
cr:
inc dh
cmp dh, ScreenRows
jbe short tty1
dec dh
; mov ah, 8
; int 10h ; read attribute at cursor pos
push bx ; save active page in bh
push dx
; xchg ax, bx
mov bh, 7 ; default attribute
mov ax, 601h
mov dh, ScreenRows
mov dl, ScreenWidth
dec dx
xor cx, cx
int 10h ; scroll up
pop dx
pop bx ; restore active page in bh
jmp short tty1
;---------------- fn 0fh, read video mode
readmode:
mov al, EgaMiscInfo
and al, 80h
or al, ActiveVideoMode
mov ah, ScreenWidth
mov bh, ActivePage
ret
;---------------- fn 10h, palette
paltable dw setonereg, palexit, setallreg, setblink, palexit, palexit, palexit, readonereg, readoverscan, readallreg, palexit, palexit, palexit, palexit, palexit, palexit
dw setoneDAC, palexit, setblockDAC, paging, palexit, readoneDAC, palexit, readblockDAC, setPELmask, getPELmask, getpaging, grayscale
pal:
cmp al, 1bh
ja short palexit
mov si, ax
add si, si
add byte ptr PalPagingCounter, ah ; prevents <palpage> re-entrance on recursive <pal> calls
call palpage
call cs:paltable[si-2000h]
call palpage
sub byte ptr PalPagingCounter, ah
palexit:
ret
palpage: ; executes only if PalPagingCounter == ah
cmp byte ptr PalPagingCounter, ah
jne short palpageexit
palpageset:
test byte ptr PalPaging, 0fh
jz short palpageexit
pusha
mov bl, byte ptr PalPaging
add bl, bl
jc short page16
shl bl, 2
page16:
shl bx, 11 ; bh=target page, bl=0 page
palpage1:
mov al, 15h
int 10h ; read 0 page DAC reg
push cx
push dx
xchg bl, bh
int 10h ; read target page DAC register
xchg bl, bh
mov al, 10h
int 10h ; write 0 page DAC register
pop dx
pop cx
xchg bl, bh
int 10h ; write target page DAC register
xchg bl, bh
add bx, 101h; next DAC reg
test bl, 0fh
jnz short palpage1
popa
palpageexit:
ret
setonereg:
cmp bl, 10h
jae setonereg1
pusha
call colfrombits
mov cl, al
call colfrombits
mov ch, al
call colfrombits
mov dh, al
mov al, 10h
int 10h
popa
setonereg1:
ret
setallreg:
pusha
mov al, 0
mov si, dx
mov bl, 15
setallreg1:
mov bh, es:[si+15]
int 10h
dec si
dec bl
jns short setallreg1
popa
ret
setblink:
pusha
cmp byte ptr ActiveVideoMode, 3
jne short setblink1
mov dx, 3c0h
mov al, 10h
out dx, al
mov al, bl
and al, 1
shl al, 3
out dx, al ; set video mode (0 or 8)
shl al, 2
xor al, VgaFlags
and al, 20h
xor VgaFlags, al
setblink1:
popa
ret
readonereg:
cmp bl, 10h
jae readonereg1
push ax
push cx
push dx
mov al, 15h
int 10h
mov al, dh ; al = R
and al, 00110000b
shr al, 2
add al, 01111000b
and al, 10000100b
mov bh, al
xchg ax, cx ; ax = GB
and ax, 0011000000110000b
shr ax, 3
shr al, 1
add ax, 0011110000011110b
and ax, 0100001000100001b
or bh, ah
or bh, al
rol bh, 3
pop dx
pop cx
pop ax
readonereg1:
ret
readallreg:
pusha
mov di, dx
mov bl, 0
readllreg1:
mov al, 7
int 10h
mov al, bh
stosb
inc bx
cmp bl, 16
jne short readllreg1
mov al, 0 ; overscan color
stosb
popa
ret
readoverscan:
mov bh, 0
ret
setoneDAC:
push ax
push dx
xchg ax, dx
mov al, bl
mov dx, 3c8h
out dx, al
inc dx
mov al, ah
out dx, al
mov al, ch
out dx, al
mov al, cl
out dx, al
pop dx
pop ax
ret
setblockDAC:
pusha
mov si, dx
mov dx, 3c8h
xchg ax, bx
out dx, al
inc dx
imul cx, 3
rep outsb dx, es:[si]
popa
ret
paging:
push bx
test bl, bl
mov bl, PalPaging
jnz short paging1
add bl, bl
ror bx, 1
jmp short paging2
paging1:
and bx, 0f80h ; bl=old page, bh=new page
or bl, bh
paging2:
mov PalPaging, bl
pop bx
ret
readoneDAC:
push ax
push dx
mov al, bl
mov dx, 3c7h
out dx, al
inc dx
inc dx
in al, dx
mov ah, al
in al, dx
mov ch, al
in al, dx
mov cl, al
pop dx
mov dh, ah
pop ax
ret
readblockDAC:
pusha
mov di, dx
mov dx, 3c7h
xchg ax, bx
out dx, al
inc dx
inc dx
imul cx, 3
rep insb
popa
ret
setPELmask:
push dx
xchg ax, bx
mov dx, 3c6h
out dx, al
xchg ax, bx
pop dx
ret
getPELmask:
push dx
xchg ax, bx
mov dx, 3c6h
in al, dx
xchg ax, bx
pop dx
ret
getpaging:
mov bh, PalPaging
mov bl, 0
rol bx, 1
shr bh, 1
ret
grayscale:
jcxz short grayscale2
pusha
mov bh, cl
grayscale1:
mov al, 15h
int 10h
shr dx, 8
imul si, dx, 77
mov dl, ch
imul dx, 151
mov ch, 0
imul cx, 28
add dx, si
add dx, cx
mov ch, dh
mov cl, dh
mov al, 10h
int 10h
inc bl
dec bh
jne short grayscale1
popa
grayscale2:
ret
colfrombits: ; input: bh, output: al
shr bh, 1
sbb al, al
and al, 2ah
test bh, 4
jz short col1
or al, 15h
col1:
ret
;---------------- fn 11h, character generator
loadUDF:
cmp bx, 1000h
jne loadUDFexit ; only 16bytes chars and font block 0 supported
pusha
xchg ax, dx
mov dx, 03cbh
out dx, ax
mov si, bp
shl cx, 4
rep outsb dx, es:[si]
popa
loadUDFexit:
ret
chargen:
test al, not 10h ; test for 00h and 10h
jz short loadUDF
test al, not 11h ; test for 01h and 11h
jz short loadROMfont
test al, not 12h ; test for 02h and 12h
jz short loadROMfont
test al, not 14h ; test for 04h and 14h
jz short loadROMfont
cmp al, 20h
jb loadUDFexit
je short set1f
cmp al, 21h
je short setgrUDF
cmp al, 24h
jbe short setROMgrFont
cmp al, 30h
je short getfontinfo
ret
loadROMFont:
push es
pusha
mov bx, 1000h ; 8x16 chars, block 0
mov cx, 100h ; all chars
xor dx, dx
mov bp, offset font8x16
push cs
pop es
mov al, 0
; int 10h ; loadUDF
popa
pop es
ret
set1f:
xor si, si
mov ds, si
mov [si+1fh*4], bp
mov [si+1fh*4+2], es
ret
setgrUDF:
pusha
jcxz short loadUDFexit
push ds
xor si, si
mov ds, si
mov [si+43h*4], bp
mov [si+43h*4+2], es
pop ds
mov ax, 200
cmp byte ptr ActiveVideoMode, 13h
jb short setgrUDFexit
je short setgrUDF1
mov ax, 480 ; mode 25h, 480 lines
setgrUDF1:
mov ScanLinesChar, cx
cwd
div cx
dec ax
mov ScreenRows, al
setgrUDFexit:
popa
ret
setROMgrFont:
pusha
push es
mov cx, 8
push cs
pop es
mov bp, offset font8x8
cmp al, 23h
je short setROMgrFont1
mov bp, offset font8x16
setROMgrFont1:
mov al, 21h
int 10h ; set graphic UDF
dec ax
mov bp, offset font8x8 + 128*8
int 10h ; set INT 1fh
pop es
popa
ret
getfontinfo:
mov cx, ScanLinesChar
mov dl, ScreenRows
cmp bh, 1
ja short getfontinfo1
push 0
pop ds
les bp, ds:[1fh*4]
jb short getfontinfoexit
les bp, ds:[43h*4]
ret
getfontinfo1:
cmp bh, 7
ja short getfontinfoexit
mov si, bx
shr si, 8
add si, si
mov bp, cs:fontinfo[si-4]
push cs
pop es
getfontinfoexit:
ret
fontinfo dw font8x16, font8x8, font8x8+128*8, font8x16, font8x16, font8x16
;---------------- fn 12h, special functions
special:
cmp bl, 10h
jne short special1
mov cl, EgaMiscInfo2 ; cl = switch settings
and cx, 15 ; ch <- 0 (feature bits)
mov bx, 3 ; bh <- 0 (color mode), bl = video memory size
ret
special1:
cmp bl, 31h
jne short special2
neg al
xor al, VgaFlags
and al, 8 ; transfer palette loading bit to VgaFlags
xor VgaFlags, al
mov al, 12h ; supported function
ret
special2:
mov al, 0 ; unsupported function
ret
;---------------- fn 13h, write string
writestr:
jcxz short wstrexit
pusha
mov si, bx
shr si, 8
add si, si
push CursorPos[si]
mov ah, 9 ; write tty char/attribute
wstr1:
push ax
test al, 2
mov al, es:[bp]
jz short noattr
inc bp
mov bl, es:[bp]
noattr:
inc bp
mov CursorPos[si], dx
call tty
pop ax
loop short wstr1
pop CursorPos[si]
test al, 1
jz short wstr2
mov ah, 2 ; set cursor pos
int 10h
wstr2:
popa
wstrexit:
ret
;---------------- fn 1ah, get/set display combination code
getdcc:
cmp al, 1
ja short getdccexit
mov al, ah
je short setdcc
mov bx, 08h
dccval label word
setdcc:
mov cs:[dccval-2], bx
getdccexit:
ret
;---------------- fn 1bh, query status
querystatus:
pusha
mov ax, offset staticfunctable
stosw
mov ax, cs
stosw
mov si, offset ActiveVideoMode
cmp byte ptr [si], 12h
mov cx, 33 ; info copied from BDA
rep movsb
mov ax, 8
stosw ; display info (one VGA analog color monitor)
mov bx, 208h ; 400 scan lines, 8 pages
mov al, 10h ; 16 colors
jb short querystatus1 ; mode03h
mov bx, 302h ; 480 scan lines, 2 pageS
je short querystatus1 ; mode12h
mov bh, 0 ; scan lines code (0=200, 1=350, 2=400, 3=480)
mov ax, 100h ; 256 colors
cmp byte ptr ActiveVideoMode, 13h
je short querystatus3 ; mode13h
mov bx, 301h ; 480 scan lines, 1 page
querystatus1:
cmp byte ptr ActiveVideoMode, 0dh
jne short querystatus3
mov bx, 0008h ; 200 scan lines, 8 pages
querystatus3:
stosw
xchg ax, bx
stosw
xor ax, ax
stosw ; font block info (45)
mov al, VgaFlags
and al, 00101111b
stosw
stosw
mov al, EgaMiscInfo
shr al, 4
and al, 7 ; video memory size
stosw
mov al, 2
stosb ; color display attached
mov cl, 6
xor ax, ax
rep stosw ; 12 reserved bytes
popa
mov al, ah ; supported function
ret
staticfunctable db 00001100b ; video modes 2h, 3h supported
db 00100000b ; video mode 0dh supported
db 00001100b ; video modes 12h, 13h supported
db 00000000b
db 00100000b ; video mode 25h supported
db 0, 0
db 00000100b ; 400 scanline supported
db 1 ; font blocks available in text mode
db 1 ; max active font blocks available in text mode
;Bit(s) Description
;0 all modes on all displays function supported
;1 gray summing function supported
;2 character font loading function supported
;3 default palette loading enable/disable supported
;4 cursor emulation function supported
;5 EGA palette present
;6 color palette present
;7 color-register paging function supported
;8 light pen supported (see AH=04h)
;9 save/restore state function 1Ch supported
;10 intensity/blinking function supported (see AX=1003h)
;11 Display Combination Code supported (see #00039)
;12-15 unused (0)
db 11101111b ; miscellaneous function support flags
db 00001100b ; miscellaneous function support flags
db 0, 0 ; reserved
db 0 ; save pointer function flags
db 0 ; reserved
vidtbl dw setmode, cursor, curpos, getcurpos, lightpen, apage, scrollup, scrolldn, readchar, writecharattr
dw writechar, nullproc, nullproc, nullproc, writecharTTY, readmode
dw pal, chargen, special, writestr, nullproc, nullproc, nullproc, nullproc, nullproc, nullproc, getdcc, querystatus, nullproc
int10 endp
; --------------------- INT 11h - Equipment ----------------
EquipmentWord equ <ds:[10h]>
int11 proc near
push ds
push 40h
pop ds
mov ax, EquipmentWord
pop ds
iret
int11 endp
; --------------------- INT 12h - Memory size ----------------
MemorySize equ <ds:[13h]>
int12 proc near
push ds
push 40h
pop ds
mov ax, MemorySize
pop ds
iret
int12 endp
; --------------------- INT 13h - Disk services ----------------
HDLastError equ <ds:[74h]>
HDOpStarted equ <ds:[92h]> ; bit 3: in INT13h (all other bits must be 0)
HDSize equ <ds:[94h]>
int13 proc near
push ds
push bp
push 40h
pop ds
xor byte ptr HDOpStarted, 8
jz short inINT13
sti
cld
cmp ah, 1ah
jbe short Disk1
sub ah, 41h-1bh ; extensions
cmp ah, 22h
jbe short Disk1
mov ah, 1 ; bad command error
jmp short exit
inINT13:
mov ah, 0aah ; drive not ready
jmp short exit2
Disk1:
mov bp, ax
shr bp, 7
and bp, 1feh
push ds
call cs:disktbl[bp]
pop ds
exit:
mov HDLastError, ah
exit2:
xor byte ptr HDOpStarted, 8
neg ah ; CF <- (AH != 0)
exit1:
mov bp, sp
rcr byte ptr [bp+8], 1
rol byte ptr [bp+8], 1 ; insert error CF on stack
neg ah
pop bp
pop ds
iret
disktbl dw DiskReset, DiskGetStatus, DiskRead, DiskWrite, DiskVerify, DiskFormat, DiskFormat, DiskFormat, DiskGetParams, DiskInit, DiskRead, DiskWrite, DiskSeek, DiskRst, DiskReadSectBuffer, DiskWriteSectBuffer
dw DiskReady, DiskRecalibrate, DiskDiag, DiskDiag, DiskDiag, DiskGetType, DiskChanged, DiskSetDASDType, DiskSetMediaType, DiskPark, DiskFormat, DiskExtInstCheck, DiskExtRead, DiskExtWrite, DiskExtVerify, DiskExtLock
dw DiskExtEject, DiskExtSeek, DiskExtGetParams
DiskGetType:
cmp dl, 80h
jne short DiskReset ; ah=0, drive not present
mov cx, HDSize
mov dx, cx
test cx, cx
jz short DiskReset ; ah=0, drive not present
mov ah, -3 ; HD present
shr cx, 6
shl dx, 10 ; CX:DX = HDSize * 1024
DiskGetTypeexit:
pop ds ; discard ret address
pop ds ; discard DS
xor byte ptr HDOpStarted, 8 ; CF <- 0
jmp short exit1
DiskExtInstCheck:
xchg bl, bh
mov ah, -1
mov cx, 1 ; extended disk access functions (AH=42h-44h,47h,48h) supported
cmp dl, 80h
jne short notready
jmp short DiskGetTypeexit
DiskReset:
DiskChanged:
DiskPark:
mov ah, 0 ; success
ret
DiskGetStatus:
mov ah, HDLastError
ret
DiskVerify:
mov bp, sdverify
jmp short DiskRead1
DiskWrite:
mov bp, sdwrite
jmp short DiskRead1
DiskRead:
mov bp, sdread
DiskRead1:
test al, al
jz short DiskReset
cmp dl, 80h
jne short notready
mov ah, 4
test cl, 3fh
jz short DiskReadend ; bad sector 0
pusha
mov ah, 0
push ax
call HCStoLBA
pop cx
push cx
call bp ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=read sectors
pop cx
sub cx, ax
neg cx ; CF=1 if cx != 0
rcl ah, 3 ; AH = 4*CF (sector not found / read error)
mov ds, ax
popa
mov ax, ds
DiskReadend:
ret
HCStoLBA: ; CX = {cyl[7:0], cyl[9:8], sect[5:0]}, DH = head. Returns DX:AX LBA
mov al, ch
mov ah, cl
shr ah, 6
shr dx, 8
imul dx, 63
and cx, 3fh
add cx, dx
dec cx
mov dx, 255*63
mul dx
add ax, cx
adc dx, 0
ret
; unsigned int s = cs & 0x3f;
; unsigned int c = ((cs & 0xc0) << 2) | (cs >> 8);
; return (c*255l + h)*63l + s - 1l;
DiskFormat:
DiskInit:
DiskSeek:
DiskRst:
DiskReady:
DiskRecalibrate:
DiskDiag:
DiskExtSeek:
cmp word ptr HDSize, 0
je short notready
cmp dl, 80h
je short DiskReset
notready:
mov ah, 0aah ; disk not ready
ret
DiskGetParams:
cmp dl, 80h
mov ah, 7
jne short DiskReadend ; ret
mov bl, 0 ; ???
mov ax, HDSize
mov dx, ax
shl ax, 10
shr dx, 6
sub ax, 30
sbb dx, 0
mov cx, 63*255
div cx
dec ax
cmp ax, 3feh
jbe dgpok
mov ax, 3feh
dgpok:
xchg al, ah
shl al, 6
or al, 3fh
mov cx, ax
mov dx, 0fe01h
xor ax, ax
ret
DiskExtVerify:
mov bp, sdverify
jmp short DiskExtRead1
DiskExtWrite:
mov bp, sdwrite
jmp short DiskExtRead1
DiskExtRead:
mov bp, sdread
DiskExtRead1:
cmp dl, 80h
jne short notready
push es
push ax
pusha
mov bx, sp
mov ds, ss:[bx+26]
mov cx, [si+2]
les bx, [si+4]
mov ax, [si+8]
mov dx, [si+10]
push ds
push si
call bp
pop si
pop ds
sub ax, [si+2]
add [si+2], ax
popa
pop ax
sbb ah, ah
and ah, 4
pop es
ret
DiskExtGetParams:
cmp dl, 80h
jne short notready
push ax
mov ax, HDSize
mov bp, sp
mov ds, [bp+8]
xor bp, bp
mov word ptr [si], 1ah ; size
mov word ptr [si+2], 0bh ; flags
mov word ptr [si+4], 1023 ; cylinders
mov word ptr [si+6], bp
mov word ptr [si+8], 255 ; heads
mov word ptr [si+10], bp
mov word ptr [si+12], 63 ; sectors/track
mov word ptr [si+14], bp
mov word ptr [si+16], ax
shl word ptr [si+16], 10
shr ax, 6
mov word ptr [si+18], ax
mov word ptr [si+20], bp
mov word ptr [si+22], bp
mov word ptr [si+24], 512 ; bytes/sector
pop ax
mov ah, 0
ret
DiskReadSectBuffer:
DiskWriteSectBuffer:
DiskSetDASDType:
DiskSetMediaType:
DiskExtLock:
DiskExtEject:
mov ah, 1 ; unsupported fn
ret
int13 endp
; --------------------- INT 15h - Extended services ----------------
UFPtr equ <ds:[98h]>
WaitCount equ <ds:[9ch]>
UWaitFlag equ <ds:[0a0h]>
HandlerPtr equ <ds:[0a1h]> ; 4 bytes
DataBuffer equ <ds:[0a5h]> ; 3 bytes
DataCounter equ <ds:[067h]> ; 1 byte
PacketSize equ <ds:[068h]> ; 1 byte, 0->3bytes, 1->4bytes
FreeXMSKb equ RAMSize*64 - 640 - 512 - 32 ;total - DOS - VGA - BIOS
; ------------ MovExt
IncSeg: ; DX = segment port address
jnz short SetSegExit
in ax, dx
and ax, RAMSize - 1
inc ax
cmp ax, 12h
jne short IncSeg1
xor ax, ax
IncSeg1:
cmp ax, 0ch
jne short SetSeg2
SetSeg: ; DX = segment port address, ax = logical segment (0..RAMSize-1)
and ax, RAMSize - 1
cmp ax, 0ch
jb short SetSeg1
add ax, 6
SetSeg2:
cmp ax, RAMSize
jb short SetSeg1
sub ax, RAMSize - 0ch
SetSeg1:
out dx, ax
SetSegExit:
ret
MovSeg equ 01h
savess dw 0
savesp dw MovExt, 0 ; tmp stack
; Log(idx) to Phy(val) segment map (RAMSize segs): 0,1,2,3,4,5,6,7,8,9,a,b,12h,13h,...,RAMSize-2,RAMSize-1,c,d,e,f,10h,11h, then wrap to 0,1,2,...
MovExt:
push es
push ds
pusha
cli
mov cs:savess, ss
push cs
pop ss
xchg sp, cs:savesp
mov dx, 80h + MovSeg + 1
jcxz short MovExt_exit
push es
pop ds
cld
mov al, [si+1ch]
mov ah, [si+1fh]
mov bl, [si+14h]
mov bh, [si+17h]
mov di, [si+1ah]
mov si, [si+12h]
call flush
call SetSeg ; 02000h = destination, DX=82h
dec dx
xchg ax, bx
call SetSeg ; 01000h = source, DX=81h
push MovSeg shl 12
pop ds
push (MovSeg + 1) shl 12
pop es
xor bx, bx
add cx, cx
adc bx, bx ; BX:CX = bytes to transfer
; move from 01000h:si to 02000h:di, 2*cx bytes
MovExtLoop:
inc dx ; 82h
mov ax, si
cmp ax, di
ja short MovExt1
mov ax, di
MovExt1:
neg ax
adc bx, -1
sub cx, ax
sbb bx, 0
xchg ax, cx ; cx = bytes to move, bx:ax = bytes left for the next transfer
jns short MovExt2 ; ax <= bx:cx
add cx, ax
xor ax, ax
inc bx
MovExt2:
movsb ; if CX = 0 transfer 10000h bytes
dec cx
jz short MovExt_next
test si, 1 ; read align
jz short raligned
movsb
dec cx
raligned:
shr cx, 1
rep movsw
jnc short MovExt_next
movsb
MovExt_next:
call flush
mov cx, ax
or ax, bx
jz short MovExt_exit ; finalized
test di, di
call incseg ; does nothing if ZF == 0, dx = 8bh
dec dx ; 81h
test si, si
call incseg ; dx = 81h
jmp short MovExtLoop
MovExt_exit:
mov ax, MovSeg + 1
out dx, ax ; 82h
dec ax
dec dx
out dx, ax ; 81h
mov ss, cs:savess
xchg sp, cs:savesp
popa
pop ds
pop es
xor ah, ah
jmp short exit_ax
MovExtProxy:
jmp MovExt
int15:
cmp ah, 4fh
je short exit_iret
xchg al, ah
cmp al, 80h
jb short exit15; CF=1 for <80h
cmp al, 83h
jb short done ; no error for 80, 81, 82
je short SetEventWait; 83
cmp al, 86h
jb short exit15; CF=1 for 84, 85
je short Wait1 ; 86
cmp al, 88h
jb short MovExtProxy ; 87
je short ExtSize ; 88
cmp al, 90h
jb short exit15; CF=1 for 89..8f
cmp al, 92h
jb short done ; no error for 90, 91
cmp al, 0c0h
jb short exit15; CF=1 for 92..bf
je short GetConfig ; c0
cmp al, 0c2h
jb short exit15; CF=1 for c1
je short Mouse ; c2
done:
cmc ; CF=1 for >c2
exit15:
mov ax, 8600h
exit_ax:
sti
retf 2 ; discard flags (need to keep CF)
exit_iret:
iret
; ------------ SetEventWait
SetEventWait:
push ds
push 40h
pop ds
xor ah, 1
jz short cancel
test ah, byte ptr UWaitFlag ; ah=1
jnz short busy ; CF=0
mov ax, 1000-1 ; 1ms
out 70h, ax ; restart RTC timer
mov UFPtr[0], bx
mov UFPtr[2], es
add ax, dx
adc cx, 0
mov WaitCount[0], ax
mov WaitCount[2], cx
mov ah, 1 ; wait in progress
cancel:
mov byte ptr UWaitFlag, ah
int 70h
stc ; no error
busy:
cmc ; eror
nowait:
pop ds
jmp short exit15
; ------------ Wait
Wait1:
push es
push bx
mov ax, 8300h
push 4ah
pop es
xor bx, bx ; user wait flag address=0040:00a0
int 15h ; returns with IF = 1
jc short wbusy
wloop:
hlt
test byte ptr es:[bx], 80h
jz short wloop
wbusy:
pop bx
pop es
jmp short exit15
; ------------ ExtSize
ExtSize:
mov ax, FreeXMSKb
jmp short exit_ax
; ------------ GetConfig
GetConfig:
xor ax, ax
push cs
pop es
mov bx, offset SysParams
jmp short exit_ax
; ------------ Mouse
Mouse:
push ds
push dx
push 40h
pop ds
test byte ptr EquipmentWord, 4 ; ps2 mouse equipement word
jnz short mouse_present
if_err:
mov ax, 03a7h ; interface error (no mouse present)
out 64h, al ; disable mouse
errexit:
stc ; error
exitok:
pushf ; save CF
in al, 21h
and al, not 10h
out 21h, al ; enable mouse interrupts
call enableKbIfPresent
popf
pop dx
pop ds
jmp exit_ax
mouse_present:
mov al, ah
mov ah, 1 ; invalid function
cmp al, 7
ja short errexit
push ax
in al, 21h
or al, 10h
out 21h, al ; disable mouse interrupts
sti ; allow interrupts for a short time, to flush possible pending KB/mouse requests
mov al, 0adh
out 64h, al ; disable kb interface
pop ax
cmp al, 1
cli ; from now on we are working with ints disabled, as the following code is highly non re-entrant
jb short en_dis
je short reset
cmp al, 3
jb short sampling
je short resolution
cmp al, 5
jb short gettype
je short reset
cmp al, 6
je short extend
; ------------- set handler
mov HandlerPtr[0], bx
mov HandlerPtr[2], es
jmp short exit_success1
; ------------- enable/disable
en_dis:
mov ax, 02f5h ; ah = invalid input
sub al, bh
cmp bh, ah
jnc short errexit
mov ah, al
call sendcmd ; enable/disable data reporting (CF = 1)
if_err1:
jc short if_err
exit_success:
mov byte ptr DataCounter, 0
exit_success1:
xor ah, ah ; success
jmp short exitok
; ------------- reset
reset:
mov ah, 0f6h ; set defaults
stc ; mouse command
call sendcmd
jc short if_err
mov bx, 00aah
mov byte ptr PacketSize, bh ; 3bytes packet
jmp short exit_success
; ------------- sampling
sampling:
cmp bh, 6
badparam:
mov ah, 2 ; invalid input
ja short errexit
shr bx, 8
mov ah, cs:sample_tbl[bx]
push ax
mov ah, 0f3h ; st sample rate
send2c:
stc
call sendcmd
pop ax
jc short if_err1
send1c:
stc
call sendcmd
jmp short if_err1
; ------------- resolution
resolution:
cmp bh, 3
ja short badparam
push bx
mov ah, 0e8h ; set resolution
jmp short send2c
; ------------- gettype
gettype:
mov ah, 0f2h
stc
call sendcmd
jc short if_err1
call getps2byte
jc short if_err1
mov bh, al
neg al ; CF=1 if al != 0
adc al, bh
mov byte ptr PacketSize, al ; 3 or 4 bytes packet
jmp short exit_success
; ------------- extended commands
extend:
test bh, bh
jnz short setscaling
mov ah, 0e9h ; status request
stc
call sendcmd
jc short if_err1
call getps2byte
jc short if_err1
mov bl, al
call getps2byte
jc short if_err1
mov cl, al
call getps2byte
jc short if_err1
pop dx
push ax ; replace dx on stack
jmp short exit_success
setscaling:
cmp bh, 2
ja short badparam
mov ah, 0e5h ; set scaling 1:1 or 2:1
add ah, bh
jmp short send1c
sample_tbl db 10, 20, 40, 60, 80, 100, 200
SysParams db 8, 0, 0fch, 0, 0
;--------------------------------------------------------------------------
; Feature byte 1
; b7: 1=DMA channel 3 used by hard disk
; b6: 1=2 interrupt controllers present
; b5: 1=RTC present
; b4: 1=BIOS calls int 15h/4Fh every key
; b3: 1=wait for extern event supported (Int 15h/41h)
; b2: 1=extended BIOS data area used
; b1: 0=AT or ESDI bus, 1=MicroChannel
; b0: 1=Dual bus (MicroChannel + ISA)
;--------------------------------------------------------------------------
db 10h
;--------------------------------------------------------------------------
; Feature byte 2
; b7: 1=32-bit DMA supported
; b6: 1=int16h, function 9 supported
; b5: 1=int15h/C6h (get POS data) supported
; b4: 1=int15h/C7h (get mem map info) supported
; b3: 1=int15h/C8h (en/dis CPU) supported
; b2: 1=non-8042 kb controller
; b1: 1=data streaming supported
; b0: reserved
;--------------------------------------------------------------------------
db 44h
;--------------------------------------------------------------------------
; Feature byte 3
; b7: not used
; b6: reserved
; b5: reserved
; b4: POST supports ROM-to-RAM enable/disable
; b3: SCSI on system board
; b2: info panel installed
; b1: Initial Machine Load (IML) system - BIOS on disk
; b0: SCSI supported in IML
;--------------------------------------------------------------------------
db 0
;--------------------------------------------------------------------------
; Feature byte 4
; b7: IBM private
; b6: EEPROM present
; b5-3: ABIOS presence (011 = not supported)
; b2: private
; b1: memory split above 16Mb supported
; b0: POSTEXT directly supported by POST
;--------------------------------------------------------------------------
db 0
;--------------------------------------------------------------------------
; Feature byte 5 (IBM)
; b1: enhanced mouse
; b0: flash EPROM
;--------------------------------------------------------------------------
db 0
; --------------------- INT 16h - keyboard interface ----------------
; AH Description
; -- ------------------------------------------------
; 00h Get a key from the keyboard, return code in AX.
; 01h Test for available key, ZF=1 if none, ZF=0 and
; AX contains next key code if key available.
; 02h Get shift status. Returns shift key status in AL.
; 03h Set Autorepeat rate. BH=0,1,2,3 (delay time in quarter seconds), BL=0..1Fh for 30 char/sec to 2 char/sec repeat rate.
; 05h Store scan code (in CX) in the type ahead buffer.
; 10h Get a key (same as 00h in this implementation).
; 11h Test for key (same as 01h).
; 12h Get extended key status. Returns status in AX.
AltKpd equ <ds:[19h]>
HeadPtr equ <ds:[1ah]>
TailPtr equ <ds:[1ch]>
Buffer equ <ds:[80h]>;1eh
EndBuf equ <ds:[82h]>;3eh
int16 proc near
push ds
push si
push 40h
pop ds
xchg al, ah ;shorter opcodes for al than ah
dec ax
test al, 0EFh ;Check for 01h and 11h
jz short TestKey ;TestKey does not need cld
inc ax
cld
test al, 0EFh ;Check for 0h and 10h
jz short GetKey
cmp al, 3 ;Check for 02h and 03h
jb short GetStatus
je short SetAutoRpt
cmp al, 5 ;Check for StoreKey function.
je short StoreKey
cmp al, 9 ;Get KB functionality
je short kbfunc
cmp al, 12h ;Extended status call
je short ExtStatus
cmp al, 92h ;stupid keyb.com
jne short Exit
kbfunc:
mov al, 24h ;AL=20h (fn 10h, 12h supported, set typematic supported)
Exit:
pop si
pop ds
iret ; unknown function, Restores flags.
GetKey1: ; wait for interrupt
hlt
GetKey: ; ----------- fn 00h, 10h
mov ah, 11h
int 16h ;See if key is available (IF becomes 1 after this int)
jz short GetKey1 ;Wait for keystroke.
cli ;Critical region! Ints off.
mov si, HeadPtr ;Ptr to next character.
lodsw ;Get the character, Bump up HeadPtr
cmp si, EndBuf
jb short noWrap
mov si, Buffer
noWrap:
mov HeadPtr, si
jmp short Exit
TestKey: ; ---------- fn 01h
mov si, HeadPtr
cmp si, TailPtr ;ZF=1, if empty buffer
lodsw ;BIOS returns avail keycode.
sti ;Ints back on.
pop si
pop ds
retf 2 ;Pop flags (ZF is important!)
StoreKey: ; ---------- fn 05h - Inserts the value in CX into the type ahead buffer.
mov si, TailPtr ;Address where we can put next key code.
mov [si], cx ;Store the key code away
inc si
inc si ;Move on to next entry in buf
cmp si, EndBuf
jb short NoWrap1
mov si, Buffer
NoWrap1:
mov al, 1 ;no room
cmp si, HeadPtr ;Data overrun?
je short Exit ;if so, ignore key entry.
mov TailPtr, si
dec ax ;al=0
jmp short Exit
ExtStatus: ; ------- fn 12h - Retrieve the extended keyboard status and return it in AH, and the standard keyboard status in AL.
mov al, KbdFlags2
and al, 01110111b ;Clear final sysreq field, and final right alt bit.
test al, 100b ;Test cur sysreq bit.
jz short NoSysReq ;Skip if it's zero.
sub al, 10000100b ;Set final sysreq bit, clear final right ctl bit.
NoSysReq:
mov ah, KbdFlags3
and ah, 1100b ;Grab rt alt/ctrl bits.
or ah, al ;Merge into AH.
GetStatus: ; --------- fn 02h
mov al, KbdFlags1 ;Just return Std Status.
Exit1:
jmp short Exit
SetAutoRpt: ; ------ fn 03h
cmp ah, 5
jne short Exit
push dx
shl bh, 5
and bl, 1fh
or bl, bh
and bl, 7fh
mov ah, 0 ; wait LED update progress to finalize
call WaitFlag ; leaves with IF=0
jc short timeout
or byte ptr KbdFlags4, SetRepeat ; set auto repeat in progress
mov ah, 0f3h ; set typematic rate and delay
push bx
xor bl, bl ; send to kb
call sendps2byte
pop bx
jc short timeout1 ; send timeout
mov ah, SetRepeat or AckReceived ; test if ACK received
call WaitFlag
jc short timeout1
mov ah, bl
xor bl, bl ; send to kb
call sendps2byte ; send data
timeout1:
and byte ptr KbdFlags4, not SetRepeat
timeout:
pop dx
jmp short Exit1
WaitFlag: ; ah = desired KbdFlags4 & (AckReceived | LEDUpdate | SetRepeat)
mov dx, 3dah
mov bh, 8*25 ; wait for max 25 * VGA frame time
wf_loop:
cli
mov al, KbdFlags4
and al, AckReceived or LEDUpdate or SetRepeat
cmp al, ah
je short wf_ok ; flag ok, CF=0
sti
in al, dx ; get vblank
xor al, bh
and al, 8h
sub bh, al
jnc short wf_loop ; IBF - buffer full, no timeout
wf_ok:
ret
int16 endp
; --------------------- INT 18h - BIOS Basic ------------------
int18 proc near
push cs
pop es
mov si, offset booterrmsg
call prts
call flush
;-------------- RS232 bootstrap
mov al, 0b4h
out 43h, al
mov ax, 0f000h
out 42h, al
out 42h, al ; 18Hz PIT CH2
out 1, ax ; disable auto flush on vblank (bit0)
mov ds,ax
mov es,ax
mov si,100h
call srecb
cli
mov bh,ah
call srecb
mov bl,ah
sloop:
call srecb
mov [si],ah
inc si
dec bx
jnz short sloop
db 0eah
dw 100h,0f000h
booterrmsg db 'No boot device available, waiting on RS232 (115200bps, f000:100) ...', 13, 10, 0
int18 endp
; --------------------- INT 19h - OS Bootstrap loader ------------------
int19 proc near
mov ax, 201h
mov cx, 1
mov dx, 80h
push 0
pop es
mov bx, 7c00h
int 13h
jc int19err
db 0eah
dw 7c00h, 0 ; jmp far 0000h:7c00h
int19err:
int 18h
int19 endp
; --------------------- INT 1ah - Get System Time ------------------
int1a proc near
push ds
push 40h
pop ds
cmp ah, 1
ja clockexit
je setclock
mov dx, ds:[6ch] ; read clock
mov cx, ds:[6eh]
mov al, ds:[70h]
clockexit1:
mov byte ptr ds:[70h], 0
clockexit:
cmc ; CF = 1 on error
pop ds
sti
retf 2
setclock:
mov ds:[6ch], dx
mov ds:[6eh], cx
stc
jmp short clockexit1
int1a endp
; --------------------- INT 70h - RTC ------------------
int70 proc near
push ds
push 40h
pop ds
test byte ptr UWaitFlag, 1 ; is wait in progress?
jz short exit
sub word ptr WaitCount[0], 1000
sbb word ptr WaitCount[2], 0
jnc short exit
mov byte ptr UWaitFlag, 0
push bx
lds bx, UFPtr
or byte ptr [bx], 80h
pop bx
exit:
pop ds
iret
int70 endp
; --------------------- INT 74h - mouse ------------------
int74 proc near
cld
pusha
push ds
push 40h
pop ds
mov ah, 0
in al, 60h
mov bx, ax
inc byte ptr DataCounter
mov al, DataCounter
mov si, ax
sub al, 3
ja short docall
mov DataBuffer[si-1], bl
cmp al, PacketSize
jne short nocall
mov bl, 0
docall:
mov byte ptr DataCounter, bh ; BH=0
mov si, offset DataBuffer-2
lodsw
or ax, [si-4]
jz short nocall
sti
push es
mov ah, 0
lodsb
push ax
lodsb
push ax
lodsb
push ax
push bx
call far ptr [si-7]
add sp, 8
pop es
nocall:
pop ds
popa
iret
int74 endp
; ---------------- serial receive byte 115200 bps --------------
srecb: mov ah, 80h
mov dx, 3dah
mov cx, -5aeh ; (half start bit)
srstb: in al, dx
shr al, 2
jc short srstb
in al, 42h ; lo counter
add ch, al
in al, 42h ; hi counter, ignore
l1:
call dlybit
in al, dx
shr al, 2
rcr ah, 1
jnc short l1
dlybit:
sub cx, 0a5bh ; (full bit)
dly1:
in al, 42h
cmp al, ch
in al, 42h
jnz short dly1
ret
; -------------------- KB/Mouse access ----------------
sendps2byte proc near ; ah=data, bl!=0 for mouse, 0 for kb. returns cf=1 if timeout (al = 8)
; changes BH, AL
push dx
mov dx, 3dah
mov bh, 8*5
sps2b2:
in al, 64h
test al, 2
jz short sps2b1; buffer empty
in al, dx ; get vblank
xor al, bh
and al, 8h
sub bh, al
jnc short sps2b2; IBF - buffer full, no timeout
jmp short exit ; timeout, CF=1
sps2b1:
test bl, bl ; CF=0
jz short sps2_kb
mov al, 0d4h ; next mouse
out 64h, al
sps2_kb:
mov al, ah
out 60h, al ; send byte
exit:
pop dx
ret
sendps2byte endp
getps2byte proc near ; returns al=data, zf=0 for mouse, 1 for kb, cf=1 if timeout (al=8)
; changes BH, DX, AL
mov dx, 3dah
mov bh, 8*5
gps2b2:
in al, 64h
test al, 1
jnz short gps2b1 ; OBF (buffer full), continue
in al, dx ; get vblank
xor al, bh
and al, 8
sub bh, al
jnc short gps2b2 ; buffer empty, no timeout
ret ; timeout, CF=1
gps2b1:
test al, 20h ; CF=0, ZF <- !MOBF
in al, 60h ; read byte (if IF=1, this data may be invalid)
ret
getps2byte endp
sendcmd proc near ; ah = command, CF=1 for mouse, CF=0 for kb. returns CF=1 on error
sbb bl, bl ; bl <- CF
call sendps2byte
jc short exit
retry:
call getps2byte
jc short exit
cmp al, 0fah ; ack (returns CF=1 on error, when al=8)
jne short retry
exit:
ret
sendcmd endp
enableKbIfPresent proc near ; input DS = 40h
; modify AL, flags
test byte ptr KbdFlags3, 10h
jz short noenablekb
mov al, 0aeh
out 64h, al ; enable kb interface
noenablekb:
ret
enableKbIfPresent endp
; ----------------------- default interrupt handler ---------------
defint proc near
iret
defint endp
; ------------------------------- flush --------------------------
flush:
pop cs:flushret
flush_nostack:
mov cs:flushbh, bh
mov bh, 64 ; flush all cache lines
flush1:
test bl, cs:[bx + 0bf00h]
dec bh
jnz short flush1
mov bh, cs:flushbh
jmp word ptr cs:flushret
flushret dw 0
flushbh db 0
; ------------------------------- misc --------------------------
dispAX:
push dx
xor dx, dx
div word ptr cs:ten
test ax, ax
jz dispAX1
call dispAX
dispAX1:
xchg ax, dx
add ax, 0e00h + '0'
int 10h
pop dx
ret
ten dw 10
prts: ; es:si = string
mov ah, 0eh
lodsb es:[si]
or al, al
jz short prtse
int 10h
jmp short prts
prtse:
ret
;--------------------- read/write byte ----------------------
sdrb: mov al,0ffh
sdsb: ; in AL=byte, DX = 03dah, out AX=result
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
in ax, dx
ret
;--------------------- write block ----------------------
sdwblk proc near ; in SI=data ptr, DX=03dah, CX=size
shr cx, 1
sdwblk1:
lodsb
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
lodsb
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
add ax, ax
out dx, al
loop short sdwblk1
ret
sdwblk endp
;--------------------- read block ----------------------
sdrblk proc near ; in DI=data ptr, DX=03dah, CX=size. Returns CF = 0
mov al, 0ffh
out dx, al
shr cx, 1 ; CF = 0
out dx, al
jmp short sdrblk2
sdrblk1:
out dx, al
mov [di], ah
out dx, al
inc di
sdrblk2:
out dx, al
nop
out dx, al
nop
out dx, al
nop
out dx, al
nop
out dx, al
nop
out dx, al
in ax, dx
out dx, al
mov [di], ah
out dx, al
inc di
out dx, al
nop
out dx, al
nop
out dx, al
nop
out dx, al
nop
out dx, al
nop
out dx, al
in ax, dx
loop short sdrblk1
mov [di], ah
inc di
ret
sdrblk endp
;--------------------- verify block ----------------------
sdvblk: ; in DI=data ptr, DX=03dah, CX=size. Returns CF=1 on error
push bx
xor bl, bl
sdvblk1:
call sdrb
sub ah, [di]
or bl, ah
inc di
loop short sdvblk1
neg bl ; CF=1 if BL != 0
pop bx
ret
;--------------------- write command ----------------------
sdcmd8T:
call sdrb
sdcmd: ; in SI=6 bytes cmd buffer, DX=03dah, out AH = 0ffh on error
mov cx, 6
call sdwblk
sdresp:
xor si, si
sdresp1:
call sdrb
inc si
jz short sdcmd1
cmp ah, 0ffh
je short sdresp1
sdcmd1: ret
;--------------------- read ----------------------
sdverify:
push sdvblk
jmp short sdread1
sdread: ; DX:AX sector, ES:BX buffer, CX=sectors. returns AX=read sectors
push sdrblk ; push proc address (read or verify) on stack
sdread1:
push ax
mov al, dl
push ax
mov dl, 51h ; CMD17
cmp cx, 1
je short sdr1s
inc dx ; CMD18 - multiple sectors
sdr1s:
push dx
mov si, sp
mov dx, 3dah
mov ah, 1
out dx, ax ; CS on
mov di, bx
mov bx, cx
mov bp, cx ; save sectors number
push ss
pop ds
mov byte ptr [si+5], 0ffh ; checksum
call sdcmd
add sp, 6
or ah, ah
jnz short sdr11 ; error
push es
pop ds
sdrms:
mov ax, di
shr ax, 4
mov si, ds
add ax, si
mov ds, ax
and di, 15
call sdresp ; wait for 0feh token
cmp ah, 0feh
jne short sdr11; read token error
mov ch, 2 ; 512 byte sector
pop si
call si ; sdrblk or sdvblk
push si
pushf
call sdrb ; ignore CRC
call sdrb ; ignore CRC
popf
jc short sdr3 ; verify error
dec bx
jnz short sdrms; multiple sectors
sdr3:
cmp bp, 1
je short sdr11; single sector
mov si, offset SD_CMD12 ; stop transfer
push cs
pop ds
call sdcmd
sdr2:
shr ah, 1
jnc short sdr11
call sdrb
jmp short sdr2
sdr11:
pop ax ; remove proc address from stack
sdr1:
xor ax, ax
out dx, ax
call sdrb ; 8T
mov ax, bp
sub ax, bx
ret
;--------------------- write ----------------------
sdwrite: ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=wrote sectors
push ax
mov al, dl
push ax
mov dl, 58h ; CMD24
cmp cx, 1
je short sdw1s
inc dx ; CMD25 - multiple sectors
sdw1s:
push dx
mov si, sp
mov dx, 3dah
mov ah, 1
out dx, ax ; CS on
mov bp, cx ; save sectors number
push ss
pop ds
mov byte ptr [si+5], 0ffh ; checksum
call sdcmd
add sp, 6
mov si, bx
mov bx, bp
or ah, ah
jnz short sdr1 ; error
push es
pop ds
sdwms:
mov ax, si
shr ax, 4
mov di, ds
add ax, di
mov ds, ax
and si, 15
mov al, 0feh ; start token
cmp bp, 1
je short sdw1s1
mov al, 0fch ; multiple sectors
sdw1s1:
call sdsb
mov ch, 2 ; 512 byte sector
call sdwblk
call sdrb ; ignore CRC
call sdrb ; ignore CRC
call sdrb ; read response byte xxx00101
and ah, 0eh
cmp ah, 4
jne short sdr1 ; write error
sdwwait:
call sdrb
shr ah, 1
jnc short sdwwait ; wait write completion
dec bx
jnz short sdwms ; multiple sectors
cmp bp, 1
je short sdr1
mov al, 0fdh ; multiple end transfer
call sdsb
call sdrb
sdwwait1:
call sdrb
shr ah, 1
jnc short sdwwait1 ; wait write completion
jmp sdr1
;--------------------- init SD ----------------------
sdinit proc near ; returns AX = num kilosectors
push ds
push cx
push dx
push si
push di
mov dx, 3dah
mov cx, 10
sdinit1: ; send 80T
call sdrb
loop short sdinit1
mov ah, 1
out dx, ax ; select SD
mov si, offset SD_CMD0
push cs
pop ds
call sdcmd
dec ah
jnz short sdexit ; error
mov si, offset SD_CMD8
call sdcmd8T
dec ah
jnz short sdexit ; error
mov cl, 4
sub sp, cx
mov di, sp
push ss
pop ds
call sdrblk
pop ax
pop ax
cmp ah, 0aah
jne short sdexit ; CMD8 error
repinit:
mov si, offset SD_CMD55
push cs
pop ds
call sdcmd8T
call sdrb
mov si, offset SD_CMD41
call sdcmd
dec ah
jz short repinit
mov si, offset SD_CMD58
call sdcmd8T
mov cl, 4
sub sp, cx
mov di, sp
push ss
pop ds
call sdrblk
pop ax
test al, 40h ; test OCR bit 30 (CCS)
pop ax
jz short sdexit; no SDHC
mov si, offset SD_CMD9 ; get size info
push cs
pop ds
call sdcmd8T
or ah, ah
jnz short sdexit
call sdresp ; wait for 0feh token
cmp ah, 0feh
jne short sdexit
mov cl, 18 ; 16bytes + 2bytes CRC
sub sp, cx
mov di, sp
push ss
pop ds
call sdrblk
mov cx, [di-10]
rol cx, 8
inc cx
mov sp, di
sdexit:
xor ax, ax ; raise CS
out dx, ax
call sdrb
pop di
pop si
pop dx
mov ax, cx
pop cx
pop ds
ret
sdinit endp
SD_CMD0 db 40h, 0, 0, 0, 0, 95h
SD_CMD8 db 48h, 0, 0, 1, 0aah, 087h
SD_CMD9 db 49h, 0, 0, 0, 0, 0ffh
SD_CMD12 db 4ch, 0, 0, 0, 0, 0ffh
SD_CMD41 db 69h, 40h, 0, 0, 0, 0ffh
SD_CMD55 db 77h, 0, 0, 0, 0, 0ffh
SD_CMD58 db 7ah, 0, 0, 0, 0, 0ffh
default_pal:
db 00h,00h,00h, 00h,00h,2ah, 00h,2ah,00h, 00h,2ah,2ah, 2ah,00h,00h, 2ah,00h,2ah, 2ah,15h,00h, 2ah,2ah,2ah
db 15h,15h,15h, 15h,15h,3fh, 15h,3fh,15h, 15h,3fh,3fh, 3fh,15h,15h, 3fh,15h,3fh, 3fh,3fh,15h, 3fh,3fh,3fh
db 00h,00h,00h, 05h,05h,05h, 08h,08h,08h, 0bh,0bh,0bh, 0eh,0eh,0eh, 11h,11h,11h, 14h,14h,14h, 18h,18h,18h
db 1ch,1ch,1ch, 20h,20h,20h, 24h,24h,24h, 28h,28h,28h, 2dh,2dh,2dh, 32h,32h,32h, 38h,38h,38h, 3fh,3fh,3fh
db 00h,00h,3fh, 10h,00h,3fh, 1fh,00h,3fh, 2fh,00h,3fh, 3fh,00h,3fh, 3fh,00h,2fh, 3fh,00h,1fh, 3fh,00h,10h
db 3fh,00h,00h, 3fh,10h,00h, 3fh,1fh,00h, 3fh,2fh,00h, 3fh,3fh,00h, 2fh,3fh,00h, 1fh,3fh,00h, 10h,3fh,00h
db 00h,3fh,00h, 00h,3fh,10h, 00h,3fh,1fh, 00h,3fh,2fh, 00h,3fh,3fh, 00h,2fh,3fh, 00h,1fh,3fh, 00h,10h,3fh
db 1fh,1fh,3fh, 27h,1fh,3fh, 2fh,1fh,3fh, 37h,1fh,3fh, 3fh,1fh,3fh, 3fh,1fh,37h, 3fh,1fh,2fh, 3fh,1fh,27h
db 3fh,1fh,1fh, 3fh,27h,1fh, 3fh,2fh,1fh, 3fh,37h,1fh, 3fh,3fh,1fh, 37h,3fh,1fh, 2fh,3fh,1fh, 27h,3fh,1fh
db 1fh,3fh,1fh, 1fh,3fh,27h, 1fh,3fh,2fh, 1fh,3fh,37h, 1fh,3fh,3fh, 1fh,37h,3fh, 1fh,2fh,3fh, 1fh,27h,3fh
db 2dh,2dh,3fh, 31h,2dh,3fh, 36h,2dh,3fh, 3ah,2dh,3fh, 3fh,2dh,3fh, 3fh,2dh,3ah, 3fh,2dh,36h, 3fh,2dh,31h
db 3fh,2dh,2dh, 3fh,31h,2dh, 3fh,36h,2dh, 3fh,3ah,2dh, 3fh,3fh,2dh, 3ah,3fh,2dh, 36h,3fh,2dh, 31h,3fh,2dh
db 2dh,3fh,2dh, 2dh,3fh,31h, 2dh,3fh,36h, 2dh,3fh,3ah, 2dh,3fh,3fh, 2dh,3ah,3fh, 2dh,36h,3fh, 2dh,31h,3fh
db 00h,00h,1ch, 07h,00h,1ch, 0eh,00h,1ch, 15h,00h,1ch, 1ch,00h,1ch, 1ch,00h,15h, 1ch,00h,0eh, 1ch,00h,07h
db 1ch,00h,00h, 1ch,07h,00h, 1ch,0eh,00h, 1ch,15h,00h, 1ch,1ch,00h, 15h,1ch,00h, 0eh,1ch,00h, 07h,1ch,00h
db 00h,1ch,00h, 00h,1ch,07h, 00h,1ch,0eh, 00h,1ch,15h, 00h,1ch,1ch, 00h,15h,1ch, 00h,0eh,1ch, 00h,07h,1ch
db 0eh,0eh,1ch, 11h,0eh,1ch, 15h,0eh,1ch, 18h,0eh,1ch, 1ch,0eh,1ch, 1ch,0eh,18h, 1ch,0eh,15h, 1ch,0eh,11h
db 1ch,0eh,0eh, 1ch,11h,0eh, 1ch,15h,0eh, 1ch,18h,0eh, 1ch,1ch,0eh, 18h,1ch,0eh, 15h,1ch,0eh, 11h,1ch,0eh
db 0eh,1ch,0eh, 0eh,1ch,11h, 0eh,1ch,15h, 0eh,1ch,18h, 0eh,1ch,1ch, 0eh,18h,1ch, 0eh,15h,1ch, 0eh,11h,1ch
db 14h,14h,1ch, 16h,14h,1ch, 18h,14h,1ch, 1ah,14h,1ch, 1ch,14h,1ch, 1ch,14h,1ah, 1ch,14h,18h, 1ch,14h,16h
db 1ch,14h,14h, 1ch,16h,14h, 1ch,18h,14h, 1ch,1ah,14h, 1ch,1ch,14h, 1ah,1ch,14h, 18h,1ch,14h, 16h,1ch,14h
db 14h,1ch,14h, 14h,1ch,16h, 14h,1ch,18h, 14h,1ch,1ah, 14h,1ch,1ch, 14h,1ah,1ch, 14h,18h,1ch, 14h,16h,1ch
db 00h,00h,10h, 04h,00h,10h, 08h,00h,10h, 0ch,00h,10h, 10h,00h,10h, 10h,00h,0ch, 10h,00h,08h, 10h,00h,04h
db 10h,00h,00h, 10h,04h,00h, 10h,08h,00h, 10h,0ch,00h, 10h,10h,00h, 0ch,10h,00h, 08h,10h,00h, 04h,10h,00h
db 00h,10h,00h, 00h,10h,04h, 00h,10h,08h, 00h,10h,0ch, 00h,10h,10h, 00h,0ch,10h, 00h,08h,10h, 00h,04h,10h
db 08h,08h,10h, 0ah,08h,10h, 0ch,08h,10h, 0eh,08h,10h, 10h,08h,10h, 10h,08h,0eh, 10h,08h,0ch, 10h,08h,0ah
db 10h,08h,08h, 10h,0ah,08h, 10h,0ch,08h, 10h,0eh,08h, 10h,10h,08h, 0eh,10h,08h, 0ch,10h,08h, 0ah,10h,08h
db 08h,10h,08h, 08h,10h,0ah, 08h,10h,0ch, 08h,10h,0eh, 08h,10h,10h, 08h,0eh,10h, 08h,0ch,10h, 08h,0ah,10h
db 0bh,0bh,10h, 0ch,0bh,10h, 0dh,0bh,10h, 0fh,0bh,10h, 10h,0bh,10h, 10h,0bh,0fh, 10h,0bh,0dh, 10h,0bh,0ch
db 10h,0bh,0bh, 10h,0ch,0bh, 10h,0dh,0bh, 10h,0fh,0bh, 10h,10h,0bh, 0fh,10h,0bh, 0dh,10h,0bh, 0ch,10h,0bh
db 0bh,10h,0bh, 0bh,10h,0ch, 0bh,10h,0dh, 0bh,10h,0fh, 0bh,10h,10h, 0bh,0fh,10h, 0bh,0dh,10h, 0bh,0ch,10h
db 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h
IFDEF SCANCODE1 ; use SCANCODE1
KeyIndex:
db 0, 82, 49, 50, 52, 51, 54, 55 ;0-7
db 56, 57, 60, 59, 65, 68, 72, 47 ;8-f
db 1, 5, 9, 13, 12, 18, 21, 23 ;10-17
db 24, 26, 67, 70, 69, 0, 4, 3 ;18-1f
db 8, 11, 17, 16, 20, 22, 25, 64 ;20-27
db 66, 48, 0, 71, 2, 7, 6, 10 ;28-2f
db 15, 14, 19, 58, 61, 62, 0, 87 ;30-37
db 0, 53, 0, 40, 41, 39, 46, 38 ;38-3f
db 45, 90, 44, 79, 43, 0, 89, 29 ;40-47
db 34, 36, 86, 28, 37, 33, 84, 27 ;48-4f
db 32, 35, 30, 31, 0, 0, 0, 83 ;50-57
db 42
E0KeyList:
db 35h, 1ch, 4fh, 4bh, 47h, 52h, 53h, 50h, 4dh, 48h, 51h, 49h
ELSE ; use SCANCODE2
KeyIndex:
db 0, 79, 0, 38, 39, 40, 41, 42
db 0, 43, 44, 45, 46, 47, 48, 0
db 0, 0, 0, 0, 0, 1, 49, 0
db 0, 0, 2, 3, 4, 5, 50, 0
db 0, 6, 7, 8, 9, 51, 52, 0
db 0, 53, 10, 11, 12, 13, 54, 0
db 0, 14, 15, 16, 17, 18, 55, 0
db 0, 0, 19, 20, 21, 56, 57, 0
db 0, 58, 22, 23, 24, 59, 60, 0
db 0, 61, 62, 25, 64, 26, 65, 0
db 0, 0, 66, 0, 67, 68, 0, 0
db 0, 0, 69, 70, 0, 71, 0, 0
db 0, 0, 0, 0, 0, 0, 72, 0
db 0, 27, 0, 28, 29, 0, 0, 0
db 30, 31, 32, 37, 33, 34, 82, 0
db 83, 84, 35, 86, 87, 36, 89, 0
db 0, 0, 0, 90
E0KeyList:
db 4ah, 5ah, 69h, 6bh, 6ch, 70h, 71h, 72h, 74h, 75h, 7ah, 7dh
ENDIF
E0KeyIndex:
db 63, 69, 73, 74, 75, 76, 77, 78, 80, 81, 85, 88
KeyCode:
; Keys affected by CapsLock
; norm shft ctrl alt
dw 0000h, 0000h, 0000h, 0000h ;17 - <0>
dw 1071h, 1051h, 1011h, 1000h ;15 - Q, (E0)PrevTrack <1>
dw 2c7ah, 2c5ah, 2c1ah, 2c00h ;1a - Z <2>
dw 1f73h, 1f53h, 1f13h, 1f00h ;1b - S <3>
dw 1e61h, 1e41h, 1e01h, 1e00h ;1c - A <4>
dw 1177h, 1157h, 1117h, 1100h ;1d - W <5>
dw 2e63h, 2e43h, 2e03h, 2e00h ;21 - C, (E0)Volume Down <6>
dw 2d78h, 2d58h, 2d18h, 2d00h ;22 - X <7>
dw 2064h, 2044h, 2004h, 2000h ;23 - D, (E0)Mute <8>
dw 1265h, 1245h, 1205h, 1200h ;24 - E <9>
dw 2f76h, 2f56h, 2f16h, 2f00h ;2a - V <10>
dw 2166h, 2146h, 2106h, 2100h ;2b - F, (E0)Calculator <11>
dw 1474h, 1454h, 1414h, 1400h ;2c - T <12>
dw 1372h, 1352h, 1312h, 1300h ;2d - R <13>
dw 316eh, 314eh, 310eh, 3100h ;31 - N <14>
dw 3062h, 3042h, 3002h, 3000h ;32 - B, (E0)Volume Up <15>
dw 2368h, 2348h, 2308h, 2300h ;33 - H <16>
dw 2267h, 2247h, 2207h, 2200h ;34 - G, (E0)Play/Pause <17>
dw 1579h, 1559h, 1519h, 1500h ;35 - Y <18>
dw 326dh, 324dh, 320dh, 3200h ;3a - M, (E0)WWW Home <19>
dw 246ah, 244ah, 240ah, 2400h ;3b - J, (E0)Stop <20>
dw 1675h, 1655h, 1615h, 1600h ;3c - U <21>
dw 256bh, 254bh, 250bh, 2500h ;42 - K <22>
dw 1769h, 1749h, 1709h, 1700h ;43 - I <23>
dw 186fh, 184fh, 180fh, 1800h ;44 - O <24>
dw 266ch, 264ch, 260ch, 2600h ;4b - L <25>
dw 1970h, 1950h, 1910h, 1900h ;4d - P, (E0)Next Track <26>
; keys affected by NumLock
dw 4f00h, 4f31h, 7500h, 0002h ;69 - KP1 <27>
dw 4b00h, 4b34h, 7300h, 0005h ;6b - KP4 <28>
dw 4700h, 4737h, 7700h, 0008h ;6c - KP7 <29>
dw 5200h, 5230h, 9200h, 0001h ;70 - KP0 <30>
dw 5300h, 532eh, 9300h, 0000h ;71 - KP. <31>
dw 5000h, 5032h, 9100h, 0003h ;72 - KP2 <32>
dw 4d00h, 4d36h, 7400h, 0007h ;74 - KP6 <33>
dw 4800h, 4838h, 8d00h, 0009h ;75 - KP8 <34>
dw 5100h, 5133h, 7600h, 0004h ;7a - KP3 <35>
dw 4900h, 4939h, 8400h, 000ah ;7d - KP9 <36>
dw 4c00h, 4c35h, 8f00h, 0006h ;73 - KP5 --- on VMWare, it does not send 4c00 <37>
; keys unaffected by CapsLock or N
dw 3f00h, 5800h, 6200h, 6c00h ;03 - F5 <38>
dw 3d00h, 5600h, 6000h, 6a00h ;04 - F3 <39>
dw 3b00h, 5400h, 5e00h, 6800h ;05 - F1 <40>
dw 3c00h, 5500h, 5f00h, 6900h ;06 - F2 <41>
dw 8600h, 8800h, 8a00h, 8c00h ;07 - F12 <42>
dw 4400h, 5d00h, 6700h, 7100h ;09 - F10 <43>
dw 4200h, 5b00h, 6500h, 6f00h ;0a - F8 <44>
dw 4000h, 5900h, 6300h, 6d00h ;0b - F6 <45>
dw 3e00h, 5700h, 6100h, 6b00h ;0c - F4 <46>
dw 0f09h, 0f00h, 9400h, 0000h ;0d - TAB <47>
dw 2960h, 297eh, 0000h, 2900h ;0e - ` ~ <48>
dw 0231h, 0221h, 0000h, 7800h ;16 - 1 ! <49>
dw 0332h, 0340h, 0300h, 7900h ;1e - 2 @ <50>
dw 0534h, 0524h, 0000h, 7b00h ;25 - 4 $ <51>
dw 0433h, 0423h, 0000h, 7a00h ;26 - 3 # <52>
dw 3920h, 3920h, 3920h, 3920h ;29 - SPC <53>
dw 0635h, 0625h, 0000h, 7c00h ;2e - 5 % <54>
dw 0736h, 075eh, 071eh, 7d00h ;36 - 6 ^ <55>
dw 0837h, 0826h, 0000h, 7e00h ;3d - 7 & <56>
dw 0938h, 092ah, 0000h, 7f00h ;3e - 8 * <57>
dw 332ch, 333ch, 0000h, 3300h ;41 - , < <58>
dw 0b30h, 0b29h, 0000h, 8100h ;45 - 0 ) <59>
dw 0a39h, 0a28h, 0000h, 8000h ;46 - 9 ( <60>
dw 342eh, 343eh, 0000h, 3400h ;49 - . > <61>
dw 352fh, 353fh, 0000h, 3500h ;4a - / ? <62>
dw 0e02fh, 0e02fh, 9500h, 0a400h ;4a - (e0)KP/ <63>
dw 273bh, 273ah, 0000h, 2700h ;4c - ; : <64>
dw 0c2dh, 0c5fh, 0c1fh, 8200h ;4e - - _ <65>
dw 1a5bh, 1a7bh, 1a1bh, 1a00h ;54 - [ { <67>
dw 0d3dh, 0d2bh, 0000h, 8300h ;55 - = + <68>
dw 1c0dh, 1c0dh, 1c0ah, 1c00h ;5a - Enter, (E0)KPEnter <69>
dw 1b5dh, 1b7dh, 1b1dh, 1b00h ;5b - ] } <70>
dw 2b5ch, 2b7ch, 2b1ch, 2b00h ;5d - \ | <71>
dw 0e08h, 0e08h, 0e7fh, 0e00h ;66 - BKSP <72>
dw 4f00h, 4f00h, 7500h, 9f00h ;69 - (E0)END <73>
dw 4b00h, 4b00h, 7300h, 9b00h ;6b - (E0)LEFT <74>
dw 4700h, 4700h, 7700h, 9700h ;6c - (E0)HOME <75>
dw 5200h, 5200h, 9200h, 0a200h ;70 - (E0)INS <76>
dw 5300h, 5300h, 9300h, 0a300h ;71 - (E0)DEL <77>
dw 5000h, 5000h, 9100h, 0a000h ;72 - (E0)DOWN <78>
dw 4300h, 5c00h, 6600h, 7000h ;01 - F9 <79>
dw 4d00h, 4d00h, 7400h, 9d00h ;74 - (E0)RIGHT <80>
dw 4800h, 4800h, 8d00h, 9800h ;75 - (E0)UP <81>
dw 011bh, 011bh, 011bh, 0100h ;76 - ESC <82>
dw 8500h, 8700h, 8900h, 8b00h ;78 - F11 <83>
dw 4e2bh, 4e2bh, 9000h, 4e00h ;79 - KP+ <84>
dw 5100h, 5100h, 7600h, 0a100h ;7a - (E0)PGDN <85>
dw 4a2dh, 4a2dh, 8e00h, 4a00h ;7b - KP- <86>
dw 372ah, 372ah, 9600h, 3700h ;7c - KP* --- on VMWare, it does not send 3710h with CTL <87>
dw 4900h, 4900h, 8400h, 9900h ;7d - (E0)PGUP <88>
dw 4600h, 4600h, 4600h, 4600h ;7e - SCRL <89>
dw 4100h, 5a00h, 6400h, 6e00h ;83 - F7 <90>
; ------------------------- POWER ON RESET -----------------------
org 0fff0h
db 0eah
dw coldboot, 0f000h
db '17/03/14'
db 0ffh, 0ffh, 0
end bios