Added DGEN to ISO and create file associatons.
[kolibrios.git] / drivers / video / vidintel.asm
blob6f72cce7607fa878e08be6caa30aae3feb76bce4
1 ; Stub of videodriver for Intel videocards.
2 ; (c) CleverMouse
4 ; When the start procedure gots control,
5 ; it tries to detect preferred resolution,
6 ; sets the detected resolution assuming 32-bpp VESA mode and exits
7 ; (without registering a service).
8 ; Detection can be overloaded with compile-time settings
9 ; use_predefined_mode/predefined_width/predefined_height.
11 ; set predefined resolution here
12 use_predefined_mode = 0;1
13 predefined_width = 0;1366
14 predefined_height = 0;768
16 ; standard driver stuff; version of driver model = 5
17 format PE DLL native 0.05
18 entry START
19 __DEBUG__ equ 1
20 __DEBUG_LEVEL__ equ 1
21 section '.flat' readable writable executable
22 include '../proc32.inc'
23 include '../struct.inc'
24 include '../macros.inc'
25 ;include 'fdo.inc'
27 DEBUG = 1
29 ; the start procedure (see the description above)
30 START:
31 ; 1. Detect device. Abort if not found.
32 push esi
33 call DetectDevice
34 test esi, esi
35 jz .return0
36 ; 2. Detect optimal mode unless the mode is given explicitly. Abort if failed.
37 if use_predefined_mode = 0
38 call DetectMode
39 end if
40 cmp [width], 0
41 jz .return0_cleanup
42 ; 3. Set the detected mode.
43 call SetMode
44 ; 4. Cleanup and return.
45 .return0_cleanup:
46 invoke FreeKernelSpace, esi
47 .return0:
48 pop esi
49 xor eax, eax
50 ret
52 ; check that there is Intel videocard
53 ; if so, map MMIO registers and set internal variables
54 ; esi points to MMIO block; NULL means no device
55 DetectDevice:
56 ; 1. Sanity check: check that we are dealing with Intel videocard.
57 ; Integrated video device for Intel is always at PCI:0:2:0.
58 xor esi, esi ; initialize return value to NULL
59 ; 1a. Get PCI VendorID and DeviceID.
60 push esi
61 push 10h
62 push esi
63 invoke PciRead32
64 ; 1b. loword(eax) = ax = VendorID, hiword(eax) = DeviceID.
65 ; Test whether we have Intel chipset.
66 cmp ax, 8086h
67 jnz .return
68 ; 1c. Say hi including DeviceID.
69 shr eax, 10h
70 push edi
71 pusha
72 mov edi, pciid_text
73 call WriteWord
74 mov esi, hellomsg
75 invoke SysMsgBoardStr
76 popa
77 ; 1d. Test whether we know this DeviceID.
78 ; If this is the case, remember the position of the device in line of Intel cards;
79 ; this knowledge will be useful later.
80 ; Tested on devices with id: 8086:0046, partially 8086:2A02.
81 mov ecx, pciids_num
82 mov edi, pciids
83 repnz scasw
84 pop edi
85 jnz .return_unknown_pciid
86 sub ecx, pciids_num - 1
87 neg ecx
88 mov [deviceType], ecx
89 ; 1e. Continue saying hi with positive intonation.
90 pusha
91 mov esi, knownmsg
92 invoke SysMsgBoardStr
93 popa
94 ; 2. Prepare MMIO region to control the card.
95 ; 2a. Read MMIO physical address from PCI config space.
96 push 10h
97 cmp ecx, i9xx_start
98 jae @f
99 mov byte [esp], 14h
101 push 10h
102 push esi
103 invoke PciRead32
104 ; 2b. Mask out PCI region type, lower 4 bits.
105 and al, not 0xF
106 ; 2c. Create virtual mapping of the physical memory.
107 push 1Bh
108 push 100000h
109 push eax
110 invoke MapIoMem
111 ; 3. Return.
112 xchg esi, eax
113 .return:
115 ; 1f. If we do not know DeviceID, continue saying hi with negative intonation.
116 .return_unknown_pciid:
117 pusha
118 mov esi, unknownmsg
119 invoke SysMsgBoardStr
120 popa
123 ; Convert word in ax to hexadecimal text in edi, advance edi.
124 WriteWord:
125 ; 1. Convert high byte.
126 push eax
127 mov al, ah
128 call WriteByte
129 pop eax
130 ; 2. Convert low byte.
131 ; Fall through to WriteByte; ret from WriteByte is ret from WriteWord too.
133 ; Convert byte in al to hexadecimal text in edi, advance edi.
134 WriteByte:
135 ; 1. Convert high nibble.
136 push eax
137 shr al, 4
138 call WriteNibble
139 pop eax
140 ; 2. Convert low nibble.
141 and al, 0xF
142 ; Fall through to WriteNibble; ret from WriteNibble is ret from WriteByte too.
144 ; Convert nibble in al to hexadecimal text in edi, advance edi.
145 WriteNibble:
146 ; Obvious, isn't it?
147 cmp al, 10
148 sbb al, 69h
150 stosb
153 if use_predefined_mode = 0
154 ; detect resolution of the flat panel
155 DetectMode:
156 push esi edi
157 ; 1. Get the location of block of GMBUS* registers.
158 ; Starting with Ironlake, GMBUS* registers were moved.
159 add esi, 5100h
160 cmp [deviceType], ironlake_start
161 jb @f
162 add esi, 0xC0000
164 ; 2. Initialize GMBUS engine.
165 mov edi, edid
166 mov ecx, 0x10000
168 test byte [esi+8+1], 80h
169 loopnz @b
170 jnz .fail
171 mov dword [esi], 3
172 test byte [esi+8+1], 4
173 jz .noreset
174 call ResetGMBus
175 jnz .fail
176 .noreset:
177 ; 3. Send read command.
178 and dword [esi+20h], 0
179 mov dword [esi+4], 4E8000A1h
180 ; 4. Wait for data, writing to the buffer as data arrive.
181 .getdata:
182 mov ecx, 0x10000
184 test byte [esi+8+1], 8
185 loopz @b
186 test byte [esi+8+1], 4
187 jz .dataok
188 call ResetGMBus
189 jmp .fail
190 .dataok:
191 mov eax, [esi+0Ch]
192 stosd
193 cmp edi, edid+80h
194 jb .getdata
195 ; 5. Wait for bus idle.
196 mov ecx, 0x10000
198 test byte [esi+8+1], 2
199 loopnz @b
200 ; 6. We got EDID; dump it if DEBUG.
201 if DEBUG
202 pusha
203 xor ecx, ecx
204 mov esi, edid
205 mov edi, edid_text
206 .dumploop:
207 lodsb
208 call WriteByte
209 mov al, ' '
210 stosb
211 inc cl
212 test cl, 15
213 jnz @f
214 mov byte [edi-1], 13
215 mov al, 10
216 stosb
218 test cl, cl
219 jns .dumploop
220 mov esi, edidmsg
221 invoke SysMsgBoardStr
222 popa
223 end if
224 ; 7. Test whether EDID is good.
225 ; 7a. Signature: 00 FF FF FF FF FF FF 00.
226 mov esi, edid
227 cmp dword [esi], 0xFFFFFF00
228 jnz .fail
229 cmp dword [esi+4], 0x00FFFFFF
230 jnz .fail
231 ; 7b. Checksum must be zero.
232 xor edx, edx
233 mov ecx, 80h
235 lodsb
236 add dl, al
237 loop @b
238 jnz .fail
239 ; 8. Get width and height from EDID.
240 xor eax, eax
241 mov ah, [esi-80h+3Ah]
242 shr ah, 4
243 mov al, [esi-80h+38h]
244 mov [width], eax
245 mov ah, [esi-80h+3Dh]
246 shr ah, 4
247 mov al, [esi-80h+3Bh]
248 mov [height], eax
249 ; 9. Return.
250 .fail:
251 pop edi esi
254 ; reset bus, clear all errors
255 ResetGMBus:
256 ; look into the PRM
257 mov dword [esi+4], 80000000h
258 mov dword [esi+4], 0
259 mov ecx, 0x10000
261 test byte [esi+8+1], 2
262 loopnz @b
264 end if
266 ; set resolution [width]*[height]
267 SetMode:
268 ; 1. Program the registers of videocard.
269 ; look into the PRM
271 ; or byte [esi+7000Ah], 0Ch ; PIPEACONF: disable Display+Cursor Planes
272 ; or byte [esi+7100Ah], 0Ch ; PIPEBCONF: disable Display+Cursor Planes
273 xor eax, eax
274 xor edx, edx
275 cmp [deviceType], i965_start
276 jb @f
277 mov dl, 9Ch - 84h
279 ; or byte [esi+71403h], 80h ; VGACNTRL: VGA Display Disable
280 and byte [esi+70080h], not 27h ; CURACNTR: disable cursor A
281 mov dword [esi+70084h], eax ; CURABASE: force write to CURA* regs
282 and byte [esi+700C0h], not 27h ; CURBCNTR: disable cursor B
283 mov dword [esi+700C4h], eax ; CURBBASE: force write to CURB* regs
284 and byte [esi+70183h], not 80h ; DSPACNTR: disable Primary A Plane
285 mov dword [esi+edx+70184h], eax ; DSPALINOFF/DSPASURF: force write to DSPA* regs
286 and byte [esi+71183h], not 80h ; DSPBCNTR: disable Primary B Plane
287 mov dword [esi+edx+71184h], eax ; DSPBLINOFF/DSPBSURF: force write to DSPB* regs
288 if 1
289 cmp [deviceType], ironlake_start
290 jae .disable_pipes
291 mov edx, 10000h
292 or byte [esi+70024h], 2 ; PIPEASTAT: clear VBLANK status
293 or byte [esi+71024h], 2 ; PIPEBSTAT: clear VBLANK status
294 .wait_vblank_preironlake1:
295 mov ecx, 1000h
296 loop $
297 test byte [esi+7000Bh], 80h ; PIPEACONF: pipe A active?
298 jz @f
299 test byte [esi+70024h], 2 ; PIPEASTAT: got VBLANK?
300 jz .wait_vblank_preironlake2
302 test byte [esi+7100Bh], 80h ; PIPEBCONF: pipe B active?
303 jz .disable_pipes
304 test byte [esi+71024h], 2 ; PIPEBSTAT: got VBLANK?
305 jnz .disable_pipes
306 .wait_vblank_preironlake2:
307 dec edx
308 jnz .wait_vblank_preironlake1
309 jmp .not_disabled
310 .disable_pipes:
311 end if
312 and byte [esi+7000Bh], not 80h ; PIPEACONF: disable pipe
313 and byte [esi+7100Bh], not 80h ; PIPEBCONF: disable pipe
314 cmp [deviceType], gen4_start
315 jb .wait_watching_scanline
316 ; g45 and later: use special flag from PIPE*CONF
317 mov edx, 10000h
319 mov ecx, 1000h
320 loop $
321 test byte [esi+7000Bh], 40h ; PIPEACONF: wait until pipe disabled
322 jz @f
323 dec edx
324 jnz @b
325 jmp .not_disabled
327 test byte [esi+7100Bh], 40h ; PIPEBCONF: wait until pipe disabled
328 jz .disabled
329 mov ecx, 1000h
330 loop $
331 dec edx
332 jnz @b
333 jmp .not_disabled
334 ; pineview and before: wait while scanline still changes
335 .wait_watching_scanline:
336 mov edx, 1000h
337 .dis1:
338 push dword [esi+71000h]
339 push dword [esi+70000h]
340 mov ecx, 10000h
341 loop $
342 pop eax
343 xor eax, [esi+70000h]
344 and eax, 1FFFh
345 pop eax
346 jnz .notdis1
347 xor eax, [esi+71000h]
348 and eax, 1FFFh
349 jz .disabled
350 .notdis1:
351 dec edx
352 jnz .dis1
353 .not_disabled:
355 jmp .return
356 .disabled:
357 lea eax, [esi+61183h]
358 cmp [deviceType], ironlake_start
359 jb @f
360 add eax, 0xE0000 - 0x60000
362 lea edx, [esi+60000h]
363 test byte [eax], 40h
364 jz @f
365 add edx, 1000h
367 mov eax, [width]
368 dec eax
369 shl eax, 16
370 mov ax, word [height]
371 dec eax
372 mov dword [edx+1Ch], eax ; PIPEASRC: set source image size
373 ror eax, 16
374 mov dword [edx+10190h], eax ; for old cards
375 mov ecx, [width]
376 add ecx, 15
377 and ecx, not 15
378 shl ecx, 2
379 mov dword [edx+10188h], ecx ; DSPASTRIDE: set scanline length
380 mov dword [edx+10184h], 0 ; DSPALINOFF: force write to DSPA* registers
381 and byte [esi+61233h], not 80h ; PFIT_CONTROL: disable panel fitting
382 or byte [edx+1000Bh], 80h ; PIPEACONF: enable pipe
383 ; and byte [edx+1000Ah], not 0Ch ; PIPEACONF: enable Display+Cursor Planes
384 or byte [edx+10183h], 80h ; DSPACNTR: enable Display Plane A
386 ; 2. Notify the kernel that resolution has changed.
387 invoke GetDisplay
388 mov edx, [width]
389 mov dword [eax+8], edx
390 mov edx, [height]
391 mov dword [eax+0Ch], edx
392 mov [eax+18h], ecx
393 mov eax, [width]
394 dec eax
395 dec edx
396 invoke SetScreen
397 .return:
400 include '../peimport.inc'
401 data fixups
402 end data
404 align 4
405 hellomsg db 'Intel videocard detected, PciId=8086:'
406 pciid_text db '0000'
407 db ', which is ', 0
408 knownmsg db 'known',13,10,0
409 unknownmsg db 'unknown',13,10,0
411 if DEBUG
412 edidmsg db 'EDID successfully read:',13,10
413 edid_text rb 8*(16*3+1)
414 db 0
415 end if
417 width dd predefined_width
418 height dd predefined_height
420 pciids:
421 dw 0x3577 ; i830m
422 dw 0x2562 ; 845g
423 dw 0x3582 ; i855gm
424 i865_start = ($ - pciids) / 2
425 dw 0x2572 ; i865g
426 i9xx_start = ($ - pciids) / 2
427 dw 0x2582 ; i915g
428 dw 0x258a ; e7221g (i915g)
429 dw 0x2592 ; i915gm
430 dw 0x2772 ; i945g
431 dw 0x27a2 ; i945gm
432 dw 0x27ae ; i945gme
433 i965_start = ($ - pciids) / 2
434 dw 0x2972 ; i946qz (i965g)
435 dw 0x2982 ; g35g (i965g)
436 dw 0x2992 ; i965q (i965g)
437 dw 0x29a2 ; i965g
438 dw 0x29b2 ; q35g
439 dw 0x29c2 ; g33g
440 dw 0x29d2 ; q33g
441 dw 0xa001 ; pineview
442 dw 0xa011 ; pineview
443 gen4_start = ($ - pciids) / 2
444 dw 0x2a02 ; i965gm
445 dw 0x2a12 ; i965gm
446 dw 0x2a42 ; gm45
447 dw 0x2e02 ; g45
448 dw 0x2e12 ; g45
449 dw 0x2e22 ; g45
450 dw 0x2e32 ; g45
451 dw 0x2e42 ; g45
452 dw 0x2e92 ; g45
453 ironlake_start = ($ - pciids) / 2
454 dw 0x0042 ; ironlake_d
455 dw 0x0046 ; ironlake_m
456 dw 0x0102 ; sandybridge_d
457 dw 0x0112 ; sandybridge_d
458 dw 0x0122 ; sandybridge_d
459 dw 0x0106 ; sandybridge_m
460 dw 0x0116 ; sandybridge_m
461 dw 0x0126 ; sandybridge_m
462 dw 0x010A ; sandybridge_d
463 pciids_num = ($ - pciids) / 2
465 align 4
466 deviceType dd ?
467 edid rb 0x80