Subversion Repositories Kolibri OS

Rev

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

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