URL
https://opencores.org/ocsvn/next186_soc_pc/next186_soc_pc/trunk
Subversion Repositories next186_soc_pc
[/] [next186_soc_pc/] [trunk/] [SW/] [BIOS_Next186/] [BIOS_Next186.asm] - Rev 7
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.codeSCANCODE1 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 15000horg 0e000hbios:biosmsg db 'Next186 Spartan3AN SoC PC BIOS (C) 2013 Nicolae Dumitrache', 0msgmb db 'MB SD Card', 13, 10, 0msgkb db 'PS2 KB detected', 13, 10, 0; Graphics character setfont8x8: ; TODO define and place fontfont8x16: ; TODO define and place fontorg 0e05bhcoldboot:warmboot:clicldmov ax, 30hmov ss, axmov sp, 100hpush 0popfmov al, 36hout 43h, alxor ax, axout 40h, alout 40h, al ; 18Hz PIT CH0out 61h, al ; speaker offnot alout 21h, al ; disable all interrupts; ------------------ MAP initcall flushmov ax, 15h ; BIOS physical segment 15h mapped on virtual segment 0chout 8ch, axpush 0c000hpop espush 0f000hpop dsxor si, sixor di, dimov cx, 8000hrep movsw ; copy BIOS virtual segment 0fh over physical segment 15hcall flushmov dx, 80hxor ax, axmapi:out dx, axinc axinc dxcmp al, 0chjne short mapi1add al, 6mapi1:cmp al, 16hjne short mapi; -------------------- Interrupt table initpush 0pop dspush dspop esxor si, simov di, 4mov word ptr [si], offset defintmov word ptr [si+2], csmov cx, 256-2rep movswmov word ptr ds:[7*4], offset int07mov word ptr ds:[8*4], offset int08mov word ptr ds:[9*4], offset int09mov word ptr ds:[10h*4], offset int10mov word ptr ds:[11h*4], offset int11mov word ptr ds:[12h*4], offset int12mov word ptr ds:[13h*4], offset int13mov word ptr ds:[15h*4], offset int15mov word ptr ds:[16h*4], offset int16mov word ptr ds:[18h*4], offset int18mov word ptr ds:[19h*4], offset int19mov word ptr ds:[1ah*4], offset int1amov word ptr ds:[70h*4], offset int70mov word ptr ds:[74h*4], offset int74; ------------------- BDA initpush 40hpop dspush dspop esxor di, dixor si, sixor ax, axmov cl, 80hrep stoswmov byte ptr [si+10h], 24h ; equipment word (color 80x25, PS2 mouse present)mov word ptr [si+13h], 640 ; memory size in KBadd word ptr [si+1ah], 1eh ; next char pointer in kb bufferadd word ptr [si+1ch], 1eh ; last char pointer in kb buffermov word ptr [si+60h], 0e0fh ; cursor shapemov word ptr [si+63h], 3d4h ; video port addressadd word ptr [si+80h], 1eh ; start kb bufferadd word ptr [si+82h], 3eh ; end kb buffermov 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 onmov byte ptr [si+96h], 10h ; 101 keyboard installed; ------------------- Graph mode initmov ax, 3int 10h; ------------------- KB init ----------------mov al, 0aehout 64h, al ; enable kbmov al, 0a7hout 64h, al ; disable mousemov cx, 25kbi1:call getps2byteloop short kbi1 ; wait for kb timeoutmov ah, 0ffh ; reset kbclc ; kb commandcall sendcmdjc short nokbmov cl, 25kbi2:dec cxjcxz short nokbcall getps2bytejc short kbi2 ; wait for BATcmp al, 0aahjne short nokbmov ah, 0f2h ; kb idcall sendcmd ; CF = 0jc short nokbcall getps2bytecmp al, 0abhjne short nokbcall getps2bytecmp al, 83h; set scan code 1IFDEF SCANCODE1jne short nokbmov ah, 0f0h ; kb scan setcall sendcmdjc short nokbmov ah, 1 ; scan set 1call sendcmdjnc short kbokELSEje short kbokENDIFnokb:mov byte ptr KbdFlags3, 0 ; kb not presentkbok:mov al, 0adhout 64h, al ; disable kb interface; ------------------- Mouse init ----------------mov al, 0a8hout 64h, al ; enable mousemousei0:call getps2bytejnc short mousei0mov ah, 0ffhcall sendcmd ; reset mouse (CF = 1)jc short nomousemov cl, 25mousei1:dec cxjcxz short nomousecall getps2bytejc short mousei1cmp al, 0aah ; BATjne short nomousecall getps2bytecmp al, 0 ; mouse IDje short mouseoknomouse:mov al, 0a7hout 64h, al ; disable mouseand byte ptr EquipmentWord, not 4 ; ps2 mouse not present in equipement wordmouseok:call enableKbIfPresentmov al, 20hout 64h, alin al, 60hor al, 3mov ah, almov al, 60hout 64h, almov al, ahout 60h, al ; enable 8042 mouse and kb interruptsmov ax,1000-1 ; 1msout 70h, ax ; set RTC frequencymov al, 0e4hout 21h, al ; enable all PIC interrupts (8h, 9h, 70h, 74h)sti ; enable CPU interrupts; --------------------- HDD initcall sdinitmov HDSize, axpush cspop esmov si, offset biosmsgcall prtsmov si, offset bioscontcall prtsmov ax, HDSizeshr ax, 1call dispAXmov si, offset msgmbcall prtstest byte ptr KbdFlags3, 10hjz nokbmsgmov si, offset msgkbcall prtsnokbmsg:test byte ptr EquipmentWord, 4jz nomousemsgmov si, offset msgmousecall prtsnomousemsg:;-------------- HD bootstrapmov ax, 305hxor bx, bxint 16h ; set typematic rate and delay to fastestint 19hmsgmouse db 'PS2 Mouse detected', 13, 10, 0bioscont db 13, 10, 'CPU: 80186 33Mhz (33MIPS, 66Mhz 32bit bus)', 13, 10db 'RAM: 64MB DDR2 133Mhz', 13, 10db 'Cache: 8x256 bytes data/inst', 13, 10db 'HD0: ', 0; ---------------------------- INT 07 ---------------------int07 proc near ; coprocessor ESC sequencepush axpush bxpush dspush bpmov bp, splds bx, [bp+8]int07_pfx:mov al, [bx]inc bxand al, 0f8hcmp al, 0d8h ; ESC codejne short int07_pfxcmp byte ptr [bx], 0c0h ; mod reg r/m of ESC 8087 instructionsbb al, aland al, [bx]and ax, 0c7hcmp al, 6jne int072mov al, 80hint072:shr al, 6inc axadd ax, bxmov [bp+8], axpop bppop dspop bxpop axiretint07 endp; ---------------------------- INT 08 ---------------------int08 proc nearpush dspush bxpush 40hpop dsmov bx, 6chadd word ptr [bx], 1adc word ptr [bx+2], 0cmp word ptr [bx+2], 18hjne short int081cmp word ptr [bx], 0b0hjne short int081mov word ptr [bx], 0mov word ptr [bx+2], 0mov byte ptr [bx+4], 1int081:int 1chstipush axmov ah, 4kloop:in al, 64htest al, 1jz short nokeydec ahjnz short klooptest al, 20hjz short kbdataint 74hjmp short nokeykbdata:int 9hnokey:pop axpop bxpop dsiretint08 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 KbdFlags1RShfDown equ 1LShfDown equ 2CtrlDown equ 4AltDown equ 8ScrLock equ 10hNumLock equ 20hCapsLock equ 40hInsert equ 80h; Bits for the KbdFlags2LCtrDown equ 1LAltDown equ 2SysReqDown equ 4Pause equ 8ScrLockDown equ 10hNumLockDown equ 20hCapsLockDown equ 40hInsDown equ 80h; Bits for the KbdFlags3LastE1 equ 1LastE0 equ 2RCtrDown equ 4RAltDown equ 8LastF0 equ 20h; Bits for the KbdFlags4ScrLockLED equ 1NumLockLED equ 2CapsLockLED equ 4SetRepeat equ 8 ; Set auto repeat command in progressAckReceived equ 10hLEDUpdate equ 40hIFDEF SCANCODE1int09 proc nearpushapush dspush espush 40hpop dsin al, 60h ; al contains the scan codemov dx, KbdFlags1mov cx, KbdFlags3cmp al, 0fah ; ACKjne short noACK; ------------ manage ACK responsetest ch, LEDUpdatejz short ToggleACK ; no LED updatetest ch, AckReceivedjnz short SecondACK ; second ACK receivedmov ah, ch ; LED update command sent, ACK received, need to send second byteand ah, ScrLockLED or NumLockLED or CapsLockLEDmov bl, 0call sendps2bytejmp short ToggleACKSecondACK:xor ch, LEDUpdate ; second ACK, clear LED update bitToggleACK:xor ch, AckReceived ; toggle ACK bitSetFlags1:jmp SetFlags; ------------ no ACKnoACK:mov ah,4fhstcint 15hjnc int09Exitcmp al, 0e0hjne short noE0or cl, LastE0jmp short SetFlags1noE0:cmp al, 0e1hjne short noE1or cl, LastE1jmp short SetFlags1noE1:cmp al, 53h ; is DEL?jne short noDELmov ah, dland ah, CtrlDown or AltDowncmp ah, CtrlDown or AltDownjne NormalKey ; is DEL, but no CTRL+ALt+DELmov word ptr ds:[72h], 1234h ; warm boot flagdb 0eahdw 0, 0ffffh ; rebootnoDEL:test cl, LastE0jnz short noRSUp ; ignore fake shiftscmp al, 2ah ; left shiftjne short noLSDownor dl, LShfDownjmp short SetFlagsKey2noLSDown:cmp al, 2ah or 80hjne short noLSUpand dl, not LShfDownjmp short SetFlagsKey2noLSUp:cmp al, 36h ; right shiftjne short noRSDownor dl, RShfDownjmp short SetFlagsKey2noRSDown:cmp al, 36h or 80hjne short noRSUPand dl, not RShfDownjmp short SetFlagsKey2noRSUp:cmp al, 38h ; ALTjne short noALTDowntest cl, LastE0jz short LALTDnor cl, RAltDownor dl, AltDownjmp short SetFlagsKey2LALTDn:or dx, (LAltDown shl 8) or AltDownjmp short SetFlagsKey2noALTDown:cmp al, 38h or 80hjne short noALTUptest cl, LastE0jz short LALTUpand cl, not RAltDownand dl, not AltDownjmp short ALTupLALTUp:and dx, not ((LAltDown shl 8) or AltDown)ALTUp:xor ax, axxchg al, AltKpdtest al, aljz short SetFlagsKey2jmp pushKeynoALTUp:cmp al, 1dh ; CTLjne short noCTLDowntest cl, lastE0jz short LCTLDnor cl, RCtrDownor dl, CtrlDownSetFlagsKey2:jmp short SetFlagsKey1LCTLDn:or dx, (LCtrDown shl 8) or CtrlDownjmp short SetFlagsKey1noCTLDown:cmp al, 1dh or 80hjne short noCTLUptest cl, LastE0jz short LCTLUpand cl, not RCtrDownand dl, not CtrlDownjmp short SetFlagsKey1LCTLUp:and dx, not ((LCtrDown shl 8) or CtrlDown)jmp short SetFlagsKey1noCTLUp:mov bx, 3a00h + CapsLockcall KeyLockjnc short SetFlagsKey1mov bx, 4600h + ScrLockpush dx ; save ScrLock state bit (dl)call KeyLockpop bx ; restore ScrLock state bit (bl)jc short noScrLocktest dl, CtrlDownjz short SetFlagsKey1; no break, just ScollLockmov dl, bl ; restore ScrLock flagtest bh, ScrLockDownjnz short SetFlagsKey1mov byte ptr CtrlBreak, 80h ; CTRL+BREAK flagmov ax, Buffermov HeadPtr, axmov TailPtr, axint 1bhxor ax, axjmp pushkeynoScrLock:test cl, LastE0 ; INSjnz short testINStest dl, RShfDown or LShfDownjnz short testINStest dl, NumLockjnz short NoInstestINS:mov bx, 5200h + Insertcall KeyLocknoIns:mov bx, 4500h + NumLockpush dx ; save NumLock state bit (dl)call KeyLockpop bx ; restore NumLock state bit (bl)jc short NormalKey ; CTRL+NumLock = Pausetest dl, CtrlDownjz short SetFlagsKey1mov dl, bl ; restore NumLock flagor dh, Pause ; set Pause bitSetFlagsKey1:jmp SetFlagsKeyE0Key:mov di, offset E0KeyListpush cxmov cx, E0KeyIndex - E0KeyListcldpush cspop esrepne scasbpop cxjne short SetFlagsKeymov al, es:[di + E0KeyIndex - E0KeyList - 1]jmp short KeyDownNormalKey:test al, 80hjnz short SetFlagsKey ; key uptest cl, LastE0jnz short E0Keycmp al, 59hsbb ah, ahand al, ahmov bx, offset KeyIndexxlat cs:[bx]KeyDown:xor bx, bxtest dl, RShfDown or LShfDownjz short noShiftmov bl, 2noShift:cmp al, 26ja short noCapstest dl, CapsLockjz short noNumxor bl, 2jmp short noNumnoCaps:cmp al, 37ja short noNumtest dl, NumLockjnz short NumDownmov bl, 2NumDown:xor bl, 2noNum:test dl, CtrlDownjz short noCtrlmov bl, 4noCtrl:test dl, AltDownjz short noAltmov bl, 6noAlt:cbwshl ax, 3add bx, axmov ax, cs:KeyCode[bx]cmp ax, 000ahja short pushKeydec axjs short SetFlagsKey ; ax was 0mov ah, AltKpdaadmov AltKpd, aljmp short SetFlagsKeypushKey:push cxmov cx, axmov ah, 5int 16hpop cxand dh, not Pause ; clear Pause bitSetFlagsKey:and cl, not (LastE0 or LastE1) ; not prefix key code, clear all prefixesSetFlags:mov al, dlshr al, 4xor al, chand al, 7jz short SF1 ; no LEDs to updatetest ch, SetRepeat or AckReceived or LEDUpdatejnz short SF1 ; can not update LEDS, so just write the flags and exitor al, LEDUpdatexor ch, al ; insert the LEDs in KbdFlags4mov ah, 0edh ; set LEDmov bl, 0call sendps2byteSF1:mov KbdFlags1, dxmov KbdFlags3, cxint09Exit:pop espop dspopairetint09 endpELSE ; SCANCODE2int09 proc nearpushapush dspush espush 40hpop dsin al, 60h ; al contains the scan codemov dx, KbdFlags1mov cx, KbdFlags3cmp al, 0fah ; ACKjne short noACK; ------------ manage ACK responsetest ch, LEDUpdatejz short ToggleACK ; no LED updatetest ch, AckReceivedjnz short SecondACK ; second ACK receivedmov ah, ch ; LED update command sent, ACK received, need to send second byteand ah, ScrLockLED or NumLockLED or CapsLockLEDmov bl, 0call sendps2bytejmp short ToggleACKSecondACK:xor ch, LEDUpdate ; second ACK, clear LED update bitToggleACK:xor ch, AckReceived ; toggle ACK bitSetFlags1:jmp SetFlags; ------------ no ACKnoACK:cmp al, 0e0hjne short noE0or cl, LastE0jmp short SetFlags1noE0:cmp al, 0e1hjne short noE1or cl, LastE1jmp short SetFlags1noE1:cmp al, 0f0hjne short noF0or cl, LastF0jmp short SetFlags1noF0:cmp al, 71h ; is DEL?jne short noDELmov ah, dland ah, CtrlDown or AltDowncmp ah, CtrlDown or AltDownje short noF01NormalKey1:jmp NormalKeynoF01:mov word ptr ds:[72h], 1234h ; warm boot flagdb 0eahdw 0, 0ffffh ; rebootnoDEL:cmp al, 83h ; is F7je short NormalKey1ja short SetFlags1test cl, LastF0 ; key up?jz short noKeyUpor al, 80h ; key up flagnoKeyUp:test cl, LastE0jnz short noRSUp ; ignore fake shiftscmp al, 12h ; left shiftjne short noLSDownor dl, LShfDownjmp short SetFlagsKey2noLSDown:cmp al, 12h or 80hjne short noLSUpand dl, not LShfDownjmp short SetFlagsKey2noLSUp:cmp al, 59h ; right shiftjne short noRSDownor dl, RShfDownjmp short SetFlagsKey2noRSDown:cmp al, 59h or 80hjne short noRSUPand dl, not RShfDownjmp short SetFlagsKey2noRSUp:cmp al, 11h ; ALTjne short noALTDowntest cl, LastE0jz short LALTDnor cl, RAltDownor dl, AltDownjmp short SetFlagsKey2LALTDn:or dx, (LAltDown shl 8) or AltDownjmp short SetFlagsKey2noALTDown:cmp al, 11h or 80hjne short noALTUptest cl, LastE0jz short LALTUpand cl, not RAltDownand dl, not AltDownjmp short ALTupLALTUp:and dx, not ((LAltDown shl 8) or AltDown)ALTUp:xor ax, axxchg al, AltKpdtest al, aljz short SetFlagsKey2jmp pushKeynoALTUp:cmp al, 14h ; CTLjne short noCTLDowntest cl, lastE0jz short LCTLDnor cl, RCtrDownor dl, CtrlDownSetFlagsKey2:jmp short SetFlagsKey1LCTLDn:or dx, (LCtrDown shl 8) or CtrlDownjmp short SetFlagsKey1noCTLDown:cmp al, 14h or 80hjne short noCTLUptest cl, LastE0jz short LCTLUpand cl, not RCtrDownand dl, not CtrlDownjmp short SetFlagsKey1LCTLUp:and dx, not ((LCtrDown shl 8) or CtrlDown)jmp short SetFlagsKey1noCTLUp:mov bx, 5800h + CapsLockcall KeyLockjnc short SetFlagsKey1mov bx, 7e00h + ScrLockpush dx ; save ScrLock state bit (dl)call KeyLockpop bx ; restore ScrLock state bit (bl)jc short noScrLocktest dl, CtrlDownjz short SetFlagsKey1; no break, just ScollLockmov dl, bl ; restore ScrLock flagtest bh, ScrLockDownjnz short SetFlagsKey1mov byte ptr CtrlBreak, 80h ; CTRL+BREAK flagmov ax, Buffermov HeadPtr, axmov TailPtr, axint 1bhxor ax, axjmp pushkeynoScrLock:test cl, LastE0 ; INSjnz short testINStest dl, RShfDown or LShfDownjnz short testINStest dl, NumLockjnz short NoInstestINS:mov bx, 7000h + Insertcall KeyLocknoIns:mov bx, 7700h + NumLockpush dx ; save NumLock state bit (dl)call KeyLockpop bx ; restore NumLock state bit (bl)jc short noPausetest dl, CtrlDownjz short SetFlagsKey1mov dl, bl ; restore NumLock flagor dh, Pause ; set Pause bitSetFlagsKey1:jmp SetFlagsKeyE0Key:mov di, offset E0KeyListpush cxmov cx, E0KeyIndex - E0KeyListcldpush cspop esrepne scasbpop cxjne short SetFlagsKeymov al, es:[di + E0KeyIndex - E0KeyList - 1]jmp short KeyDownnoPause:and al, 07fh ; delete up bitNormalKey:test cl, LastF0jnz short SetFlagsKey ; key uptest cl, LastE0jnz short E0Keymov bx, offset KeyIndexxlat cs:[bx]KeyDown:xor bx, bxtest dl, RShfDown or LShfDownjz short noShiftmov bl, 2noShift:cmp al, 26ja short noCapstest dl, CapsLockjz short noNumxor bl, 2jmp short noNumnoCaps:cmp al, 37ja short noNumtest dl, NumLockjnz short NumDownmov bl, 2NumDown:xor bl, 2noNum:test dl, CtrlDownjz short noCtrlmov bl, 4noCtrl:test dl, AltDownjz short noAltmov bl, 6noAlt:cbwshl ax, 3add bx, axmov ax, cs:KeyCode[bx]cmp ax, 000ahja short pushKeydec axjs short SetFlagsKey ; ax was 0mov ah, AltKpdaadmov AltKpd, aljmp short SetFlagsKeypushKey:push cxmov cx, axmov al, ah ; scan codemov ah,4fhstcint 15hjnc nopushmov ah, 5int 16hnopush:pop cxand dh, not Pause ; clear Pause bitSetFlagsKey:and cl, not (LastE0 or LastE1 or LastF0) ; not prefix key code, clear all prefixesSetFlags:mov al, dlshr al, 4xor al, chand al, 7jz short SF1 ; no LEDs to updatetest ch, SetRepeat or AckReceived or LEDUpdatejnz short SF1 ; can not update LEDS, so just write the flags and exitor al, LEDUpdatexor ch, al ; insert the LEDs in KbdFlags4mov ah, 0edh ; set LEDmov bl, 0call sendps2byteSF1:mov KbdFlags1, dxmov KbdFlags3, cxint09Exit:pop espop dspopairetint09 endpENDIFKeyLock proc near ; input: BH = expected scan code, al = scan code, BL = key lock flag. Returns CF=1 to continue, CF=0 to exitxor bh, aljnz short s2mov ah, dhor dh, bl ; set flagxor ah, dh ; get flag differencexor dl, ah ; toggle only if key was not already downrets2: cmp bh, 80hstcjne short exitxor dh, bl ; key upexit:retKeyLock endp; --------------------- INT 10h - Video ----------------ActiveVideoMode equ <ds:[49h]> ; 1 byteScreenWidth equ <ds:[4ah]> ; 2 Screen width in text columnsRegenLength 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 pageCursorPos 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 numberPortAddress equ <ds:[63h]> ; 2 Port address for 6845 video controller chip; see CGA I/O PortsCrtMode 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 EgaMiscInfoRecEgaMiscInfo2 equ <ds:[88h]> ; 1 EGA flags; see EgaMiscInfo2RecVgaFlags equ <ds:[89h]> ; 1 VGA flags; see VgaFlagsRecVgaFlags2 equ <ds:[8ah]> ; 1 VGA flags2PalPaging equ <ds:[69h]> ; 1 Palette paging status: bit7=0 for 4x64, 1 for 16x16. bit3:0=active pagePalPagingCounter equ <ds:[6ah]> ; 1 Palette paging counterint10 proc nearsti ; no interrupt reentrantcldpush dspush sipush 40hpop dscmp ah, 4fhje short svgacmp ah, 1chja short exitmov si, axshr si, 7and si, 1fehcall cs:vidtbl[si]exit:pop sipop dsiretsvga:cmp al, 5je short VESAMemControlcmp al, 1jb short VESAGetInfoje short VESAGetModeInfocmp al, 3jb short VESASetModeje short VESAGetModemov ax, 100hjmp short exit; ---------------- VESA fn00VESAGetInfo:push cxpush dimov si, offset VESAInfomov cx, 10rep movsw es:[di], cs:[si]mov cl, 118 ; 236 bytes 0VESASupportedClear:xor ax, axrep stoswpop dipop cxVESASupported:mov ah, 0 ; successVESASupportedErr:mov al, 4fhjmp short exit; ---------------- VESA fn01VESAGetModeInfo:cmp cx, 101hVESAGetModeInfo1:mov ah, 1 ; errorjne short VESASupportedErrpush cxpush dimov cx, 9mov si, offset VESAModeInforep movsw es:[di], cs:[si]mov cl, 119jmp short VESASupportedClear; ---------------- VESA fn02VESASetMode:imul ax, bx, 2cmp ax, 101h*2jne short VESASetMode1lea ax, [bx+23ffh]xchg ah, alint 10hjmp short VESASupportedVESASetMode1:mov al, blmov ah, 0int 10hjmp short VESASupported; ---------------- VESA fn03VESAGetMode:mov bh, EgaMiscInfoand bh, 80hmov bl, ActiveVideoModecmp bl, 25hje short VESAGetMode1or bl, bhmov bh, 0jmp short VESASupportedVESAGetMode1:add bx, 257-25jmp short VESASupported; ---------------- VESA fn05VESAMemControl:; test bx, not 101h ; BX validation; jnz short VESAGetModeInfo1 ; errorpush cspush offset VESASupported; call VESAMemControlCB; jmp short VESASupportedVESAMemControlCB:pushfclipush axpush dxmov ax, bxand ax, 1add al, 8ahxchg ax, dxand ax, 7add al, 0ahtest bh, bhjnz getpageinfocall flushout dx, axpop dxpop axpopfretfgetpageinfo:in ax, dxsub al, 0ahand ax, 7xchg ax, dxpop axpop axpopfretfVESAInfo db 'VESA'dw 100h, VESAOEM, 0f000h, 2, 0, VESAModes, 0f000h, 8VESAOEM db 'Nicolae Dumitrache', 0VESAModes dw 101h, 0ffffhVESAModeInfo:;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 reserveddw 0000000010011001b;Bit(s) Description - window attributes;0 exists;1 readable;2 writable;3-7 reserveddb 00000111b, 00000111bdw 64, 64, 0a000h, 0b000h, VESAMemControlCB, 0f000h, 640; --------------- fn 00h, set video modesetmode:pushapush esadd al, al ; CF = cls bitrcl byte ptr EgaMiscInfo, 1ror byte ptr EgaMiscInfo, 1cmp al, 3*2ja short setmode1mov al, 0b6h ; reset sound generatorout 43h, almov al, 0out 42h, alout 42h, almov ax, 0806h ; text mode (80x25, 16 colors), flash enabledmov word ptr ScreenWidth, 80mov word ptr RegenLength, 1000hmov byte ptr ScreenRows, 25-1mov word ptr ScanLinesChar, 16mov bx, 0b800h ; segmentmov cx, 4000h ; video len/2mov si, 0720h ; clear valuejmp short setmode2setmode1:cmp al, 13h*2jne short setmode3mov ah, 41h ; graphic mode, 320x200, 256 colorsmov word ptr ScreenWidth, 40mov word ptr RegenLength, 2000hjmp short setmode21setmode3:cmp al, 25h*2jne short setmodeexitmov ah, 1 ; graphic mode, 640x400, 256 colorsmov word ptr ScreenWidth, 80mov word ptr RegenLength, 2000hsetmode21:mov bx, 0a000h ; segmentmov cx, 8000h ; video len/2 - clears only the first segment (TODO clear full screen)xor si, si ; clear valuesetmode2:shr al, 1mov ActiveVideoMode, alpush axpush cxpush dspop esxor ax, axmov di, offset CursorPosmov cx, 8rep stosw ; reset cursor position for all pagesmov ax, 0500hint 10h ; set page0pop cxpop axtest byte ptr EgaMiscInfo, 80hjnz short setmode4 ; no clear video memorymov es, bxxchg ax, sixor di, direp stoswxchg ax, sicall palpagesetmov byte ptr PalPaging, cl ; reset pagingsetmode4:mov dx, 3c0hmov al, 10hout dx, almov al, ahout dx, al ; set video modemov ax, 1123hint 10h ; set ROM 8x8 font for graphics modemov ah, 1xor cx, cxint 10h ; show cursortest byte ptr VgaFlags, 8 ; test default palette loadingjnz short setmodeexit ; no default palettemov ax, 1012hxor bx, bxmov cx, 100hmov dx, offset default_palpush cspop esint 10h ; set default palettesetmodeexit:pop espopanullproc: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 offpush axpush dxmov dx, 3d4hmov al, 0ahout dx, almov al, chshr al, 1or al, chinc dxout dx, alpop dxpop axret;---------------- fn 02h, set cursor poscurpos:push axpush bxmov al, bhshr bx, 7and bx, 0ehmov CursorPos[bx], dxcmp byte ptr ActiveVideoMode, 3jne short curpos1cmp al, ActivePagejne short curpos1push dxxor ax, axxchg al, dhimul ax, 80add ax, dxmov dx, 3d4hpush axmov al, 0fhout dx, alinc dxpop axout dx, aldec dxmov al, 0ehout dx, alinc dxmov al, ahout dx, alpop dxcurpos1:pop bxpop axret;---------------- fn 03h, get cursor posgetcurpos:push bxshr bx, 7and bx, 0ehmov dx, CursorPos[bx]mov cx, CursorShapepop bxret;---------------- fn 04h, light penlightpen:mov ah, 0 ; not triggeredret;---------------- fn 05h, set active video pageapage:pushacall flushand al, 7mov bh, almov ActivePage, almov al, ActiveVideoModecmp al, 3jne short apage1mov ax, 0ahout 8ah, axinc axout 8bh, axmov ah, 3int 10h ; get cursor posmov ah, 2int 10h ; set cursor posmov ax, 200h ; page size / 8jmp short apage2apage1: ; mode 13h and 25hmov ax, 0ahadd al, bhout 8ah, axinc axcmp al, 12hjne short apage4mov al, 0ahapage4: out 8bh, axmov ax, 2000h ; page size / 8apage2:shr bx, 8 ; page numbermul bxpush axshl ax, 3mov PageOffset, axmov dx, 3d4hmov al, 0dhout dx, alinc dxpop axout dx, aldec dxmov al, 0chout dx, alinc dxmov al, ahout dx, alpoparet;---------------- fn 06h, scroll up / clrscrollup:pushapush esxchg cx, dxsub cx, dxinc cxcmp byte ptr ActiveVideoMode, 13hjae short scrollup1call scr_paramsscrollup6:push 0b800h ; segmentpop esadd dl, dladd di, diadd di, PageOffset ; di = top left corner addressxchg ax, cx ; ah = 0test bl, bljz short scrollup3 ; clearsub ah, bljb short scrollup3 ; clearadd si, discrollup4:mov cl, alrep movsw es:[si], es:[di]add si, dxadd di, dxdec ahjns short scrollup4 ; ch = lines - 1scrollup3:add ah, bl ; clear rectangle: DI=address, ah=lines, al=columns, bh=attributexchg ax, bxmov al, ' 'scrollup5:mov cl, blrep stoswadd di, dxdec bhjns short scrollup5 ; ch = lines - 1scrollexit:pop espoparetscrollup1:ja short scrollup2; TODO mode13h scroll upjmp short scrollexitscrollup2:; TODO mode25h scroll upjmp short scrollexit;---------------- fn 07h, scroll dn / clrscrolldn:stdpushapush esneg cxadd cx, dxinc cxcmp byte ptr ActiveVideoMode, 13hjae short scrolldn1call scr_paramsneg dxneg sijmp short scrollup6scrolldn1:ja short scrolldn2; TODO mode13h scroll downjmp short scrollexitscrolldn2:; TODO mode25h scroll downjmp short scrollexitscr_params:mov bl, al ; linesxor ax, axxchg al, dhimul di, ax, 80add di, dxmov dl, 80 ; dh = 0sub dl, clmov al, blimul si, ax, 160ret;---------------- fn 08h, read char/attrreadchar:push bxmov al, ActiveVideoModecmp al, 3xor ax, axjne short readchar1call mode3chaddrmov ax, [bx]readcharexit:pop bxretreadchar1:cmp al, 13hjne short readchar2; TODO mode13hjmp short readcharexitreadchar2:; TODO mode25hjmp short readcharexitmode3chaddr: ; returns current char address in mode3 in ds:bx. Input: bh=page, ds=40hpush axand bx, 700hlea ax, [bx+0b800h]shr bx, 7mov bx, CursorPos[bx]mov ds, axxor ax, axxchg al, bhimul ax, 80add bx, axadd bx, bxpop axret;---------------- fn 09h, write char/attrwritecharattr:push axpush espush bxpush cxcmp byte ptr ActiveVideoMode, 3jne short writecharattr1mov ah, blcall mode3chaddrpush dspop esxchg di, bxrep stoswxchg di, bxwritecharattrexit:pop cxpop bxpop espop axretwritecharattr1:cmp byte ptr ActiveVideoMode, 13hjne short writecharattr2; TODO mode13hjmp short writecharattrexitwritecharattr2:; TODO mode25hjmp short writecharattrexit;---------------- fn 0ah, write charwritechar:jcxz short writecharskippush bxpush cxcmp byte ptr ActiveVideoMode, 3jne short writechar1call mode3chaddrwritechar3:mov [bx], aladd bx, 2loop short writechar3writecharexit:pop cxpop bxwritecharskip:retwritechar1:cmp byte ptr ActiveVideoMode, 13hjne short writechar2; TODO mode13hjmp short writecharexitwritechar2:; TODO mode25hjmp short writecharexit;---------------- fn 0eh, write char as TTYwritecharTTY:push axpush bxpush dxmov bl, ActivePagemov bh, 0add bx, bxmov dx, CursorPos[bx]shl bx, 7mov ah, 0ahcall ttymov ah, 2 ; set cursor posint 10hpop dxpop bxpop axrettty: ; dx=xy, bh=page, al=char, bl=attr, ah=0ah(no attr) or 09h(with attr)test word ptr KbdFlags2, Pausejnz short ttypush cxcmp al, 7je short bellcmp al, 8je short bscmp al, 0ahje short crcmp al, 0dhje short lfmov cx, 1int 10h ; write char at cursorinc dxcmp dl, ScreenWidthjae short crlftty1:pop cxretbell:; TODO bell codejmp short tty1bs:sub dl, 1adc dl, 0jmp short tty1lf:mov dl, 0jmp short tty1crlf:mov dl, 0cr:inc dhcmp dh, ScreenRowsjbe short tty1dec dh; mov ah, 8; int 10h ; read attribute at cursor pospush bx ; save active page in bhpush dx; xchg ax, bxmov bh, 7 ; default attributemov ax, 601hmov dh, ScreenRowsmov dl, ScreenWidthdec dxxor cx, cxint 10h ; scroll uppop dxpop bx ; restore active page in bhjmp short tty1;---------------- fn 0fh, read video modereadmode:mov al, EgaMiscInfoand al, 80hor al, ActiveVideoModemov ah, ScreenWidthmov bh, ActivePageret;---------------- fn 10h, palettepaltable dw setonereg, palexit, setallreg, setblink, palexit, palexit, palexit, readonereg, readoverscan, readallreg, palexit, palexit, palexit, palexit, palexit, palexitdw setoneDAC, palexit, setblockDAC, paging, palexit, readoneDAC, palexit, readblockDAC, setPELmask, getPELmask, getpaging, grayscalepal:cmp al, 1bhja short palexitmov si, axadd si, siadd byte ptr PalPagingCounter, ah ; prevents <palpage> re-entrance on recursive <pal> callscall palpagecall cs:paltable[si-2000h]call palpagesub byte ptr PalPagingCounter, ahpalexit:retpalpage: ; executes only if PalPagingCounter == ahcmp byte ptr PalPagingCounter, ahjne short palpageexitpalpageset:test byte ptr PalPaging, 0fhjz short palpageexitpushamov bl, byte ptr PalPagingadd bl, bljc short page16shl bl, 2page16:shl bx, 11 ; bh=target page, bl=0 pagepalpage1:mov al, 15hint 10h ; read 0 page DAC regpush cxpush dxxchg bl, bhint 10h ; read target page DAC registerxchg bl, bhmov al, 10hint 10h ; write 0 page DAC registerpop dxpop cxxchg bl, bhint 10h ; write target page DAC registerxchg bl, bhadd bx, 101h; next DAC regtest bl, 0fhjnz short palpage1popapalpageexit:retsetonereg:cmp bl, 10hjae setonereg1pushacall colfrombitsmov cl, alcall colfrombitsmov ch, alcall colfrombitsmov dh, almov al, 10hint 10hpopasetonereg1:retsetallreg:pushamov al, 0mov si, dxmov bl, 15setallreg1:mov bh, es:[si+15]int 10hdec sidec bljns short setallreg1poparetsetblink:pushacmp byte ptr ActiveVideoMode, 3jne short setblink1mov dx, 3c0hmov al, 10hout dx, almov al, bland al, 1shl al, 3out dx, al ; set video mode (0 or 8)shl al, 2xor al, VgaFlagsand al, 20hxor VgaFlags, alsetblink1:poparetreadonereg:cmp bl, 10hjae readonereg1push axpush cxpush dxmov al, 15hint 10hmov al, dh ; al = Rand al, 00110000bshr al, 2add al, 01111000band al, 10000100bmov bh, alxchg ax, cx ; ax = GBand ax, 0011000000110000bshr ax, 3shr al, 1add ax, 0011110000011110band ax, 0100001000100001bor bh, ahor bh, alrol bh, 3pop dxpop cxpop axreadonereg1:retreadallreg:pushamov di, dxmov bl, 0readllreg1:mov al, 7int 10hmov al, bhstosbinc bxcmp bl, 16jne short readllreg1mov al, 0 ; overscan colorstosbpoparetreadoverscan:mov bh, 0retsetoneDAC:push axpush dxxchg ax, dxmov al, blmov dx, 3c8hout dx, alinc dxmov al, ahout dx, almov al, chout dx, almov al, clout dx, alpop dxpop axretsetblockDAC:pushamov si, dxmov dx, 3c8hxchg ax, bxout dx, alinc dximul cx, 3rep outsb dx, es:[si]poparetpaging:push bxtest bl, blmov bl, PalPagingjnz short paging1add bl, blror bx, 1jmp short paging2paging1:and bx, 0f80h ; bl=old page, bh=new pageor bl, bhpaging2:mov PalPaging, blpop bxretreadoneDAC:push axpush dxmov al, blmov dx, 3c7hout dx, alinc dxinc dxin al, dxmov ah, alin al, dxmov ch, alin al, dxmov cl, alpop dxmov dh, ahpop axretreadblockDAC:pushamov di, dxmov dx, 3c7hxchg ax, bxout dx, alinc dxinc dximul cx, 3rep insbpoparetsetPELmask:push dxxchg ax, bxmov dx, 3c6hout dx, alxchg ax, bxpop dxretgetPELmask:push dxxchg ax, bxmov dx, 3c6hin al, dxxchg ax, bxpop dxretgetpaging:mov bh, PalPagingmov bl, 0rol bx, 1shr bh, 1retgrayscale:jcxz short grayscale2pushamov bh, clgrayscale1:mov al, 15hint 10hshr dx, 8imul si, dx, 77mov dl, chimul dx, 151mov ch, 0imul cx, 28add dx, siadd dx, cxmov ch, dhmov cl, dhmov al, 10hint 10hinc bldec bhjne short grayscale1popagrayscale2:retcolfrombits: ; input: bh, output: alshr bh, 1sbb al, aland al, 2ahtest bh, 4jz short col1or al, 15hcol1:ret;---------------- fn 11h, character generatorloadUDF:cmp bx, 1000hjne loadUDFexit ; only 16bytes chars and font block 0 supportedpushaxchg ax, dxmov dx, 03cbhout dx, axmov si, bpshl cx, 4rep outsb dx, es:[si]popaloadUDFexit:retchargen:test al, not 10h ; test for 00h and 10hjz short loadUDFtest al, not 11h ; test for 01h and 11hjz short loadROMfonttest al, not 12h ; test for 02h and 12hjz short loadROMfonttest al, not 14h ; test for 04h and 14hjz short loadROMfontcmp al, 20hjb loadUDFexitje short set1fcmp al, 21hje short setgrUDFcmp al, 24hjbe short setROMgrFontcmp al, 30hje short getfontinforetloadROMFont:push espushamov bx, 1000h ; 8x16 chars, block 0mov cx, 100h ; all charsxor dx, dxmov bp, offset font8x16push cspop esmov al, 0; int 10h ; loadUDFpopapop esretset1f:xor si, simov ds, simov [si+1fh*4], bpmov [si+1fh*4+2], esretsetgrUDF:pushajcxz short loadUDFexitpush dsxor si, simov ds, simov [si+43h*4], bpmov [si+43h*4+2], espop dsmov ax, 200cmp byte ptr ActiveVideoMode, 13hjb short setgrUDFexitje short setgrUDF1mov ax, 480 ; mode 25h, 480 linessetgrUDF1:mov ScanLinesChar, cxcwddiv cxdec axmov ScreenRows, alsetgrUDFexit:poparetsetROMgrFont:pushapush esmov cx, 8push cspop esmov bp, offset font8x8cmp al, 23hje short setROMgrFont1mov bp, offset font8x16setROMgrFont1:mov al, 21hint 10h ; set graphic UDFdec axmov bp, offset font8x8 + 128*8int 10h ; set INT 1fhpop espoparetgetfontinfo:mov cx, ScanLinesCharmov dl, ScreenRowscmp bh, 1ja short getfontinfo1push 0pop dsles bp, ds:[1fh*4]jb short getfontinfoexitles bp, ds:[43h*4]retgetfontinfo1:cmp bh, 7ja short getfontinfoexitmov si, bxshr si, 8add si, simov bp, cs:fontinfo[si-4]push cspop esgetfontinfoexit:retfontinfo dw font8x16, font8x8, font8x8+128*8, font8x16, font8x16, font8x16;---------------- fn 12h, special functionsspecial:cmp bl, 10hjne short special1mov cl, EgaMiscInfo2 ; cl = switch settingsand cx, 15 ; ch <- 0 (feature bits)mov bx, 3 ; bh <- 0 (color mode), bl = video memory sizeretspecial1:cmp bl, 31hjne short special2neg alxor al, VgaFlagsand al, 8 ; transfer palette loading bit to VgaFlagsxor VgaFlags, almov al, 12h ; supported functionretspecial2:mov al, 0 ; unsupported functionret;---------------- fn 13h, write stringwritestr:jcxz short wstrexitpushamov si, bxshr si, 8add si, sipush CursorPos[si]mov ah, 9 ; write tty char/attributewstr1:push axtest al, 2mov al, es:[bp]jz short noattrinc bpmov bl, es:[bp]noattr:inc bpmov CursorPos[si], dxcall ttypop axloop short wstr1pop CursorPos[si]test al, 1jz short wstr2mov ah, 2 ; set cursor posint 10hwstr2:popawstrexit:ret;---------------- fn 1ah, get/set display combination codegetdcc:cmp al, 1ja short getdccexitmov al, ahje short setdccmov bx, 08hdccval label wordsetdcc:mov cs:[dccval-2], bxgetdccexit:ret;---------------- fn 1bh, query statusquerystatus:pushamov ax, offset staticfunctablestoswmov ax, csstoswmov si, offset ActiveVideoModecmp byte ptr [si], 13hmov cx, 33 ; info copied from BDArep movsbmov ax, 8stosw ; display info (one VGA analog color monitor)mov bx, 208h ; 400 scan lines, 8 pagesmov al, 10h ; 16 colorsjb short querystatus1 ; mode03hmov bh, 0 ; scan lines code (0=200, 1=350, 2=400, 3=480), 8 pagesmov ax, 100h ; 256 colorsje short querystatus1 ; mode13hmov bx, 301h ; 480 scan lines, 1 pagequerystatus1:stoswxchg ax, bxstoswxor ax, axstosw ; font block info (45)mov al, VgaFlagsand al, 00101111bstoswstoswmov al, EgaMiscInfoshr al, 4and al, 7 ; video memory sizestoswmov al, 2stosb ; color display attachedmov cl, 6xor ax, axrep stosw ; 12 reserved bytespopamov al, ah ; supported functionretstaticfunctable db 00001100b ; video mode 2h, 3h supporteddb 00000000bdb 00001000b ; video mode 13h supporteddb 00000000bdb 00100000b ; video mode 25h supporteddb 0, 0db 00000100b ; 400 scanline supporteddb 1 ; font blocks available in text modedb 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 flagsdb 00001100b ; miscellaneous function support flagsdb 0, 0 ; reserveddb 0 ; save pointer function flagsdb 0 ; reservedvidtbl dw setmode, cursor, curpos, getcurpos, lightpen, apage, scrollup, scrolldn, readchar, writecharattrdw writechar, nullproc, nullproc, nullproc, writecharTTY, readmodedw pal, chargen, special, writestr, nullproc, nullproc, nullproc, nullproc, nullproc, nullproc, getdcc, querystatus, nullprocint10 endp; --------------------- INT 11h - Equipment ----------------EquipmentWord equ <ds:[10h]>int11 proc nearpush dspush 40hpop dsmov ax, EquipmentWordpop dsiretint11 endp; --------------------- INT 12h - Memory size ----------------MemorySize equ <ds:[13h]>int12 proc nearpush dspush 40hpop dsmov ax, MemorySizepop dsiretint12 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 nearpush dspush bppush 40hpop dsxor byte ptr HDOpStarted, 8jz short inINT13sticldcmp ah, 1ahjbe short Disk1sub ah, 41h-1bh ; extensionscmp ah, 22hjbe short Disk1mov ah, 1 ; bad command errorjmp short exitinINT13:mov ah, 0aah ; drive not readyjmp short exit2Disk1:mov bp, axshr bp, 7and bp, 1fehpush dscall cs:disktbl[bp]pop dsexit:mov HDLastError, ahexit2:xor byte ptr HDOpStarted, 8neg ah ; CF <- (AH != 0)exit1:mov bp, sprcr byte ptr [bp+8], 1rol byte ptr [bp+8], 1 ; insert error CF on stackneg ahpop bppop dsiretdisktbl dw DiskReset, DiskGetStatus, DiskRead, DiskWrite, DiskVerify, DiskFormat, DiskFormat, DiskFormat, DiskGetParams, DiskInit, DiskRead, DiskWrite, DiskSeek, DiskRst, DiskReadSectBuffer, DiskWriteSectBufferdw DiskReady, DiskRecalibrate, DiskDiag, DiskDiag, DiskDiag, DiskGetType, DiskChanged, DiskSetDASDType, DiskSetMediaType, DiskPark, DiskFormat, DiskExtInstCheck, DiskExtRead, DiskExtWrite, DiskExtVerify, DiskExtLockdw DiskExtEject, DiskExtSeek, DiskExtGetParamsDiskGetType:cmp dl, 80hjne short DiskReset ; ah=0, drive not presentmov cx, HDSizemov dx, cxtest cx, cxjz short DiskReset ; ah=0, drive not presentmov ah, -3 ; HD presentshr cx, 6shl dx, 10 ; CX:DX = HDSize * 1024DiskGetTypeexit:pop ds ; discard ret addresspop ds ; discard DSxor byte ptr HDOpStarted, 8 ; CF <- 0jmp short exit1DiskExtInstCheck:xchg bl, bhmov ah, -1mov cx, 1 ; extended disk access functions (AH=42h-44h,47h,48h) supportedcmp dl, 80hjne short notreadyjmp short DiskGetTypeexitDiskReset:DiskChanged:DiskPark:mov ah, 0 ; successretDiskGetStatus:mov ah, HDLastErrorretDiskVerify:mov bp, sdverifyjmp short DiskRead1DiskWrite:mov bp, sdwritejmp short DiskRead1DiskRead:mov bp, sdreadDiskRead1:test al, aljz short DiskResetcmp dl, 80hjne short notreadymov ah, 4test cl, 3fhjz short DiskReadend ; bad sector 0pushamov ah, 0push axcall HCStoLBApop cxpush cxcall bp ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=read sectorspop cxsub cx, axneg cx ; CF=1 if cx != 0rcl ah, 3 ; AH = 4*CF (sector not found / read error)mov ds, axpopamov ax, dsDiskReadend:retHCStoLBA: ; CX = {cyl[7:0], cyl[9:8], sect[5:0]}, DH = head. Returns DX:AX LBAmov al, chmov ah, clshr ah, 6shr dx, 8imul dx, 63and cx, 3fhadd cx, dxdec cxmov dx, 255*63mul dxadd ax, cxadc dx, 0ret; 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, 0je short notreadycmp dl, 80hje short DiskResetnotready:mov ah, 0aah ; disk not readyretDiskGetParams:cmp dl, 80hmov ah, 7jne short DiskReadend ; retmov bl, 0 ; ???mov ax, HDSizemov dx, axshl ax, 10shr dx, 6sub ax, 30sbb dx, 0mov cx, 63*255div cxdec axcmp ax, 3fehjbe dgpokmov ax, 3fehdgpok:xchg al, ahshl al, 6or al, 3fhmov cx, axmov dx, 0fe01hxor ax, axretDiskExtVerify:mov bp, sdverifyjmp short DiskExtRead1DiskExtWrite:mov bp, sdwritejmp short DiskExtRead1DiskExtRead:mov bp, sdreadDiskExtRead1:cmp dl, 80hjne short notreadypush espush axpushamov bx, spmov ds, ss:[bx+26]mov cx, [si+2]les bx, [si+4]mov ax, [si+8]mov dx, [si+10]push dspush sicall bppop sipop dssub ax, [si+2]add [si+2], axpopapop axsbb ah, ahand ah, 4pop esretDiskExtGetParams:cmp dl, 80hjne short notreadypush axmov ax, HDSizemov bp, spmov ds, [bp+8]xor bp, bpmov word ptr [si], 1ah ; sizemov word ptr [si+2], 0bh ; flagsmov word ptr [si+4], 1023 ; cylindersmov word ptr [si+6], bpmov word ptr [si+8], 255 ; headsmov word ptr [si+10], bpmov word ptr [si+12], 63 ; sectors/trackmov word ptr [si+14], bpmov word ptr [si+16], axshl word ptr [si+16], 10shr ax, 6mov word ptr [si+18], axmov word ptr [si+20], bpmov word ptr [si+22], bpmov word ptr [si+24], 512 ; bytes/sectorpop axmov ah, 0retDiskReadSectBuffer:DiskWriteSectBuffer:DiskSetDASDType:DiskSetMediaType:DiskExtLock:DiskExtEject:mov ah, 1 ; unsupported fnretint13 endp; --------------------- INT 15h - Extended services ----------------UFPtr equ <ds:[98h]>WaitCount equ <ds:[9ch]>UWaitFlag equ <ds:[0a0h]>HandlerPtr equ <ds:[0a1h]> ; 4 bytesDataBuffer equ <ds:[0a5h]> ; 3 bytesDataCounter equ <ds:[067h]> ; 1 bytePacketSize equ <ds:[068h]> ; 1 byte, 0->3bytes, 1->4bytesFreeXMSKb equ (1024 - 16 - 6)*64; ------------ MovExtIncSeg: ; DX = segment port addressjnz short SetSegExitin ax, dxand ax, 3ffhinc axcmp ax, 12hjne short IncSeg1xor ax, axIncSeg1:cmp ax, 0chjne short SetSeg2SetSeg: ; DX = segment port address, ax = logical segment (0..1023)and ax, 3ffhcmp ax, 0chjb short SetSeg1add ax, 6SetSeg2:cmp ax, 400hjb short SetSeg1sub ax, 400h - 0chSetSeg1:out dx, axSetSegExit:retMovSeg equ 01hsavess dw 0savesp dw MovExt, 0 ; tmp stack; Log(idx) to Phy(val) segment map (1024segs): 0,1,2,3,4,5,6,7,8,9,a,b,12h,13h,...,3feh,3ffh,c,d,e,f,10h,11h, then wrap to 0,1,2,...MovExt:push espush dspushaclimov cs:savess, sspush cspop ssxchg sp, cs:savespmov dx, 80h + MovSeg + 1jcxz short MovExt_exitpush espop dscldmov al, [si+1ch]mov ah, [si+1fh]mov bl, [si+14h]mov bh, [si+17h]mov di, [si+1ah]mov si, [si+12h]call flushcall SetSeg ; 02000h = destination, DX=82hdec dxxchg ax, bxcall SetSeg ; 01000h = source, DX=81hpush MovSeg shl 12pop dspush (MovSeg + 1) shl 12pop esxor bx, bxadd cx, cxadc bx, bx ; BX:CX = bytes to transfer; move from 01000h:si to 02000h:di, 2*cx bytesMovExtLoop:inc dx ; 82hmov ax, sicmp ax, dija short MovExt1mov ax, diMovExt1:neg axadc bx, -1sub cx, axsbb bx, 0xchg ax, cx ; cx = bytes to move, bx:ax = bytes left for the next transferjns short MovExt2 ; ax <= bx:cxadd cx, axxor ax, axinc bxMovExt2:movsb ; if CX = 0 transfer 10000h bytesdec cxjz short MovExt_nexttest si, 1 ; read alignjz short ralignedmovsbdec cxraligned:shr cx, 1rep movswjnc short MovExt_nextmovsbMovExt_next:call flushmov cx, axor ax, bxjz short MovExt_exit ; finalizedtest di, dicall incseg ; does nothing if ZF == 0, dx = 8bhdec dx ; 81htest si, sicall incseg ; dx = 81hjmp short MovExtLoopMovExt_exit:mov ax, MovSeg + 1out dx, ax ; 82hdec axdec dxout dx, ax ; 81hmov ss, cs:savessxchg sp, cs:savesppopapop dspop esxor ah, ahjmp short exit_axMovExtProxy:jmp MovExtint15:cmp ah, 4fhje short exit_iretxchg al, ahcmp al, 80hjb short exit15; CF=1 for <80hcmp al, 83hjb short done ; no error for 80, 81, 82je short SetEventWait; 83cmp al, 86hjb short exit15; CF=1 for 84, 85je short Wait1 ; 86cmp al, 88hjb short MovExtProxy ; 87je short ExtSize ; 88cmp al, 90hjb short exit15; CF=1 for 89..8fcmp al, 92hjb short done ; no error for 90, 91cmp al, 0c0hjb short exit15; CF=1 for 92..bfje short GetConfig ; c0cmp al, 0c2hjb short exit15; CF=1 for c1je short Mouse ; c2done:cmc ; CF=1 for >c2exit15:mov ax, 8600hexit_ax:stiretf 2 ; discard flags (need to keep CF)exit_iret:iret; ------------ SetEventWaitSetEventWait:push dspush 40hpop dsxor ah, 1jz short canceltest ah, byte ptr UWaitFlag ; ah=1jnz short busy ; CF=0mov ax, 1000-1 ; 1msout 70h, ax ; restart RTC timermov UFPtr[0], bxmov UFPtr[2], esadd ax, dxadc cx, 0mov WaitCount[0], axmov WaitCount[2], cxmov ah, 1 ; wait in progresscancel:mov byte ptr UWaitFlag, ahint 70hstc ; no errorbusy:cmc ; erornowait:pop dsjmp short exit15; ------------ WaitWait1:push espush bxmov ax, 8300hpush 4ahpop esxor bx, bx ; user wait flag address=0040:00a0int 15h ; returns with IF = 1jc short wbusywloop:hlttest byte ptr es:[bx], 80hjz short wloopwbusy:pop bxpop esjmp short exit15; ------------ ExtSizeExtSize:mov ax, FreeXMSKbjmp short exit_ax; ------------ GetConfigGetConfig:xor ax, axpush cspop esmov bx, offset SysParamsjmp short exit_ax; ------------ MouseMouse:push dspush dxpush 40hpop dstest byte ptr EquipmentWord, 4 ; ps2 mouse equipement wordjnz short mouse_presentif_err:mov ax, 03a7h ; interface error (no mouse present)out 64h, al ; disable mouseerrexit:stc ; errorexitok:pushf ; save CFin al, 21hand al, not 10hout 21h, al ; enable mouse interruptscall enableKbIfPresentpopfpop dxpop dsjmp exit_axmouse_present:mov al, ahmov ah, 1 ; invalid functioncmp al, 7ja short errexitpush axin al, 21hor al, 10hout 21h, al ; disable mouse interruptssti ; allow interrupts for a short time, to flush possible pending KB/mouse requestsmov al, 0adhout 64h, al ; disable kb interfacepop axcmp al, 1cli ; from now on we are working with ints disabled, as the following code is highly non re-entrantjb short en_disje short resetcmp al, 3jb short samplingje short resolutioncmp al, 5jb short gettypeje short resetcmp al, 6je short extend; ------------- set handlermov HandlerPtr[0], bxmov HandlerPtr[2], esjmp short exit_success1; ------------- enable/disableen_dis:mov ax, 02f5h ; ah = invalid inputsub al, bhcmp bh, ahjnc short errexitmov ah, alcall sendcmd ; enable/disable data reporting (CF = 1)if_err1:jc short if_errexit_success:mov byte ptr DataCounter, 0exit_success1:xor ah, ah ; successjmp short exitok; ------------- resetreset:mov ah, 0f6h ; set defaultsstc ; mouse commandcall sendcmdjc short if_errmov bx, 00aahmov byte ptr PacketSize, bh ; 3bytes packetjmp short exit_success; ------------- samplingsampling:cmp bh, 6badparam:mov ah, 2 ; invalid inputja short errexitshr bx, 8mov ah, cs:sample_tbl[bx]push axmov ah, 0f3h ; st sample ratesend2c:stccall sendcmdpop axjc short if_err1send1c:stccall sendcmdjmp short if_err1; ------------- resolutionresolution:cmp bh, 3ja short badparampush bxmov ah, 0e8h ; set resolutionjmp short send2c; ------------- gettypegettype:mov ah, 0f2hstccall sendcmdjc short if_err1call getps2bytejc short if_err1mov bh, alneg al ; CF=1 if al != 0adc al, bhmov byte ptr PacketSize, al ; 3 or 4 bytes packetjmp short exit_success; ------------- extended commandsextend:test bh, bhjnz short setscalingmov ah, 0e9h ; status requeststccall sendcmdjc short if_err1call getps2bytejc short if_err1mov bl, alcall getps2bytejc short if_err1mov cl, alcall getps2bytejc short if_err1pop dxpush ax ; replace dx on stackjmp short exit_successsetscaling:cmp bh, 2ja short badparammov ah, 0e5h ; set scaling 1:1 or 2:1add ah, bhjmp short send1csample_tbl db 10, 20, 40, 60, 80, 100, 200SysParams 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]>;1ehEndBuf equ <ds:[82h]>;3ehint16 proc nearpush dspush sipush 40hpop dsxchg al, ah ;shorter opcodes for al than ahdec axtest al, 0EFh ;Check for 01h and 11hjz short TestKey ;TestKey does not need cldinc axcldtest al, 0EFh ;Check for 0h and 10hjz short GetKeycmp al, 3 ;Check for 02h and 03hjb short GetStatusje short SetAutoRptcmp al, 5 ;Check for StoreKey function.je short StoreKeycmp al, 9 ;Get KB functionalityje short kbfunccmp al, 12h ;Extended status callje short ExtStatuscmp al, 92h ;stupid keyb.comjne short Exitkbfunc:mov al, 24h ;AL=20h (fn 10h, 12h supported, set typematic supported)Exit:pop sipop dsiret ; unknown function, Restores flags.GetKey1: ; wait for interrupthltGetKey: ; ----------- fn 00h, 10hmov ah, 11hint 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 HeadPtrcmp si, EndBufjb short noWrapmov si, BuffernoWrap:mov HeadPtr, sijmp short ExitTestKey: ; ---------- fn 01hmov si, HeadPtrcmp si, TailPtr ;ZF=1, if empty bufferlodsw ;BIOS returns avail keycode.sti ;Ints back on.pop sipop dsretf 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 awayinc siinc si ;Move on to next entry in bufcmp si, EndBufjb short NoWrap1mov si, BufferNoWrap1:mov al, 1 ;no roomcmp si, HeadPtr ;Data overrun?je short Exit ;if so, ignore key entry.mov TailPtr, sidec ax ;al=0jmp short ExitExtStatus: ; ------- fn 12h - Retrieve the extended keyboard status and return it in AH, and the standard keyboard status in AL.mov al, KbdFlags2and 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, KbdFlags3and ah, 1100b ;Grab rt alt/ctrl bits.or ah, al ;Merge into AH.GetStatus: ; --------- fn 02hmov al, KbdFlags1 ;Just return Std Status.Exit1:jmp short ExitSetAutoRpt: ; ------ fn 03hcmp ah, 5jne short Exitpush dxshl bh, 5and bl, 1fhor bl, bhand bl, 7fhmov ah, 0 ; wait LED update progress to finalizecall WaitFlag ; leaves with IF=0jc short timeoutor byte ptr KbdFlags4, SetRepeat ; set auto repeat in progressmov ah, 0f3h ; set typematic rate and delaypush bxxor bl, bl ; send to kbcall sendps2bytepop bxjc short timeout1 ; send timeoutmov ah, SetRepeat or AckReceived ; test if ACK receivedcall WaitFlagjc short timeout1mov ah, blxor bl, bl ; send to kbcall sendps2byte ; send datatimeout1:and byte ptr KbdFlags4, not SetRepeattimeout:pop dxjmp short Exit1WaitFlag: ; ah = desired KbdFlags4 & (AckReceived | LEDUpdate | SetRepeat)mov dx, 3dahmov bh, 8*25 ; wait for max 25 * VGA frame timewf_loop:climov al, KbdFlags4and al, AckReceived or LEDUpdate or SetRepeatcmp al, ahje short wf_ok ; flag ok, CF=0stiin al, dx ; get vblankxor al, bhand al, 8hsub bh, aljnc short wf_loop ; IBF - buffer full, no timeoutwf_ok:retint16 endp; --------------------- INT 18h - BIOS Basic ------------------int18 proc nearpush cspop esmov si, offset booterrmsgcall prts;-------------- RS232 bootstrapmov al, 0b4hout 43h, almov ax, 0f000hout 42h, alout 42h, al ; 18Hz PIT CH2mov ds,axmov es,axmov si,100hcall srecbclimov bh,ahcall srecbmov bl,ahsloop:call srecbmov [si],ahinc sidec bxjnz short sloopdb 0eahdw 100h,0f000hbooterrmsg db 'No boot device available, waiting on RS232 (115200bps, f000:100) ...', 13, 10, 0int18 endp; --------------------- INT 19h - OS Bootstrap loader ------------------int19 proc nearmov ax, 201hmov cx, 1mov dx, 80hpush 0pop esmov bx, 7c00hint 13hjc int19errdb 0eahdw 7c00h, 0 ; jmp far 0000h:7c00hint19err:int 18hint19 endp; --------------------- INT 1ah - Get System Time ------------------int1a proc nearpush dspush 40hpop dscmp ah, 1ja clockexitje setclockmov dx, ds:[6ch] ; read clockmov cx, ds:[6eh]mov al, ds:[70h]clockexit1:mov byte ptr ds:[70h], 0clockexit:cmc ; CF = 1 on errorpop dsstiretf 2setclock:mov ds:[6ch], dxmov ds:[6eh], cxstcjmp short clockexit1int1a endp; --------------------- INT 70h - RTC ------------------int70 proc nearpush dspush 40hpop dstest byte ptr UWaitFlag, 1 ; is wait in progress?jz short exitsub word ptr WaitCount[0], 1000sbb word ptr WaitCount[2], 0jnc short exitmov byte ptr UWaitFlag, 0push bxlds bx, UFPtror byte ptr [bx], 80hpop bxexit:pop dsiretint70 endp; --------------------- INT 74h - mouse ------------------int74 proc nearcldpushapush dspush 40hpop dsmov ah, 0in al, 60hmov bx, axinc byte ptr DataCountermov al, DataCountermov si, axsub al, 3ja short docallmov DataBuffer[si-1], blcmp al, PacketSizejne short nocallmov bl, 0docall:mov byte ptr DataCounter, bh ; BH=0mov si, offset DataBuffer-2lodswor ax, [si-4]jz short nocallstipush esmov ah, 0lodsbpush axlodsbpush axlodsbpush axpush bxcall far ptr [si-7]add sp, 8pop esnocall:pop dspopairetint74 endp; ---------------- serial receive byte 115200 bps --------------srecb: mov ah, 80hmov dx, 3dahmov cx, -5aeh ; (half start bit)srstb: in al, dxshr al, 2jc short srstbin al, 42h ; lo counteradd ch, alin al, 42h ; hi counter, ignorel1:call dlybitin al, dxshr al, 2rcr ah, 1jnc short l1dlybit:sub cx, 0a5bh ; (full bit)dly1:in al, 42hcmp al, chin al, 42hjnz short dly1ret; -------------------- KB/Mouse access ----------------sendps2byte proc near ; ah=data, bl!=0 for mouse, 0 for kb. returns cf=1 if timeout (al = 8); changes BH, ALpush dxmov dx, 3dahmov bh, 8*5sps2b2:in al, 64htest al, 2jz short sps2b1; buffer emptyin al, dx ; get vblankxor al, bhand al, 8hsub bh, aljnc short sps2b2; IBF - buffer full, no timeoutjmp short exit ; timeout, CF=1sps2b1:test bl, bl ; CF=0jz short sps2_kbmov al, 0d4h ; next mouseout 64h, alsps2_kb:mov al, ahout 60h, al ; send byteexit:pop dxretsendps2byte endpgetps2byte proc near ; returns al=data, zf=0 for mouse, 1 for kb, cf=1 if timeout (al=8); changes BH, DX, ALmov dx, 3dahmov bh, 8*5gps2b2:in al, 64htest al, 1jnz short gps2b1 ; OBF (buffer full), continuein al, dx ; get vblankxor al, bhand al, 8sub bh, aljnc short gps2b2 ; buffer empty, no timeoutret ; timeout, CF=1gps2b1:test al, 20h ; CF=0, ZF <- !MOBFin al, 60h ; read byte (if IF=1, this data may be invalid)retgetps2byte endpsendcmd proc near ; ah = command, CF=1 for mouse, CF=0 for kb. returns CF=1 on errorsbb bl, bl ; bl <- CFcall sendps2bytejc short exitretry:call getps2bytejc short exitcmp al, 0fah ; ack (returns CF=1 on error, when al=8)jne short retryexit:retsendcmd endpenableKbIfPresent proc near ; input DS = 40h; modify AL, flagstest byte ptr KbdFlags3, 10hjz short noenablekbmov al, 0aehout 64h, al ; enable kb interfacenoenablekb:retenableKbIfPresent endp; ----------------------- default interrupt handler ---------------defint proc neariretdefint endp; ------------------------------- flush --------------------------flush:pop cs:flushretflush_nostack:mov cs:flushbh, bhmov bh, 7 ; flush all 7 cache lines (the 8th one is CS:IP)flush1:test bl, cs:[bx + 0e000h]dec bhjnz short flush1mov bh, cs:flushbhjmp word ptr cs:flushretflushret dw 0flushbh db 0; ------------------------------- misc --------------------------dispAX:push dxxor dx, dxdiv word ptr cs:tentest ax, axjz dispAX1call dispAXdispAX1:xchg ax, dxadd ax, 0e00h + '0'int 10hpop dxretten dw 10prts: ; es:si = stringmov ah, 0ehlodsb es:[si]or al, aljz short prtseint 10hjmp short prtsprtse:ret;--------------------- read/write byte ----------------------sdrb: mov al,0ffhsdsb: ; in AL=byte, DX = 03dah, out AX=resultout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, alin ax, dxret;--------------------- write block ----------------------sdwblk proc near ; in SI=data ptr, DX=03dah, CX=sizeshr cx, 1sdwblk1:lodsbout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, allodsbout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, aladd ax, axout dx, alloop short sdwblk1retsdwblk endp;--------------------- read block ----------------------sdrblk proc near ; in DI=data ptr, DX=03dah, CX=size. Returns CF = 0mov al, 0ffhout dx, alshr cx, 1 ; CF = 0out dx, aljmp short sdrblk2sdrblk1:out dx, almov [di], ahout dx, alinc disdrblk2:out dx, alnopout dx, alnopout dx, alnopout dx, alnopout dx, alnopout dx, alin ax, dxout dx, almov [di], ahout dx, alinc diout dx, alnopout dx, alnopout dx, alnopout dx, alnopout dx, alnopout dx, alin ax, dxloop short sdrblk1mov [di], ahinc diretsdrblk endp;--------------------- verify block ----------------------sdvblk: ; in DI=data ptr, DX=03dah, CX=size. Returns CF=1 on errorpush bxxor bl, blsdvblk1:call sdrbsub ah, [di]or bl, ahinc diloop short sdvblk1neg bl ; CF=1 if BL != 0pop bxret;--------------------- write command ----------------------sdcmd8T:call sdrbsdcmd: ; in SI=6 bytes cmd buffer, DX=03dah, out AH = 0ffh on errormov cx, 6call sdwblksdresp:xor si, sisdresp1:call sdrbinc sijz short sdcmd1cmp ah, 0ffhje short sdresp1sdcmd1: ret;--------------------- read ----------------------sdverify:push sdvblkjmp short sdread1sdread: ; DX:AX sector, ES:BX buffer, CX=sectors. returns AX=read sectorspush sdrblk ; push proc address (read or verify) on stacksdread1:push axmov al, dlpush axmov dl, 51h ; CMD17cmp cx, 1je short sdr1sinc dx ; CMD18 - multiple sectorssdr1s:push dxmov si, spmov dx, 3dahmov ah, 1out dx, ax ; CS onmov di, bxmov bx, cxmov bp, cx ; save sectors numberpush sspop dscall sdcmdadd sp, 6or ah, ahjnz short sdr11 ; errorpush espop dssdrms:mov ax, dishr ax, 4mov si, dsadd ax, simov ds, axand di, 15call sdresp ; wait for 0feh tokencmp ah, 0fehjne short sdr11; read token errormov ch, 2 ; 512 byte sectorpop sicall si ; sdrblk or sdvblkpush sipushfcall sdrb ; ignore CRCcall sdrb ; ignore CRCpopfjc short sdr3 ; verify errordec bxjnz short sdrms; multiple sectorssdr3:cmp bp, 1je short sdr11; single sectormov si, offset SD_CMD12 ; stop transferpush cspop dscall sdcmdsdr2:shr ah, 1jnc short sdr11call sdrbjmp short sdr2sdr11:pop ax ; remove proc address from stacksdr1:xor ax, axout dx, axcall sdrb ; 8Tmov ax, bpsub ax, bxret;--------------------- write ----------------------sdwrite: ; DX:AX sector, ES:BX buffer, CX=sectors, returns AX=wrote sectorspush axmov al, dlpush axmov dl, 58h ; CMD24cmp cx, 1je short sdw1sinc dx ; CMD25 - multiple sectorssdw1s:push dxmov si, spmov dx, 3dahmov ah, 1out dx, ax ; CS onmov bp, cx ; save sectors numberpush sspop dscall sdcmdadd sp, 6mov si, bxmov bx, bpor ah, ahjnz short sdr1 ; errorpush espop dssdwms:mov ax, sishr ax, 4mov di, dsadd ax, dimov ds, axand si, 15mov al, 0feh ; start tokencmp bp, 1je short sdw1s1mov al, 0fch ; multiple sectorssdw1s1:call sdsbmov ch, 2 ; 512 byte sectorcall sdwblkcall sdrb ; ignore CRCcall sdrb ; ignore CRCcall sdrb ; read response byte xxx00101and ah, 0ehcmp ah, 4jne short sdr1 ; write errorsdwwait:call sdrbshr ah, 1jnc short sdwwait ; wait write completiondec bxjnz short sdwms ; multiple sectorscmp bp, 1je short sdr1mov al, 0fdh ; multiple end transfercall sdsbsdwwait1:call sdrbshr ah, 1jnc short sdwwait1 ; wait write completionjmp sdr1;--------------------- init SD ----------------------sdinit proc near ; returns AX = num kilosectorspush dspush cxpush dxpush sipush dimov dx, 3dahmov cx, 10sdinit1: ; send 80Tcall sdrbloop short sdinit1mov ah, 1out dx, ax ; select SDmov si, offset SD_CMD0push cspop dscall sdcmddec ahjnz short sdexit ; errormov si, offset SD_CMD8call sdcmd8Tdec ahjnz short sdexit ; errormov cl, 4sub sp, cxmov di, sppush sspop dscall sdrblkpop axpop axcmp ah, 0aahjne short sdexit ; CMD8 errorrepinit:mov si, offset SD_CMD55push cspop dscall sdcmd8Tcall sdrbmov si, offset SD_CMD41call sdcmddec ahjz short repinitmov si, offset SD_CMD58call sdcmd8Tmov cl, 4sub sp, cxmov di, sppush sspop dscall sdrblkpop axtest al, 40h ; test OCR bit 30 (CCS)pop axjz short sdexit; no SDHCmov si, offset SD_CMD9 ; get size infopush cspop dscall sdcmd8Tor ah, ahjnz short sdexitcall sdresp ; wait for 0feh tokencmp ah, 0fehjne short sdexitmov cl, 18 ; 16bytes + 2bytes CRCsub sp, cxmov di, sppush sspop dscall sdrblkmov cx, [di-10]rol cx, 8inc cxmov sp, disdexit:xor ax, ax ; raise CSout dx, axcall sdrbpop dipop sipop dxmov ax, cxpop cxpop dsretsdinit endpSD_CMD0 db 40h, 0, 0, 0, 0, 95hSD_CMD8 db 48h, 0, 0, 1, 0aah, 087hSD_CMD9 db 49h, 0, 0, 0, 0, 0ffhSD_CMD12 db 4ch, 0, 0, 0, 0, 0ffhSD_CMD41 db 69h, 40h, 0, 0, 0, 0ffhSD_CMD55 db 77h, 0, 0, 0, 0, 0ffhSD_CMD58 db 7ah, 0, 0, 0, 0, 0ffhdefault_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,2ahdb 15h,15h,15h, 15h,15h,3fh, 15h,3fh,15h, 15h,3fh,3fh, 3fh,15h,15h, 3fh,15h,3fh, 3fh,3fh,15h, 3fh,3fh,3fhdb 00h,00h,00h, 05h,05h,05h, 08h,08h,08h, 0bh,0bh,0bh, 0eh,0eh,0eh, 11h,11h,11h, 14h,14h,14h, 18h,18h,18hdb 1ch,1ch,1ch, 20h,20h,20h, 24h,24h,24h, 28h,28h,28h, 2dh,2dh,2dh, 32h,32h,32h, 38h,38h,38h, 3fh,3fh,3fhdb 00h,00h,3fh, 10h,00h,3fh, 1fh,00h,3fh, 2fh,00h,3fh, 3fh,00h,3fh, 3fh,00h,2fh, 3fh,00h,1fh, 3fh,00h,10hdb 3fh,00h,00h, 3fh,10h,00h, 3fh,1fh,00h, 3fh,2fh,00h, 3fh,3fh,00h, 2fh,3fh,00h, 1fh,3fh,00h, 10h,3fh,00hdb 00h,3fh,00h, 00h,3fh,10h, 00h,3fh,1fh, 00h,3fh,2fh, 00h,3fh,3fh, 00h,2fh,3fh, 00h,1fh,3fh, 00h,10h,3fhdb 1fh,1fh,3fh, 27h,1fh,3fh, 2fh,1fh,3fh, 37h,1fh,3fh, 3fh,1fh,3fh, 3fh,1fh,37h, 3fh,1fh,2fh, 3fh,1fh,27hdb 3fh,1fh,1fh, 3fh,27h,1fh, 3fh,2fh,1fh, 3fh,37h,1fh, 3fh,3fh,1fh, 37h,3fh,1fh, 2fh,3fh,1fh, 27h,3fh,1fhdb 1fh,3fh,1fh, 1fh,3fh,27h, 1fh,3fh,2fh, 1fh,3fh,37h, 1fh,3fh,3fh, 1fh,37h,3fh, 1fh,2fh,3fh, 1fh,27h,3fhdb 2dh,2dh,3fh, 31h,2dh,3fh, 36h,2dh,3fh, 3ah,2dh,3fh, 3fh,2dh,3fh, 3fh,2dh,3ah, 3fh,2dh,36h, 3fh,2dh,31hdb 3fh,2dh,2dh, 3fh,31h,2dh, 3fh,36h,2dh, 3fh,3ah,2dh, 3fh,3fh,2dh, 3ah,3fh,2dh, 36h,3fh,2dh, 31h,3fh,2dhdb 2dh,3fh,2dh, 2dh,3fh,31h, 2dh,3fh,36h, 2dh,3fh,3ah, 2dh,3fh,3fh, 2dh,3ah,3fh, 2dh,36h,3fh, 2dh,31h,3fhdb 00h,00h,1ch, 07h,00h,1ch, 0eh,00h,1ch, 15h,00h,1ch, 1ch,00h,1ch, 1ch,00h,15h, 1ch,00h,0eh, 1ch,00h,07hdb 1ch,00h,00h, 1ch,07h,00h, 1ch,0eh,00h, 1ch,15h,00h, 1ch,1ch,00h, 15h,1ch,00h, 0eh,1ch,00h, 07h,1ch,00hdb 00h,1ch,00h, 00h,1ch,07h, 00h,1ch,0eh, 00h,1ch,15h, 00h,1ch,1ch, 00h,15h,1ch, 00h,0eh,1ch, 00h,07h,1chdb 0eh,0eh,1ch, 11h,0eh,1ch, 15h,0eh,1ch, 18h,0eh,1ch, 1ch,0eh,1ch, 1ch,0eh,18h, 1ch,0eh,15h, 1ch,0eh,11hdb 1ch,0eh,0eh, 1ch,11h,0eh, 1ch,15h,0eh, 1ch,18h,0eh, 1ch,1ch,0eh, 18h,1ch,0eh, 15h,1ch,0eh, 11h,1ch,0ehdb 0eh,1ch,0eh, 0eh,1ch,11h, 0eh,1ch,15h, 0eh,1ch,18h, 0eh,1ch,1ch, 0eh,18h,1ch, 0eh,15h,1ch, 0eh,11h,1chdb 14h,14h,1ch, 16h,14h,1ch, 18h,14h,1ch, 1ah,14h,1ch, 1ch,14h,1ch, 1ch,14h,1ah, 1ch,14h,18h, 1ch,14h,16hdb 1ch,14h,14h, 1ch,16h,14h, 1ch,18h,14h, 1ch,1ah,14h, 1ch,1ch,14h, 1ah,1ch,14h, 18h,1ch,14h, 16h,1ch,14hdb 14h,1ch,14h, 14h,1ch,16h, 14h,1ch,18h, 14h,1ch,1ah, 14h,1ch,1ch, 14h,1ah,1ch, 14h,18h,1ch, 14h,16h,1chdb 00h,00h,10h, 04h,00h,10h, 08h,00h,10h, 0ch,00h,10h, 10h,00h,10h, 10h,00h,0ch, 10h,00h,08h, 10h,00h,04hdb 10h,00h,00h, 10h,04h,00h, 10h,08h,00h, 10h,0ch,00h, 10h,10h,00h, 0ch,10h,00h, 08h,10h,00h, 04h,10h,00hdb 00h,10h,00h, 00h,10h,04h, 00h,10h,08h, 00h,10h,0ch, 00h,10h,10h, 00h,0ch,10h, 00h,08h,10h, 00h,04h,10hdb 08h,08h,10h, 0ah,08h,10h, 0ch,08h,10h, 0eh,08h,10h, 10h,08h,10h, 10h,08h,0eh, 10h,08h,0ch, 10h,08h,0ahdb 10h,08h,08h, 10h,0ah,08h, 10h,0ch,08h, 10h,0eh,08h, 10h,10h,08h, 0eh,10h,08h, 0ch,10h,08h, 0ah,10h,08hdb 08h,10h,08h, 08h,10h,0ah, 08h,10h,0ch, 08h,10h,0eh, 08h,10h,10h, 08h,0eh,10h, 08h,0ch,10h, 08h,0ah,10hdb 0bh,0bh,10h, 0ch,0bh,10h, 0dh,0bh,10h, 0fh,0bh,10h, 10h,0bh,10h, 10h,0bh,0fh, 10h,0bh,0dh, 10h,0bh,0chdb 10h,0bh,0bh, 10h,0ch,0bh, 10h,0dh,0bh, 10h,0fh,0bh, 10h,10h,0bh, 0fh,10h,0bh, 0dh,10h,0bh, 0ch,10h,0bhdb 0bh,10h,0bh, 0bh,10h,0ch, 0bh,10h,0dh, 0bh,10h,0fh, 0bh,10h,10h, 0bh,0fh,10h, 0bh,0dh,10h, 0bh,0ch,10hdb 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00h, 00h,00h,00hIFDEF SCANCODE1 ; use SCANCODE1KeyIndex:db 0, 82, 49, 50, 52, 51, 54, 55 ;0-7db 56, 57, 60, 59, 65, 68, 72, 47 ;8-fdb 1, 5, 9, 13, 12, 18, 21, 23 ;10-17db 24, 26, 67, 70, 69, 0, 4, 3 ;18-1fdb 8, 11, 17, 16, 20, 22, 25, 64 ;20-27db 66, 48, 0, 71, 2, 7, 6, 10 ;28-2fdb 15, 14, 19, 58, 61, 62, 0, 87 ;30-37db 0, 53, 0, 40, 41, 39, 46, 38 ;38-3fdb 45, 90, 44, 79, 43, 0, 89, 29 ;40-47db 34, 36, 86, 28, 37, 33, 84, 27 ;48-4fdb 32, 35, 30, 31, 0, 0, 0, 83 ;50-57db 42E0KeyList:db 35h, 1ch, 4fh, 4bh, 47h, 52h, 53h, 50h, 4dh, 48h, 51h, 49hELSE ; use SCANCODE2KeyIndex:db 0, 79, 0, 38, 39, 40, 41, 42db 0, 43, 44, 45, 46, 47, 48, 0db 0, 0, 0, 0, 0, 1, 49, 0db 0, 0, 2, 3, 4, 5, 50, 0db 0, 6, 7, 8, 9, 51, 52, 0db 0, 53, 10, 11, 12, 13, 54, 0db 0, 14, 15, 16, 17, 18, 55, 0db 0, 0, 19, 20, 21, 56, 57, 0db 0, 58, 22, 23, 24, 59, 60, 0db 0, 61, 62, 25, 64, 26, 65, 0db 0, 0, 66, 0, 67, 68, 0, 0db 0, 0, 69, 70, 0, 71, 0, 0db 0, 0, 0, 0, 0, 0, 72, 0db 0, 27, 0, 28, 29, 0, 0, 0db 30, 31, 32, 37, 33, 34, 82, 0db 83, 84, 35, 86, 87, 36, 89, 0db 0, 0, 0, 90E0KeyList:db 4ah, 5ah, 69h, 6bh, 6ch, 70h, 71h, 72h, 74h, 75h, 7ah, 7dhENDIFE0KeyIndex:db 63, 69, 73, 74, 75, 76, 77, 78, 80, 81, 85, 88KeyCode:; Keys affected by CapsLock; norm shft ctrl altdw 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 NumLockdw 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 Ndw 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 0fff0hdb 0eahdw coldboot, 0f000hdb '02/05/13'db 0ffh, 0ffh, 0end bios
