Subversion Repositories Kolibri OS

Rev

Rev 5039 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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.  
  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'
  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:
  46.         invoke  FreeKernelSpace, esi
  47. .return0:
  48.         pop     esi
  49.         xor     eax, eax
  50.         ret
  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
  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
  100. @@:
  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:
  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
  119.         invoke  SysMsgBoardStr
  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
  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
  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
  314.         cmp     [deviceType], gen4_start
  315.         jb      .wait_watching_scanline
  316. ; g45 and later: use special flag from PIPE*CONF
  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
  325.         jmp     .not_disabled
  326. @@:
  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:
  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
  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
  385.         sti
  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:
  398.         ret
  399.  
  400. include '../peimport.inc'
  401. data fixups
  402. end data
  403.  
  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
  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
  464.  
  465. align 4
  466. deviceType      dd      ?
  467. edid    rb      0x80
  468.