Subversion Repositories Kolibri OS

Rev

Rev 5077 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. format PE DLL native 0.05
  9. entry START
  10.  
  11. DEBUG           equ 1
  12.  
  13. API_VERSION     equ 0x01000100
  14. DEBUG_IRQ       equ 0
  15.  
  16. USE_COM_IRQ     equ 0    ;make irq 3 and irq 4 available for PCI devices
  17. IRQ_REMAP       equ 0
  18. IRQ_LINE        equ 0
  19.  
  20.  
  21. ;irq 0,1,2,8,12,13 недоступны
  22. ;                   FEDCBA9876543210
  23. VALID_IRQ       equ 1100111011111000b
  24. ATTCH_IRQ       equ 0000111010100000b
  25.  
  26. if USE_COM_IRQ
  27. ATTCH_IRQ       equ 0000111010111000b
  28. end if
  29.  
  30. CPU_FREQ        equ  2000d
  31.  
  32. BIT0  EQU 0x00000001
  33. BIT1  EQU 0x00000002
  34. BIT2  EQU 0x00000004
  35. BIT3  EQU 0x00000008
  36. BIT4  EQU 0x00000010
  37. BIT5  EQU 0x00000020
  38. BIT6  EQU 0x00000040
  39. BIT7  EQU 0x00000080
  40. BIT8  EQU 0x00000100
  41. BIT9  EQU 0x00000200
  42. BIT10 EQU 0x00000400
  43. BIT11 EQU 0x00000800
  44. BIT12 EQU 0x00001000
  45. BIT13 EQU 0x00002000
  46. BIT14 EQU 0x00004000
  47. BIT15 EQU 0x00008000
  48. BIT16 EQU 0x00010000
  49. BIT17 EQU 0x00020000
  50. BIT18 EQU 0x00040000
  51. BIT19 EQU 0x00080000
  52. BIT20 EQU 0x00100000
  53. BIT21 EQU 0x00200000
  54. BIT22 EQU 0x00400000
  55. BIT23 EQU 0x00800000
  56. BIT24 EQU 0x00100000
  57. BIT25 EQU 0x02000000
  58. BIT26 EQU 0x04000000
  59. BIT27 EQU 0x08000000
  60. BIT28 EQU 0x10000000
  61. BIT29 EQU 0x20000000
  62. BIT30 EQU 0x40000000
  63. BIT31 EQU 0x80000000
  64.  
  65. VID_SIS           equ 0x1039
  66. CTRL_SIS          equ 0x7012
  67.  
  68. PCM_OUT_BDL       equ  0x10  ; PCM out buffer descriptors list
  69. PCM_OUT_CR_REG    equ  0x1b  ; PCM out Control Register
  70. PCM_OUT_LVI_REG   equ  0x15      ; PCM last valid index
  71. PCM_OUT_SR_REG    equ  0x18  ; PCM out Status register
  72. PCM_OUT_PIV_REG   equ  0x1a      ; PCM out prefetched index
  73. PCM_OUT_CIV_REG   equ  0x14      ; PCM out current index
  74.  
  75. PCM_IN_CR_REG     equ  0x0b      ; PCM in Control Register
  76. MC_IN_CR_REG      equ  0x2b  ; MIC in Control Register
  77. RR                equ  BIT1      ; reset registers.  Nukes all regs
  78.  
  79. CODEC_MASTER_VOL_REG            equ     0x02
  80. CODEC_AUX_VOL                   equ     0x04    ;
  81. CODEC_PCM_OUT_REG            equ 0x18 ; PCM output volume
  82. CODEC_EXT_AUDIO_REG          equ 0x28 ; extended audio
  83. CODEC_EXT_AUDIO_CTRL_REG     equ 0x2a ; extended audio control
  84. CODEC_PCM_FRONT_DACRATE_REG  equ 0x2c ; PCM out sample rate
  85. CODEC_PCM_SURND_DACRATE_REG  equ 0x2e ; surround sound sample rate
  86. CODEC_PCM_LFE_DACRATE_REG    equ 0x30 ; LFE sample rate
  87.  
  88. GLOB_CTRL         equ  0x2C        ;   Global Control
  89. CTRL_STAT         equ  0x30        ;   Global Status
  90. CTRL_CAS          equ  0x34        ;   Codec Access Semiphore
  91.  
  92. CAS_FLAG          equ  0x01        ;   Codec Access Semiphore Bit
  93.  
  94. CTRL_ST_CREADY    equ  BIT8+BIT9+BIT28 ;   Primary Codec Ready
  95.  
  96. CTRL_ST_RCS       equ  0x00008000  ;   Read Completion Status
  97.  
  98. CTRL_CNT_CRIE     equ  BIT4+BIT5+BIT6  ;   Codecs Resume Interrupt Enable
  99. CTRL_CNT_AC_OFF   equ  0x00000008  ;   ACLINK Off
  100. CTRL_CNT_WARM     equ  0x00000004  ;   AC97 Warm Reset
  101. CTRL_CNT_COLD     equ  0x00000002  ;   AC97 Cold Reset
  102. CTRL_CNT_GIE      equ  0x00000001  ;   GPI Interrupt Enable
  103.  
  104. CODEC_REG_POWERDOWN   equ 0x26
  105. CODEC_REG_ST          equ 0x26
  106.  
  107. SRV_GETVERSION        equ  0
  108. DEV_PLAY              equ  1
  109. DEV_STOP              equ  2
  110. DEV_CALLBACK          equ  3
  111. DEV_SET_BUFF          equ  4
  112. DEV_NOTIFY            equ  5
  113. DEV_SET_MASTERVOL     equ  6
  114. DEV_GET_MASTERVOL     equ  7
  115. DEV_GET_INFO          equ  8
  116.  
  117. struc AC_CNTRL              ;AC controller base class
  118. { .bus                dd ?
  119.   .devfn              dd ?
  120.  
  121.   .vendor             dd ?
  122.   .dev_id             dd ?
  123.   .pci_cmd            dd ?
  124.   .pci_stat           dd ?
  125.  
  126.   .codec_io_base      dd ?
  127.   .codec_mem_base     dd ?
  128.  
  129.   .ctrl_io_base       dd ?
  130.   .ctrl_mem_base      dd ?
  131.   .cfg_reg            dd ?
  132.   .int_line           dd ?
  133.  
  134.   .vendor_ids         dd ?    ;vendor id string
  135.   .ctrl_ids           dd ?    ;hub id string
  136.  
  137.   .buffer             dd ?
  138.  
  139.   .notify_pos         dd ?
  140.   .notify_task        dd ?
  141.  
  142.   .lvi_reg            dd ?
  143.   .ctrl_setup         dd ?
  144.   .user_callback      dd ?
  145.   .codec_read16       dd ?
  146.   .codec_write16      dd ?
  147.  
  148.   .ctrl_read8         dd ?
  149.   .ctrl_read16        dd ?
  150.   .ctrl_read32        dd ?
  151.  
  152.   .ctrl_write8        dd ?
  153.   .ctrl_write16       dd ?
  154.   .ctrl_write32       dd ?
  155. }
  156.  
  157. struc CODEC                ;Audio Chip base class
  158. {
  159.   .chip_id            dd ?
  160.   .flags              dd ?
  161.   .status             dd ?
  162.  
  163.   .ac_vendor_ids      dd ?    ;ac vendor id string
  164.   .chip_ids           dd ?    ;chip model string
  165.  
  166.   .shadow_flag        dd ?
  167.                       dd ?
  168.  
  169.   .regs               dw ?     ; codec registers
  170.   .reg_master_vol     dw ?     ;0x02
  171.   .reg_aux_out_vol    dw ?     ;0x04
  172.   .reg_mone_vol       dw ?     ;0x06
  173.   .reg_master_tone    dw ?     ;0x08
  174.   .reg_beep_vol       dw ?     ;0x0A
  175.   .reg_phone_vol      dw ?     ;0x0C
  176.   .reg_mic_vol        dw ?     ;0x0E
  177.   .reg_line_in_vol    dw ?     ;0x10
  178.   .reg_cd_vol         dw ?     ;0x12
  179.   .reg_video_vol      dw ?     ;0x14
  180.   .reg_aux_in_vol     dw ?     ;0x16
  181.   .reg_pcm_out_vol    dw ?     ;0x18
  182.   .reg_rec_select     dw ?     ;0x1A
  183.   .reg_rec_gain       dw ?     ;0x1C
  184.   .reg_rec_gain_mic   dw ?     ;0x1E
  185.   .reg_gen            dw ?     ;0x20
  186.   .reg_3d_ctrl        dw ?     ;0X22
  187.   .reg_page           dw ?     ;0X24
  188.   .reg_powerdown      dw ?     ;0x26
  189.   .reg_ext_audio      dw ?     ;0x28
  190.   .reg_ext_st         dw ?     ;0x2a
  191.   .reg_pcm_front_rate dw ?     ;0x2c
  192.   .reg_pcm_surr_rate  dw ?     ;0x2e
  193.   .reg_lfe_rate       dw ?     ;0x30
  194.   .reg_pcm_in_rate    dw ?     ;0x32
  195.                       dw ?     ;0x34
  196.   .reg_cent_lfe_vol   dw ?     ;0x36
  197.   .reg_surr_vol       dw ?     ;0x38
  198.   .reg_spdif_ctrl     dw ?     ;0x3A
  199.                       dw ?     ;0x3C
  200.                       dw ?     ;0x3E
  201.                       dw ?     ;0x40
  202.                       dw ?     ;0x42
  203.                       dw ?     ;0x44
  204.                       dw ?     ;0x46
  205.                       dw ?     ;0x48
  206.                       dw ?     ;0x4A
  207.                       dw ?     ;0x4C
  208.                       dw ?     ;0x4E
  209.                       dw ?     ;0x50
  210.                       dw ?     ;0x52
  211.                       dw ?     ;0x54
  212.                       dw ?     ;0x56
  213.                       dw ?     ;0x58
  214.                       dw ?     ;0x5A
  215.                       dw ?     ;0x5C
  216.                       dw ?     ;0x5E
  217.   .reg_page_0         dw ?     ;0x60
  218.   .reg_page_1         dw ?     ;0x62
  219.   .reg_page_2         dw ?     ;0x64
  220.   .reg_page_3         dw ?     ;0x66
  221.   .reg_page_4         dw ?     ;0x68
  222.   .reg_page_5         dw ?     ;0x6A
  223.   .reg_page_6         dw ?     ;0x6C
  224.   .reg_page_7         dw ?     ;0x6E
  225.                       dw ?     ;0x70
  226.                       dw ?     ;0x72
  227.                       dw ?     ;0x74
  228.                       dw ?     ;0x76
  229.                       dw ?     ;0x78
  230.                       dw ?     ;0x7A
  231.   .reg_vendor_id_1    dw ?     ;0x7C
  232.   .reg_vendor_id_2    dw ?     ;0x7E
  233.  
  234.  
  235.   .reset              dd ?    ;virual
  236.   .set_master_vol     dd ?
  237. }
  238.  
  239. struc CTRL_INFO
  240. {   .pci_cmd          dd ?
  241.     .irq              dd ?
  242.     .glob_cntrl       dd ?
  243.     .glob_sta         dd ?
  244.     .codec_io_base    dd ?
  245.     .ctrl_io_base     dd ?
  246.     .codec_mem_base   dd ?
  247.     .ctrl_mem_base    dd ?
  248.     .codec_id         dd ?
  249. }
  250.  
  251. EVENT_NOTIFY          equ 0x00000200
  252.  
  253. section '.flat' code readable writable executable
  254. include '../struct.inc'
  255. include '../macros.inc'
  256. include '../proc32.inc'
  257. include '../peimport.inc'
  258.  
  259.  
  260. proc START c uses ebx esi edi, state:dword, cmdline:dword
  261.  
  262.         cmp     [state], 1
  263.         jne     .stop
  264.  
  265.      if DEBUG
  266.         mov     esi, msgInit
  267.         invoke  SysMsgBoardStr
  268.      end if
  269.  
  270.         call    detect_controller
  271.         test    eax, eax
  272.         jz      .fail
  273.  
  274.      if DEBUG
  275.         mov     esi, [ctrl.vendor_ids]
  276.         invoke  SysMsgBoardStr
  277.         mov     esi, [ctrl.ctrl_ids]
  278.         invoke  SysMsgBoardStr
  279.  
  280.      end if
  281.  
  282.         call    init_controller
  283.         test    eax, eax
  284.         jz      .fail
  285.  
  286.         call    init_codec
  287.         test    eax, eax
  288.         jz      .fail
  289.  
  290.         call    reset_controller
  291.         call    setup_codec
  292.  
  293.         mov     esi, msgPrimBuff
  294.         invoke  SysMsgBoardStr
  295.         call    create_primary_buff
  296.         mov     esi, msgDone
  297.         invoke  SysMsgBoardStr
  298.  
  299.   if IRQ_REMAP
  300.         pushf
  301.         cli
  302.  
  303.         mov     ebx, [ctrl.int_line]
  304.         in      al, 0xA1
  305.         mov     ah, al
  306.         in      al, 0x21
  307.         test    ebx, ebx
  308.         jz      .skip
  309.         bts     ax, bx                     ;mask old line
  310. .skip:
  311.         bts     ax, IRQ_LINE               ;mask new ine
  312.         out     0x21, al
  313.         mov     al, ah
  314.         out     0xA1, al
  315.                                            ;remap IRQ
  316.         invoke  PciWrite8, 0, 0xF8, 0x61, IRQ_LINE
  317.  
  318.         mov     dx, 0x4d0                  ;8259 ELCR1
  319.         in      al, dx
  320.         bts     ax, IRQ_LINE
  321.         out     dx, al                     ;set level-triggered mode
  322.         mov     [ctrl.int_line], IRQ_LINE
  323.         popf
  324.         mov     esi, msgRemap
  325.         invoke  SysMsgBoardStr
  326.   end if
  327.  
  328.         mov     eax, VALID_IRQ
  329.         mov     ebx, [ctrl.int_line]
  330.         mov     esi, msgInvIRQ
  331.         bt      eax, ebx
  332.         jnc     .fail_msg
  333.         mov     eax, ATTCH_IRQ
  334.         mov     esi, msgAttchIRQ
  335.         bt      eax, ebx
  336.         jnc     .fail_msg
  337.  
  338.         invoke  AttachIntHandler, ebx, ac97_irq, 0
  339. .reg:
  340.         invoke  RegService, sz_sound_srv, service_proc
  341.         ret
  342. .fail:
  343.    if DEBUG
  344.         mov     esi, msgFail
  345.         invoke  SysMsgBoardStr
  346.    end if
  347.         xor     eax, eax
  348.         ret
  349. .fail_msg:
  350.         invoke  SysMsgBoardStr
  351.         xor     eax, eax
  352.         ret
  353. .stop:
  354.         call    stop
  355.         xor     eax, eax
  356.         ret
  357. endp
  358.  
  359. handle     equ  IOCTL.handle
  360. io_code    equ  IOCTL.io_code
  361. input      equ  IOCTL.input
  362. inp_size   equ  IOCTL.inp_size
  363. output     equ  IOCTL.output
  364. out_size   equ  IOCTL.out_size
  365.  
  366. align 4
  367. proc service_proc stdcall, ioctl:dword
  368.  
  369.         mov     edi, [ioctl]
  370.         mov     eax, [edi+io_code]
  371.  
  372.         cmp     eax, SRV_GETVERSION
  373.         jne     @F
  374.  
  375.         mov     eax, [edi+output]
  376.         cmp     [edi+out_size], 4
  377.         jne     .fail
  378.  
  379.         mov     [eax], dword API_VERSION
  380.         xor     eax, eax
  381.         ret
  382. @@:
  383.         cmp     eax, DEV_PLAY
  384.         jne     @F
  385.      if DEBUG
  386.         mov     esi, msgPlay
  387.         invoke  SysMsgBoardStr
  388.      end if
  389.         call    play
  390.         ret
  391. @@:
  392.         cmp     eax, DEV_STOP
  393.         jne     @F
  394.      if DEBUG
  395.         mov     esi, msgStop
  396.         invoke  SysMsgBoardStr
  397.      end if
  398.         call    stop
  399.         ret
  400. @@:
  401.         cmp     eax, DEV_CALLBACK
  402.         jne     @F
  403.         mov     ebx, [edi+input]
  404.         stdcall set_callback, [ebx]
  405.         ret
  406. @@:
  407.         cmp     eax, DEV_SET_MASTERVOL
  408.         jne     @F
  409.         mov     eax, [edi+input]
  410.         mov     eax, [eax]
  411.         call    set_master_vol      ;eax= vol
  412.         ret
  413. @@:
  414.         cmp     eax, DEV_GET_MASTERVOL
  415.         jne     @F
  416.         mov     ebx, [edi+output]
  417.         stdcall get_master_vol, ebx
  418.         ret
  419. ;@@:
  420. ;           cmp eax, DEV_GET_INFO
  421. ;           jne @F
  422. ;           mov ebx, [edi+output]
  423. ;           stdcall get_dev_info, ebx
  424. ;           ret
  425. @@:
  426. .fail:
  427.         or      eax, -1
  428.         ret
  429. endp
  430.  
  431. restore   handle
  432. restore   io_code
  433. restore   input
  434. restore   inp_size
  435. restore   output
  436. restore   out_size
  437.  
  438. align 4
  439. proc ac97_irq
  440.  
  441.      if DEBUG_IRQ
  442.         mov     esi, msgIRQ
  443.         invoke  SysMsgBoardStr
  444.      end if
  445.  
  446.         mov     edx, PCM_OUT_CR_REG
  447.         mov     al, 0x10
  448.         call    [ctrl.ctrl_write8]
  449.  
  450.         mov     ax, 0x1c
  451.         mov     edx, PCM_OUT_SR_REG
  452.         call    [ctrl.ctrl_write16]
  453.  
  454.         mov     edx, PCM_OUT_CIV_REG
  455.         call    [ctrl.ctrl_read8]
  456.  
  457.         and     eax, 0x1F
  458.         cmp     eax, [civ_val]
  459.         je      .skip
  460.  
  461.         mov     [civ_val], eax
  462.         dec     eax
  463.         and     eax, 0x1F
  464.         mov     [ctrl.lvi_reg], eax
  465.  
  466.         mov     edx, PCM_OUT_LVI_REG
  467.         call    [ctrl.ctrl_write8]
  468.  
  469.         mov     edx, PCM_OUT_CR_REG
  470.         mov     ax, 0x11
  471.         call    [ctrl.ctrl_write8]
  472.  
  473.         mov     eax, [civ_val]
  474.         add     eax, 1
  475.         and     eax, 31
  476.         mov     ebx, dword [buff_list+eax*4]
  477.  
  478.         cmp     [ctrl.user_callback], 0
  479.         je      @f
  480.  
  481.         stdcall [ctrl.user_callback], ebx
  482. @@:
  483.         ret
  484.  
  485. .skip:
  486.         mov     edx, PCM_OUT_CR_REG
  487.         mov     ax, 0x11
  488.         call    [ctrl.ctrl_write8]
  489.         ret
  490. endp
  491.  
  492. align 4
  493. proc create_primary_buff
  494.  
  495.         invoke  KernelAlloc, 0x10000
  496.         mov     [ctrl.buffer], eax
  497.  
  498.         mov     edi, eax
  499.         mov     ecx, 0x10000/4
  500.         xor     eax, eax
  501.         cld
  502.         rep stosd
  503.  
  504.         mov     eax, [ctrl.buffer]
  505.         invoke  GetPgAddr
  506.  
  507.         mov     ebx, 0xC0004000
  508.         mov     ecx, 4
  509.         mov     edi, pcmout_bdl
  510. @@:
  511.         mov     [edi], eax
  512.         mov     [edi+4], ebx
  513.  
  514.         mov     [edi+32], eax
  515.         mov     [edi+4+32], ebx
  516.  
  517.         mov     [edi+64], eax
  518.         mov     [edi+4+64], ebx
  519.  
  520.         mov     [edi+96], eax
  521.         mov     [edi+4+96], ebx
  522.  
  523.         mov     [edi+128], eax
  524.         mov     [edi+4+128], ebx
  525.  
  526.         mov     [edi+160], eax
  527.         mov     [edi+4+160], ebx
  528.  
  529.         mov     [edi+192], eax
  530.         mov     [edi+4+192], ebx
  531.  
  532.         mov     [edi+224], eax
  533.         mov     [edi+4+224], ebx
  534.  
  535.         add     eax, 0x4000
  536.         add     edi, 8
  537.         loop    @B
  538.  
  539.         mov     edi, buff_list
  540.         mov     eax, [ctrl.buffer]
  541.         mov     ecx, 4
  542. @@:
  543.         mov     [edi], eax
  544.         mov     [edi+16], eax
  545.         mov     [edi+32], eax
  546.         mov     [edi+48], eax
  547.         mov     [edi+64], eax
  548.         mov     [edi+80], eax
  549.         mov     [edi+96], eax
  550.         mov     [edi+112], eax
  551.  
  552.         add     eax, 0x4000
  553.         add     edi, 4
  554.         loop    @B
  555.  
  556.         mov     eax, pcmout_bdl
  557.         mov     ebx, eax
  558.         invoke  GetPgAddr     ;eax
  559.         and     ebx, 0xFFF
  560.         add     eax, ebx
  561.  
  562.         mov     edx, PCM_OUT_BDL
  563.         call    [ctrl.ctrl_write32]
  564.  
  565.         mov     eax, 16
  566.         mov     [ctrl.lvi_reg], eax
  567.         mov     edx, PCM_OUT_LVI_REG
  568.         call    [ctrl.ctrl_write8]
  569.  
  570.         mov     edx, GLOB_CTRL
  571.         call    [ctrl.ctrl_read32]
  572.         and     eax, not 0x000000C0
  573.         mov     edx, GLOB_CTRL
  574.         call    [ctrl.ctrl_write32]
  575.  
  576.         ret
  577. endp
  578.  
  579. align 4
  580. proc detect_controller
  581.         push    ebx
  582.         invoke  GetPCIList
  583.         mov     ebx, eax
  584. .next_dev:
  585.         mov     eax, [eax+PCIDEV.fd]
  586.         cmp     eax, ebx
  587.         je      .err
  588.         cmp     [eax+PCIDEV.class], 0x060100  ;pci-isa
  589.         jne     .no_bridge
  590.         movzx   edx, [eax+PCIDEV.bus]
  591.         mov     [brg_bus], edx
  592.         movzx   edx, [eax+PCIDEV.devfn]
  593.         mov     [brg_devfn], edx
  594. .no_bridge:
  595.         mov     edx, [eax+PCIDEV.vendor_device_id]
  596.         mov     esi, devices
  597. @@:
  598.         cmp     dword [esi], 0
  599.         jz      .next_dev
  600.         cmp     dword [esi], edx
  601.         jz      .found
  602.         add     esi, 12
  603.         jmp     @b
  604. .err:
  605.         xor     eax, eax
  606.         pop     ebx
  607.         ret
  608. .found:
  609.         movzx   ebx, [eax+PCIDEV.bus]
  610.         mov     [ctrl.bus], ebx
  611.  
  612.         movzx   ecx, [eax+PCIDEV.devfn]
  613.         mov     [ctrl.devfn], ecx
  614.  
  615.         mov     eax, edx
  616.         and     edx, 0xFFFF
  617.         mov     [ctrl.vendor], edx
  618.         shr     eax, 16
  619.         mov     [ctrl.dev_id], eax
  620.  
  621.         mov     ebx, [esi+4]
  622.         mov     [ctrl.ctrl_ids], ebx
  623.         mov     [ctrl.vendor_ids], msg_SIS
  624.  
  625.         mov     eax, [esi+8]
  626.         mov     [ctrl.ctrl_setup], eax
  627.         pop     ebx
  628.         ret
  629. endp
  630.  
  631. align 4
  632. proc init_controller
  633.  
  634.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 4
  635.         mov     ebx, eax
  636.         or      al, 5
  637.         invoke  PciWrite16, [ctrl.bus], [ctrl.devfn], 4, eax
  638.         movzx   eax, bx
  639.         mov     [ctrl.pci_cmd], eax
  640.         shr     ebx, 16
  641.         mov     [ctrl.pci_stat], ebx
  642.  
  643.         mov     esi, msgPciCmd
  644.         invoke  SysMsgBoardStr
  645.         call    dword2str
  646.         invoke  SysMsgBoardStr
  647.  
  648.         mov     esi, msgPciStat
  649.         invoke  SysMsgBoardStr
  650.         mov     eax, [ctrl.pci_stat]
  651.         call    dword2str
  652.         invoke  SysMsgBoardStr
  653.  
  654.         mov     esi, msgMixIsaIo
  655.         invoke  SysMsgBoardStr
  656.  
  657.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 0x10
  658.  
  659.         call    dword2str
  660.         invoke  SysMsgBoardStr
  661.  
  662.         and     eax, 0xFFFE
  663.         mov     [ctrl.codec_io_base], eax
  664.  
  665.         mov     esi, msgCtrlIsaIo
  666.         invoke  SysMsgBoardStr
  667.  
  668.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 0x14
  669.  
  670.         call    dword2str
  671.         invoke  SysMsgBoardStr
  672.  
  673.         and     eax, 0xFFC0
  674.         mov     [ctrl.ctrl_io_base], eax
  675.  
  676.         mov     esi, msgMixMMIo
  677.         invoke  SysMsgBoardStr
  678.  
  679.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 0x18
  680.         mov     [ctrl.codec_mem_base], eax
  681.  
  682.         call    dword2str
  683.         invoke  SysMsgBoardStr
  684.  
  685.         mov     esi, msgCtrlMMIo
  686.         invoke  SysMsgBoardStr
  687.  
  688.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 0x1C
  689.         mov     [ctrl.ctrl_mem_base], eax
  690.  
  691.         call    dword2str
  692.         invoke  SysMsgBoardStr
  693.  
  694.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 0x3C
  695.         cmp     al, 0xFF
  696.         jnz     @f
  697.         movzx   eax, ah
  698.         add     eax, 0x40
  699.         invoke  PciWrite8, [brg_bus], [brg_devfn], eax, 5
  700.         invoke  PciWrite8, [ctrl.bus], [ctrl.devfn], 0x3C, 5
  701.         mov     al, 5
  702. @@:
  703.         and     eax, 0xFF
  704.         mov     [ctrl.int_line], eax
  705.  
  706.         invoke  PciRead8, [ctrl.bus], [ctrl.devfn], 0x41
  707.         and     eax, 0xFF
  708.         mov     [ctrl.cfg_reg], eax
  709.  
  710.         call    [ctrl.ctrl_setup]
  711.         xor     eax, eax
  712.         inc     eax
  713.         ret
  714. endp
  715.  
  716. align 4
  717. proc set_SIS
  718.         mov     [ctrl.codec_read16], codec_io_r16    ;virtual
  719.         mov     [ctrl.codec_write16], codec_io_w16   ;virtual
  720.  
  721.         mov     [ctrl.ctrl_read8 ], ctrl_io_r8      ;virtual
  722.         mov     [ctrl.ctrl_read16], ctrl_io_r16      ;virtual
  723.         mov     [ctrl.ctrl_read32], ctrl_io_r32      ;virtual
  724.  
  725.         mov     [ctrl.ctrl_write8 ], ctrl_io_w8     ;virtual
  726.         mov     [ctrl.ctrl_write16], ctrl_io_w16     ;virtual
  727.         mov     [ctrl.ctrl_write32], ctrl_io_w32     ;virtual
  728.         ret
  729. endp
  730.  
  731. align 4
  732. proc reset_controller
  733.  
  734.         xor     eax, eax
  735.         mov     edx, PCM_IN_CR_REG
  736.         call    [ctrl.ctrl_write8]
  737.  
  738.         mov     edx, PCM_OUT_CR_REG
  739.         call    [ctrl.ctrl_write8]
  740.  
  741.         mov     edx, MC_IN_CR_REG
  742.         call    [ctrl.ctrl_write8]
  743.  
  744.         mov     eax, RR
  745.         mov     edx, PCM_IN_CR_REG
  746.         call    [ctrl.ctrl_write8]
  747.  
  748.         mov     edx, PCM_OUT_CR_REG
  749.         call    [ctrl.ctrl_write8]
  750.  
  751.         mov     edx, MC_IN_CR_REG
  752.         call    [ctrl.ctrl_write8]
  753.         ret
  754. endp
  755.  
  756. align 4
  757. proc init_codec
  758.            locals
  759.              counter dd ?
  760.            endl
  761.  
  762.         mov     esi, msgControl
  763.         invoke  SysMsgBoardStr
  764.  
  765.         mov     edx, GLOB_CTRL
  766.         call    [ctrl.ctrl_read32]
  767.         call    dword2str
  768.         invoke  SysMsgBoardStr
  769.  
  770.         mov     esi, msgStatus
  771.         invoke  SysMsgBoardStr
  772.  
  773.         mov     edx, CTRL_STAT
  774.         call    [ctrl.ctrl_read32]
  775.         push    eax
  776.         call    dword2str
  777.         invoke  SysMsgBoardStr
  778.         pop     eax
  779.         cmp     eax, 0xFFFFFFFF
  780.         je      .err
  781.  
  782.         test    eax, CTRL_ST_CREADY
  783.         jnz     .ready
  784.  
  785.         call    reset_codec
  786.         test    eax, eax
  787.         jz      .err
  788.  
  789. .ready:
  790.         xor     edx, edx    ;ac_reg_0
  791.         call    [ctrl.codec_write16]
  792.  
  793.         xor     eax, eax
  794.         mov     edx, CODEC_REG_POWERDOWN
  795.         call    [ctrl.codec_write16]
  796.  
  797.         mov     [counter], 200    ; total 200*5 ms = 1s
  798. .wait:
  799.         mov     eax, 5000  ; wait 5 ms
  800.         call    StallExec
  801.  
  802.         mov     edx, CODEC_REG_POWERDOWN
  803.         call    [ctrl.codec_read16]
  804.         and     eax, 0x0F
  805.         cmp     eax, 0x0F
  806.         je      .done
  807.  
  808.         sub     [counter] , 1
  809.         jnz     .wait
  810. .err:
  811.         xor     eax, eax       ; timeout error
  812.         ret
  813. .done:
  814.         mov     eax, 2     ;force set 16-bit 2-channel PCM
  815.         mov     edx, GLOB_CTRL
  816.         call    [ctrl.ctrl_write32]
  817.         mov     eax, 5000  ; wait 5 ms
  818.         call    StallExec
  819.  
  820.         call    detect_codec
  821.  
  822.         xor     eax, eax
  823.         inc     eax
  824.         ret
  825. endp
  826.  
  827. align 4
  828. proc reset_codec
  829.         mov     edx, GLOB_CTRL
  830.         call    [ctrl.ctrl_read32]
  831.  
  832.         test    eax, 0x02
  833.         jz      .cold
  834.  
  835.         call    warm_reset
  836.         jnc     .ok
  837. .cold:
  838.         call    cold_reset
  839.         jnc     .ok
  840.  
  841.      if DEBUG
  842.         mov     esi, msgCFail
  843.         invoke  SysMsgBoardStr
  844.      end if
  845.         xor     eax, eax    ; timeout error
  846.         ret
  847. .ok:
  848.         xor     eax, eax
  849.         inc     eax
  850.         ret
  851. endp
  852.  
  853. align 4
  854. proc warm_reset
  855.            locals
  856.              counter dd ?
  857.            endl
  858.  
  859.         mov     eax, 0x06
  860.         mov     edx, GLOB_CTRL
  861.         call    [ctrl.ctrl_write32]
  862.  
  863.      if DEBUG
  864.         mov     esi, msgWarm
  865.         invoke  SysMsgBoardStr
  866.      end if
  867.  
  868.         mov     [counter], 10   ; total 10*100 ms = 1s
  869. .wait:
  870.         mov     eax, 100000   ; wait 100 ms
  871.         call    StallExec
  872.  
  873.         mov     edx, CTRL_STAT
  874.         call    [ctrl.ctrl_read32]
  875.         test    eax, CTRL_ST_CREADY
  876.         jnz     .ok
  877.  
  878.         dec     [counter]
  879.         jnz     .wait
  880.  
  881.      if DEBUG
  882.         mov     esi, msgWRFail
  883.         invoke  SysMsgBoardStr
  884.      end if
  885. .fail:
  886.         stc
  887.         ret
  888. .ok:
  889.         clc
  890.         ret
  891. endp
  892.  
  893. align 4
  894. proc cold_reset
  895.            locals
  896.              counter dd ?
  897.             endl
  898.  
  899.         mov     eax, 0x02
  900.         mov     edx, GLOB_CTRL
  901.         call    [ctrl.ctrl_write32]
  902.  
  903.      if DEBUG
  904.         mov     esi, msgCold
  905.         invoke  SysMsgBoardStr
  906.      end if
  907.  
  908.         mov     eax, 400000    ; wait 400 ms
  909.         call    StallExec
  910.  
  911.         mov     [counter], 16   ; total 20*100 ms = 2s
  912. .wait:
  913.  
  914.         mov     edx, CTRL_STAT
  915.         call    [ctrl.ctrl_read32]
  916.         test    eax, CTRL_ST_CREADY
  917.         jnz     .ok
  918.  
  919.         mov     eax, 100000   ; wait 100 ms
  920.         call    StallExec
  921.  
  922.         dec     [counter]
  923.         jnz     .wait
  924.  
  925.      if DEBUG
  926.         mov     esi, msgCRFail
  927.         invoke  SysMsgBoardStr
  928.      end if
  929.  
  930. .fail:
  931.         stc
  932.         ret
  933. .ok:
  934.         mov     esi, msgControl
  935.         invoke  SysMsgBoardStr
  936.  
  937.         mov     edx, GLOB_CTRL
  938.         call    [ctrl.ctrl_read32]
  939.         call    dword2str
  940.         invoke  SysMsgBoardStr
  941.  
  942.         mov     esi, msgStatus
  943.         invoke  SysMsgBoardStr
  944.  
  945.         mov     edx, CTRL_STAT
  946.         call    [ctrl.ctrl_read32]
  947.         push    eax
  948.         call    dword2str
  949.         invoke  SysMsgBoardStr
  950.         pop     eax
  951.  
  952.         test    eax, CTRL_ST_CREADY
  953.         jz      .fail
  954.         clc
  955.         ret
  956. endp
  957.  
  958. align 4
  959. play:
  960.         xor     eax, eax
  961.         mov     [civ_val], eax
  962.         mov     edx, PCM_OUT_CIV_REG
  963.         call    [ctrl.ctrl_write8]
  964.  
  965.         mov     eax, 16
  966.         mov     [ctrl.lvi_reg], eax
  967.         mov     edx, PCM_OUT_LVI_REG
  968.         call    [ctrl.ctrl_write8]
  969.  
  970.         mov     edx, PCM_OUT_CR_REG
  971.         mov     ax, 0x1D
  972.         call    [ctrl.ctrl_write8]
  973.         xor     eax, eax
  974.         ret
  975.  
  976. align 4
  977. stop:
  978.         mov     edx, PCM_OUT_CR_REG
  979.         mov     ax, 0x0
  980.         call    [ctrl.ctrl_write8]
  981.  
  982.         mov     ax, 0x1c
  983.         mov     edx, PCM_OUT_SR_REG
  984.         call    [ctrl.ctrl_write16]
  985.         xor     eax, eax
  986.         ret
  987.  
  988. align 4
  989. proc get_dev_info stdcall, p_info:dword
  990.            virtual at esi
  991.              CTRL_INFO CTRL_INFO
  992.            end virtual
  993.  
  994.         mov     esi, [p_info]
  995.         mov     eax, [ctrl.int_line]
  996.         mov     ebx, [ctrl.codec_io_base]
  997.         mov     ecx, [ctrl.ctrl_io_base]
  998.         mov     edx, [ctrl.codec_mem_base]
  999.         mov     edi, [ctrl.ctrl_mem_base]
  1000.  
  1001.         mov     [CTRL_INFO.irq], eax
  1002.         mov     [CTRL_INFO.codec_io_base], ebx
  1003.         mov     [CTRL_INFO.ctrl_io_base], ecx
  1004.         mov     [CTRL_INFO.codec_mem_base], edx
  1005.         mov     [CTRL_INFO.ctrl_mem_base], edi
  1006.  
  1007.         mov     eax, [codec.chip_id]
  1008.         mov     [CTRL_INFO.codec_id], eax
  1009.  
  1010.         mov     edx, GLOB_CTRL
  1011.         call    [ctrl.ctrl_read32]
  1012.         mov     [CTRL_INFO.glob_cntrl], eax
  1013.  
  1014.         mov     edx, CTRL_STAT
  1015.         call    [ctrl.ctrl_read32]
  1016.         mov     [CTRL_INFO.glob_sta], eax
  1017.  
  1018.         mov     ebx, [ctrl.pci_cmd]
  1019.         mov     [CTRL_INFO.pci_cmd], ebx
  1020.         ret
  1021. endp
  1022.  
  1023. align 4
  1024. proc set_callback stdcall, handler:dword
  1025.         mov     eax, [handler]
  1026.         mov     [ctrl.user_callback], eax
  1027.         ret
  1028. endp
  1029.  
  1030. align 4
  1031. proc codec_read stdcall, ac_reg:dword      ; reg = edx, reval = eax
  1032.  
  1033.         mov     edx, [ac_reg]
  1034.  
  1035.         mov     ebx, edx
  1036.         shr     ebx, 1
  1037.         bt      [codec.shadow_flag], ebx
  1038.         jc      .use_shadow
  1039.  
  1040.         call    [ctrl.codec_read16]  ;change edx !!!
  1041.         mov     ecx, eax
  1042.  
  1043.         mov     edx, CTRL_STAT
  1044.         call    [ctrl.ctrl_read32]
  1045.         test    eax, CTRL_ST_RCS
  1046.         jz      .read_ok
  1047.  
  1048.         mov     edx, CTRL_STAT
  1049.         call    [ctrl.ctrl_write32]
  1050.         xor     eax, eax
  1051.         not     eax ;timeout
  1052.         ret
  1053. .read_ok:
  1054.         mov     edx, [ac_reg]
  1055.         mov     [codec.regs+edx], cx
  1056.         bts     [codec.shadow_flag], ebx
  1057.         mov     eax, ecx
  1058.         ret
  1059. .use_shadow:
  1060.         movzx   eax, word [codec.regs+edx]
  1061.         ret
  1062. endp
  1063.  
  1064. align 4
  1065. proc codec_write stdcall, ac_reg:dword
  1066.         mov     esi, [ac_reg]
  1067.         mov     edx, esi
  1068.         call    [ctrl.codec_write16]
  1069.         mov     [codec.regs+esi], ax
  1070.         shr     esi, 1
  1071.         bts     [codec.shadow_flag], esi
  1072.         ret
  1073. endp
  1074.  
  1075. align 4
  1076. proc codec_check_ready
  1077.  
  1078.         mov     edx, CTRL_ST
  1079.         call    [ctrl.ctrl_read32]
  1080.         and     eax, CTRL_ST_CREADY
  1081.         jz      .not_ready
  1082.  
  1083.         xor     eax, wax
  1084.         inc     eax
  1085.         ret
  1086. .not_ready:
  1087.         xor     eax, eax
  1088.         ret
  1089. endp
  1090.  
  1091. align 4
  1092. proc check_semaphore
  1093.            local counter:DWORD
  1094.  
  1095.         mov     [counter], 100
  1096. .l1:
  1097.         mov     edx, CTRL_CAS
  1098.         call    [ctrl.ctrl_read8]
  1099.         and     eax, CAS_FLAG
  1100.         jz      .ok
  1101.  
  1102.         mov     eax, 1
  1103.         call    StallExec
  1104.         sub     [counter], 1
  1105.         jnz     .l1
  1106.         xor     eax, eax
  1107.         ret
  1108. align 4
  1109. .ok:
  1110.         xor     eax, eax
  1111.         inc     eax
  1112.         ret
  1113. endp
  1114.  
  1115. align 4
  1116. proc StallExec
  1117.         push    ecx
  1118.         push    edx
  1119.         push    ebx
  1120.         push    eax
  1121.  
  1122.         mov     ecx, CPU_FREQ
  1123.         mul     ecx
  1124.         mov     ebx, eax      ;low
  1125.         mov     ecx, edx      ;high
  1126.         rdtsc
  1127.         add     ebx, eax
  1128.         adc     ecx, edx
  1129. @@:
  1130.         rdtsc
  1131.         sub     eax, ebx
  1132.         sbb     edx, ecx
  1133.         js      @B
  1134.  
  1135.         pop     eax
  1136.         pop     ebx
  1137.         pop     edx
  1138.         pop     ecx
  1139.         ret
  1140. endp
  1141.  
  1142. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1143. ;          CONTROLLER IO functions
  1144. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1145.  
  1146. align 4
  1147. proc codec_io_r16
  1148.         push    eax edx
  1149.         call    check_semaphore
  1150.         test    eax, eax
  1151.         pop     edx eax
  1152.         jz      .err
  1153.         add     edx, [ctrl.codec_io_base]
  1154.         in      ax, dx
  1155. .err:
  1156.         ret
  1157. endp
  1158.  
  1159. align 4
  1160. proc codec_io_w16
  1161.         push    eax edx
  1162.         call    check_semaphore
  1163.         test    eax, eax
  1164.         pop     edx eax
  1165.         jz      .err
  1166.         add     edx, [ctrl.codec_io_base]
  1167.         out     dx, ax
  1168. .err:
  1169.         ret
  1170. endp
  1171.  
  1172. align 4
  1173. proc ctrl_io_r8
  1174.         add     edx, [ctrl.ctrl_io_base]
  1175.         in      al, dx
  1176.         ret
  1177. endp
  1178.  
  1179. align 4
  1180. proc ctrl_io_r16
  1181.         add     edx, [ctrl.ctrl_io_base]
  1182.         in      ax, dx
  1183.         ret
  1184. endp
  1185.  
  1186. align 4
  1187. proc ctrl_io_r32
  1188.         add     edx, [ctrl.ctrl_io_base]
  1189.         in      eax, dx
  1190.         ret
  1191. endp
  1192.  
  1193. align 4
  1194. proc ctrl_io_w8
  1195.         add     edx, [ctrl.ctrl_io_base]
  1196.         out     dx, al
  1197.         ret
  1198. endp
  1199.  
  1200. align 4
  1201. proc ctrl_io_w16
  1202.         add     edx, [ctrl.ctrl_io_base]
  1203.         out     dx, ax
  1204.         ret
  1205. endp
  1206.  
  1207. align 4
  1208. proc ctrl_io_w32
  1209.         add     edx, [ctrl.ctrl_io_base]
  1210.         out     dx, eax
  1211.         ret
  1212. endp
  1213.  
  1214. align 4
  1215. dword2str:
  1216.         mov     esi, hex_buff
  1217.         mov     ecx, -8
  1218. @@:
  1219.         rol     eax, 4
  1220.         mov     ebx, eax
  1221.         and     ebx, 0x0F
  1222.         mov     bl, [ebx+hexletters]
  1223.         mov     [8+esi+ecx], bl
  1224.         inc     ecx
  1225.         jnz     @B
  1226.         ret
  1227.  
  1228. hexletters   db '0123456789ABCDEF'
  1229. hex_buff     db 8 dup(0),13,10,0
  1230.  
  1231. include "codec.inc"
  1232.  
  1233. align 4
  1234. devices dd (CTRL_SIS  shl 16)+VID_SIS,msg_AC, set_SIS
  1235.         dd 0
  1236.  
  1237. msg_AC       db '7012 AC97 controller',13,10, 0
  1238. msg_SIS      db 'Silicon Integrated Systems',13,10, 0
  1239.  
  1240. sz_sound_srv        db 'SOUND',0
  1241.  
  1242. msgInit      db 'detect hardware...',13,10,0
  1243. msgFail      db 'device not found',13,10,0
  1244. msgAttchIRQ  db 'IRQ line not supported', 13,10, 0
  1245. msgInvIRQ    db 'IRQ line not assigned or invalid', 13,10, 0
  1246. msgPlay      db 'start play', 13,10,0
  1247. msgStop      db 'stop play',  13,10,0
  1248. ;msgNotify    db 'call notify',13,10,0
  1249. msgIRQ       db 'AC97 IRQ', 13,10,0
  1250. msgInitCtrl  db 'init controller',13,10,0
  1251. ;msgInitCodec db 'init codec',13,10,0
  1252. msgPrimBuff  db 'create primary buffer ...',0
  1253. msgDone      db 'done',13,10,0
  1254. msgRemap     db 'Remap IRQ',13,10,0
  1255. ;msgReg       db 'set service handler',13,10,0
  1256. msgOk        db 'service installed',13,10,0
  1257. msgCold      db 'cold reset',13,10,0
  1258. msgWarm      db 'warm reset',13,10,0
  1259. msgWRFail    db 'warm reset failed',13,10,0
  1260. msgCRFail    db 'cold reset failed',13,10,0
  1261. msgCFail     db 'codec not ready',13,10,0
  1262. msgResetOk   db 'reset complete',13,10,0
  1263. msgStatus    db 'global status   ',0
  1264. msgControl   db 'global control  ',0
  1265. msgPciCmd    db 'PCI command     ',0
  1266. msgPciStat   db 'PCI status      ',0
  1267. msgCtrlIsaIo db 'controller io base   ',0
  1268. msgMixIsaIo  db 'codec io base        ',0
  1269. msgCtrlMMIo  db 'controller mmio base ',0
  1270. msgMixMMIo   db 'codec mmio base      ',0
  1271. msgIrqMap    db 'AC97 irq map as      ',0
  1272.  
  1273. align 4
  1274. data fixups
  1275. end data
  1276.  
  1277. align 8
  1278. pcmout_bdl       rq 32
  1279. buff_list        rd 32
  1280.  
  1281. codec CODEC
  1282. ctrl AC_CNTRL
  1283.  
  1284. lpc_bus  rd 1
  1285. civ_val  rd 1
  1286.  
  1287. brg_bus   dd ?
  1288. brg_devfn dd ?
  1289.