Subversion Repositories Kolibri OS

Rev

Rev 2288 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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.  
  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
  473.