* better
[mascara-docs.git] / amd64 / bareMetalOS-0.5.2 / pure64.boot0 / src / init_isa.asm
blob141804e311e80a10fe42c4bd80be54392f4a085a
1 ; =============================================================================
2 ; Pure64 -- a 64-bit OS loader written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2011 Return Infinity -- see LICENSE.TXT
5 ; INIT ISA
6 ; =============================================================================
9 isa_setup:
11 mov edi, 0x00004000
12 xor eax, eax
13 mov ecx, 2048
14 rep stosd
16 ; Get the BIOS E820 Memory Map
17 ; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
18 ; inputs: es:di -> destination buffer for 24 byte entries
19 ; outputs: bp = entry count, trashes all registers except esi
20 do_e820:
21 mov edi, 0x00004000 ; location that memory map will be stored to
22 xor ebx, ebx ; ebx must be 0 to start
23 xor bp, bp ; keep an entry count in bp
24 mov edx, 0x0534D4150 ; Place "SMAP" into edx
25 mov eax, 0xe820
26 mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
27 mov ecx, 24 ; ask for 24 bytes
28 int 0x15
29 jc nomemmap ; carry set on first call means "unsupported function"
30 mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
31 cmp eax, edx ; on success, eax must have been reset to "SMAP"
32 jne nomemmap
33 test ebx, ebx ; ebx = 0 implies list is only 1 entry long (worthless)
34 je nomemmap
35 jmp jmpin
36 e820lp:
37 mov eax, 0xe820 ; eax, ecx get trashed on every int 0x15 call
38 mov [es:di + 20], dword 1 ; force a valid ACPI 3.X entry
39 mov ecx, 24 ; ask for 24 bytes again
40 int 0x15
41 jc memmapend ; carry set means "end of list already reached"
42 mov edx, 0x0534D4150 ; repair potentially trashed register
43 jmpin:
44 jcxz skipent ; skip any 0 length entries
45 cmp cl, 20 ; got a 24 byte ACPI 3.X response?
46 jbe notext
47 test byte [es:di + 20], 1 ; if so: is the "ignore this data" bit clear?
48 je skipent
49 notext:
50 mov ecx, [es:di + 8] ; get lower dword of memory region length
51 test ecx, ecx ; is the qword == 0?
52 jne goodent
53 mov ecx, [es:di + 12] ; get upper dword of memory region length
54 jecxz skipent ; if length qword is 0, skip entry
55 goodent:
56 inc bp ; got a good entry: ++count, move to next storage spot
57 add di, 32
58 skipent:
59 test ebx, ebx ; if ebx resets to 0, list is complete
60 jne e820lp
61 nomemmap:
62 mov byte [cfg_e820], 0 ; No memory map function
63 memmapend:
64 xor eax, eax ; Create a blank record for termination (32 bytes)
65 mov ecx, 8
66 rep stosd
68 ; Enable the A20 gate
69 set_A20:
70 in al, 0x64
71 test al, 0x02
72 jnz set_A20
73 mov al, 0xD1
74 out 0x64, al
75 check_A20:
76 in al, 0x64
77 test al, 0x02
78 jnz check_A20
79 mov al, 0xDF
80 out 0x60, al
82 ; Configure serial port 1
83 mov dx, 0
84 mov al, 11100011b ; 9600 baud, no parity, 8 data bits, 1 stop bit
85 mov ah, 0
86 int 14h
88 ; Set PIT Channel 0 to fire at 1000Hz (Divisor = 1193180 / hz)
89 mov al, 0x36 ; Set Timer
90 out 0x43, al
91 mov al, 0xA9 ; We want 100MHz so 0x2E9B
92 out 0x40, al ; 1000MHz would be 0x04A9
93 mov al, 0x04
94 out 0x40, al
96 ; Set keyboard repeat rate to max
97 mov al, 0xf3
98 out 0x60, al ; Set Typematic Rate/Delay
99 xor al, al
100 out 0x60, al ; 30 cps and .25 second delay
101 mov al, 0xed
102 out 0x60, al ; Set/Reset LEDs
103 xor al, al
104 out 0x60, al ; all off
106 ; Set up RTC
107 mov al, 0x0B
108 out 0x70, al
109 in al, 0x71
110 or al, 00000010b ; Bit 2 (0) Data Mode to BCD, Bit 1 (1) 24 hour mode
111 push ax
112 mov al, 0x0B
113 out 0x70, al
114 pop ax
115 out 0x71, al
117 ; VBE init
118 cmp byte [cfg_vesa], 1 ; Check if VESA should be enabled
119 jne VBEdone ; If not then skip VESA init
120 mov edi, VBEModeInfoBlock ; VBE data will be stored at this address
121 mov ax, 0x4F01 ; GET SuperVGA MODE INFORMATION - http://www.ctyme.com/intr/rb-0274.htm
122 ; CX queries the mode, it should be in the form 0x41XX as bit 14 is set for LFB and bit 8 is set for VESA mode
123 ; 0x4112 is 640x480x24bit 0x4129 is 640x480x32bit
124 ; 0x4115 is 800x600x24bit 0x412E is 800x600x32bit
125 ; 0x4118 is 1024x768x24bit 0x4138 is 1024x768x32bit
126 ; 0x411B is 1280x1024x24bit 0x413D is 1280x1024x32bit
127 mov cx, 0x4112 ; Put your desired mode here
128 mov bx, cx ; Mode is saved to BX for the set command later
129 int 0x10
131 cmp ax, 0x004F ; Return value in AX should equal 0x004F if supported and sucessful
132 jne VBEfail
133 cmp byte[VBEModeInfoBlock.BitsPerPixel], 24 ; Make sure this matches the number of bits for the mode!
134 jne VBEfail ; If set bit mode was unsucessful then bail out
136 mov ax, 0x4F02 ; SET SuperVGA VIDEO MODE - http://www.ctyme.com/intr/rb-0275.htm
137 int 0x10
138 cmp ax, 0x004F ; Return value in AX should equal 0x004F if supported and sucessful
139 jne VBEfail
141 jmp VBEdone
143 VBEfail:
144 mov byte [cfg_vesa], 0 ; Clear the VESA config as it was not sucessful
146 VBEdone:
148 ; Remap IRQ's
149 ; As heard on an episode of Jerry Springer.. "It's time to lose the zero (8259 PIC) and get with a hero (IOAPIC)".
150 ; http://osdever.net/tutorials/apicarticle.php
151 mov al, 00010001b ; begin PIC 1 initialization
152 out 0x20, al
153 mov al, 00010001b ; begin PIC 2 initialization
154 out 0xA0, al
155 mov al, 0x20 ; IRQ 0-7: interrupts 20h-27h
156 out 0x21, al
157 mov al, 0x28 ; IRQ 8-15: interrupts 28h-2Fh
158 out 0xA1, al
159 mov al, 4
160 out 0x21, al
161 mov al, 2
162 out 0xA1, al
163 mov al, 1
164 out 0x21, al
165 out 0xA1, al
167 in al, 0x21
168 mov al, 11111110b ; Disable all IRQs except for timer
169 out 0x21, al
170 in al, 0xA1
171 mov al, 11111111b
172 out 0xA1, al
177 ; =============================================================================
178 ; EOF