Subversion Repositories Kolibri OS

Rev

Rev 5363 | 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. DEBUG_IRQ       equ 0
  13.  
  14. API_VERSION     equ 0x01000100
  15.  
  16.  
  17. ;irq 0,13 unavailable
  18. ;                   FEDCBA9876543210
  19. VALID_IRQ       equ 1101111111111110b
  20.  
  21. CPU_FREQ        equ  2000d
  22.  
  23. BIT0  EQU 0x00000001
  24. BIT1  EQU 0x00000002
  25. BIT2  EQU 0x00000004
  26. BIT3  EQU 0x00000008
  27. BIT4  EQU 0x00000010
  28. BIT5  EQU 0x00000020
  29. BIT6  EQU 0x00000040
  30. BIT7  EQU 0x00000080
  31. BIT8  EQU 0x00000100
  32. BIT9  EQU 0x00000200
  33. BIT10 EQU 0x00000400
  34. BIT11 EQU 0x00000800
  35. BIT12 EQU 0x00001000
  36. BIT13 EQU 0x00002000
  37. BIT14 EQU 0x00004000
  38. BIT15 EQU 0x00008000
  39. BIT16 EQU 0x00010000
  40. BIT17 EQU 0x00020000
  41. BIT18 EQU 0x00040000
  42. BIT19 EQU 0x00080000
  43. BIT20 EQU 0x00100000
  44. BIT21 EQU 0x00200000
  45. BIT22 EQU 0x00400000
  46. BIT23 EQU 0x00800000
  47. BIT24 EQU 0x00100000
  48. BIT25 EQU 0x02000000
  49. BIT26 EQU 0x04000000
  50. BIT27 EQU 0x08000000
  51. BIT28 EQU 0x10000000
  52. BIT29 EQU 0x20000000
  53. BIT30 EQU 0x40000000
  54. BIT31 EQU 0x80000000
  55.  
  56. VID_FM801         equ 0x1319
  57. CTRL_FM801        equ 0x0801
  58.  
  59. FM_PCM_VOLUME         equ 0x00
  60. FM_FM_VOLUME          equ 0x02
  61. FM_I2S_VOLUME         equ 0x04
  62. FM_RECORD_SOURCE      equ 0x06
  63.  
  64. FM_PLAY_CTL           equ 0x08
  65. FM_PLAY_RATE_MASK     equ 0x0f00
  66. FM_PLAY_BUF1_LAST     equ 0x0001
  67. FM_PLAY_BUF2_LAST     equ 0x0002
  68. FM_PLAY_START         equ 0x0020
  69. FM_PLAY_PAUSE         equ 0x0040
  70. FM_PLAY_STOPNOW       equ 0x0080
  71. FM_PLAY_16BIT         equ 0x4000
  72. FM_PLAY_STEREO        equ 0x8000
  73.  
  74. FM_PLAY_DMALEN        equ 0x0a
  75. FM_PLAY_DMABUF1       equ 0x0c
  76. FM_PLAY_DMABUF2       equ 0x10
  77.  
  78. FM_REC_CTL            equ 0x14
  79. FM_REC_RATE_MASK      equ 0x0f00
  80. FM_REC_BUF1_LAST      equ 0x0001
  81. FM_REC_BUF2_LAST      equ 0x0002
  82. FM_REC_START          equ 0x0020
  83. FM_REC_PAUSE          equ 0x0040
  84. FM_REC_STOPNOW        equ 0x0080
  85. FM_REC_16BIT          equ 0x4000
  86. FM_REC_STEREO         equ 0x8000
  87.  
  88. FM_REC_DMALEN         equ 0x16
  89. FM_REC_DMABUF1        equ 0x18
  90. FM_REC_DMABUF2        equ 0x1c
  91.  
  92. FM_CODEC_CTL          equ 0x22
  93. FM_VOLUME             equ 0x26
  94. FM_VOLUME_MUTE        equ 0x8000
  95.  
  96. FM_CODEC_CMD          equ 0x2a
  97. FM_CODEC_CMD_READ     equ 0x0080
  98. FM_CODEC_CMD_VALID    equ 0x0100
  99. FM_CODEC_CMD_BUSY     equ 0x0200
  100.  
  101. FM_CODEC_DATA         equ 0x2c
  102.  
  103. FM_IO_CTL             equ 0x52
  104. FM_CARD_CTL           equ 0x54
  105.  
  106. FM_INTMASK            equ 0x56
  107. FM_INTMASK_PLAY       equ 0x0001
  108. FM_INTMASK_REC        equ 0x0002
  109. FM_INTMASK_VOL        equ 0x0040
  110. FM_INTMASK_MPU        equ 0x0080
  111.  
  112. FM_INTSTATUS          equ 0x5a
  113. FM_INTSTATUS_PLAY     equ 0x0100
  114. FM_INTSTATUS_REC      equ 0x0200
  115. FM_INTSTATUS_VOL      equ 0x4000
  116. FM_INTSTATUS_MPU      equ 0x8000
  117.  
  118. CODEC_MASTER_VOL_REG         equ 0x02 ;
  119. CODEC_AUX_VOL                equ 0x04 ;
  120. CODEC_PCM_OUT_REG            equ 0x18 ; PCM output volume
  121. CODEC_EXT_AUDIO_REG          equ 0x28 ; extended audio
  122. CODEC_EXT_AUDIO_CTRL_REG     equ 0x2a ; extended audio control
  123. CODEC_PCM_FRONT_DACRATE_REG  equ 0x2c ; PCM out sample rate
  124. CODEC_PCM_SURND_DACRATE_REG  equ 0x2e ; surround sound sample rate
  125. CODEC_PCM_LFE_DACRATE_REG    equ 0x30 ; LFE sample rate
  126.  
  127. SRV_GETVERSION        equ  0
  128. DEV_PLAY              equ  1
  129. DEV_STOP              equ  2
  130. DEV_CALLBACK          equ  3
  131. DEV_SET_BUFF          equ  4
  132. DEV_NOTIFY            equ  5
  133. DEV_SET_MASTERVOL     equ  6
  134. DEV_GET_MASTERVOL     equ  7
  135. DEV_GET_INFO          equ  8
  136.  
  137. struc AC_CNTRL    ;AC controller base class
  138. { .bus                dd ?
  139.   .devfn              dd ?
  140.  
  141.   .vendor             dd ?
  142.   .dev_id             dd ?
  143.   .pci_cmd            dd ?
  144.   .pci_stat           dd ?
  145.  
  146.   .codec_io_base      dd ?
  147.   .codec_mem_base     dd ?
  148.  
  149.   .ctrl_io_base       dd ?
  150.   .ctrl_mem_base      dd ?
  151.   .cfg_reg            dd ?
  152.   .int_line           dd ?
  153.  
  154.   .vendor_ids         dd ?    ;vendor id string
  155.   .ctrl_ids           dd ?    ;hub id string
  156.  
  157.   .buffer             dd ?
  158.  
  159.   .notify_pos         dd ?
  160.   .notify_task        dd ?
  161.  
  162.   .lvi_reg            dd ?
  163.   .ctrl_setup         dd ?
  164.   .user_callback      dd ?
  165.   .codec_read16       dd ?
  166.   .codec_write16      dd ?
  167.  
  168.   .ctrl_read8         dd ?
  169.   .ctrl_read16        dd ?
  170.   .ctrl_read32        dd ?
  171.  
  172.   .ctrl_write8        dd ?
  173.   .ctrl_write16       dd ?
  174.   .ctrl_write32       dd ?
  175. }
  176.  
  177. struc CODEC   ;Audio Chip base class
  178. {
  179.   .chip_id            dd ?
  180.   .flags              dd ?
  181.   .status             dd ?
  182.  
  183.   .ac_vendor_ids      dd ?    ;ac vendor id string
  184.   .chip_ids           dd ?    ;chip model string
  185.  
  186.   .shadow_flag        dd ?
  187.                       dd ?
  188.  
  189.   .regs               dw ?     ; codec registers
  190.   .reg_master_vol     dw ?     ;0x02
  191.   .reg_aux_out_vol    dw ?     ;0x04
  192.   .reg_mone_vol       dw ?     ;0x06
  193.   .reg_master_tone    dw ?     ;0x08
  194.   .reg_beep_vol       dw ?     ;0x0A
  195.   .reg_phone_vol      dw ?     ;0x0C
  196.   .reg_mic_vol        dw ?     ;0x0E
  197.   .reg_line_in_vol    dw ?     ;0x10
  198.   .reg_cd_vol         dw ?     ;0x12
  199.   .reg_video_vol      dw ?     ;0x14
  200.   .reg_aux_in_vol     dw ?     ;0x16
  201.   .reg_pcm_out_vol    dw ?     ;0x18
  202.   .reg_rec_select     dw ?     ;0x1A
  203.   .reg_rec_gain       dw ?     ;0x1C
  204.   .reg_rec_gain_mic   dw ?     ;0x1E
  205.   .reg_gen            dw ?     ;0x20
  206.   .reg_3d_ctrl        dw ?     ;0X22
  207.   .reg_page           dw ?     ;0X24
  208.   .reg_powerdown      dw ?     ;0x26
  209.   .reg_ext_audio      dw ?     ;0x28
  210.   .reg_ext_st         dw ?     ;0x2a
  211.   .reg_pcm_front_rate dw ?     ;0x2c
  212.   .reg_pcm_surr_rate  dw ?     ;0x2e
  213.   .reg_lfe_rate       dw ?     ;0x30
  214.   .reg_pcm_in_rate    dw ?     ;0x32
  215.                       dw ?     ;0x34
  216.   .reg_cent_lfe_vol   dw ?     ;0x36
  217.   .reg_surr_vol       dw ?     ;0x38
  218.   .reg_spdif_ctrl     dw ?     ;0x3A
  219.                       dw ?     ;0x3C
  220.                       dw ?     ;0x3E
  221.                       dw ?     ;0x40
  222.                       dw ?     ;0x42
  223.                       dw ?     ;0x44
  224.                       dw ?     ;0x46
  225.                       dw ?     ;0x48
  226.                       dw ?     ;0x4A
  227.                       dw ?     ;0x4C
  228.                       dw ?     ;0x4E
  229.                       dw ?     ;0x50
  230.                       dw ?     ;0x52
  231.                       dw ?     ;0x54
  232.                       dw ?     ;0x56
  233.                       dw ?     ;0x58
  234.                       dw ?     ;0x5A
  235.                       dw ?     ;0x5C
  236.                       dw ?     ;0x5E
  237.   .reg_page_0         dw ?     ;0x60
  238.   .reg_page_1         dw ?     ;0x62
  239.   .reg_page_2         dw ?     ;0x64
  240.   .reg_page_3         dw ?     ;0x66
  241.   .reg_page_4         dw ?     ;0x68
  242.   .reg_page_5         dw ?     ;0x6A
  243.   .reg_page_6         dw ?     ;0x6C
  244.   .reg_page_7         dw ?     ;0x6E
  245.                       dw ?     ;0x70
  246.                       dw ?     ;0x72
  247.                       dw ?     ;0x74
  248.                       dw ?     ;0x76
  249.                       dw ?     ;0x78
  250.                       dw ?     ;0x7A
  251.   .reg_vendor_id_1    dw ?     ;0x7C
  252.   .reg_vendor_id_2    dw ?     ;0x7E
  253.  
  254.  
  255.   .reset              dd ?    ;virual
  256.   .set_master_vol     dd ?
  257. }
  258.  
  259. struc CTRL_INFO
  260. {   .pci_cmd          dd ?
  261.     .irq              dd ?
  262.     .glob_cntrl       dd ?
  263.     .glob_sta         dd ?
  264.     .codec_io_base    dd ?
  265.     .ctrl_io_base     dd ?
  266.     .codec_mem_base   dd ?
  267.     .ctrl_mem_base    dd ?
  268.     .codec_id         dd ?
  269. }
  270.  
  271. EVENT_NOTIFY      equ 0x00000200
  272.  
  273. section '.flat' code readable writable executable
  274. include '../struct.inc'
  275. include '../macros.inc'
  276. include '../proc32.inc'
  277. include '../peimport.inc'
  278.  
  279. proc START c uses ebx esi edi, state:dword, cmdline:dword
  280.  
  281.         cmp     [state], 1
  282.         jne     .stop
  283.  
  284.      if DEBUG
  285.         mov     eax, START
  286.         call    dword2str
  287.         invoke  SysMsgBoardStr
  288.         mov     esi, msgInit
  289.         invoke  SysMsgBoardStr
  290.      end if
  291.  
  292.         call    detect_controller
  293.         test    eax, eax
  294.         jz      .fail
  295.  
  296.      if DEBUG
  297.         mov     esi, [ctrl.vendor_ids]
  298.         invoke  SysMsgBoardStr
  299.         mov     esi, [ctrl.ctrl_ids]
  300.         invoke  SysMsgBoardStr
  301.  
  302.      end if
  303.  
  304.         call    init_controller
  305.         test    eax, eax
  306.         jz      .fail
  307.  
  308.         call    init_codec
  309.         test    eax, eax
  310.         jz      .fail
  311.  
  312.         call    reset_controller
  313.         call    setup_codec
  314.  
  315.         mov     esi, msgPrimBuff
  316.         invoke  SysMsgBoardStr
  317.         call    create_primary_buff
  318.  
  319.         mov     esi, msgDone
  320.         invoke  SysMsgBoardStr
  321.  
  322.         mov     eax, VALID_IRQ
  323.         mov     ebx, [ctrl.int_line]
  324.         mov     esi, msgInvIRQ
  325.         bt      eax, ebx
  326.         jnc     .fail_msg
  327.  
  328.         invoke  AttachIntHandler, ebx, ac97_irq, dword 0
  329. .reg:
  330.  
  331.         invoke  RegService, sz_sound_srv, service_proc
  332.         ret
  333. .fail:
  334.    if DEBUG
  335.         mov     esi, msgFail
  336.         invoke  SysMsgBoardStr
  337.    end if
  338.         xor     eax, eax
  339.         ret
  340. .fail_msg:
  341.         invoke  SysMsgBoardStr
  342.         xor     eax, eax
  343.         ret
  344. .stop:
  345.         call    stop
  346.         xor     eax, eax
  347.         ret
  348. endp
  349.  
  350. handle     equ  IOCTL.handle
  351. io_code    equ  IOCTL.io_code
  352. input      equ  IOCTL.input
  353. inp_size   equ  IOCTL.inp_size
  354. output     equ  IOCTL.output
  355. out_size   equ  IOCTL.out_size
  356.  
  357. align 4
  358. proc service_proc stdcall, ioctl:dword
  359.  
  360.         mov     edi, [ioctl]
  361.         mov     eax, [edi+io_code]
  362.  
  363.         cmp     eax, SRV_GETVERSION
  364.         jne     @F
  365.  
  366.         mov     eax, [edi+output]
  367.         cmp     [edi+out_size], 4
  368.         jne     .fail
  369.  
  370.         mov     [eax], dword API_VERSION
  371.         xor     eax, eax
  372.         ret
  373. @@:
  374.         cmp     eax, DEV_PLAY
  375.         jne     @F
  376.      if DEBUG
  377.         mov     esi, msgPlay
  378.         invoke  SysMsgBoardStr
  379.      end if
  380.         call    play
  381.         ret
  382. @@:
  383.         cmp     eax, DEV_STOP
  384.         jne     @F
  385.      if DEBUG
  386.         mov     esi, msgStop
  387.         invoke  SysMsgBoardStr
  388.      end if
  389.         call    stop
  390.         ret
  391. @@:
  392.         cmp     eax, DEV_CALLBACK
  393.         jne     @F
  394.         mov     ebx, [edi+input]
  395.         stdcall set_callback, [ebx]
  396.         ret
  397. @@:
  398.         cmp     eax, DEV_SET_MASTERVOL
  399.         jne     @F
  400.         mov     eax, [edi+input]
  401.         mov     eax, [eax]
  402.         call    set_master_vol      ;eax= vol
  403.         ret
  404. @@:
  405.         cmp     eax, DEV_GET_MASTERVOL
  406.         jne     @F
  407.         mov     ebx, [edi+output]
  408.         stdcall get_master_vol, ebx
  409.         ret
  410. ;@@:
  411. ;           cmp eax, DEV_GET_INFO
  412. ;           jne @F
  413. ;           mov ebx, [edi+output]
  414. ;           stdcall get_dev_info, ebx
  415. ;           ret
  416. @@:
  417. .fail:
  418.         or      eax, -1
  419.         ret
  420. endp
  421.  
  422. restore   handle
  423. restore   io_code
  424. restore   input
  425. restore   inp_size
  426. restore   output
  427. restore   out_size
  428.  
  429. align 4
  430. proc fill_buffer
  431.  
  432.         cmp     [ctrl.user_callback], 0
  433.         je      .exit
  434.  
  435.         mov     esi, [ctrl.buffer]
  436.         mov     eax, int_flip_flop
  437.         inc     dword [eax]
  438.         test    dword [eax], 1
  439.         je      @f
  440.         add     esi, 0x4000
  441. @@:
  442.         stdcall [ctrl.user_callback], esi
  443.  
  444.         mov     edx, FM_PLAY_DMABUF1
  445.         mov     eax, [buffer_pgaddr]
  446.         mov     esi, int_flip_flop
  447.         test    dword [esi], 1
  448.         je      @f
  449.         mov     edx, FM_PLAY_DMABUF2
  450.         add     eax, 0x4000
  451. @@:
  452.         call    [ctrl.ctrl_write32]
  453.  
  454. .exit:
  455.         ret
  456. endp
  457.  
  458. align 4
  459. proc ac97_irq
  460.  
  461.      if DEBUG_IRQ
  462.         mov     esi, msgIRQ
  463.         invoke  SysMsgBoardStr
  464.      end if
  465.  
  466.         mov     edx, FM_INTSTATUS
  467.         call    [ctrl.ctrl_read16]
  468.  
  469.         test    eax, FM_INTSTATUS_PLAY
  470.         je      .exit
  471.  
  472.         push    eax
  473.         call    fill_buffer
  474.         pop     eax
  475.  
  476. .exit:
  477.         mov     edx, FM_INTSTATUS
  478.         call    [ctrl.ctrl_write16]
  479.  
  480.         ret
  481. endp
  482.  
  483. align 4
  484. proc create_primary_buff
  485.  
  486.         invoke  KernelAlloc, 0x10000
  487.         mov     [ctrl.buffer], eax
  488.  
  489.         mov     edi, eax
  490.         mov     ecx, 0x10000/4
  491.         xor     eax, eax
  492.         cld
  493.         rep stosd
  494.  
  495.         mov     eax, [ctrl.buffer]
  496.         invoke  GetPgAddr
  497.         mov     [buffer_pgaddr], eax
  498.  
  499.         ret
  500. endp
  501.  
  502. align 4
  503. proc detect_controller
  504.            locals
  505.              last_bus dd ?
  506.              bus      dd ?
  507.              devfn    dd ?
  508.            endl
  509.  
  510.         xor     eax, eax
  511.         mov     [bus], eax
  512.         inc     eax
  513.         invoke  PciApi
  514.         cmp     eax, -1
  515.         je      .err
  516.  
  517.         mov     [last_bus], eax
  518.  
  519. .next_bus:
  520.         and     [devfn], 0
  521. .next_dev:
  522.         invoke  PciRead32, [bus], [devfn], dword 0
  523.         test    eax, eax
  524.         jz      .next
  525.         cmp     eax, -1
  526.         je      .next
  527.  
  528.         push    eax
  529.         invoke  PciRead32, [bus], [devfn], dword 0x09
  530.         and     eax, 0xffffff
  531.         cmp     eax, 0x060100 ;pci-isa
  532.         jne     .no_bridge
  533.  
  534.         mov     eax, [bus]
  535.         mov     [brg_bus], eax
  536.         mov     eax, [devfn]
  537.         mov     [brg_devfn], eax
  538. .no_bridge:
  539.         pop     eax
  540.  
  541.         mov     edi, devices
  542. @@:
  543.         mov     ebx, [edi]
  544.         test    ebx, ebx
  545.         jz      .next
  546.  
  547.         cmp     eax, ebx
  548.         je      .found
  549.         add     edi, 12
  550.         jmp     @B
  551. .next:
  552.         inc     [devfn]
  553.         cmp     [devfn], 256
  554.         jb      .next_dev
  555.         mov     eax, [bus]
  556.         inc     eax
  557.         mov     [bus], eax
  558.         cmp     eax, [last_bus]
  559.         jna     .next_bus
  560.         xor     eax, eax
  561.         ret
  562. .found:
  563.         mov     ebx, [bus]
  564.         mov     [ctrl.bus], ebx
  565.  
  566.         mov     ecx, [devfn]
  567.         mov     [ctrl.devfn], ecx
  568.  
  569.         mov     edx, eax
  570.         and     edx, 0xFFFF
  571.         mov     [ctrl.vendor], edx
  572.         shr     eax, 16
  573.         mov     [ctrl.dev_id], eax
  574.  
  575.         mov     ebx, [edi+4]
  576.         mov     [ctrl.ctrl_ids], ebx
  577.         mov     [ctrl.vendor_ids], msg_FM
  578.  
  579.         mov     esi, [edi+8]
  580.         mov     [ctrl.ctrl_setup], esi
  581.         ret
  582. .err:
  583.         xor     eax, eax
  584.         ret
  585. endp
  586.  
  587. align 4
  588. proc init_controller
  589.  
  590.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 4
  591.         mov     ebx, eax
  592.         and     eax, 0xFFFF
  593.         mov     [ctrl.pci_cmd], eax
  594.         shr     ebx, 16
  595.         mov     [ctrl.pci_stat], ebx
  596.  
  597.         mov     esi, msgPciCmd
  598.         invoke  SysMsgBoardStr
  599.         call    dword2str
  600.         invoke  SysMsgBoardStr
  601.  
  602.         mov     esi, msgPciStat
  603.         invoke  SysMsgBoardStr
  604.         mov     eax, [ctrl.pci_stat]
  605.         call    dword2str
  606.         invoke  SysMsgBoardStr
  607.  
  608.         mov     esi, msgCtrlIsaIo
  609.         invoke  SysMsgBoardStr
  610.  
  611.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 0x10
  612.  
  613.         call    dword2str
  614.         invoke  SysMsgBoardStr
  615.  
  616.         and     eax, 0xFFFE
  617.         mov     [ctrl.ctrl_io_base], eax
  618.  
  619.         mov     esi, msgIrqNum
  620.         invoke  SysMsgBoardStr
  621.  
  622.         invoke  PciRead32, [ctrl.bus], [ctrl.devfn], 0x3C
  623.         and     eax, 0xFF
  624.         mov     [ctrl.int_line], eax
  625.  
  626.         call    dword2str
  627.         invoke  SysMsgBoardStr
  628.  
  629.         call    [ctrl.ctrl_setup]
  630.         xor     eax, eax
  631.         inc     eax
  632.         ret
  633. endp
  634.  
  635. align 4
  636. proc set_FM
  637.         mov     [ctrl.codec_read16], codec_io_r16    ;virtual
  638.         mov     [ctrl.codec_write16], codec_io_w16   ;virtual
  639.  
  640.         mov     [ctrl.ctrl_read8 ], ctrl_io_r8      ;virtual
  641.         mov     [ctrl.ctrl_read16], ctrl_io_r16      ;virtual
  642.         mov     [ctrl.ctrl_read32], ctrl_io_r32      ;virtual
  643.  
  644.         mov     [ctrl.ctrl_write8 ], ctrl_io_w8     ;virtual
  645.         mov     [ctrl.ctrl_write16], ctrl_io_w16     ;virtual
  646.         mov     [ctrl.ctrl_write32], ctrl_io_w32     ;virtual
  647.         ret
  648. endp
  649.  
  650. align 4
  651. proc reset_controller
  652.  
  653.         mov     esi, msgInitCtrl
  654.         invoke  SysMsgBoardStr
  655.  
  656.         mov     edx, FM_CARD_CTL
  657.         call    [ctrl.ctrl_read8]
  658.         push    eax
  659.         or      al, 1
  660.         mov     edx, FM_CARD_CTL
  661.         call    [ctrl.ctrl_write8]
  662.         mov     eax, 10
  663.         call    StallExec
  664.         pop     eax
  665.         and     al, 0xFE
  666.         mov     edx, FM_CARD_CTL
  667.         call    [ctrl.ctrl_write8]
  668.         mov     eax, 10
  669.         call    StallExec
  670.  
  671.         mov     eax, 0x0404
  672.         mov     edx, FM_PCM_VOLUME
  673.         call    [ctrl.ctrl_write16]
  674.         mov     edx, FM_FM_VOLUME
  675.         call    [ctrl.ctrl_write16]
  676.         mov     edx, FM_I2S_VOLUME
  677.         call    [ctrl.ctrl_write16]
  678.  
  679.         mov     edx, FM_INTMASK
  680.         call    [ctrl.ctrl_read16]
  681.         and     eax, not FM_INTMASK_PLAY
  682.         or      eax, FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL
  683.         mov     edx, FM_INTMASK
  684.         call    [ctrl.ctrl_write16]
  685.  
  686.         mov     eax, FM_INTMASK_PLAY or FM_INTMASK_REC or FM_INTMASK_MPU or FM_INTMASK_VOL
  687.         mov     edx, FM_INTSTATUS
  688.         call    [ctrl.ctrl_write16]
  689.  
  690.         ret
  691. endp
  692.  
  693. align 4
  694. proc init_codec
  695.  
  696.         mov     esi, msgInitCodec
  697.         invoke  SysMsgBoardStr
  698.  
  699.         mov     al, FM_CODEC_CMD_READ
  700.         mov     edx, FM_CODEC_CMD
  701.         call    [ctrl.ctrl_write8]
  702.  
  703.         call    reset_codec
  704.  
  705.         call    detect_codec
  706.  
  707.         xor     eax, eax
  708.         inc     eax
  709.         ret
  710. endp
  711.  
  712. align 4
  713. proc reset_codec
  714.  
  715.         mov     ecx, 255
  716. .L1:
  717.         mov     edx, FM_CODEC_CMD
  718.         call    [ctrl.ctrl_read16]
  719.         test    ah, FM_CODEC_CMD_VALID shr 8
  720.         jne     .L2
  721.         loop    .L1
  722. .L2:
  723.         mov     edx, FM_CODEC_CTL
  724.         call    [ctrl.ctrl_read8]
  725.         push    eax
  726.         or      al, 0x20
  727.         mov     edx, FM_CODEC_CTL
  728.         call    [ctrl.ctrl_write8]
  729.         pop     eax
  730.         and     al, 0xDF
  731.         mov     edx, FM_CODEC_CTL
  732.         call    [ctrl.ctrl_write8]
  733.  
  734.         xor     eax, eax
  735.         inc     eax
  736.         ret
  737. endp
  738.  
  739. align 4
  740. play:
  741.         mov     eax, 0x4000-1
  742.         mov     edx, FM_PLAY_DMALEN
  743.         call    [ctrl.ctrl_write16]
  744.  
  745.         call    fill_buffer
  746.  
  747.         mov     eax, FM_PLAY_START or FM_PLAY_STOPNOW or FM_PLAY_STEREO or FM_PLAY_16BIT or 0xA00
  748.         mov     edx, FM_PLAY_CTL
  749.         call    [ctrl.ctrl_write16]
  750.  
  751.         xor     eax, eax
  752.         ret
  753.  
  754. align 4
  755. stop:
  756.         mov     edx, FM_PLAY_CTL
  757.         call    [ctrl.ctrl_read16]
  758.         and     eax, not (FM_PLAY_START or FM_PLAY_STOPNOW)
  759.         or      eax, FM_PLAY_BUF1_LAST or FM_PLAY_BUF2_LAST
  760.         mov     edx, FM_PLAY_CTL
  761.         call    [ctrl.ctrl_write16]
  762.  
  763.         xor     eax, eax
  764.         ret
  765.  
  766. align 4
  767. proc get_dev_info stdcall, p_info:dword
  768.            virtual at esi
  769.              CTRL_INFO CTRL_INFO
  770.            end virtual
  771.  
  772.         mov     esi, [p_info]
  773.         mov     eax, [ctrl.int_line]
  774.         mov     ebx, [ctrl.codec_io_base]
  775.         mov     ecx, [ctrl.ctrl_io_base]
  776.         mov     edx, [ctrl.codec_mem_base]
  777.         mov     edi, [ctrl.ctrl_mem_base]
  778.  
  779.         mov     [CTRL_INFO.irq], eax
  780.         mov     [CTRL_INFO.codec_io_base], ebx
  781.         mov     [CTRL_INFO.ctrl_io_base], ecx
  782.         mov     [CTRL_INFO.codec_mem_base], edx
  783.         mov     [CTRL_INFO.ctrl_mem_base], edi
  784.  
  785.         mov     eax, [codec.chip_id]
  786.         mov     [CTRL_INFO.codec_id], eax
  787.  
  788.         mov     ebx, [ctrl.pci_cmd]
  789.         mov     [CTRL_INFO.pci_cmd], ebx
  790.         ret
  791. endp
  792.  
  793. align 4
  794. proc set_callback stdcall, handler:dword
  795.         mov     eax, [handler]
  796.         mov     [ctrl.user_callback], eax
  797.         ret
  798. endp
  799.  
  800. align 4
  801. proc codec_read stdcall, ac_reg:dword   ; reg = edx, reval = eax
  802.  
  803.         mov     edx, [ac_reg]
  804.  
  805.         mov     ebx, edx
  806.         shr     ebx, 1
  807.         bt      [codec.shadow_flag], ebx
  808.         jc      .use_shadow
  809.  
  810.         call    [ctrl.codec_read16]  ;change edx !!!
  811.         mov     ecx, eax
  812.  
  813. .read_ok:
  814.         mov     edx, [ac_reg]
  815.         mov     [codec.regs+edx], cx
  816.         bts     [codec.shadow_flag], ebx
  817.         mov     eax, ecx
  818.         ret
  819. .use_shadow:
  820.         movzx   eax, word [codec.regs+edx]
  821.         ret
  822.  
  823. endp
  824.  
  825. align 4
  826. proc codec_write stdcall, ac_reg:dword
  827.  
  828.         mov     esi, [ac_reg]
  829.  
  830.         mov     edx, esi
  831.  
  832.         call    [ctrl.codec_write16]
  833.  
  834.         mov     [codec.regs+esi], ax
  835.         shr     esi, 1
  836.         bts     [codec.shadow_flag], esi
  837.  
  838.         ret
  839. endp
  840.  
  841. align 4
  842. proc check_semafore
  843. align 4
  844. .ok:
  845.         xor     eax, eax
  846.         inc     eax
  847.         ret
  848. endp
  849.  
  850. align 4
  851. proc StallExec
  852.         push    ecx
  853.         push    edx
  854.         push    ebx
  855.         push    eax
  856.  
  857.         mov     ecx, CPU_FREQ
  858.         mul     ecx
  859.         mov     ebx, eax      ;low
  860.         mov     ecx, edx      ;high
  861.         rdtsc
  862.         add     ebx, eax
  863.         adc     ecx, edx
  864. @@:
  865.         rdtsc
  866.         sub     eax, ebx
  867.         sbb     edx, ecx
  868.         js      @B
  869.  
  870.         pop     eax
  871.         pop     ebx
  872.         pop     edx
  873.         pop     ecx
  874.         ret
  875. endp
  876.  
  877. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  878. ;          CONTROLLER IO functions
  879. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  880.  
  881. align 4
  882. proc codec_io_r16
  883.  
  884.         push    edx
  885.         mov     ecx, 255
  886. .L1:
  887.         mov     edx, FM_CODEC_CMD
  888.         call    [ctrl.ctrl_read16]
  889.         test    ah, FM_CODEC_CMD_BUSY shr 8
  890.         je      .L2
  891.         loop    .L1
  892. .L2:
  893.         pop     eax
  894.         or      al, FM_CODEC_CMD_READ
  895.         mov     edx, FM_CODEC_CMD
  896.         call    [ctrl.ctrl_write8]
  897.  
  898.         mov     ecx, 255
  899. .L3:
  900.         mov     edx, FM_CODEC_CMD
  901.         call    [ctrl.ctrl_read16]
  902.         test    ah, FM_CODEC_CMD_VALID shr 8
  903.         jne     .L4
  904.         loop    .L3
  905. .L4:
  906.         mov     edx, FM_CODEC_DATA
  907.         call    [ctrl.ctrl_read16]
  908.  
  909.         ret
  910. endp
  911.  
  912. align 4
  913. proc codec_io_w16
  914.  
  915.         push    edx
  916.         push    eax
  917.         mov     ecx, 255
  918. .L1:
  919.         mov     edx, FM_CODEC_CMD
  920.         call    [ctrl.ctrl_read16]
  921.         test    ah, FM_CODEC_CMD_BUSY shr 8
  922.         je      .L2
  923.         loop    .L1
  924. .L2:
  925.         pop     eax
  926.         mov     edx, FM_CODEC_DATA
  927.         call    [ctrl.ctrl_write16]
  928.  
  929.         pop     eax
  930.         mov     edx, FM_CODEC_CMD
  931.         call    [ctrl.ctrl_write16]
  932.  
  933.         ret
  934. endp
  935.  
  936. align 4
  937. proc ctrl_io_r8
  938.         add     edx, [ctrl.ctrl_io_base]
  939.         in      al, dx
  940.         ret
  941. endp
  942.  
  943. align 4
  944. proc ctrl_io_r16
  945.         add     edx, [ctrl.ctrl_io_base]
  946.         in      ax, dx
  947.         ret
  948. endp
  949.  
  950. align 4
  951. proc ctrl_io_r32
  952.         add     edx, [ctrl.ctrl_io_base]
  953.         in      eax, dx
  954.         ret
  955. endp
  956.  
  957. align 4
  958. proc ctrl_io_w8
  959.         add     edx, [ctrl.ctrl_io_base]
  960.         out     dx, al
  961.         ret
  962. endp
  963.  
  964. align 4
  965. proc ctrl_io_w16
  966.         add     edx, [ctrl.ctrl_io_base]
  967.         out     dx, ax
  968.         ret
  969. endp
  970.  
  971. align 4
  972. proc ctrl_io_w32
  973.         add     edx, [ctrl.ctrl_io_base]
  974.         out     dx, eax
  975.         ret
  976. endp
  977.  
  978. align 4
  979. dword2str:
  980.         mov     esi, hex_buff
  981.         mov     ecx, -8
  982. @@:
  983.         rol     eax, 4
  984.         mov     ebx, eax
  985.         and     ebx, 0x0F
  986.         mov     bl, [ebx+hexletters]
  987.         mov     [8+esi+ecx], bl
  988.         inc     ecx
  989.         jnz     @B
  990.         ret
  991.  
  992. hexletters   db '0123456789ABCDEF'
  993. hex_buff     db 8 dup(0),13,10,0
  994. brg_bus      dd ?
  995. brg_devfn    dd ?
  996. include "codec.inc"
  997.  
  998. align 4
  999. devices dd (CTRL_FM801 shl 16)+VID_FM801, msg_FM801, set_FM
  1000.         dd 0
  1001.  
  1002. msg_FM801    db 'FM801 AC97 controller',13,10, 0
  1003. msg_FM       db 'Forte Media',13,10, 0
  1004.  
  1005. sz_sound_srv db 'SOUND',0
  1006.  
  1007. msgInit       db 'detect hardware...',13,10,0
  1008. msgFail       db 'device not found',13,10,0
  1009. msgInvIRQ     db 'IRQ line not assigned or invalid', 13,10, 0
  1010. msgPlay       db 'start play', 13,10,0
  1011. msgStop       db 'stop play',  13,10,0
  1012. ;msgNotify    db 'call notify',13,10,0
  1013. msgIRQ        db 'AC97 IRQ', 13,10,0
  1014. msgInitCtrl  db 'init controller',13,10,0
  1015. msgInitCodec db 'init codec',13,10,0
  1016. msgPrimBuff   db 'create primary buffer ...',0
  1017. msgDone       db 'done',13,10,0
  1018. ;msgReg       db 'set service handler',13,10,0
  1019. ;msgOk        db 'service installed',13,10,0
  1020. ;msgStatus    db 'global status   ',0
  1021. ;msgControl   db 'global control  ',0
  1022. msgPciCmd     db 'PCI command     ',0
  1023. msgPciStat    db 'PCI status      ',0
  1024. msgCtrlIsaIo  db 'controller io base   ',0
  1025. msgIrqNum     db 'IRQ default          ',0
  1026. ;msgIrqMap    db 'AC97 irq map as      ',0
  1027.  
  1028. align 4
  1029. data fixups
  1030. end data
  1031.  
  1032. codec CODEC
  1033. ctrl AC_CNTRL
  1034.  
  1035. int_flip_flop      rd 1
  1036. buffer_pgaddr      rd 1
  1037.