Subversion Repositories Kolibri OS

Rev

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

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