Subversion Repositories Kolibri OS

Rev

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