VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS/orgs.asm@ 49286

Last change on this file since 49286 was 49286, checked in by vboxsync, 11 years ago

BIOS: Added invalid opcode handler.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 37.8 KB
Line 
1;;
2;; Copyright (C) 2006-2011 Oracle Corporation
3;;
4;; This file is part of VirtualBox Open Source Edition (OSE), as
5;; available from http://www.virtualbox.org. This file is free software;
6;; you can redistribute it and/or modify it under the terms of the GNU
7;; General Public License (GPL) as published by the Free Software
8;; Foundation, in version 2 as it comes in the "COPYING" file of the
9;; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
10;; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
11;; --------------------------------------------------------------------
12;;
13;; This code is based on:
14;;
15;; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
16;;
17;; Copyright (C) 2002 MandrakeSoft S.A.
18;;
19;; MandrakeSoft S.A.
20;; 43, rue d'Aboukir
21;; 75002 Paris - France
22;; http://www.linux-mandrake.com/
23;; http://www.mandrakesoft.com/
24;;
25;; This library is free software; you can redistribute it and/or
26;; modify it under the terms of the GNU Lesser General Public
27;; License as published by the Free Software Foundation; either
28;; version 2 of the License, or (at your option) any later version.
29;;
30;; This library is distributed in the hope that it will be useful,
31;; but WITHOUT ANY WARRANTY; without even the implied warranty of
32;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33;; Lesser General Public License for more details.
34;;
35;; You should have received a copy of the GNU Lesser General Public
36;; License along with this library; if not, write to the Free Software
37;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
38;;
39;;
40
41
42; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
43; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
44; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
45; a choice of LGPL license versions is made available with the language indicating
46; that LGPLv2 or any later version may be used, or where a choice of which version
47; of the LGPL is applied is otherwise unspecified.
48
49EBDA_SEG equ 09FC0h ; starts at 639K
50EBDA_SIZE equ 1 ; 1K
51BASE_MEM_IN_K equ (640 - EBDA_SIZE)
52
53CMOS_ADDR equ 070h
54CMOS_DATA equ 071h
55
56
57PIC_CMD_EOI equ 020h
58PIC_MASTER equ 020h
59PIC_SLAVE equ 0A0h
60
61BIOS_FIX_BASE equ 0E000h
62
63SYS_MODEL_ID equ 0FCh ; PC/AT
64SYS_SUBMODEL_ID equ 0
65BIOS_REVISION equ 1
66
67BIOS_BUILD_DATE equ '06/23/99'
68BIOS_COPYRIGHT equ 'Oracle VM VirtualBox BIOS'
69
70BX_ROMBIOS32 equ 0
71BX_CALL_INT15_4F equ 1
72
73;; Set a fixed BIOS location, with a marker for verification
74BIOSORG macro addr
75 org addr - BIOS_FIX_BASE - 2
76 db 'XM'
77 endm
78
79;; Set an interrupt vector (not very efficient if multiple vectors are
80;; programmed in one go)
81SET_INT_VECTOR macro vec, segm, offs
82 mov ax, offs
83 mov ds:[vec*4], ax
84 mov ax, segm
85 mov ds:[vec*4+2], ax
86endm
87
88; Set up an environment C code expects. DS must point to the BIOS segment
89; and the direction flag must be cleared(!)
90C_SETUP macro
91 push cs
92 pop ds
93 cld
94endm
95
96;; External function in separate modules
97extrn _dummy_isr_function:near
98extrn _log_bios_start:near
99extrn _nmi_handler_msg:near
100extrn _int18_panic_msg:near
101extrn _int09_function:near
102extrn _int13_diskette_function:near
103extrn _int13_eltorito:near
104extrn _int13_cdemu:near
105extrn _int13_cdrom:near
106extrn _cdemu_isactive:near
107extrn _cdemu_emulated_drive:near
108extrn _int13_harddisk:near
109extrn _int13_harddisk_ext:near
110extrn _int14_function:near
111extrn _int15_function:near
112extrn _int15_function_mouse:near
113extrn _int15_function32:near
114extrn _int16_function:near
115extrn _int17_function:near
116extrn _int19_function:near
117extrn _int1a_function:near
118extrn _pci16_function:near
119extrn _int70_function:near
120extrn _int74_function:near
121extrn _apm_function:near
122extrn _ata_init:near
123extrn _ahci_init:near
124extrn _scsi_init:near
125extrn _ata_detect:near
126extrn _cdemu_init:near
127extrn _keyboard_init:near
128extrn _print_bios_banner:near
129extrn _inv_op_handler:near
130
131
132;; Symbols referenced from C code
133public _diskette_param_table
134public _pmode_IDT
135public _rmode_IDT
136public post
137public eoi_both_pics
138public rtc_post
139
140;; Additional publics for easier disassembly and debugging
141ifndef DEBUG
142 DEBUG equ 1
143endif
144ifdef DEBUG
145
146public int08_handler
147public int0e_handler
148public int11_handler
149public int12_handler
150public int13_handler
151public int13_relocated
152public int15_handler
153public int17_handler
154public int19_handler
155public int19_relocated
156public dummy_iret
157public nmi
158public rom_fdpt
159public cpu_reset
160public normal_post
161public eoi_jmp_post
162public eoi_master_pic
163public ebda_post
164public hard_drive_post
165public int13_legacy
166public int70_handler
167public int75_handler
168public int15_handler32
169public int15_handler_mouse
170public iret_modify_cf
171public rom_scan
172public rom_checksum
173public init_pic
174public floppy_post
175public int13_out
176public int13_disk
177public int13_notfloppy
178public int13_legacy
179public int13_noeltorito
180public int1c_handler
181public int10_handler
182public int74_handler
183public int76_handler
184public detect_parport
185public detect_serial
186public font8x8
187
188endif
189
190;; NOTE: The last 8K of the ROM BIOS are peppered with fixed locations which
191;; must be retained for compatibility. As a consequence, some of the space is
192;; going to be wasted, but the gaps should be filled with miscellaneous code
193;; and data when possible.
194
195.286p
196
197BIOSSEG segment 'CODE'
198 assume cs:BIOSSEG
199
200;;
201;; Start of fixed code - eoi_jmp_post is kept here to allow short jumps.
202;;
203 BIOSORG 0E030h
204eoi_jmp_post:
205 call eoi_both_pics
206 xor ax, ax
207 mov ds, ax
208 jmp dword ptr ds:[0467h]
209
210eoi_both_pics:
211 mov al, PIC_CMD_EOI
212 out PIC_SLAVE, al
213eoi_master_pic:
214 mov al, PIC_CMD_EOI
215 out PIC_MASTER, al
216 ret
217
218 ;; routine to write the pointer in DX:AX to memory starting
219 ;; at DS:BX (repeat CX times)
220 ;; - modifies BX, CX
221set_int_vects proc near
222
223 mov [bx], ax
224 mov [bx+2], dx
225 add bx, 4
226 loop set_int_vects
227 ret
228
229set_int_vects endp
230
231;; --------------------------------------------------------
232;; POST entry point
233;; --------------------------------------------------------
234 BIOSORG 0E05Bh
235post:
236 cli
237
238 ;; Check if in protected (V86) mode. If so, the CPU needs
239 ;; to be reset.
240 smsw ax
241 test ax, 1
242 jz in_real_mode
243
244 ;; Reset processor to get out of protected mode. Use system
245 ;; port instead of KBC.
246 ;; NB: We only need bit 0 to be set in AL, which we just
247 ;; determined to be the case.
248 out 92h, al
249 jmp $ ; not strictly necessary in a VM
250
251
252in_real_mode:
253 ;; TODO: Check KBC system flag first
254
255 ;; read the CMOS shutdown status
256 mov al, 0Fh
257 out CMOS_ADDR, al
258 in al, CMOS_DATA
259
260 ;; save status
261 xchg ah, al
262
263 ;; reset the shutdown status in CMOS
264 mov al, 0Fh
265 out CMOS_ADDR, al
266 mov al, 0
267 out CMOS_DATA, al
268
269 ;; pre-check the shutdown status - shutdown codes 9/A leave
270 ;; the hardware alone
271 mov al, ah
272 cmp al, 09h
273 jz check_shutdown
274 cmp al, 0Ah
275 jz check_shutdown
276
277 xor al, al
278
279 ;; reset the DMA controllers
280 out 00Dh, al
281 out 0DAh, al
282
283 ;; then initialize the DMA controllers
284 mov al, 0C0h
285 out 0D6h, al ; enable channel 4 cascade
286 mov al, 0
287 out 0D4h, al ; unmask channel 4
288
289check_shutdown:
290 ;; examine the shutdown status code
291 mov al, ah
292 cmp al, 0
293 jz normal_post
294
295 cmp al, 0Dh
296 jae normal_post
297 cmp al, 9
298 jne check_next_std
299 jmp return_blkmove
300check_next_std:
301
302 ;; 05h = EOI + jump through 40:67
303 cmp al, 5
304 je eoi_jmp_post
305
306 ;; any other shutdown status values are ignored
307 ;; OpenSolaris sets the status to 0Ah in some cases?
308 jmp normal_post
309
310normal_post:
311 ;; shutdown code 0: normal startup
312
313 ;; Set up the stack top at 0:7800h. The stack should not be
314 ;; located above 0:7C00h; that conflicts with PXE, which
315 ;; considers anything above that address to be fair game.
316 ;; The traditional locations are 30:100 (PC) or 0:400 (PC/AT).
317 mov ax, 7800h
318 mov sp, ax
319 xor ax, ax
320 mov ds, ax
321 mov ss, ax
322
323 ;; clear the bottom of memory except for the word at 40:72
324 ;; TODO: Why not clear all of it? What's the point?
325 mov es, ax
326 xor di, di
327 cld
328 mov cx, 0472h / 2
329 rep stosw
330 inc di
331 inc di
332 mov cx, (1000h - 0472h - 2) / 2
333 rep stosw
334
335 ;; clear the remaining base memory except for the top
336 ;; of the EBDA (the MP table is planted there)
337 xor bx, bx
338memory_zero_loop:
339 add bx, 1000h
340 cmp bx, 9000h
341 jae memory_cleared
342 mov es, bx
343 xor di, di
344 mov cx, 8000h ; 32K words
345 rep stosw
346 jmp memory_zero_loop
347memory_cleared:
348 mov es, bx
349 xor di, di
350 mov cx, 7FF8h ; all but the last 16 bytes
351 rep stosw
352 xor bx, bx
353
354
355 C_SETUP
356 call _log_bios_start
357
358 call pmode_setup
359
360 ;; set all interrupts in 00h-5Fh range to default handler
361 xor bx, bx
362 mov ds, bx
363 mov cx, 60h ; leave the rest as zeros
364 mov ax, dummy_iret
365 mov dx, BIOSSEG
366 call set_int_vects
367
368 ;; also set 68h-77h to default handler; note that the
369 ;; 60h-67h range must contain zeros for certain programs
370 ;; to function correctly
371 mov bx, 68h * 4
372 mov cx, 10h
373 call set_int_vects
374
375 ;; base memory in K to 40:13
376 mov ax, BASE_MEM_IN_K
377 mov ds:[413h], ax
378
379 ;; manufacturing test at 40:12
380 ;; zeroed out above
381
382 ;; set up various service vectors
383 ;; TODO: This should use the table at FEF3h instead
384 SET_INT_VECTOR 06h, BIOSSEG, int06_handler
385 SET_INT_VECTOR 11h, BIOSSEG, int11_handler
386 SET_INT_VECTOR 12h, BIOSSEG, int12_handler
387 SET_INT_VECTOR 15h, BIOSSEG, int15_handler
388 SET_INT_VECTOR 17h, BIOSSEG, int17_handler
389 SET_INT_VECTOR 18h, BIOSSEG, int18_handler
390 SET_INT_VECTOR 19h, BIOSSEG, int19_handler
391 SET_INT_VECTOR 1Ch, BIOSSEG, int1c_handler
392
393 call ebda_post
394
395 ;; PIT setup
396 SET_INT_VECTOR 08h, BIOSSEG, int08_handler
397 mov al, 34h ; timer 0, binary, 16-bit, mode 2
398 out 43h, al
399 mov al, 0 ; max count -> ~18.2 Hz
400 out 40h, al
401 out 40h, al
402
403 ;; keyboard setup
404 SET_INT_VECTOR 09h, BIOSSEG, int09_handler
405 SET_INT_VECTOR 16h, BIOSSEG, int16_handler
406
407 xor ax, ax
408 mov ds, ax
409 ;; TODO: What's the point? The BDA is zeroed already?!
410 mov ds:[417h], al ; keyboard shift flags, set 1
411 mov ds:[418h], al ; keyboard shift flags, set 2
412 mov ds:[419h], al ; keyboard Alt-numpad work area
413 mov ds:[471h], al ; keyboard Ctrl-Break flag
414 mov ds:[497h], al ; keyboard status flags 4
415 mov al, 10h
416 mov ds:[496h], al ; keyboard status flags 3
417
418 mov bx, 1Eh
419 mov ds:[41Ah], bx ; keyboard buffer head
420 mov ds:[41Ch], bx ; keyboard buffer tail
421 mov ds:[480h], bx ; keyboard buffer start
422 mov bx, 3Eh
423 mov ds:[482h], bx ; keyboard buffer end
424
425 push ds
426 C_SETUP
427 call _keyboard_init
428 pop ds
429
430
431 ;; store CMOS equipment byte in BDA
432 mov al, 14h
433 out CMOS_ADDR, al
434 in al, CMOS_DATA
435 mov ds:[410h], al
436
437 ;; parallel setup
438 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_iret
439 xor ax, ax
440 mov ds, ax
441 xor bx, bx
442 mov cl, 14h ; timeout value
443 mov dx, 378h ; parallel port 1
444 call detect_parport
445 mov dx, 278h ; parallel port 2
446 call detect_parport
447 shl bx, 0Eh
448 mov ax, ds:[410h] ; equipment word
449 and ax, 3FFFh
450 or ax, bx ; set number of parallel ports
451 mov ds:[410h], ax ; store in BDA
452
453 ;; Serial setup
454 SET_INT_VECTOR 0Bh, BIOSSEG, dummy_isr
455 SET_INT_VECTOR 0Ch, BIOSSEG, dummy_isr
456 SET_INT_VECTOR 14h, BIOSSEG, int14_handler
457 xor bx, bx
458 mov cl, 0Ah ; timeout value
459 mov dx, 3F8h ; first serial address
460 call detect_serial
461 mov dx, 2F8h ; second serial address
462 call detect_serial
463 mov dx, 3E8h ; third serial address
464 call detect_serial
465 mov dx, 2E8h ; fourth serial address
466 call detect_serial
467 shl bx, 9
468 mov ax, ds:[410h] ; equipment word
469 and ax, 0F1FFh ; bits 9-11 determine serial ports
470 or ax, bx
471 mov ds:[410h], ax
472
473 ;; CMOS RTC
474 SET_INT_VECTOR 1Ah, BIOSSEG, int1a_handler
475 SET_INT_VECTOR 4Ah, BIOSSEG, dummy_iret ; TODO: redundant?
476 SET_INT_VECTOR 70h, BIOSSEG, int70_handler
477 ;; BIOS DATA AREA 4CEh ???
478 call rtc_post
479
480 ;; PS/2 mouse setup
481 SET_INT_VECTOR 74h, BIOSSEG, int74_handler
482
483 ;; IRQ 13h (FPU exception) setup
484 SET_INT_VECTOR 75h, BIOSSEG, int75_handler
485
486 ;; Video setup
487 SET_INT_VECTOR 10h, BIOSSEG, int10_handler
488
489 call init_pic
490
491 call pcibios_init_iomem_bases
492 call pcibios_init_irqs
493
494 call rom_scan
495
496 jmp norm_post_cont
497
498
499;; --------------------------------------------------------
500;; NMI handler
501;; --------------------------------------------------------
502 BIOSORG 0E2C3h
503nmi:
504 C_SETUP
505 call _nmi_handler_msg
506 iret
507
508int75_handler:
509 out 0F0h, al ; clear IRQ13
510 call eoi_both_pics
511 int 2 ; emulate legacy NMI
512 iret
513
514
515hard_drive_post proc near
516
517 xor ax, ax
518 mov ds, ax
519 ;; TODO: Didn't we just clear the entire EBDA?
520 mov ds:[474h], al ; last HD operation status
521 mov ds:[477h], al ; HD port offset (XT only???)
522 mov ds:[48Ch], al ; HD status register
523 mov ds:[48Dh], al ; HD error register
524 mov ds:[48Eh], al ; HD task complete flag
525 mov al, 0C0h
526 mov ds:[476h], al ; HD control byte
527 ;; set up hard disk interrupt vectors
528 SET_INT_VECTOR 13h, BIOSSEG, int13_handler
529 SET_INT_VECTOR 76h, BIOSSEG, int76_handler
530 ;; INT 41h/46h: hard disk 0/1 dpt
531 ; TODO: This should be done from the code which
532 ; builds the DPTs?
533 SET_INT_VECTOR 41h, EBDA_SEG, 3Dh
534 SET_INT_VECTOR 46h, EBDA_SEG, 4Dh
535 ret
536
537hard_drive_post endp
538
539
540norm_post_cont:
541 C_SETUP
542 ;; ATA/ATAPI driver setup
543 call _ata_init
544 call _ata_detect
545
546ifdef VBOX_WITH_AHCI
547 ; AHCI driver setup
548 call _ahci_init
549endif
550
551ifdef VBOX_WITH_SCSI
552 ; SCSI driver setup
553 call _scsi_init
554endif
555
556 ;; floppy setup
557 call floppy_post
558
559 ;; hard drive setup
560 call hard_drive_post
561
562 C_SETUP ; in case assembly code changed things
563 call _print_bios_banner
564
565 ;; El Torito floppy/hard disk emulation
566 call _cdemu_init
567
568 ; TODO: what's the point of enabling interrupts here??
569 sti ; enable interrupts
570 int 19h
571 ;; does not return here
572 sti
573wait_forever:
574 hlt
575 jmp wait_forever
576 cli
577 hlt
578
579
580;;
581;; Return from block move (shutdown code 09h). Care must be taken to disturb
582;; register and memory state as little as possible.
583;;
584return_blkmove:
585 mov ax, 40h
586 mov ds, ax
587 ;; restore user stack
588 mov ss, ds:[69h]
589 mov sp, ds:[67h]
590 ;; reset A20 gate
591 in al, 92h
592 and al, 0FDh
593 out 92h, al
594 ;; ensure proper real mode IDT
595 lidt fword ptr cs:_rmode_IDT
596 ;; restore user segments
597 pop ds
598 pop es
599 ;; set up BP
600 mov bp, sp
601 ;; restore status code
602 in al, 80h
603 mov [bp+15], al
604 ;; set ZF/CF
605 cmp ah,al ; AH is zero here!
606 ;; restore registers and return
607 popa
608 sti
609 retf 2
610
611
612;; --------------------------------------------------------
613;; INT 13h handler - Disk services
614;; --------------------------------------------------------
615 BIOSORG 0E3FEh
616
617int13_handler:
618 jmp int13_relocated
619
620
621;; --------------------------------------------------------
622;; Fixed Disk Parameter Table
623;; --------------------------------------------------------
624;; BIOSORG 0E401h - fixed wrt preceding
625
626rom_fdpt:
627
628;; --------------------------------------------------------
629;; INT 19h handler - Boot load service
630;; --------------------------------------------------------
631 BIOSORG 0E6F2h
632
633int19_handler:
634 jmp int19_relocated
635
636
637
638;; --------------------------------------------------------
639;; System BIOS Configuration Table
640;; --------------------------------------------------------
641;; BIOSORG 0E6F5h - fixed wrt preceding
642; must match BIOS_CONFIG_TABLE
643bios_cfg_table:
644 dw 9 ; table size in bytes
645 db SYS_MODEL_ID
646 db SYS_SUBMODEL_ID
647 db BIOS_REVISION
648 ; Feature byte 1
649 ; b7: 1=DMA channel 3 used by hard disk
650 ; b6: 1=2 interrupt controllers present
651 ; b5: 1=RTC present
652 ; b4: 1=BIOS calls int 15h/4Fh for every key
653 ; b3: 1=wait for extern event supported (Int 15h/41h)
654 ; b2: 1=extended BIOS data area used
655 ; b1: 0=AT or ESDI bus, 1=MicroChannel
656 ; b0: 1=Dual bus (MicroChannel + ISA)
657ifdef BX_CALL_INT15_4F
658 db 74h; or USE_EBDA
659else
660 db 64h; or USE_EBDA
661endif
662 ; Feature byte 2
663 ; b7: 1=32-bit DMA supported
664 ; b6: 1=int16h, function 9 supported
665 ; b5: 1=int15h/C6h (get POS data) supported
666 ; b4: 1=int15h/C7h (get mem map info) supported
667 ; b3: 1=int15h/C8h (en/dis CPU) supported
668 ; b2: 1=non-8042 kb controller
669 ; b1: 1=data streaming supported
670 ; b0: reserved
671 db 40h
672 ; Feature byte 3
673 ; b7: not used
674 ; b6: reserved
675 ; b5: reserved
676 ; b4: POST supports ROM-to-RAM enable/disable
677 ; b3: SCSI on system board
678 ; b2: info panel installed
679 ; b1: Initial Machine Load (IML) system - BIOS on disk
680 ; b0: SCSI supported in IML
681 db 0
682 ; Feature byte 4
683 ; b7: IBM private
684 ; b6: EEPROM present
685 ; b5-3: ABIOS presence (011 = not supported)
686 ; b2: private
687 ; b1: memory split above 16Mb supported
688 ; b0: POSTEXT directly supported by POST
689 db 0
690 ; Feature byte 5 (IBM)
691 ; b1: enhanced mouse
692 ; b0: flash EPROM
693 db 0
694
695
696;; --------------------------------------------------------
697;; Baud Rate Generator Table
698;; --------------------------------------------------------
699 BIOSORG 0E729h
700
701
702;; --------------------------------------------------------
703;; INT 14h handler - Serial Communication Service
704;; --------------------------------------------------------
705 BIOSORG 0E739h
706int14_handler:
707 push ds
708 push es
709 pusha
710 C_SETUP
711 call _int14_function
712 popa
713 pop es
714 pop ds
715 iret
716
717
718
719;;
720;; Handler for unexpected hardware interrupts
721;;
722dummy_isr:
723 push ds
724 push es
725 pusha
726 C_SETUP
727 call _dummy_isr_function
728 popa
729 pop es
730 pop ds
731 iret
732
733
734rom_checksum proc near
735 push ax
736ifdef CHECKSUM_ROMS
737 push bx
738 push cx
739 xor ax, ax
740 xor bx, bx
741 xor cx, cx
742 mov ch, ds:[2]
743 shl cx, 1
744checksum_loop:
745 add al, [bx]
746 inc bx
747 loop checksum_loop
748 and al, 0FFh ; set flags
749 pop cx
750 pop bx
751else
752 xor al, al
753endif
754 pop ax
755 ret
756rom_checksum endp
757
758
759;;
760;; ROM scan - scan for valid ROMs and initialize them
761;;
762rom_scan:
763 mov cx, 0C000h ; start at C000
764rom_scan_loop:
765 mov ds, cx
766 mov ax, 4 ; scan in 2K increments
767 cmp word ptr ds:[0], 0AA55h ; look for signature
768 jne rom_scan_increment
769
770 call rom_checksum
771 jnz rom_scan_increment
772
773 mov al, ds:[2] ; set increment to ROM length
774 test al, 3
775 jz block_count_rounded
776
777 and al, 0FCh ; round up
778 add al, 4 ; to nearest 2K
779block_count_rounded:
780 xor bx, bx
781 mov ds, bx
782 push ax
783 push cx ; push segment...
784 push 3 ; ...and offset of ROM entry
785 mov bp, sp
786 call dword ptr [bp] ; call ROM init routine
787 cli ; in case ROM enabled interrupts
788 add sp, 2 ; get rid of offset
789 pop cx ; restore registers
790 pop ax
791rom_scan_increment:
792 shl ax, 5 ; convert to 16-byte increments
793 add cx, ax
794 cmp cx, 0E800h ; must encompass VBOX_LANBOOT_SEG!
795 jbe rom_scan_loop
796
797 xor ax, ax ; DS back to zero
798 mov ds, ax
799 ret
800
801init_pic proc near
802
803 mov al, 11h ; send init commands
804 out PIC_MASTER, al
805 out PIC_SLAVE, al
806 mov al, 08h ; base 08h
807 out PIC_MASTER+1, al
808 mov al, 70h ; base 70h
809 out PIC_SLAVE+1, al
810 mov al, 04h ; master PIC
811 out PIC_MASTER+1, al
812 mov al, 02h ; slave PIC
813 out PIC_SLAVE+1, al
814 mov al, 01h
815 out PIC_MASTER+1, al
816 out PIC_SLAVE+1, al
817 mov al, 0B8h ; unmask IRQs 0/1/2/6
818 out PIC_MASTER+1, al
819 mov al, 08Fh
820 out PIC_SLAVE+1, al ; unmask IRQs 12/13/14
821 ret
822
823init_pic endp
824
825ebda_post proc near
826
827 SET_INT_VECTOR 0Dh, BIOSSEG, dummy_isr ; IRQ 5
828 SET_INT_VECTOR 0Fh, BIOSSEG, dummy_isr ; IRQ 7
829 SET_INT_VECTOR 72h, BIOSSEG, dummy_isr ; IRQ 11
830 SET_INT_VECTOR 77h, BIOSSEG, dummy_isr ; IRQ 15
831
832 mov ax, EBDA_SEG
833 mov ds, ax
834 mov byte ptr ds:[0], EBDA_SIZE
835 ;; store EBDA seg in 40:0E
836 xor ax, ax
837 mov ds, ax
838 mov word ptr ds:[40Eh], EBDA_SEG
839 ret
840
841ebda_post endp
842
843
844
845;; --------------------------------------------------------
846;; INT 16h handler - Keyboard service
847;; --------------------------------------------------------
848 BIOSORG 0E82Eh
849int16_handler:
850 sti
851 push es
852 push ds
853 pusha
854
855 cmp ah, 0
856 je int16_F00
857
858 cmp ah, 10h
859 je int16_F00
860
861 C_SETUP
862 call _int16_function
863 popa
864 pop ds
865 pop es
866 iret
867
868int16_F00:
869 mov bx, 40h ; TODO: why 40h here and 0 elsewhere?
870 mov ds, bx
871int16_wait_for_key:
872 cli
873 mov bx, ds:[1Ah]
874 cmp bx, ds:[1Ch]
875 jne int16_key_found
876 sti
877 nop
878; TODO: review/enable?
879if 0
880 push ax
881 mov ax, 9002h
882 int 15h
883 pop ax
884endif
885 jmp int16_wait_for_key
886
887int16_key_found:
888 C_SETUP
889 call _int16_function
890 popa
891 pop ds
892 pop es
893; TODO: review/enable? If so, flags should be restored here?
894if 0
895 push ax
896 mov ax, 9202h
897 int 15h
898 pop ax
899endif
900 iret
901
902
903;; Quick and dirty protected mode entry/exit routines
904include pmode.inc
905
906;; Initialization code which needs to run in protected mode (LAPIC etc.)
907include pmsetup.inc
908
909
910KBDC_DISABLE EQU 0ADh
911KBDC_ENABLE EQU 0AEh
912KBC_CMD EQU 64h
913KBC_DATA EQU 60h
914
915;; --------------------------------------------------------
916;; INT 09h handler - Keyboard ISR (IRQ 1)
917;; --------------------------------------------------------
918 BIOSORG 0E987h
919int09_handler:
920 cli ; TODO: why? they're off already!
921 push ax
922 mov al, KBDC_DISABLE
923 out KBC_CMD, al
924
925 mov al, 0Bh
926 out PIC_MASTER, al
927 in al, PIC_MASTER
928 and al, 2
929 jz int09_finish
930
931 in al, KBC_DATA
932 push ds
933 pusha
934 cld ; Before INT 15h (and any C code)
935ifdef BX_CALL_INT15_4F
936 mov ah, 4Fh
937 stc
938 int 15h ; keyboard intercept
939 jnc int09_done
940endif
941 sti ; Only after calling INT 15h
942
943 ;; check for extended key
944 cmp al, 0E0h
945 jne int09_check_pause
946 xor ax, ax
947 mov ds, ax
948 mov al, ds:[496h] ; mf2_state |= 0x02
949 or al, 2 ; TODO: why not RMW?
950 mov ds:[496h], al
951 jmp int09_done
952
953int09_check_pause:
954 cmp al, 0E1h ; pause key?
955 jne int09_process_key
956 xor ax, ax
957 mov ds, ax ; TODO: haven't we just done that??
958 mov al, ds:[496h]
959 or al, 1
960 mov ds:[496h], al ; TODO: why not RMW?
961 jmp int09_done
962
963int09_process_key:
964 push es
965 C_SETUP
966 call _int09_function
967 pop es
968
969int09_done:
970 popa
971 pop ds
972 cli
973 call eoi_master_pic
974
975int09_finish:
976 mov al, KBDC_ENABLE
977 out KBC_CMD, al
978 pop ax
979 iret
980
981
982;; --------------------------------------------------------
983;; INT 06h handler - Invalid Opcode Exception
984;; --------------------------------------------------------
985
986int06_handler:
987 pusha
988 push es
989 push ds
990 C_SETUP
991 call _inv_op_handler
992 pop ds
993 pop es
994 popa
995 iret
996
997;; --------------------------------------------------------
998;; INT 13h handler - Diskette service
999;; --------------------------------------------------------
1000 BIOSORG 0EC59h
1001int13_diskette:
1002 jmp int13_noeltorito
1003
1004
1005
1006;; --------------------------------------------------------
1007;; INT 13h handler - Disk service
1008;; --------------------------------------------------------
1009int13_relocated:
1010 ;; check for an El-Torito function
1011 cmp ah, 4Ah
1012 jb int13_not_eltorito
1013
1014 cmp ah, 4Dh
1015 ja int13_not_eltorito
1016
1017 pusha
1018 push es
1019 push ds
1020 C_SETUP ; TODO: setup C envrionment only once?
1021 push int13_out ; simulate a call
1022 jmp _int13_eltorito ; ELDX not used
1023
1024int13_not_eltorito:
1025 push es
1026 push ax ; TODO: better register save/restore
1027 push bx
1028 push cx
1029 push dx
1030
1031 ;; check if emulation is active
1032 call _cdemu_isactive
1033 cmp al, 0
1034 je int13_cdemu_inactive
1035
1036 ;; check if access to the emulated drive
1037 call _cdemu_emulated_drive
1038 pop dx ; recover dx (destroyed by C code)
1039 push dx
1040 cmp al, dl ; INT 13h on emulated drive
1041 jne int13_nocdemu
1042
1043 pop dx
1044 pop cx
1045 pop bx
1046 pop ax
1047 pop es
1048
1049 pusha
1050 push es
1051 push ds
1052 C_SETUP ; TODO: setup environment only once?
1053
1054 push int13_out ; simulate a call
1055 jmp _int13_cdemu ; ELDX not used
1056
1057int13_nocdemu:
1058 and dl, 0E0h ; mask to get device class
1059 cmp al, dl
1060 jne int13_cdemu_inactive
1061
1062 pop dx
1063 pop cx
1064 pop bx
1065 pop ax
1066 pop es
1067
1068 push ax
1069 push cx
1070 push dx
1071 push bx
1072
1073 dec dl ; real drive is dl - 1
1074 jmp int13_legacy
1075
1076int13_cdemu_inactive:
1077 pop dx
1078 pop cx
1079 pop bx
1080 pop ax
1081 pop es
1082
1083int13_noeltorito:
1084 push ax
1085 push cx
1086 push dx
1087 push bx
1088int13_legacy:
1089 push dx ; push eltorito dx in place of sp
1090 push bp
1091 push si
1092 push di
1093 push es
1094 push ds
1095 C_SETUP ; TODO: setup environment only once?
1096
1097 ;; now the registers can be restored with
1098 ;; pop ds; pop es; popa; iret
1099 test dl, 80h ; non-removable?
1100 jnz int13_notfloppy
1101
1102 push int13_out ; simulate a near call
1103 jmp _int13_diskette_function
1104
1105int13_notfloppy:
1106 cmp dl, 0E0h
1107 jb int13_notcdrom
1108
1109 ;; ebx may be modified, save here
1110 ;; TODO: check/review 32-bit register use
1111 .386
1112 shr ebx, 16
1113 push bx
1114 call _int13_cdrom
1115 pop bx
1116 shl ebx, 16
1117 .286
1118
1119 jmp int13_out
1120
1121int13_notcdrom:
1122int13_disk:
1123 cmp ah,40h
1124 ja int13x
1125 call _int13_harddisk
1126 jmp int13_out
1127
1128int13x:
1129 call _int13_harddisk_ext
1130
1131int13_out:
1132 pop ds
1133 pop es
1134 popa
1135 iret
1136
1137
1138
1139; parallel port detection: port in dx, index in bx, timeout in cl
1140detect_parport proc near
1141
1142 push dx
1143 inc dx
1144 inc dx
1145 in al, dx
1146 and al, 0DFh ; clear input mode
1147 out dx, al
1148 pop dx
1149 mov al, 0AAh
1150 out dx, al
1151 in al, dx
1152 cmp al, 0AAh
1153 jne no_parport
1154
1155 push bx
1156 shl bx, 1
1157 mov [bx+408h], dx ; parallel I/O address
1158 pop bx
1159 mov [bx+478h], cl ; parallel printer timeout
1160 inc bx
1161no_parport:
1162 ret
1163
1164detect_parport endp
1165
1166; setial port detection: port in dx, index in bx, timeout in cl
1167detect_serial proc near
1168
1169 push dx
1170 inc dx
1171 mov al, 2
1172 out dx, al
1173 in al, dx
1174 cmp al, 2
1175 jne no_serial
1176
1177 inc dx
1178 in al, dx
1179 cmp al, 2
1180 jne no_serial
1181
1182 dec dx
1183 xor al, al
1184 pop dx
1185 push bx
1186 shl bx, 1
1187 mov [bx+400h], dx ; serial I/O address
1188 pop bx
1189 mov [bx+47Ch], cl ; serial timeout
1190 inc bx
1191 ret
1192
1193no_serial:
1194 pop dx
1195 ret
1196
1197detect_serial endp
1198
1199
1200;;
1201;; POST: Floppy drive
1202;;
1203floppy_post proc near
1204
1205 xor ax, ax
1206 mov ds, ax
1207
1208 ;; TODO: This code is really stupid. Zeroing the BDA byte
1209 ;; by byte is dumb, and it's been already zeroed elsewhere!
1210 mov al, 0
1211 mov ds:[43Eh], al ; drive 0/1 uncalibrated, no IRQ
1212 mov ds:[43Fh], al ; motor status
1213 mov ds:[440h], al ; motor timeout counter
1214 mov ds:[441h], al ; controller status return code
1215 mov ds:[442h], al ; hd/floppy ctlr status register
1216 mov ds:[443h], al ; controller status register 1
1217 mov ds:[444h], al ; controller status register 2
1218 mov ds:[445h], al ; cylinder number
1219 mov ds:[446h], al ; head number
1220 mov ds:[447h], al ; sector number
1221 mov ds:[448h], al ; bytes written
1222
1223 mov ds:[48Bh], al ; configuration data
1224
1225 mov al, 10h ; floppy drive type
1226 out CMOS_ADDR, al
1227 in al, CMOS_DATA
1228 mov ah, al ; save drive type byte
1229
1230look_drive0:
1231 ; TODO: pre-init bl to reduce jumps
1232 shr al, 4 ; drive 0 in high nibble
1233 jz f0_missing ; jump if no drive
1234 mov bl, 7 ; drv0 determined, multi-rate, chgline
1235 jmp look_drive1
1236
1237f0_missing:
1238 mov bl, 0 ; no drive 0
1239
1240look_drive1:
1241 mov al, ah ; restore CMOS data
1242 and al, 0Fh ; drive 1 in low nibble
1243 jz f1_missing
1244 or bl, 70h ; drv1 determined, multi-rate, chgline
1245f1_missing:
1246 mov ds:[48Fh], bl ; store in BDA
1247
1248 ;; TODO: See above. Dumb *and* redundant!
1249 mov al, 0
1250 mov ds:[490h], al ; drv0 media state
1251 mov ds:[491h], al ; drv1 media state
1252 mov ds:[492h], al ; drv0 operational state
1253 mov ds:[493h], al ; drv1 operational state
1254 mov ds:[494h], al ; drv0 current cylinder
1255 mov ds:[495h], al ; drv1 current cylinder
1256
1257 mov al, 2
1258 out 0Ah, al ; unmask DMA channel 2
1259
1260 SET_INT_VECTOR 1Eh, BIOSSEG, _diskette_param_table
1261 SET_INT_VECTOR 40h, BIOSSEG, int13_diskette
1262 SET_INT_VECTOR 0Eh, BIOSSEG, int0e_handler ; IRQ 6
1263
1264 ret
1265
1266floppy_post endp
1267
1268
1269bcd_to_bin proc near
1270
1271 ;; in : AL in packed BCD format
1272 ;; out: AL in binary, AH always 0
1273 shl ax, 4
1274 shr al, 4
1275 aad
1276 ret
1277
1278bcd_to_bin endp
1279
1280rtc_post proc near
1281
1282 .386
1283 ;; get RTC seconds
1284 xor eax, eax
1285 mov al, 0
1286 out CMOS_ADDR, al
1287 in al, CMOS_DATA ; RTC seconds, in BCD
1288 call bcd_to_bin ; eax now has seconds in binary
1289 mov edx, 18206507
1290 mul edx
1291 mov ebx, 1000000
1292 xor edx, edx
1293 div ebx
1294 mov ecx, eax ; total ticks in ecx
1295
1296 ;; get RTC minutes
1297 xor eax, eax
1298 mov al, 2
1299 out CMOS_ADDR, al
1300 in al, CMOS_DATA ; RTC minutes, in BCD
1301 call bcd_to_bin ; eax now has minutes in binary
1302 mov edx, 10923904
1303 mul edx
1304 mov ebx, 10000
1305 xor edx, edx
1306 div ebx
1307 add ecx, eax ; add to total ticks
1308
1309 ;; get RTC hours
1310 xor eax, eax
1311 mov al, 4
1312 out CMOS_ADDR, al
1313 in al, CMOS_DATA ; RTC hours, in BCD
1314 call bcd_to_bin ; eax now has hours in binary
1315 mov edx, 65543427
1316 mul edx
1317 mov ebx, 1000
1318 xor edx, edx
1319 div ebx
1320 add ecx, eax ; add to total ticks
1321
1322 mov ds:[46Ch], ecx ; timer tick count
1323 xor al, al ; TODO: redundant?
1324 mov ds:[470h], al ; rollover flag
1325 .286
1326 ret
1327
1328rtc_post endp
1329
1330
1331
1332;; --------------------------------------------------------
1333;; INT 0Eh handler - Diskette IRQ 6 ISR
1334;; --------------------------------------------------------
1335 BIOSORG 0EF57h
1336int0e_handler:
1337 push ax
1338 push dx
1339 mov dx, 3F4h
1340 in al, dx
1341 and al, 0C0h
1342 cmp al, 0C0h
1343 je int0e_normal
1344 mov dx, 3F5h
1345 mov al, 08h ; sense interrupt
1346 out dx, al
1347int0e_loop1:
1348 mov dx, 3F4h ; TODO: move out of the loop?
1349 in al, dx
1350 and al, 0C0h
1351 cmp al, 0C0h
1352 jne int0e_loop1
1353
1354int0e_loop2:
1355 mov dx, 3F5h ; TODO: inc/dec dx instead
1356 in al, dx
1357 mov dx, 3F4h
1358 in al, dx
1359 and al, 0C0h
1360 cmp al, 0C0h
1361 je int0e_loop2
1362
1363int0e_normal:
1364 push ds
1365 xor ax, ax
1366 mov ds, ax
1367 call eoi_master_pic
1368 ; indicate that an interrupt occurred
1369 or byte ptr ds:[43Eh], 80h
1370 pop ds
1371 pop dx
1372 pop ax
1373 iret
1374
1375
1376;; --------------------------------------------------------
1377;; Diskette Parameter Table
1378;; --------------------------------------------------------
1379 BIOSORG 0EFC7h
1380_diskette_param_table:
1381 db 0AFh
1382 db 2 ; HLT=1, DMA mode
1383 db 025h
1384 db 2
1385 db 18 ; SPT (good for 1.44MB media)
1386 db 01Bh
1387 db 0FFh
1388 db 06Ch
1389 db 0F6h ; format filler
1390 db 15
1391 db 8
1392
1393
1394
1395;; --------------------------------------------------------
1396;; INT 17h handler - Printer service
1397;; --------------------------------------------------------
1398;; BIOSORG 0EFD2h - fixed WRT preceding code
1399
1400 jmp int17_handler ; NT floppy boot workaround
1401 ; see @bugref{6481}
1402int17_handler:
1403 push ds
1404 push es
1405 pusha
1406 C_SETUP
1407 call _int17_function
1408 popa
1409 pop es
1410 pop ds
1411 iret
1412
1413
1414
1415;; Protected mode IDT descriptor
1416;;
1417;; The limit is 0 to cause a shutdown if an exception occurs
1418;; in protected mode. TODO: Is that what we really want?
1419;;
1420;; Set base to F0000 to correspond to beginning of BIOS,
1421;; in case an IDT is defined later.
1422
1423_pmode_IDT:
1424 dw 0 ; limit 15:0
1425 dw 0 ; base 15:0
1426 dw 0Fh ; base 23:16
1427
1428
1429;; Real mode IDT descriptor
1430;;
1431;; Set to typical real-mode values.
1432;; base = 000000
1433;; limit = 03ff
1434
1435_rmode_IDT:
1436 dw 3FFh ; limit 15:00
1437 dw 0 ; base 15:00
1438 dw 0 ; base 23:16
1439
1440
1441;;
1442;; INT 1Ch
1443;;
1444;; TODO: Why does this need a special handler?
1445int1c_handler: ;; user timer tick
1446 iret
1447
1448
1449
1450;; --------------------------------------------------------
1451;; INT 10h functions 0-Fh entry point
1452;; --------------------------------------------------------
1453 BIOSORG 0F045h
1454i10f0f_entry:
1455 iret
1456
1457
1458;; --------------------------------------------------------
1459;; INT 10h handler - MDA/CGA video
1460;; --------------------------------------------------------
1461 BIOSORG 0F065h
1462int10_handler:
1463 ;; do nothing - assumes VGA
1464 iret
1465
1466
1467;; --------------------------------------------------------
1468;; MDA/CGA Video Parameter Table (INT 1Dh)
1469;; --------------------------------------------------------
1470 BIOSORG 0F0A4h
1471mdacga_vpt:
1472
1473
1474;;
1475;; INT 18h - boot failure
1476;;
1477int18_handler:
1478 C_SETUP
1479 call _int18_panic_msg
1480 ;; TODO: handle failure better?
1481 hlt
1482 iret
1483
1484;;
1485;; INT 19h - boot service - relocated
1486;;
1487int19_relocated:
1488; If an already booted OS calls int 0x19 to reboot, it is not sufficient
1489; just to try booting from the configured drives. All BIOS variables and
1490; interrupt vectors need to be reset, otherwise strange things may happen.
1491; The approach used is faking a warm reboot (which just skips showing the
1492; logo), which is a bit more than what we need, but hey, it's fast.
1493 mov bp, sp
1494 mov ax, [bp+2] ; TODO: redundant? address via sp?
1495 cmp ax, BIOSSEG ; check caller's segment
1496 jz bios_initiated_boot
1497
1498 xor ax, ax
1499 mov ds, ax
1500 mov ax, 1234h
1501 mov ds:[472], ax
1502 jmp post
1503
1504bios_initiated_boot:
1505 ;; The C worker function returns the boot drive in bl and
1506 ;; the boot segment in ax. In case of failure, the boot
1507 ;; segment will be zero.
1508 C_SETUP ; TODO: Here? Now?
1509 push bp
1510 mov bp, sp
1511
1512 ;; 1st boot device
1513 mov ax, 1
1514 push ax
1515 call _int19_function
1516 inc sp
1517 inc sp
1518 test ax, ax ; if 0, try next device
1519 jnz boot_setup
1520
1521 ;; 2nd boot device
1522 mov ax, 2
1523 push ax
1524 call _int19_function
1525 inc sp
1526 inc sp
1527 test ax, ax ; if 0, try next device
1528 jnz boot_setup
1529
1530 ; 3rd boot device
1531 mov ax, 3
1532 push 3
1533 call _int19_function
1534 inc sp
1535 inc sp
1536 test ax, ax ; if 0, try next device
1537 jnz boot_setup
1538
1539 ; 4th boot device
1540 mov ax, 4
1541 push ax
1542 call _int19_function
1543 inc sp
1544 inc sp
1545 test ax, ax ; if 0, invoke INT 18h
1546 jz int18_handler
1547
1548boot_setup:
1549; TODO: the drive should be in dl already??
1550;; mov dl, bl ; tell guest OS what boot drive is
1551 .386 ; NB: We're getting garbage into high eax bits
1552 shl eax, 4 ; convert seg to ip
1553 mov [bp+2], ax ; set ip
1554
1555 shr eax, 4 ; get cs back
1556 .286
1557 and ax, BIOSSEG ; remove what went in ip
1558 mov [bp+4], ax ; set cs
1559 xor ax, ax
1560 mov ds, ax
1561 mov es, ax
1562 mov [bp], ax ; TODO: what's this?!
1563 mov ax, 0AA55h ; set ok flag ; TODO: and this?
1564
1565 pop bp ; TODO: why'd we just zero it??
1566 iret ; beam me up scotty
1567
1568;; PCI BIOS
1569
1570include pcibios.inc
1571include pirq.inc
1572
1573
1574;; --------------------------------------------------------
1575;; INT 12h handler - Memory size
1576;; --------------------------------------------------------
1577 BIOSORG 0F841h
1578int12_handler:
1579 ;; Don't touch - fixed size!
1580 sti
1581 push ds
1582 mov ax, 40h
1583 mov ds, ax
1584 mov ax, ds:[13h]
1585 pop ds
1586 iret
1587
1588
1589;; --------------------------------------------------------
1590;; INT 11h handler - Equipment list service
1591;; --------------------------------------------------------
1592;; BIOSORG 0F84Dh - fixed wrt preceding code
1593int11_handler:
1594 ;; Don't touch - fixed size!
1595 sti
1596 push ds
1597 mov ax, 40h
1598 mov ds, ax
1599 mov ax, ds:[10h]
1600 pop ds
1601 iret
1602
1603
1604;; --------------------------------------------------------
1605;; INT 15h handler - System services
1606;; --------------------------------------------------------
1607;; BIOSORG 0F859h - fixed wrt preceding code
1608int15_handler:
1609 pushf
1610 push ds
1611 push es
1612 C_SETUP
1613 cmp ah, 86h
1614 je int15_handler32
1615 cmp ah, 0E8h
1616 je int15_handler32
1617 cmp ah, 0d0h
1618 je int15_handler32
1619 pusha
1620 cmp ah, 53h ; APM function?
1621 je apm_call
1622 cmp ah, 0C2h ; PS/2 mouse function?
1623 je int15_handler_mouse
1624
1625 call _int15_function
1626int15_handler_popa_ret:
1627 popa
1628int15_handler32_ret:
1629 pop es
1630 pop ds
1631 popf
1632 jmp iret_modify_cf
1633
1634apm_call:
1635 call _apm_function
1636 jmp int15_handler_popa_ret
1637
1638int15_handler_mouse:
1639 call _int15_function_mouse
1640 jmp int15_handler_popa_ret
1641
1642int15_handler32:
1643 ;; need to save/restore 32-bit registers
1644 .386
1645 pushad
1646 call _int15_function32
1647 popad
1648 .286
1649 jmp int15_handler32_ret
1650
1651;;
1652;; Perform an IRET but retain the current carry flag value
1653;;
1654iret_modify_cf:
1655 jc carry_set
1656 push bp
1657 mov bp, sp
1658 and byte ptr [bp + 6], 0FEh
1659 pop bp
1660 iret
1661carry_set:
1662 push bp
1663 mov bp, sp
1664 or byte ptr [bp + 6], 1
1665 pop bp
1666 iret
1667
1668;;
1669;; INT 74h handler - PS/2 mouse (IRQ 12)
1670;;
1671int74_handler proc
1672
1673 sti
1674 pusha
1675 push es
1676 push ds
1677 push 0 ; placeholder for status
1678 push 0 ; placeholder for X
1679 push 0 ; placeholder for Y
1680 push 0 ; placeholder for Z
1681 push 0 ; placeholder for make_far_call bool
1682 C_SETUP
1683 call _int74_function
1684 pop cx ; pop make_far_call flag
1685 jcxz int74_done
1686
1687 ;; make far call to EBDA:0022
1688 push 0
1689 pop ds
1690 push ds:[40Eh]
1691 pop ds
1692 call far ptr ds:[22h]
1693int74_done:
1694 cli
1695 call eoi_both_pics
1696 add sp, 8 ; remove status, X, Y, Z
1697 pop ds
1698 pop es
1699 popa
1700 iret
1701
1702int74_handler endp
1703
1704int76_handler proc
1705
1706 ;; record completion in BIOS task complete flag
1707 push ax
1708 push ds
1709 mov ax, 40h
1710 mov ds, ax
1711 mov byte ptr ds:[8Eh], 0FFh
1712 call eoi_both_pics
1713 pop ds
1714 pop ax
1715 iret
1716
1717int76_handler endp
1718
1719;; --------------------------------------------------------
1720;; 8x8 font (first 128 characters)
1721;; --------------------------------------------------------
1722 BIOSORG 0FA6Eh
1723include font8x8.inc
1724
1725
1726;; --------------------------------------------------------
1727;; INT 1Ah handler - Time of the day + PCI BIOS
1728;; --------------------------------------------------------
1729;; BIOSORG 0FE6Eh - fixed wrt preceding table
1730int1a_handler:
1731 cmp ah, 0B1h
1732 jne int1a_normal
1733
1734 push es
1735 push ds
1736 C_SETUP
1737 .386
1738 pushad
1739 call _pci16_function
1740 popad
1741 .286
1742 pop ds
1743 pop es
1744 iret
1745
1746int1a_normal:
1747 push es
1748 push ds
1749 pusha
1750 C_SETUP
1751int1a_callfunction:
1752 call _int1a_function
1753 popa
1754 pop ds
1755 pop es
1756 iret
1757
1758
1759;;
1760;; IRQ 8 handler (RTC)
1761;;
1762int70_handler:
1763 push es
1764 push ds
1765 pusha
1766 C_SETUP
1767 call _int70_function
1768 popa
1769 pop ds
1770 pop es
1771 iret
1772
1773
1774;; --------------------------------------------------------
1775;; Timer tick - IRQ 0 handler
1776;; --------------------------------------------------------
1777 BIOSORG 0FEA5h
1778int08_handler:
1779 .386
1780 sti
1781 push eax
1782 push ds
1783 push dx
1784 mov ax, 40h
1785 mov ds, ax
1786
1787 mov eax, ds:[6Ch] ; get ticks dword
1788 inc eax
1789
1790 ;; compare eax to one day's worth of ticks (at 18.2 Hz)
1791 cmp eax, 1800B0h
1792 jb int08_store_ticks
1793 ;; there has been a midnight rollover
1794 xor eax, eax
1795 inc byte ptr ds:[70h] ; increment rollover flag
1796
1797int08_store_ticks:
1798 mov ds:[6Ch], eax
1799
1800 ;; time to turn off floppy drive motor(s)?
1801 mov al, ds:[40h]
1802 or al, al
1803 jz int08_floppy_off
1804 dec al
1805 mov ds:[40h], al
1806 jnz int08_floppy_off
1807 ;; turn motor(s) off
1808 mov dx, 03F2h
1809 in al, dx
1810 and al, 0CFh
1811 out dx, al
1812int08_floppy_off:
1813
1814 int 1Ch ; call the user timer handler
1815
1816 cli
1817 call eoi_master_pic
1818 pop dx
1819 pop ds
1820 pop eax
1821 .286
1822 iret
1823
1824
1825;; --------------------------------------------------------
1826;; Initial interrupt vector offsets for POST
1827;; --------------------------------------------------------
1828 BIOSORG 0FEF3h
1829vector_table:
1830
1831
1832
1833;; --------------------------------------------------------
1834;; BIOS copyright string
1835;; --------------------------------------------------------
1836 BIOSORG 0FF00h
1837bios_string:
1838 db BIOS_COPYRIGHT
1839
1840
1841;; --------------------------------------------------------
1842;; IRET - default interrupt handler
1843;; --------------------------------------------------------
1844 BIOSORG 0FF53h
1845
1846dummy_iret:
1847 iret
1848
1849
1850;; --------------------------------------------------------
1851;; INT 05h - Print Screen service
1852;; --------------------------------------------------------
1853;; BIOSORG 0FF54h - fixed wrt preceding
1854int05_handler:
1855 ;; Not implemented
1856 iret
1857
1858include smidmi.inc
1859
1860;; --------------------------------------------------------
1861;; Processor reset entry point
1862;; --------------------------------------------------------
1863 BIOSORG 0FFF0h
1864cpu_reset:
1865 ;; This is where the CPU starts executing after a reset
1866 jmp far ptr post
1867
1868 ;; BIOS build date
1869 db BIOS_BUILD_DATE
1870 db 0 ; padding
1871 ;; System model ID
1872 db SYS_MODEL_ID
1873 ;; Checksum byte
1874 db 0FFh
1875
1876
1877BIOSSEG ends
1878
1879 end
1880
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette