Subversion Repositories Kolibri OS

Rev

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

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