1 ; Stub of videodriver for Intel videocards.
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
21 section '.flat' readable writable executable
22 include '../proc32.inc'
23 include '../struct.inc'
24 include '../macros.inc'
29 ; the start procedure (see the description above)
31 ; 1. Detect device. Abort if not found.
36 ; 2. Detect optimal mode unless the mode is given explicitly. Abort if failed.
37 if use_predefined_mode
= 0
42 ; 3. Set the detected mode.
44 ; 4. Cleanup and return.
46 invoke FreeKernelSpace
, esi
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
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.
64 ; 1b. loword(eax) = ax = VendorID, hiword(eax) = DeviceID.
65 ; Test whether we have Intel chipset.
68 ; 1c. Say hi including DeviceID.
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.
85 jnz .return_unknown_pciid
86 sub ecx, pciids_num
- 1
89 ; 1e. Continue saying hi with positive intonation.
94 ; 2. Prepare MMIO region to control the card.
95 ; 2a. Read MMIO physical address from PCI config space.
104 ; 2b. Mask out PCI region type, lower 4 bits.
106 ; 2c. Create virtual mapping of the physical memory.
115 ; 1f. If we do not know DeviceID, continue saying hi with negative intonation.
116 .
return_unknown_pciid:
119 invoke SysMsgBoardStr
123 ; Convert word in ax to hexadecimal text in edi, advance edi.
125 ; 1. Convert high byte.
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.
135 ; 1. Convert high nibble.
140 ; 2. Convert low nibble.
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.
153 if use_predefined_mode
= 0
154 ; detect resolution of the flat panel
157 ; 1. Get the location of block of GMBUS* registers.
158 ; Starting with Ironlake, GMBUS* registers were moved.
160 cmp [deviceType
], ironlake_start
164 ; 2. Initialize GMBUS engine.
168 test byte [esi+8+1], 80h
172 test byte [esi+8+1], 4
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.
184 test byte [esi+8+1], 8
186 test byte [esi+8+1], 4
195 ; 5. Wait for bus idle.
198 test byte [esi+8+1], 2
200 ; 6. We got EDID; dump it if DEBUG.
221 invoke SysMsgBoardStr
224 ; 7. Test whether EDID is good.
225 ; 7a. Signature: 00 FF FF FF FF FF FF 00.
227 cmp dword [esi], 0xFFFFFF00
229 cmp dword [esi+4], 0x00FFFFFF
231 ; 7b. Checksum must be zero.
239 ; 8. Get width and height from EDID.
241 mov ah, [esi-80h+3Ah]
243 mov al, [esi-80h+38h]
245 mov ah, [esi-80h+3Dh]
247 mov al, [esi-80h+3Bh]
254 ; reset bus, clear all errors
257 mov dword [esi+4], 80000000h
261 test byte [esi+8+1], 2
266 ; set resolution [width]*[height]
268 ; 1. Program the registers of videocard.
271 ; or byte [esi+7000Ah], 0Ch ; PIPEACONF: disable Display+Cursor Planes
272 ; or byte [esi+7100Ah], 0Ch ; PIPEBCONF: disable Display+Cursor Planes
275 cmp [deviceType
], i965_start
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
289 cmp [deviceType
], ironlake_start
292 or byte [esi+70024h], 2 ; PIPEASTAT: clear VBLANK status
293 or byte [esi+71024h], 2 ; PIPEBSTAT: clear VBLANK status
294 .
wait_vblank_preironlake1:
297 test byte [esi+7000Bh], 80h ; PIPEACONF: pipe A active?
299 test byte [esi+70024h], 2 ; PIPEASTAT: got VBLANK?
300 jz .wait_vblank_preironlake2
302 test byte [esi+7100Bh], 80h ; PIPEBCONF: pipe B active?
304 test byte [esi+71024h], 2 ; PIPEBSTAT: got VBLANK?
306 .
wait_vblank_preironlake2:
308 jnz .wait_vblank_preironlake1
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
321 test byte [esi+7000Bh], 40h ; PIPEACONF: wait until pipe disabled
327 test byte [esi+7100Bh], 40h ; PIPEBCONF: wait until pipe disabled
334 ; pineview and before: wait while scanline still changes
335 .
wait_watching_scanline:
338 push dword [esi+71000h]
339 push dword [esi+70000h]
343 xor eax, [esi+70000h]
347 xor eax, [esi+71000h]
357 lea eax, [esi+61183h]
358 cmp [deviceType
], ironlake_start
360 add eax, 0xE0000 - 0x60000
362 lea edx, [esi+60000h]
370 mov ax, word [height
]
372 mov dword [edx+1Ch], eax ; PIPEASRC: set source image size
374 mov dword [edx+10190h], eax ; for old cards
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.
389 mov dword [eax+8], edx
391 mov dword [eax+0Ch], edx
400 include '../peimport.inc'
405 hellomsg
db 'Intel videocard detected, PciId=8086:'
408 knownmsg
db 'known',13,10,0
409 unknownmsg
db 'unknown',13,10,0
412 edidmsg
db 'EDID successfully read:',13,10
413 edid_text rb
8*(16*3+1)
417 width dd predefined_width
418 height
dd predefined_height
424 i865_start
= ($
- pciids
) / 2
426 i9xx_start
= ($
- pciids
) / 2
428 dw 0x258a ; e7221g (i915g)
433 i965_start
= ($
- pciids
) / 2
434 dw 0x2972 ; i946qz (i965g)
435 dw 0x2982 ; g35g (i965g)
436 dw 0x2992 ; i965q (i965g)
443 gen4_start
= ($
- pciids
) / 2
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