Subversion Repositories Kolibri OS

Rev

Rev 3708 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
; Stub of videodriver for Intel videocards.
2
; (c) CleverMouse
3
 
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.
10
 
11
; set predefined resolution here
12
use_predefined_mode = 0;1
13
predefined_width = 0;1366
14
predefined_height = 0;768
15
 
5039 clevermous 16
; standard driver stuff; target OS version = 0.80
17
format PE DLL native 0.80
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'
2288 clevermous 26
 
27
DEBUG = 1
28
 
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:
5039 clevermous 46
        invoke  FreeKernelSpace, esi
2288 clevermous 47
.return0:
48
        pop     esi
49
        xor     eax, eax
5039 clevermous 50
        ret
2288 clevermous 51
 
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
5039 clevermous 63
        invoke  PciRead32
2288 clevermous 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
5039 clevermous 75
        invoke  SysMsgBoardStr
2288 clevermous 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
5039 clevermous 92
        invoke  SysMsgBoardStr
2288 clevermous 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
100
@@:
101
        push    10h
102
        push    esi
5039 clevermous 103
        invoke  PciRead32
2288 clevermous 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
5039 clevermous 110
        invoke  MapIoMem
2288 clevermous 111
; 3. Return.
112
        xchg    esi, eax
113
.return:
114
        ret
115
; 1f. If we do not know DeviceID, continue saying hi with negative intonation.
116
.return_unknown_pciid:
117
        pusha
118
        mov     esi, unknownmsg
5039 clevermous 119
        invoke  SysMsgBoardStr
2288 clevermous 120
        popa
121
        ret
122
 
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.
132
 
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.
143
 
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
149
        das
150
        stosb
151
        ret
152
 
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
163
@@:
164
; 2. Initialize GMBUS engine.
165
        mov     edi, edid
166
        mov     ecx, 0x10000
167
@@:
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
183
@@:
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
197
@@:
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
217
@@:
218
        test    cl, cl
219
        jns     .dumploop
220
        mov     esi, edidmsg
5039 clevermous 221
        invoke  SysMsgBoardStr
2288 clevermous 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
234
@@:
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
252
        ret
253
 
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
260
@@:
261
        test    byte [esi+8+1], 2
262
        loopnz  @b
263
        ret
264
end if
265
 
266
; set resolution [width]*[height]
267
SetMode:
268
; 1. Program the registers of videocard.
269
; look into the PRM
270
        cli
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
278
@@:
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
301
@@:
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
3708 clevermous 314
        cmp     [deviceType], gen4_start
315
        jb      .wait_watching_scanline
316
; g45 and later: use special flag from PIPE*CONF
2288 clevermous 317
        mov     edx, 10000h
318
@@:
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
3708 clevermous 325
        jmp     .not_disabled
2288 clevermous 326
@@:
327
        test    byte [esi+7100Bh], 40h  ; PIPEBCONF: wait until pipe disabled
3708 clevermous 328
        jz      .disabled
2288 clevermous 329
        mov     ecx, 1000h
330
        loop    $
331
        dec     edx
332
        jnz     @b
333
        jmp     .not_disabled
3708 clevermous 334
; pineview and before: wait while scanline still changes
335
.wait_watching_scanline:
2288 clevermous 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:
354
        sti
355
        jmp     .return
356
.disabled:
357
        lea     eax, [esi+61183h]
358
        cmp     [deviceType], ironlake_start
359
        jb      @f
360
        add     eax, 0xE0000 - 0x60000
361
@@:
362
        lea     edx, [esi+60000h]
363
        test    byte [eax], 40h
364
        jz      @f
365
        add     edx, 1000h
366
@@:
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
3708 clevermous 380
        mov     dword [edx+10184h], 0   ; DSPALINOFF: force write to DSPA* registers
2288 clevermous 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
385
        sti
386
; 2. Notify the kernel that resolution has changed.
5039 clevermous 387
        invoke  GetDisplay
2288 clevermous 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
5039 clevermous 396
        invoke  SetScreen
2288 clevermous 397
.return:
398
        ret
399
 
5039 clevermous 400
include '../peimport.inc'
401
data fixups
402
end data
403
 
2288 clevermous 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
410
 
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
416
 
417
width   dd      predefined_width
418
height  dd      predefined_height
419
 
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
3708 clevermous 441
        dw      0xa001  ; pineview
442
        dw      0xa011  ; pineview
443
gen4_start = ($ - pciids) / 2
2288 clevermous 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
464
 
465
align 4
466
deviceType      dd      ?
467
edid    rb      0x80