home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / msdos / sndbords / proaudio / pcmtlsrc / pcm.arj / MVSOUND.ASM < prev    next >
Assembly Source File  |  1992-09-01  |  54KB  |  2,170 lines

  1. ;$Author:   BCRANE  $
  2. ;$Date:   01 Sep 1992 13:33:02  $
  3. ;$Header:   X:/sccs/sdkapp/mvsound.asv   1.1   01 Sep 1992 13:33:02   BCRANE  $
  4. ;$Log:   X:/sccs/sdkapp/mvsound.asv  $
  5. ;  
  6. ;     Rev 1.1   01 Sep 1992 13:33:02   BCRANE
  7. ;  moved data from gethw.asm and state.asm into here, added check for 
  8. ;  previous initialization to not call gethw() or state() again
  9. ;  
  10. ;     Rev 1.0   31 Aug 1992 09:42:52   BCRANE
  11. ;  Initial revision.
  12. ;  
  13. ;     Rev 1.4   17 Jul 1992 14:18:22   DCODY
  14. ;  moved TheDMAchannel and TheIRQchannel out to another module. Made the
  15. ;  hardware I/O relocatable. Made initmvsound recallable without ill effects.
  16. ;  
  17. ;     Rev 1.3   09 Jul 1992 10:07:50   DCODY
  18. ;  corrected MV101 bit test and jumps
  19. ;  
  20. ;     Rev 1.2   26 Jun 1992 14:13:48   DCODY
  21. ;  added the parameter to GetHWVersion call
  22. ;  
  23. ;     Rev 1.1   23 Jun 1992 17:06:04   DCODY
  24. ;  PAS2 update
  25. ;  
  26. ;     Rev 1.0   15 Jun 1992 09:43:46   BCRANE
  27. ;  Initial revision.
  28. ;$Logfile:   X:/sccs/sdkapp/mvsound.asv  $
  29. ;$Modtimes$
  30. ;$Revision:   1.1  $
  31. ;$Workfile:   mvsound.asm  $ 
  32.  
  33.         page    64,131
  34.     subttl    MVSOUND  --  Pro Audio Spectrum Sound Support Code
  35.  
  36. ;   /*\
  37. ;---|*|----====< MVSOUND >====----
  38. ;---|*|
  39. ;---|*|  This module contains the code for supporting PCM I/O.
  40. ;---|*|
  41. ;---|*|  Media Vision, Inc. Copyright (c) 1991,1992. All Rights Reserved.
  42. ;---|*|
  43. ;   \*/
  44.  
  45. ;
  46. ; The following set of equates are used to control what routines are compiled
  47. ; by doing this, MVSOUND.ASM can contain all the necessary code in one file,
  48. ; but generate separate, linkable objects with just the necessary code.
  49. ;
  50. ALLOBJS     = 0     ; individual objects are being built
  51. DATAOBJ     = 0     ; data code to be compiled
  52. MISC1OBJ    = 0     ; minimum code needed from the library
  53. MISC2OBJ    = 0     ; other miscellaneous code
  54. PCMOBJ        = 0     ; PCM code to be compiled
  55.  
  56. ifdef BUILDDATA
  57.   DATAOBJ   = 1     ; data code to be compiled
  58. endif
  59.  
  60. ifdef BUILDMISC1
  61.   MISC1OBJ  = 1     ; misc module #1 code to be compiled
  62. endif
  63.  
  64. ifdef BUILDMISC2
  65.   MISC2OBJ  = 1     ; misc module #2 code to be compiled
  66. endif
  67.  
  68. ifdef BUILDPCM
  69.   PCMOBJ    = 1     ; data code to be compiled
  70. endif
  71.  
  72. ifdef BUILDALL
  73.   ALLOBJS   = 1     ; all objects are being built
  74.   DATAOBJ   = 1     ; data code to be compiled
  75.   MISC1OBJ  = 1     ; miscellaneous code to be compiled
  76.   MISC2OBJ  = 1     ; miscellaneous code to be compiled
  77.   PCMOBJ    = 1     ; PCM code to be compiled
  78. endif
  79.  
  80.     .xlist
  81.         include masm.inc
  82.     include target.inc
  83.     include state.inc
  84.     include common.inc
  85.     .list
  86.  
  87. ;
  88. ; structure for pointing to the above table of DMA addresses
  89. ;
  90.  
  91. dmaaddr struc
  92. _dmach        db    ?    ; DMA channel selected
  93. _dmardstat      db      ?       ; DMA read status
  94. _dmawrcntrl    db    ?    ; DMA write command register
  95. _dmawreq    db    ?    ; DMA write request register
  96. _dmawrsmr    db    ?    ; DMA write single mask register
  97. _dmawrmode    db    ?    ; DMA write mode register
  98. _dmaclear    db    ?    ; DMA clear low/high flip-flop
  99. _dmardtemp    db    ?    ; DMA read temp register
  100. _dmawrclr    db    ?    ; DMA write master clear
  101. _dmaclrmsk    db    ?    ; DMA clear mask register
  102. _dmawrall    db    ?    ; DMA write all mask register bits
  103. dmaaddr ends
  104.  
  105. ;
  106. ;---------------------------========================---------------------------
  107. ;---------------------------====< DATA SECTION >====---------------------------
  108. ;---------------------------========================---------------------------
  109. ;
  110. ;if MODELSIZE eq 0
  111. ;    .code
  112. ;else
  113. ;    .data
  114. ;endif
  115.  
  116. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  117. ;; gethw.asm data
  118. ;
  119. ;---------------------------========================---------------------------
  120. ;---------------------------====< DATA SECTION >====---------------------------
  121. ;---------------------------========================---------------------------
  122. ;
  123. ;    .data
  124. ;
  125. ; The board base address for the original PAS card was based at 388. This will
  126. ; be XORed to the new address to derive a translation code. This code can be
  127. ; XORed back into any original PAS address resulting in the true card address.
  128. ;
  129.  
  130.     public    _MVTranslateCode
  131. _MVTranslateCode    dw    0    ; I/O base xor default_base
  132.  
  133.     public    _MVHWVersionBits
  134. _MVHWVersionBits    dw    -1    ; holds the product feature bits
  135.  
  136. VERSION_PAS             equ     0       ; Pro Audio Spectrum
  137. VERSION_PASPLUS     equ    1    ; Pro Audio Plus card
  138. VERSION_PAS16        equ    2    ; Pro Audio 16 card
  139. VERSION_CDPC        equ    3    ; CDPC card & unit
  140.  
  141. PASdocare    equ    <NOT (bMVSCSI+bMVENHSCSI+bMV101_REV)>
  142. PASPLUSdocare    equ    <NOT (bMVSCSI+bMVENHSCSI+bMVSONY+bMV101_REV)>
  143. PAS16docare    equ    <NOT (bMVSCSI+bMVENHSCSI+bMV101_REV)>
  144. CDPCdocare    equ    <NOT (bMVSCSI+bMVENHSCSI+bMV101_REV)>
  145.  
  146. ;
  147. ProductIDTable    label    word
  148.     dw    PRODUCT_PROAUDIO and PASdocare
  149.     dw    PRODUCT_PROPLUS  and PASPLUSdocare
  150.     dw    PRODUCT_PRO16     and PAS16docare
  151.     dw    PRODUCT_CDPC     and CDPCdocare
  152.     dw    -1
  153. ;
  154. DoCareBits    label    word
  155.     dw    PASdocare
  156.     dw    PASPLUSdocare
  157.     dw    PAS16docare
  158.     dw    CDPCdocare
  159.     dw    -1                ; table terminator
  160.  
  161.     public    TheDMAChannel        ; defaults to channel 1
  162. TheDMAChannel   db      DEFAULTDMA      ; defaults to channel 1
  163.     public    TheIRQChannel        ; defaults to IRQ 7
  164. TheIRQChannel    db    DEFAULTIRQ    ; defaults to IRQ 7
  165.  
  166. ;;
  167. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  168.  
  169. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  170. ;; mvstate.asm data
  171.  
  172. ;    .data
  173. ;
  174. ; This pointer points to a state table of hardware variables
  175. ;
  176.         public  mvhwShadowPointer
  177. mvhwShadowPointer    dd    0    ; points to the start of the data table
  178.  
  179. ;
  180. ; These variables mirror the hardware state
  181. ;
  182. HardwareShadowTable    db    (size MVState) dup (0)
  183.  
  184. ;;
  185. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  186.  
  187. if DATAOBJ                              ; include if we are building DATA.OBJ
  188.  
  189. ;
  190. ; These variables are DMA/Buffer control variables
  191. ;
  192. TheIRQMask    db    INT7MSK     ; 8259 interrupt mask
  193.  
  194. TheDMAMode    db    00h        ; 44h for input, 48h for output
  195. LinearPtr    dd    0        ; holds linear address
  196. SegmentedPtr    dd    0        ; holds segmented address (real mode)
  197. DMABuffLength    dw    0        ; DMA Length (0 based) (MUST BE EVEN!)
  198. DMABuffDivides    db    0        ; # of splits in the DMA buffer
  199.  
  200. TheSampleRate    dd    0        ; 3k through 88k
  201. StereoMono    db    0        ; ff for mono, 00 for stereo
  202. PCMDirection    db    0        ; bit mask for the DMA controller
  203. SampleSize    db    0        ; sample size: 0=8,1=12,2=16
  204.  
  205.     public    DMAAutoInit        ; TRUE(0ffh) or FALSE(000h)
  206. DMAAutoInit    db    0ffh        ; to allow auto-init on DMA access
  207.  
  208. UserRoutine     dd      0               ; User Code
  209.  
  210. StatusWord      dw      0               ; Holds current status:
  211. ;                    ;   0 = inactive, available
  212. ;                    ;   1 = currently playing
  213. ;                    ;   2 = currently recording
  214.  
  215. OldIRQRoutine   dd      0               ; holds the original routine
  216.  
  217. polledmask    equ    bICsamprate+bICsampbuff ; polled mask
  218. dmamask     equ    bICsampbuff        ; dma mask
  219.  
  220. DMAOUTPUT    equ    0+dmamask    ; DMA is used to drive the output
  221. POLLEDOUTPUT    equ    0+polledmask    ; Polling routine drives output
  222. DMAINPUT    equ    1+dmamask    ; DMA is used to read input
  223. POLLEDINPUT    equ    1+polledmask    ; Polling routine reads input
  224. TypeOfSetup    db    0        ; polled/dma interrupt masks & stuff..
  225.  
  226.     public    NumberOfInterrupts
  227. NumberOfInterrupts      dw      0       ; number of interrupts that have occured
  228. ;
  229. ; These variables direct our code to the proper DMA channel
  230. ;
  231. OurDMAPageReg    dw    CH1PAGEREG    ; default to DMA channel 1 page reg
  232. OurDMAddress    dw    DMAC1ADDR    ; default to DMA channel 1 address reg
  233.  
  234. ;
  235. ; table of address pointers to the various DMA 2 addresses
  236. ;
  237.         public  DMA1AddrTable
  238. DMA1AddrTable    label    byte
  239.     db    DEFAULTDMA    ; DMA channel selected
  240.         db      DMARDSTAT       ; DMA read status
  241.     db    DMAWRCNTRL    ; DMA write command register
  242.     db    DMAWREQ     ; DMA write request register
  243.     db    DMAWRSMR    ; DMA write single mask register
  244.     db    DMAWRMODE    ; DMA write mode register
  245.     db    DMACLEAR    ; DMA clear low/high flip-flop
  246.     db    DMARDTEMP    ; DMA read temp register
  247.     db    DMAWRCLR    ; DMA write master clear
  248.     db    DMACLRMSK    ; DMA clear mask register
  249.     db    DMAWRALL    ; DMA write all mask register bits
  250. ;
  251. ; table of address pointers to the various DMA 2 addresses
  252. ;
  253.     public    DMA2AddrTable
  254. DMA2AddrTable   label   byte
  255.         db      DEFAULTDMA      ; DMA channel selected
  256.     db    DMA2RDSTAT    ; DMA read status
  257.     db    DMA2WRCNTRL    ; DMA write command register
  258.     db    DMA2WREQ    ; DMA write request register
  259.     db    DMA2WRSMR    ; DMA write single mask register
  260.     db    DMA2WRMODE    ; DMA write mode register
  261.     db    DMA2CLEAR    ; DMA clear low/high flip-flop
  262.     db    DMA2RDTEMP    ; DMA read temp register
  263.     db    DMA2WRCLR    ; DMA write master clear
  264.     db    DMA2CLRMSK    ; DMA clear mask register
  265.     db    DMA2WRALL    ; DMA write all mask register bits
  266.  
  267.     public    DMAPointer
  268. DMAPointer      dw      offset DMA1AddrTable    ; default to channel 1 table
  269. ;
  270. ; working variables
  271. ;
  272. ;
  273.     public    TheIRQMask        ; 8259 interrupt mask
  274.     public    TheDMAMode        ; 55h for input, 59h for output
  275.     public    LinearPtr        ; holds linear address
  276.     public    SegmentedPtr        ; holds segmented address (real mode)
  277.     public    DMABuffLength        ; DMA Length (0 based) (MUST BE EVEN!)
  278.     public    DMABuffDivides        ; # of splits in the DMA buffer
  279.     public    TheSampleRate        ; 3k through 88k
  280.     public    StereoMono        ; ff for mono, 00 for stereo
  281.     public    PCMDirection        ; bit mask for the DMA controller
  282.     public    SampleSize        ; sample size: 0=8,1=12,2=16
  283.     public    DMAAutoInit        ; TRUE/FALSE flag for DMA autoinit bit
  284.     public    UserRoutine        ; User Code
  285.     public    StatusWord        ; Holds current status:
  286.     public    OldIRQRoutine        ; holds the original routine
  287. polledmask    equ    bICsamprate+bICsampbuff ; polled mask
  288. dmamask     equ    bICsampbuff        ; dma mask
  289. DMAOUTPUT    equ    0+dmamask    ; DMA is used to drive the output
  290. POLLEDOUTPUT    equ    0+polledmask    ; Polling routine drives output
  291. DMAINPUT    equ    1+dmamask    ; DMA is used to read input
  292. POLLEDINPUT    equ    1+polledmask    ; Polling routine reads input
  293.     public    TypeOfSetup        ; polled/dma interrupt masks & stuff..
  294.     public    NumberOfInterrupts    ; number of interrupts that have occured
  295.     public    OurDMAPageReg        ; default to DMA channel 1 page reg
  296.     public    OurDMAddress        ; default to DMA channel 1 address reg
  297.  
  298. else    ; not building DATA.OBJ, declare all publics
  299.  
  300.     extrn    DMAPointer    :word    ; pointer to the DMA address table
  301.     extrn    DMA1AddrTable    :byte    ; 1st DMA controller table
  302.     extrn    DMA2AddrTable    :byte    ; 2nd DMA controller table
  303.     extrn    TheIRQMask    :byte    ; 8259 interrupt mask
  304.     extrn    TheDMAMode    :byte    ; 55h for input, 59h for output
  305.     extrn    LinearPtr    :dword    ; holds linear address
  306.     extrn    SegmentedPtr    :dword    ; holds segmented address (real mode)
  307.     extrn    DMABuffLength    :word    ; DMA Length (0 based) (MUST BE EVEN!)
  308.     extrn    DMABuffDivides    :byte    ; # of splits in the DMA buffer
  309.     extrn    TheSampleRate    :dword    ; 3k through 88k
  310.     extrn    StereoMono    :byte    ; ff for mono, 00 for stereo
  311.     extrn    PCMDirection    :byte    ; bit mask for the DMA controller
  312.     extrn    SampleSize    :byte    ; sample size: 0=8,1=12,2=16
  313.     extrn    DMAAutoInit    :byte    ; TRUE/FALSE flag for DMA autoinit bit
  314.     extrn    UserRoutine    :dword    ; User Code
  315.     extrn    StatusWord    :word    ; Holds current status:
  316.     extrn    OldIRQRoutine    :dword    ; holds the original routine
  317.     extrn    TypeOfSetup    :byte    ; polled/dma interrupt masks & stuff..
  318.     extrn    NumberOfInterrupts:word ; number of interrupts that have occured
  319.     extrn    OurDMAPageReg    :word    ; default to DMA channel 1 page reg
  320.     extrn    OurDMAddress    :word    ; default to DMA channel 1 address reg
  321.  
  322.  
  323. polledmask    equ    bICsamprate+bICsampbuff ; polled mask
  324. dmamask     equ    bICsampbuff        ; dma mask
  325. DMAOUTPUT    equ    0+dmamask    ; DMA is used to drive the output
  326. POLLEDOUTPUT    equ    0+polledmask    ; Polling routine drives output
  327. DMAINPUT    equ    1+dmamask    ; DMA is used to read input
  328. POLLEDINPUT    equ    1+polledmask    ; Polling routine reads input
  329. SHADOWTABLELEN  equ     28              ; 28 entries in the shadow data table
  330.  
  331. endif
  332.  
  333. ;    extrn    TheDMAChannel      :byte ; defaults to channel 1
  334. ;    extrn    TheIRQChannel      :byte ; defaults to IRQ 7
  335.  
  336. ;        extrn   mvhwShadowPointer :dword; a common variable for all
  337. ;    extrn    _MVHWVersionBits  :word ; hardware state bits
  338. ;    extrn    _MVTranslateCode   :word
  339.  
  340.     .code
  341.  
  342. ;    externADDR    MVInitStatePtr        ; pointer to the state table init code
  343. ;    externADDR    MVGetHWVersion        ; returns the hardware bits
  344. ;
  345. ; TEXT SEGMENT externals for the different modules
  346. ;
  347.  
  348. if PCMOBJ AND (NOT ALLOBJS)        ; added for independent PCMOBJ module
  349.     externADDR    SelectIRQ        ; PCM uses "SelectIRQ"
  350.     externADDR    _unloadirqvector    ; PCM uses "_unloadirqvector"
  351.     externADDR    _getirqoffset        ; PCM uses "_getirqoffset"
  352. endif
  353.  
  354. ;
  355. ;---------------------------========================---------------------------
  356. ;---------------------------====< CODE SECTION >====---------------------------
  357. ;---------------------------========================---------------------------
  358. ;
  359. ;   /*\
  360. ;---|*|
  361. ;---|*|---------------====< Prototypes >====---------------
  362. ;---|*|
  363. ;---|*| void far *DMABuffer(char far *, int, int )
  364. ;---|*|
  365. ;---|*|     Passes in a pointer and length to the buffer.
  366. ;---|*|     Also flushes the buffer. Returns 0 or true DMA buffer ptr.
  367. ;---|*|
  368. ;---|*| int EnablePCMPlay()
  369. ;---|*|
  370. ;---|*|     Sets up the PCM hardware for polled output
  371. ;---|*|
  372. ;---|*| int EnablePCMRecord()
  373. ;---|*|
  374. ;---|*|     Sets up the PCM hardware for polled input
  375. ;---|*|
  376. ;---|*| char huge *FindDMABuffer(char huge *, int )
  377. ;---|*|
  378. ;---|*|     Takes a memory address & return the next 64k boundary
  379. ;---|*|
  380. ;---|*| MVState far *InitMVSound()
  381. ;---|*|
  382. ;---|*|     Initializes the int 2F interface & some global variables.
  383. ;---|*|
  384. ;---|*| int InitPCM()
  385. ;---|*|
  386. ;---|*|     Initializes the PCM code.
  387. ;---|*|
  388. ;---|*| void PausePCM()
  389. ;---|*|
  390. ;---|*|     Temporarily stops the PCM I/O by disabling the timers
  391. ;---|*|
  392. ;---|*| int PCMInfo( long ,int, int, int )
  393. ;---|*|
  394. ;---|*|     Sets up the transfer rate & stereo/mono/compression/data size
  395. ;---|*|
  396. ;---|*| int PCMPlay()
  397. ;---|*|
  398. ;---|*|     Starts the DMA feeding the DAC
  399. ;---|*|
  400. ;---|*| int PCMRecord()
  401. ;---|*|
  402. ;---|*|     Starts the DMA reading the ADC
  403. ;---|*|
  404. ;---|*| void RemovePCM()
  405. ;---|*|
  406. ;---|*|     kills the PCM code.
  407. ;---|*|
  408. ;---|*| void ResumePCM()
  409. ;---|*|
  410. ;---|*|     Restarts the PCM I/O by enabling the timers
  411. ;---|*|
  412. ;---|*| int SelectDMA( int )
  413. ;---|*|
  414. ;---|*|     Selects the DMA channel 1, or 3
  415. ;---|*|
  416. ;---|*| int SelectIRQ( int )
  417. ;---|*|
  418. ;---|*|     Selects the IRQ line for DMA control
  419. ;---|*|
  420. ;---|*| void StopPCM()
  421. ;---|*|
  422. ;---|*|     Turn off the PCM timers, interrupts, and state machine.
  423. ;---|*|
  424. ;---|*| void UserFunc((*long)())
  425. ;---|*|
  426. ;---|*|     Call back routine when Half way buffer is full/empty.
  427. ;---|*|
  428. ;   \*/
  429.  
  430. if PCMOBJ
  431.  
  432. ;   /*\
  433. ;---|*|------====< void far * DMABuffer( char far *, int, int ) >====------
  434. ;---|*|
  435. ;---|*| Passes in a pointer and length to the buffer
  436. ;---|*|
  437. ;---|*| Entry Conditions:
  438. ;---|*|     dParm1 points to DMA buffer
  439. ;---|*|     wParm3 points to the length (wParm3 * 1024 is the total length )
  440. ;---|*|     wParm4 is the # of divisions of the DMA buffer
  441. ;---|*|
  442. ;---|*| Exit Conditions:
  443. ;---|*|     DX:AX = 0 - bad buffer
  444. ;---|*|     DX:AX = returns buffer pointer
  445. ;---|*|
  446. ;   \*/
  447.  
  448.     public    DMABuffer
  449. DMABuffer    proc
  450.         push    bp
  451.     mov    bp,sp
  452.     push    es
  453.     push    di
  454.  
  455.     mov    cx,wParm3        ; get the dma size (4/8/16/32/64)
  456.     or ch, ch
  457.     jz @F
  458.     mov ax, cx
  459.     jmp short savebufferlength
  460.  
  461. @@:    cmp    cx,64            ; too high?
  462.     ja    dmabbad         ; yes, bomb out
  463.  
  464.         mov     ax,1024
  465.     cwd
  466.     mul    cx            ; get the length - 1
  467. savebufferlength:
  468.     dec    ax
  469.     mov    [DMABuffLength],ax    ; and save for later use
  470.  
  471.     les    di,dParm1        ; get the far pointer to the buffer
  472.  
  473.         mov     ax,di
  474.     mov    bx,es            ; convert it to a linear address
  475.     mov    dx,es
  476.     mov    cl,4
  477.     rol    dx,cl
  478.     and    dx,000fh
  479.     shl    bx,cl            ; add offset portion of seg to offset
  480.     add    ax,bx
  481.     jc    dmabbad         ; bad if extends over a 64k boundary
  482.  
  483.     mov    wptr [LinearPtr+0],ax    ; save the linear address
  484.     mov    wptr [LinearPtr+2],dx
  485.     mov    wptr [SegmentedPtr+0],di
  486.     mov    wptr [SegmentedPtr+2],es
  487.  
  488.     mov    bx,wParm4        ; get the # of DMA buffer divisions
  489.     mov    [DMABuffDivides],bl
  490.  
  491.     push    ax            ; save the buffer offset
  492.  
  493.     mov    cx,[DMABuffLength]    ; get the clearing length
  494.         mov     al,80h                  ; PCM silent code
  495.     cld
  496.     rep stosb            ; flush the buffer length...
  497.     stosb                ; + 1
  498.  
  499.     mov    dx,es
  500.         pop     ax                      ; return dx:ax
  501.     jmp    short dmabdone
  502. ;
  503. dmabbad:
  504.     sub    ax,ax
  505.     cwd
  506. ;
  507. dmabdone:
  508.         pop     di
  509.     pop    es
  510.     pop    bp
  511.     ret
  512.  
  513. DMABuffer    endp
  514.  
  515.  
  516. ;   /*\
  517. ;---|*|---------------====< EnablePCMPlay() >====---------------
  518. ;---|*|
  519. ;---|*| Enabled the DAC hardware for polled output (no interrupts)
  520. ;---|*|
  521. ;---|*| Entry Conditions:
  522. ;---|*|     None
  523. ;---|*|
  524. ;---|*| Exit Conditions:
  525. ;---|*|     AX =  0 good start
  526. ;---|*|     AX = -1 not started, problem occured
  527. ;   \*/
  528.  
  529.     public    EnablePCMPlay
  530. EnablePCMPlay    proc
  531.     push    es
  532.  
  533.     mov    ax,wptr [TheSampleRate+0] ; Validate the sample rate
  534.     or    ax,wptr [TheSampleRate+2]
  535.     jz    enaPCMPlay_bad          ; zero sample rate, bomb out...
  536.  
  537.     call    FFAR ptr EnablePlaying      ; go for it...
  538.     mov    ax,0
  539.     jmp    short enaPCMPlay_exit
  540. ;
  541. enaPCMPlay_bad:
  542.     mov    ax,-1
  543. ;
  544. enaPCMPlay_exit:
  545.     pop    es
  546.         ret
  547.  
  548. EnablePCMPlay    endp
  549.  
  550.  
  551. ;   /*\
  552. ;---|*|---------------====< EnablePCMRecord() >====---------------
  553. ;---|*|
  554. ;---|*| Enabled the ADC hardware for polled input (no interrupts)
  555. ;---|*|
  556. ;---|*| Entry Conditions:
  557. ;---|*|     None
  558. ;---|*|
  559. ;---|*| Exit Conditions:
  560. ;---|*|     AX =  0 recording has started
  561. ;---|*|     AX = -1 recording did not start
  562. ;---|*|
  563. ;   \*/
  564.  
  565.     public    EnablePCMRecord
  566. EnablePCMRecord proc
  567.         push    es
  568.  
  569.     mov    ax,wptr [TheSampleRate+0] ; Validate the sample rate
  570.     or    ax,wptr [TheSampleRate+2]
  571.     jz    enaPCMRec_bad
  572.  
  573.     call    FFAR ptr EnableRecording  ; go for it...
  574.     mov    ax,0
  575.     jmp    short enaPCMRec_exit
  576. ;
  577. enaPCMRec_bad:
  578.     mov    ax,-1
  579. ;
  580. enaPCMRec_exit:
  581.     pop    es
  582.         ret
  583.  
  584. EnablePCMRecord endp
  585.  
  586.  
  587. ;   /*\
  588. ;---|*|------====< char far *FindDMABuffer(char far *,int ) >====------
  589. ;---|*|
  590. ;---|*| Finds the next 64k boundary starting with dParm1 address
  591. ;---|*|
  592. ;---|*| Entry Conditions:
  593. ;---|*|     dParm1 points to a buffer twice the size needed for the DMA
  594. ;---|*|     wParm2 is the size of the DMA buffer (4/8/16/32/64)
  595. ;---|*|
  596. ;---|*| Exit Conditions:
  597. ;---|*|     DX:AX = returns buffer pointer on a 64k boundary
  598. ;---|*|     DX:AX = 0 if boundary wraps beyond 1 meg.
  599. ;---|*|
  600. ;   \*/
  601.  
  602.     public    FindDMABuffer
  603. FindDMABuffer    proc
  604.     push    bp
  605.     mov    bp,sp
  606.  
  607.     sub    ax,ax            ; default to bad...
  608.     cwd
  609.  
  610.         mov     cx,wParm3               ; get the length
  611.     cmp    cx,64            ; 64k buffer requested?
  612.     ja    fdb_exit        ; too high, exit
  613.     jz    fdb_64k         ; yes, special case it...
  614.     cmp    cl,4
  615.     jb    fdb_exit        ; too low, exit
  616.  
  617.     mov    ax,1024         ; calculate the length of the DMA buffer
  618.     mul    cx
  619.     mov    bx,ax            ; bx holds the length
  620.  
  621.     mov    dx,wptr dParm1+2
  622.     mov    ax,dx            ; accumulate the offset in ax
  623.     and    ax,0fffh        ; get the offset portion of the segment
  624.     and    dx,0f000h        ; make DX a 64k segment register
  625.         mov     cl,4
  626.     shl    ax,cl            ; make the segment an offset
  627.     add    ax,wptr dParm1+0    ; accumulate the rest of the offset
  628.     add    bx,ax            ; does the buffer cross a 64k boundary?
  629.     cmc                ; carry set if 64k crossing
  630.     sbb    bx,bx            ; bx = ffff if no crossing, 0 if crossed
  631.     and    ax,bx            ; clear ax if crossed
  632.     not    bx            ; bx = ffff if crossed, 0000 if not
  633.     and    bx,1000h
  634.     add    dx,bx            ; advance dx if we crossed a 64k boundary
  635.     jmp    short fdb_exit
  636. ;
  637. fdb_64k:
  638.     mov    dx,wptr dParm1+2    ; get the segment
  639.         sub     ax,ax                   ; offset is zero
  640.     and    dx,0f000h        ; find the next segment
  641.     add    dx,1000h        ; move to next segment
  642.     jnc    fdb_exit        ; if doesn't wraps past 1 meg, it's good
  643.         cwd                             ; bad, flush it...
  644. ;
  645. fdb_exit:
  646.     pop    bp
  647.     ret
  648.  
  649. FindDMABuffer    endp
  650. ;
  651. endif    ; PCMOBJ
  652. if MISC1OBJ
  653.  
  654. ;
  655. ;   /*\
  656. ;---|*|---------------====< InitMVSound() >====---------------
  657. ;---|*|
  658. ;---|*| Initializes this body of code. It will try to find the int 2F DOS
  659. ;---|*| interface to the MVPROAS device. Once found, the new state table
  660. ;---|*| pointer will be loaded.
  661. ;---|*|
  662. ;---|*| Entry Conditions:
  663. ;---|*|     None
  664. ;---|*|
  665. ;---|*| Exit Conditions:
  666. ;---|*|     DX:AX point to the state table
  667. ;   \*/
  668.  
  669. mvsoundinited    db 0
  670.  
  671.     public    InitMVSound
  672. InitMVSound    proc
  673.     mov al, mvsoundinited
  674.     or al, al
  675.     jz @F
  676.     ret
  677.     
  678. @@:    inc al
  679.     mov mvsoundinited, al
  680.     push    es
  681.     push    di
  682.     mov    ax,ds
  683.     mov    es,ax
  684. ;
  685. ; find the hardware. Should be installed for this to run
  686. ;
  687.     call    MVInitStatePtr        ; initialize the state table ptr
  688.  
  689.     cmp    _MVHWVersionBits,-1    ; initialized yet?
  690.     jnz    @F            ; yes, continue on...
  691.     mov    ax,USE_ACTIVE_ADDR    ; pass in the base address
  692.     push    ax
  693.     call    MVGetHWVersion        ; no, checkout the hardware
  694.     pop    ax
  695.     ;
  696.     @@:
  697.     mov    ax,wptr [mvhwShadowPointer+0]
  698.     mov    dx,wptr [mvhwShadowPointer+2]
  699.  
  700.     pop    di
  701.     pop    es
  702.     ret
  703.  
  704. InitMVSound    endp
  705. ;
  706. endif    ; MISC1OBJ
  707. if    PCMOBJ
  708. ;
  709. ;   /*\
  710. ;---|*|---------------====< InitPCM() >====---------------
  711. ;---|*|
  712. ;---|*| Initializes the PCM code
  713. ;---|*|
  714. ;---|*| Entry Conditions:
  715. ;---|*|     None
  716. ;---|*|
  717. ;---|*| Exit Conditions:
  718. ;---|*|     AX =  Version of this Code
  719. ;   \*/
  720.  
  721.     public    InitPCM
  722. InitPCM proc
  723.     push    es
  724.  
  725.     mov    [TypeOfSetup],polledmask    ; flushes both interrupts
  726.                         ; for upcoming calls
  727.     mov    al,TheDMAChannel        ; initialize the DMA now...
  728.     cbw
  729.     push    ax
  730.     call    FFAR ptr SelectDMA
  731.     pop    ax
  732.  
  733.     mov    al,TheIRQChannel        ; initialize the IRQ now...
  734.     cbw
  735.     push    ax
  736.     call    FFAR ptr SelectIRQ        ; also removes the IRQ
  737.     pop    ax
  738.  
  739.         call    FFAR ptr StopPCM                ; kill the Audio Spectrum board
  740.  
  741.     mov    dx,INTRCTLRST            ; flush any pending PCM irq
  742.     xor    dx,[_MVTranslateCode]        ; xlate the board address
  743.     out    dx,al
  744.  
  745.     sub    ax,ax
  746.     mov    [TypeOfSetup],al        ; unknown type
  747.  
  748.     mov    wptr [UserRoutine+0],ax
  749.     mov    wptr [UserRoutine+2],ax
  750.  
  751.     mov    wptr [LinearPtr+0],ax
  752.     mov    wptr [LinearPtr+2],ax
  753.     mov    wptr [SegmentedPtr+0],ax
  754.         mov     wptr [SegmentedPtr+2],ax
  755.  
  756.     mov    wptr [DMABuffLength],ax
  757.  
  758.     not    al
  759.     mov    [StereoMono],al         ; mono
  760.  
  761.     mov    ax,11025
  762.     cwd
  763.  
  764.     call    FFAR ptr _calcsamplerate    ; setup the default rate
  765.     mov    wptr [TheSampleRate+0],ax
  766.     mov    wptr [TheSampleRate+2],dx
  767.  
  768.     mov    ax,0003h            ; for compatibility, version 00.03
  769.  
  770.     pop    es
  771.     ret
  772.  
  773. InitPCM endp
  774. ;
  775. endif    ; PCMOBJ
  776. if PCMOBJ
  777. ;
  778. ;
  779. ;   /*\
  780. ;---|*|---------------====< PausePCM >====---------------
  781. ;---|*|
  782. ;---|*| Turn off the h/w timer enables to effectively stop pcm temporarily.
  783. ;---|*|
  784. ;---|*| Entry Conditions:
  785. ;---|*|     None
  786. ;---|*|
  787. ;---|*| Exit Conditions:
  788. ;---|*|     Nothing
  789. ;---|*|
  790. ;   \*/
  791. ;
  792.     public    PausePCM
  793. PausePCM    proc
  794.     push    es
  795.     push    di
  796. ;
  797. ; Setup the audio filter sample bits
  798. ;
  799.     les    di,[mvhwShadowPointer]
  800.         mov     dx,AUDIOFILT
  801.     xor    dx,[_MVTranslateCode]       ; xlate the board address
  802.  
  803.         disable
  804.  
  805.         mov     al,es:[di._audiofilt]
  806.     and    al,not bFIsrate        ; flush the enable bits
  807.     mov    es:[di._audiofilt],al
  808.     out    dx,al
  809.  
  810.     enable
  811.  
  812.         pop     di
  813.     pop    es
  814.     ret
  815.  
  816. PausePCM    endp
  817.  
  818. ;
  819. ;   /*\
  820. ;---|*|---------------====< PCMInfo ( long, int, int, int ) >====---------------
  821. ;---|*|
  822. ;---|*| Selects xfer rate & stereo/mono
  823. ;---|*|
  824. ;---|*| Entry Conditions:
  825. ;---|*|     Parm #1 (wParm1, wParm2) is the rate
  826. ;---|*|     Parm #2 (wParm3)         is the stereo(1) or mono (0)
  827. ;---|*|     Parm #3 (wParm4)         is the compression flag
  828. ;---|*|     Parm #4 (wParm5)         is the data size (8/12/16 bits per sample)
  829. ;---|*|
  830. ;---|*| Exit Conditions:
  831. ;---|*|     AX =  0, good data
  832. ;---|*|     AX = -1, bum transfer rate
  833. ;---|*|
  834. ;   \*/
  835.  
  836.     public    PCMInfo
  837. PCMInfo     proc
  838.     push    bp
  839.     mov    bp,sp
  840.  
  841.     mov    al,wParm4+2        ; get the data size
  842.     cbw
  843.     cmp    al,8            ; 8 bit channel?
  844.     jz    @F
  845.  
  846.         inc     ah
  847.     cmp    al,12            ; 12 bit channel
  848.     jz    @F
  849.  
  850.     inc    ah
  851.     cmp    al,16            ; 16 bit channel?
  852.     jnz    pcinf_bad        ; no, bomb out...
  853.     ;
  854.     @@:
  855.     mov    [SampleSize],ah
  856.  
  857.         mov     cx,wParm3               ; get the stereo flag
  858.     shr    cx,1
  859.     jnz    pcinf_bad        ; exit bad if not zero
  860.  
  861.     cmc                ; set for mono, cleared for stereo
  862.     sbb    cx,cx            ; make a full bit mask
  863.     mov    [StereoMono],cl     ; save only valid values
  864.  
  865.         mov     ax,dParm1+0             ; get the sample rate
  866.     mov    dx,dParm1+2
  867.  
  868.     or    cx,cx            ; is it mono?
  869.     jnz    @F            ; yes, skip the doubling
  870.     shl    ax,1            ; no, stereo, so double the sample rate
  871.     adc    dx,dx
  872.     ;
  873.     @@:
  874.     call    FFAR ptr _calcsamplerate
  875.     jc    pcinf_bad
  876.     mov    wptr [TheSampleRate+0],ax
  877.     mov    wptr [TheSampleRate+2],dx
  878.  
  879.     sub    ax,ax
  880.     jmp    short pcinf_exit
  881. ;
  882. pcinf_bad:
  883.     mov    ax,-1
  884. ;
  885. pcinf_exit:
  886.         pop     bp
  887.     ret
  888.  
  889. PCMInfo     endp
  890. ;
  891. ;
  892. ;   /*\
  893. ;---|*|---------------====< PCMPlay() >====---------------
  894. ;---|*|
  895. ;---|*| Starts the DMA feeding the DAC
  896. ;---|*|
  897. ;---|*| Entry Conditions:
  898. ;---|*|     None
  899. ;---|*|
  900. ;---|*| Exit Conditions:
  901. ;---|*|     AX =  0 good start
  902. ;---|*|     AX = -1 not started, problem occured
  903. ;   \*/
  904.  
  905.     public    PCMPlay
  906. PCMPlay proc
  907.     push    es
  908.  
  909.     les    ax,LinearPtr          ; Validate the buffer pointer
  910.     mov    bx,es
  911.     or    ax,bx
  912.     jz    PCMPlay_bad
  913.  
  914.     mov    ax,[DMABuffLength]      ; Validate the buffer count
  915.     or    ax,ax
  916.     jz    PCMPlay_bad
  917.  
  918.     mov    ax,wptr [TheSampleRate+0] ; Validate the sample rate
  919.     or    ax,wptr [TheSampleRate+2]
  920.     jz    PCMPlay_bad          ; zero sample rate, bomb out...
  921.  
  922.     call    FFAR ptr StartPlaying      ; go for it...
  923.     sub    ax,ax
  924.     jmp    short PCMPlay_exit
  925. ;
  926. PCMPlay_bad:
  927.     mov    ax,-1
  928. ;
  929. PCMPlay_exit:
  930.     pop    es
  931.         ret
  932.  
  933. PCMPlay endp
  934. ;
  935. ;
  936. ;   /*\
  937. ;---|*|---------------====< PCMRecord() >====---------------
  938. ;---|*|
  939. ;---|*| Starts the DMA reading the ADC
  940. ;---|*|
  941. ;---|*| Entry Conditions:
  942. ;---|*|     None
  943. ;---|*|
  944. ;---|*| Exit Conditions:
  945. ;---|*|     AX =  0 recording has started
  946. ;---|*|     AX = -1 recording did not start
  947. ;---|*|
  948. ;   \*/
  949.  
  950.     public    PCMRecord
  951. PCMRecord proc
  952.         push    es
  953.  
  954.     les    ax,LinearPtr          ; Validate the buffer pointer
  955.     mov    bx,es
  956.     or    ax,bx
  957.     jz    PCMRec_bad
  958.  
  959.     mov    ax,[DMABuffLength]      ; Validate the buffer count
  960.     or    ax,ax
  961.     jz    PCMRec_bad
  962.  
  963.     mov    ax,wptr [TheSampleRate+0] ; Validate the sample rate
  964.     or    ax,wptr [TheSampleRate+2]
  965.     jz    PCMRec_bad
  966.  
  967.     call    FFAR ptr StartRecording   ; go for it...
  968.     mov    ax,0
  969.     jmp    short PCMRec_exit
  970. ;
  971. PCMRec_bad:
  972.     mov    ax,-1
  973. ;
  974. PCMRec_exit:
  975.     pop    es
  976.         ret
  977.  
  978. PCMRecord    endp
  979. ;
  980. ;
  981. ;   /*\
  982. ;---|*|---------------====< RemovePCM () >====---------------
  983. ;---|*|
  984. ;---|*| Remove our code from the system
  985. ;---|*|
  986. ;---|*| Entry Conditions:
  987. ;---|*|     None
  988. ;---|*|
  989. ;---|*| Exit Conditions:
  990. ;---|*|     None
  991. ;   \*/
  992.  
  993.     public    RemovePCM
  994. RemovePCM proc
  995.  
  996.     call    FFAR ptr StopPCM        ; kill the Audio Spectrum board
  997.  
  998.         mov     dx,INTRCTLRST                   ; flush any pending PCM irq
  999.         xor     dx,[_MVTranslateCode]           ; xlate the board address
  1000.         out     dx,al
  1001.  
  1002.     call    FFAR ptr _unloadirqvector    ; restore the original vector
  1003.  
  1004.         ret
  1005.  
  1006. RemovePCM endp
  1007. ;
  1008. ;
  1009. ;   /*\
  1010. ;---|*|---------------====< ResumePCM >====---------------
  1011. ;---|*|
  1012. ;---|*| Turn on the h/w from making interrupt and DMA requests. This assumes
  1013. ;---|*| the hardware has already been setup and is ready to go...
  1014. ;---|*|
  1015. ;---|*| Entry Conditions:
  1016. ;---|*|     None
  1017. ;---|*|
  1018. ;---|*| Exit Conditions:
  1019. ;---|*|     Nothing
  1020. ;---|*|
  1021. ;   \*/
  1022. ;
  1023.     public    ResumePCM
  1024. ResumePCM    proc
  1025.     push    es
  1026.     push    di
  1027. ;
  1028. ; Setup the audio filter sample bits
  1029. ;
  1030.     les    di,[mvhwShadowPointer]
  1031.     call    FFAR ptr _ASloadtimer0
  1032.  
  1033.         disable
  1034.  
  1035.         mov     dx,AUDIOFILT
  1036.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1037.     mov    al,es:[di._audiofilt]
  1038.     or    al,bFIsrate        ; enable sample rate and buffer timers
  1039.     mov    es:[di._audiofilt],al
  1040.     out    dx,al
  1041.  
  1042.     enable
  1043.  
  1044.         pop     di
  1045.     pop    es
  1046.     ret
  1047.  
  1048. ResumePCM       endp
  1049. ;
  1050. ;
  1051. ;
  1052. ;   /*\
  1053. ;---|*|---------------====< SelectDMA( int ) >====---------------
  1054. ;---|*|
  1055. ;---|*| Selects the DMA channel 0 - 7, excluding 4
  1056. ;---|*|
  1057. ;---|*| Entry Conditions:
  1058. ;---|*|     wParm1 points to DMA number (0, 1, 2, 3, 5, 6, 7 )
  1059. ;---|*|
  1060. ;---|*| Exit Conditions:
  1061. ;---|*|     AX =  0, good buffer, all okay
  1062. ;---|*|     AX = -1, good buffer, all okay
  1063. ;---|*|
  1064. ;   \*/
  1065.  
  1066.         public  SelectDMA
  1067. SelectDMA    proc
  1068.     push    bp
  1069.     mov    bp,sp
  1070.  
  1071.         mov     ax,wParm1               ; get the DMA #
  1072.  
  1073.     and    ax,0111b        ; save the channels
  1074.  
  1075.         mov     bx,ax                   ; get some of the I/O addreses
  1076.     shl    bx,1            ; into DX
  1077.     jnz    seldma_02        ; not channel 0, go use it...
  1078.     push    sp            ; 8088/86 class machine?
  1079.     pop    cx
  1080.     cmp    cx,sp
  1081.     jnz    seldma_bad        ; yes, can't do channel 0 dma
  1082.     ;
  1083.     seldma_02:
  1084.         mov     dx,cs:[dmatable+bx]
  1085.     or    dx,dx            ; valid entry?
  1086.     jz    seldma_bad        ; no, bomb out...
  1087.  
  1088.         mov     TheDMAChannel,al        ; select the channel.
  1089.     mov    bptr OurDMAPageReg,dh    ; ...the page register,
  1090.     mov    bptr OurDMAddress,dl    ; ...the address register,
  1091.  
  1092.     lea    bx,DMA1AddrTable    ; get the DMA channel addresses
  1093.     cmp    al,4
  1094.     jl    seldma_05
  1095.     lea    bx,DMA2AddrTable    ; get the DMA channel addresses
  1096.     sub    al,4            ; make it zero based
  1097.     ;
  1098.     seldma_05:
  1099.     mov    [bx._dmach],al        ; save the adjusted dma channel #
  1100.     mov    [DMAPointer],bx     ; save the pointer to all DMA addrs
  1101.     sub    ax,ax
  1102.     pop    bp
  1103.     ret
  1104. ;
  1105. seldma_bad:
  1106.     mov    ax,-1
  1107.     pop    bp
  1108.     ret
  1109. ;
  1110. ; dma channels, etc
  1111. ;
  1112. dmatable    label    word
  1113.     dw    (CH0PAGEREG SHL 8) + DMAC0ADDR
  1114.         dw      (CH1PAGEREG SHL 8) + DMAC1ADDR
  1115.     dw    (CH2PAGEREG SHL 8) + DMAC2ADDR
  1116.     dw    (CH3PAGEREG SHL 8) + DMAC3ADDR
  1117.         dw      0
  1118.     dw    (CH5PAGEREG SHL 8) + DMA2C5ADDR
  1119.     dw    (CH6PAGEREG SHL 8) + DMA2C6ADDR
  1120.     dw    (CH7PAGEREG SHL 8) + DMA2C7ADDR
  1121.  
  1122. SelectDMA       endp
  1123.  
  1124. endif    ; PCMOBJ
  1125. if MISC2OBJ
  1126.  
  1127. ;   /*\
  1128. ;---|*|---------------====< SelectIRQ( int ) >====---------------
  1129. ;---|*|
  1130. ;---|*| Selects the IRQ line for DMA control
  1131. ;---|*|
  1132. ;---|*| Entry Conditions:
  1133. ;---|*|     wParm1 points to IRQ number (3,5,6,7)
  1134. ;---|*|
  1135. ;---|*| Exit Conditions:
  1136. ;---|*|     AX =  0, good buffer, all okay
  1137. ;---|*|     AX = -1, bad IRQ #
  1138. ;---|*|
  1139. ;   \*/
  1140.  
  1141.         public  SelectIRQ
  1142. SelectIRQ    proc
  1143.     push    bp
  1144.     mov    bp,sp
  1145.  
  1146.     call    FFAR ptr _unloadirqvector ; attempt to restore original vector
  1147.  
  1148.     sub    ax,ax            ; flush ax for a bad return
  1149.  
  1150.     mov    cx,wParm1        ; get the irq # (2-7,10-12,14-15)
  1151.     and    cl,0fh            ; save only the valid bits
  1152.     mov    bx,01
  1153.     shl    bx,cl
  1154.  
  1155.     and    bx,1001110010111100b    ; save the mask bit only if the irq
  1156.         jz      seirqbad                ; is a valid selection
  1157.  
  1158.     mov    TheIRQChannel,cl    ; save the channel number
  1159.  
  1160.     cmp    cl,8            ; 2nd interrupt controller?
  1161.     jb    @F            ; no, skip
  1162.     xchg    bh,bl
  1163.     ;
  1164.     @@:
  1165.     mov    TheIRQMask,bl
  1166.     call    FFAR ptr _loadirqvector ; load the new vector
  1167.     mov    ax,1
  1168. ;
  1169. seirqbad:
  1170.     dec    ax
  1171.     pop    bp
  1172.     ret
  1173.  
  1174. SelectIRQ       endp
  1175. ;
  1176. endif    ; MISC2OBJ
  1177. if PCMOBJ
  1178.  
  1179. ;
  1180. ;   /*\
  1181. ;---|*|--------------------====< void StopPCM() >====--------------------
  1182. ;---|*|
  1183. ;---|*| Turn off the PCM timers, interrupts, and state machine.
  1184. ;---|*|
  1185. ;---|*| Entry Conditions:
  1186. ;---|*|
  1187. ;---|*| Exit  Conditions:
  1188. ;---|*|
  1189. ;---|*|
  1190. ;   \*/
  1191.  
  1192.     public    StopPCM
  1193. StopPCM proc
  1194.     push    es
  1195.     push    di
  1196.     les    di,[mvhwShadowPointer]
  1197. ;
  1198. ; clear the audio filter sample bits
  1199. ;
  1200.     mov    dx,AUDIOFILT
  1201.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1202.     disable             ; drop dead...
  1203.     mov    al,es:[di._audiofilt]    ; get the state
  1204.     and    al,not (bFIsrate+bFIsbuff) ; flush the sample timer bits
  1205.     mov    es:[di._audiofilt],al    ; save the new state
  1206.     out    dx,al
  1207. ;
  1208. ; clear the PCM enable bit
  1209. ;
  1210.     mov    al,es:[di._crosschannel]; get the current cross channel
  1211.     and    al,not bCCenapcm    ; clear the PCM enable bit
  1212.     or    al,bCCdac
  1213.         mov     dx,CROSSCHANNEL
  1214.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1215.     out    dx,al            ; end to the hardware
  1216.     mov    es:[di._crosschannel],al
  1217. ;
  1218. ; disable the 16 bit stuff
  1219. ;
  1220.     test    [_MVHWVersionBits],bMV101  ; 101 chip?
  1221.     jz    stpc02               ; no, don't touch this...
  1222.     mov    dx,SYSCONFIG2
  1223.     xor    dx,[_MVTranslateCode]       ; xlate the board address
  1224.     in    al,dx
  1225.     and    al,not bSC216bit+bSC212bit ; flush the 16 bit stuff
  1226.     out    dx,al
  1227.     ;
  1228.     stpc02:
  1229. ;
  1230. ; clear the appropriate Interrupt Control Register bit
  1231. ;
  1232.     mov    ah,TypeOfSetup
  1233.     and    ah,bICsamprate+bICsampbuff
  1234.     not    ah
  1235.     mov    dx,INTRCTLR
  1236.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1237.     in    al,dx
  1238.     and    al,ah            ; kill sample timer interrupts
  1239.     out    dx,al
  1240.     mov    es:[di._intrctlr],al
  1241. ;
  1242. ; clear the system interrupt mask only if no other ints are used
  1243. ;
  1244.     test    al,fICintmaskbits XOR (bICsamprate+bICsampbuff)
  1245.     jnz    stpc10
  1246. ;
  1247. ; select the correct IRQ controller, then mask it...
  1248. ;
  1249.     cmp    TheIRQChannel,2     ; Chained IRQ channel?
  1250.     jz    stpc10            ; yes, leave it open...
  1251.  
  1252.         mov     dx,IRQ1MASKREG
  1253.     cmp    TheIRQChannel,8     ; 2nd IRQ controller?
  1254.     jl    stpc05
  1255.     mov    dl,IRQ2MASKREG
  1256.     ;
  1257.     stpc05:
  1258.     in    al,dx
  1259.     or    al,[TheIRQMask]
  1260.     out    dx,al
  1261.     enable                ; start again...
  1262. ;
  1263. stpc10:
  1264.     call    FFAR ptr KillDMA    ; stop the DMA too...
  1265.  
  1266.     mov    [StatusWord],0        ; inactive, available
  1267.  
  1268.     pop    di
  1269.     pop    es
  1270.     ret
  1271.  
  1272. StopPCM endp
  1273.  
  1274. ;
  1275. ;   /*\
  1276. ;---|*|---------------====< UserFunc((*long)()) >====---------------
  1277. ;---|*|
  1278. ;---|*| Call back routine when Half way buffer is full/empty.
  1279. ;---|*|
  1280. ;---|*| Entry Conditions:
  1281. ;---|*|     dParm1 points to the user routine
  1282. ;---|*|
  1283. ;---|*| Exit Conditions:
  1284. ;---|*|     Nothing
  1285. ;---|*|
  1286. ;   \*/
  1287.  
  1288.     public    UserFunc
  1289. UserFunc proc
  1290.     push    bp
  1291.     mov    bp,sp
  1292.  
  1293.         push    es
  1294.  
  1295.     les    ax,dParm1        ; get the routine
  1296.     mov    dx,es
  1297.     or    dx,ax
  1298.     jz    usfu_bad
  1299.  
  1300.     mov    wptr [UserRoutine+0],ax
  1301.     mov    wptr [UserRoutine+2],es
  1302. ;
  1303. usfu_bad:
  1304.     pop    es
  1305.     pop    bp
  1306.     ret
  1307.  
  1308. UserFunc endp
  1309.  
  1310. endif    ; PCMOBJ
  1311.  
  1312. ;
  1313. ;
  1314. ;----------------------------========================--------------------------
  1315. ;----------------------------========================--------------------------
  1316. ;----------------------------========================--------------------------
  1317. ;
  1318. ;
  1319. ;            PPPPPPPP      CCCCCC   MMM     MMM
  1320. ;            PPPPPPPP     CCCCCCC   MMMM    MMMM
  1321. ;            PPP   PPP   CCC        MMMMM   MMMMM
  1322. ;            PPP   PPP   CCC        MMMMMM MMMMMM
  1323. ;            PPPPPPPP    CCC        MMM MMMMM MMM
  1324. ;            PPPPPPPP    CCC        MMM  MMM  MMM
  1325. ;            PPP        CCC        MMM   M     MMM
  1326. ;            PPP        CCC        MMM     MMM
  1327. ;            PPP         CCCCCCC   MMM     MMM
  1328. ;            PPP          CCCCCC   MMM     MMM
  1329. ;
  1330. ;     rrrrr      oooo     uu  uu  tttttt  iiiiii  nn  nn   eeeee   sssss
  1331. ;     rr  rr  oo  oo  uu  uu    tt       ii     nnn nn  ee     ss
  1332. ;     rrrrrr  oo  oo  uu  uu    tt       ii     nnnnnn  eeeeee   ssss
  1333. ;     rr rr     oo  oo  uu  uu    tt       ii     nn nnn  ee         ss
  1334. ;     rr  rr   oooo      uuuuuu   tt     iiiiii  nn  nn   eeeee  sssss
  1335. ;
  1336. ;
  1337. ;
  1338. ;----------------------------========================--------------------------
  1339. ;----------------------------========================--------------------------
  1340. ;----------------------------========================--------------------------
  1341.  
  1342. if PCMOBJ
  1343.  
  1344. ;
  1345. ;----------------------------====< _ASloadtimer0 >====-------------------------
  1346. ;
  1347. ;
  1348. ; Setup the Sample Timer (T0 & square wave output)
  1349. ;
  1350. ;   Entry Conditions:
  1351. ;    ES:DI point to the state table.
  1352. ;   Exit Conditions:
  1353. ;    The timer is loaded with the new sample rate
  1354. ;
  1355.     public    _ASloadtimer0
  1356. _ASloadtimer0    proc
  1357.  
  1358.         mov     al,00110110b            ; 36h Timer 0 & square wave
  1359.     mov    dx,TMRCTLR
  1360.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1361.  
  1362.     pushf
  1363.     cli
  1364.  
  1365.     out    dx,al            ; setup the mode, etc
  1366.         mov     es:[di._tmrctlr],al
  1367.  
  1368.     mov    ax,es:[di._samplerate]    ; pre-calculated & saved in prior code
  1369.     mov    dx,SAMPLERATE
  1370.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1371.     out    dx,al            ; output the timer value
  1372.  
  1373.         pause
  1374.  
  1375.         xchg    ah,al
  1376.     out    dx,al
  1377.  
  1378.         popf
  1379.     ret
  1380.  
  1381. _ASloadtimer0   endp
  1382.  
  1383. ;
  1384. ;----------------------------====< _ASloadtimer1 >====-------------------------
  1385. ;
  1386.         public  _ASloadtimer1
  1387. _ASloadtimer1   proc
  1388.     push    es
  1389.     push    di
  1390.     les    di,[mvhwShadowPointer]
  1391.  
  1392.         push    dx                      ; do not disturb any register
  1393.     push    ax
  1394.  
  1395.         mov     al,01110100b            ; 74h Timer 1 & rate generator
  1396.     mov    dx,TMRCTLR
  1397.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1398.  
  1399.         disable
  1400.  
  1401.         out     dx,al
  1402.     mov    es:[di._tmrctlr],al    ; local timer control register
  1403.  
  1404.     pop    ax
  1405.  
  1406.         mov     dx,SAMPLECNT
  1407.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1408.     mov    es:[di._samplecnt],ax
  1409.  
  1410.         out     dx,al
  1411.         pause
  1412.     xchg    ah,al
  1413.     out    dx,al
  1414.  
  1415.     enable
  1416.  
  1417.     xchg    ah,al
  1418.  
  1419.     pop    dx
  1420.     pop    di
  1421.     pop    es
  1422.     ret
  1423.  
  1424. _ASloadtimer1    endp
  1425. ;
  1426. ;
  1427. ;--------------------------====< _calcsamplerate >====-------------------------
  1428. ;
  1429. ;  Calculate the H/W timer value (internal routine)
  1430. ;
  1431. ; Entry Conditions:
  1432. ;    DX:AX hold the users requested sample rate
  1433. ;
  1434. ; Exit Conditions:
  1435. ;    carry SET if bad value
  1436. ;    No registers modified
  1437. ;
  1438. ;
  1439.     public    _calcsamplerate
  1440. _calcsamplerate proc
  1441.     push    es
  1442.     push    di
  1443.     les    di,[mvhwShadowPointer]
  1444.  
  1445.     push    ax
  1446.     push    bx
  1447.     push    cx
  1448.     push    dx
  1449. ;
  1450. ; make sure sample rate does not exceed 88200
  1451. ;
  1452.         mov     cx,ax                   ; do 32 bit subtraction
  1453.     sub    cx,05888H+1        ; 157C0 is decimal 88200
  1454.     mov    cx,dx            ; too high?
  1455.     sbb    cx,00001H        ;  over 88200 khz is bad
  1456.     jnc    CaSaRa_bad        ; bomb out greater than 88200
  1457. ;
  1458. ; load 1193180 in bx:cx for 32x32 bit division
  1459. ;
  1460.     mov    bx,0012h
  1461.     mov    cx,34dch        ; load bx:cx with 1193180
  1462.  
  1463.     xchg    bx,dx            ; dx:ax = 1193180
  1464.     xchg    cx,ax            ; bx:cx = sample rate
  1465. ;
  1466. ; since we don't have 32x32 bit division, we'll cheat here. No great loss.
  1467. ;
  1468.     or    bx,bx            ; is value over 64k?
  1469.     jz    @F            ; no, continue on...
  1470.     shr    bx,1            ; yes, divide all by 2
  1471.     rcr    cx,1            ; to allow division of 32x16 bits
  1472.     shr    dx,1
  1473.     rcr    ax,1
  1474. ;
  1475. @@:
  1476.     div    cx
  1477.     mov    es:[di._samplerate],ax    ; save just the low order
  1478.     clc
  1479.     jmp    short CaSaRa_exit
  1480. ;
  1481. CaSaRa_bad:
  1482.     stc
  1483. ;
  1484. CaSaRa_exit:
  1485.     pop    dx
  1486.     pop    cx
  1487.     pop    bx
  1488.     pop    ax
  1489.  
  1490.         pop     di
  1491.     pop    es
  1492.     ret
  1493.  
  1494. _calcsamplerate endp
  1495. ;
  1496. ;
  1497. ;----------------------------====< EnableRecording >====-----------------------
  1498. ;
  1499.     public    EnableRecording
  1500. EnableRecording  proc
  1501. ;
  1502. ; Save the type of setup. It contains the interrupt masks needed
  1503. ;
  1504.     mov    [TypeOfSetup],POLLEDINPUT
  1505.     mov    [PCMDirection],0    ; bit 6 is cleared (DAC enable)
  1506. ;
  1507. ; enable the onboard sampling timers, disable interrupts
  1508. ;
  1509.     call    FFAR ptr SetupPCMPolledIO ; Setup the MV Hardware
  1510.     mov    StatusWord,2        ; set the global status word
  1511.         ret
  1512.  
  1513. EnableRecording  endp
  1514. ;
  1515. ;
  1516. ;----------------------------====< EnablePlaying >====-------------------------
  1517. ;
  1518.     public    EnablePlaying
  1519. EnablePlaying    proc
  1520. ;
  1521. ; Save the type of setup. It contains the interrupt masks needed
  1522. ;
  1523.     mov    [TypeOfSetup],POLLEDOUTPUT
  1524.         mov     [PCMDirection],bCCdac   ; bit d6 of interrupt control register
  1525. ;
  1526. ; enable the onboard sampling timers, etc.
  1527. ;
  1528.     call    FFAR ptr SetupPCMPolledIO ; Setup the MV Hardware
  1529.     mov    StatusWord,1        ; set the global status word
  1530.  
  1531.         ret
  1532.  
  1533. EnablePlaying     endp
  1534. ;
  1535. endif    ; PCMOBJ
  1536. if MISC2OBJ
  1537. ;
  1538. ;---------------------------====< _getirqoffset >====--------------------------
  1539. ;
  1540. ; takes the IRQ # & converts to offset in vector table
  1541. ;
  1542. ;
  1543.     public    _getirqoffset
  1544. _getirqoffset   proc
  1545.         sub     bh,bh
  1546.     shl    bx,1
  1547.     mov    bx,cs:[irqoffsets+bx]
  1548.     ret
  1549.  
  1550. irqoffsets    label    word
  1551.     dw    (8+0)*4         ; IRQ 0 clock timer
  1552.     dw    (8+1)*4         ; IRQ 1 keyboard
  1553.     dw    (8+2)*4         ; IRQ 2 available
  1554.     dw    (8+3)*4         ; IRQ 3 COM2
  1555.     dw    (8+4)*4         ; IRQ 4 COM1
  1556.     dw    (8+5)*4         ; IRQ 5 available
  1557.     dw    (8+6)*4         ; IRQ 6 floppy controller
  1558.     dw    (8+7)*4         ; IRQ 7 LPT
  1559.     dw    (70h+0)*4        ; IRQ 8 real time clock
  1560.     dw    (70h+1)*4        ; IRQ 9 Re-Directed IRQ2
  1561.     dw    (70h+2)*4        ; IRQ a available
  1562.     dw    (70h+3)*4        ; IRQ b available
  1563.     dw    (70h+4)*4        ; IRQ c available
  1564.     dw    (70h+5)*4        ; IRQ d coprocessor
  1565.     dw    (70h+6)*4        ; IRQ e Hard Disk
  1566.     dw    (70h+7)*4        ; IRQ f available
  1567.  
  1568. _getirqoffset   endp
  1569. ;
  1570. endif    ; MISC2OBJ
  1571. if PCMOBJ
  1572. ;
  1573. ;------------------------------====< KillDMA >====-----------------------------
  1574. ;
  1575. ; KillDMA  -- flush our settings
  1576. ;
  1577. ; Entry Conditions:
  1578. ;
  1579. KillDMA proc
  1580.     push    es
  1581.     push    di
  1582.  
  1583.         cmp     StatusWord,0            ; is there any activity?
  1584.     jz    kidm_none
  1585.  
  1586.     mov    di,[DMAPointer]     ; get the DMA pointer
  1587.         sub     dx,dx                   ; clear out the high byte
  1588. ;
  1589. ; mask out the DMA to stop it
  1590. ;
  1591.     disable
  1592.     mov    al,[di._dmach]        ; get the adjusted dma channel #
  1593.         or      al,0100b                ; disable the DMA
  1594.     mov    dl,[di._dmawrsmr]
  1595.     out    dx,al
  1596. ;
  1597. ; remove control on the DRQ line
  1598. ;
  1599.         les     di,[mvhwShadowPointer]
  1600.  
  1601.         mov     al,es:[di._crosschannel]; get the state
  1602.         mov     dx,CROSSCHANNEL
  1603.         xor     dx,[_MVTranslateCode]           ; xlate the board address
  1604.     and    al,not bCCdrq        ; clear the DRQ bit
  1605.     out    dx,al
  1606.  
  1607.         mov     es:[di._crosschannel],al; and save the new state
  1608.     enable
  1609. ;
  1610. kidm_none:
  1611.     pop    di
  1612.     pop    es
  1613.     ret
  1614.  
  1615. KillDMA endp
  1616. ;
  1617. endif    ; PCMOBJ
  1618. if PCMOBJ
  1619. ;
  1620. ;------------------------------====< LoadDMA >====-----------------------------
  1621. ;
  1622. ; LoadDMA  -- Load the DMA controller to read/write data to the MV board
  1623. ;
  1624. ; Entry Conditions:
  1625. ;
  1626. ;
  1627.     public    LoadDMA
  1628. LoadDMA proc
  1629.     push    es
  1630.     push    di
  1631.     push    si
  1632.  
  1633.         les     di,[mvhwShadowPointer]
  1634.  
  1635.     mov    si,[DMAPointer]     ; point to the DMA controller table
  1636.     sub    dx,dx            ; clear out the high byte
  1637. ;
  1638. ; kill the dma until all programming is done
  1639. ;
  1640.     mov    al,[si._dmach]        ; get the adjusted dma channel #
  1641.         or      al,0100b                ; causes all DMA to be suspended
  1642.     mov    dl,[si._dmawrsmr]
  1643.     out    dx,al
  1644. ;
  1645. ; program the mode
  1646. ;
  1647.         mov     al,[TheDMAmode]         ; get the app's desired mode
  1648.     or    al,[si._dmach]        ; merge the adjusted dma channel #
  1649.     mov    dl,[si._dmawrmode]
  1650.         out     dx,al
  1651. ;
  1652. ; adjust the address for a 16 bit channel
  1653. ;
  1654.     mov    ax,wptr [LinearPtr+2]    ; get the page #
  1655. ;
  1656. ; setup the page register
  1657. ;
  1658.     mov    dx,[OurDMAPageReg]
  1659.     out    dx,al
  1660.     mov    bl,al
  1661. ;
  1662. ; reset the flip-flop, then output the address, then count
  1663. ;
  1664.     mov    dl,[si._dmaclear]    ; dh is still clear...
  1665.         out     dx,al                   ; flush...
  1666.  
  1667.     mov    ax,wptr [LinearPtr+0]    ; get the low 16 bits
  1668.     cmp    si,offset DMA1AddrTable ; 1st DMA controller?
  1669.     jz    @F            ; yes, continue on...
  1670.     shr    bl,1            ; no, divide the buffer in half
  1671.     rcr    ax,1            ; by shifting 17 bits
  1672.     ;
  1673.     @@:
  1674.     mov    dx,[OurDMAddress]
  1675.     out    dx,al
  1676.     pause
  1677.     xchg    ah,al
  1678.     out    dx,al
  1679.  
  1680.     mov    ax,[DMABuffLength]
  1681.     cmp    si,offset DMA1AddrTable ; is this the 2nd dma controller?
  1682.     jz    lodma03         ; no, use the full length
  1683.     shr    ax,1
  1684.         inc     dx                      ; move to next port address
  1685.     ;
  1686.     lodma03:
  1687.     inc    dx            ; move to next port address
  1688.     out    dx,al
  1689.     pause
  1690.     xchg    ah,al
  1691.     out    dx,al
  1692. ;
  1693. ; before we enable the DMA, let's make sure the DRQ is controlled, not floating
  1694. ;
  1695.     mov    al,es:[di._crosschannel]; get the state
  1696.         mov     dx,CROSSCHANNEL
  1697.         xor     dx,[_MVTranslateCode]           ; xlate the board address
  1698.     or    al,bCCdrq        ; set the DRQ bit to control it
  1699.     out    dx,al
  1700.     mov    es:[di._crosschannel],al; and save the new state
  1701. ;
  1702. ; re-enable the dma now that all programming is done
  1703. ;
  1704.     mov    al,[si._dmach]        ; get the adjusted dma channel #
  1705.         sub     dx,dx                   ; clear dh
  1706.     mov    dl,[si._dmawrsmr]
  1707.     out    dx,al            ; & let'er loose (not moving though...)
  1708. ;
  1709. ; all done, return home...
  1710. ;
  1711.     pop    si
  1712.     pop    di
  1713.     pop    es
  1714.     ret
  1715.  
  1716. LoadDMA endp
  1717. ;
  1718. endif    ; PCMOBJ
  1719. if MISC2OBJ
  1720. ;
  1721. ;--------------------------====< _loadirqvector >====--------------------------
  1722. ;
  1723. ; Restore the original vector
  1724. ;
  1725. ; Entry Conditions:
  1726. ;
  1727. ; Exit Conditions:
  1728. ;     Nothing
  1729.  
  1730.     public    _loadirqvector
  1731. _loadirqvector  proc
  1732.     push    es
  1733.  
  1734.         les     ax,OldIRQRoutine
  1735.     mov    bx,es
  1736.     or    bx,ax
  1737.     jnz    @F
  1738.  
  1739.     lea    ax,OurIntVector
  1740.     mov    dx,cs
  1741.  
  1742.     mov    bl,[TheIRQChannel]
  1743.     call    FFAR ptr _getirqoffset
  1744.  
  1745.     push    ds
  1746.     sub    cx,cx
  1747.     mov    ds,cx
  1748.  
  1749.     disable
  1750.     xchg    ds:[bx+0],ax
  1751.     xchg    ds:[bx+2],dx
  1752.     enable
  1753.  
  1754.     pop    ds
  1755.  
  1756.     mov    wptr [OldIRQRoutine+0],ax
  1757.     mov    wptr [OldIRQRoutine+2],dx
  1758. ;
  1759. @@:
  1760.     pop    es
  1761.     ret
  1762.  
  1763. _loadirqvector    endp
  1764. ;
  1765. endif    ; MISC2OBJ
  1766. if MISC2OBJ
  1767. ;
  1768. ;---------------------------====< OurIntVector >====---------------------------
  1769. ;
  1770. ; OurIntVector    -- process DMA interrupts
  1771. ;
  1772.  
  1773. intsemaphore    db    -1        ; -1 free, 0+ locked
  1774.  
  1775.     public    OurIntVector
  1776. OurIntVector    proc
  1777.     push    dx
  1778.     push    ax
  1779.         push    ds
  1780.  
  1781. if MODELSIZE eq 0
  1782.     mov    ax,cs            ; tiny (.com) model uses cs segment
  1783. else
  1784.     mov    ax,@data        ; all others use their data segments
  1785. endif
  1786.     mov    ds,ax
  1787.  
  1788.     mov    dx,INTRCTLRST        ; clear the interrupt
  1789.         xor     dx,[_MVTranslateCode]           ; xlate the board address
  1790.     in    al,dx
  1791.  
  1792.         test    al,bISsampbuff          ; our interrupt?
  1793.     jz    skip_int        ; no, continue on...
  1794.  
  1795.     out    dx,al            ; yes, flush it...
  1796.  
  1797.     mov    al,EOI            ; clear the interrupt
  1798.     cmp    TheIRQChannel,8     ; 2nd IRQ controller?
  1799.     jb    @F
  1800.     out    IRQ2ACKREG,al
  1801.     ;
  1802.     @@:
  1803.     out    IRQ1ACKREG,al
  1804.  
  1805.         inc     [NumberOfInterrupts]
  1806.  
  1807.     inc    cs:[intsemaphore]
  1808.         jnz     oiv_done
  1809.  
  1810.     sti                ; let interrupts go while we work
  1811.  
  1812.     cmp    wptr [UserRoutine+2],0    ; call the user function?
  1813.     jz    oiv_done        ; no, just exit
  1814.  
  1815.     call    dword ptr [UserRoutine]
  1816. ;
  1817. oiv_done:
  1818.     dec    cs:[intsemaphore]
  1819. ;
  1820. exit_int:
  1821.     pop    ds
  1822.     pop    ax
  1823.     pop    dx
  1824.     iret
  1825. ;
  1826. skip_int:
  1827.     pushf
  1828.     call    dword ptr ds:[OldIRQRoutine] ; perform the old interrupt
  1829.     jmp    short exit_int
  1830.  
  1831. OurIntVector    endp
  1832. ;
  1833. endif    ; MISC2OBJ
  1834. if PCMOBJ
  1835. ;
  1836. ;---------------------------====< SetupPCMDMAIO >====--------------------------
  1837. ;
  1838. ; SetupPCMDMAIO  --  Setup to output to the DAC
  1839. ;
  1840.     public    SetupPCMDMAIO
  1841. SetupPCMDMAIO   proc
  1842.     push    es
  1843.     push    di
  1844.     les    di,[mvhwShadowPointer]
  1845. ;
  1846. ; setup the sample rate timer
  1847. ;
  1848.         call    _ASloadtimer0
  1849. ;
  1850. ; Setup the Sample Buffer Counter Timer (T1 & rate generator)
  1851. ;
  1852.         mov     ax,[DMABuffLength]      ; get the count
  1853.     sub    dx,dx
  1854.     add    ax,1            ; make it 1 based (1 - 64k)
  1855.     adc    dx,dx
  1856.     mov    cl,[DMABUffDivides]    ; get the buffer size
  1857.     sub    ch,ch
  1858.     div    cx            ; now, we must be flexible
  1859.  
  1860.     mov    bl,[TheDMAChannel]    ; is this a 16 bit channel?
  1861.     mov    bh,[SampleSize]     ; CX = sample size, channel
  1862.  
  1863.     sub    cx,cx            ; ch = multiplier, cl=divider
  1864.     cmp    bx,0003h        ; 8 bits on 8 bit channel?
  1865.     jbe    @F            ; yes, continue on...
  1866.  
  1867.     inc    cx            ; divide by 2
  1868.     cmp    bx,0007h        ; 8 bits on 16 bit channel?
  1869.     jbe    @F            ; yes, continue on...
  1870.  
  1871.     xchg    ch,cl            ; multiply by 2
  1872.     cmp    bx,0203h        ; 16 bits on 8 bit channel?
  1873.     jbe    @F            ; yes, continue on...
  1874.     sub    cx,cx            ; no multiply or divide
  1875.     ;
  1876.     @@:
  1877.         shr     ax,cl                   ; if 8 on 16 divide by 2
  1878.     xchg    ch,cl
  1879.     shl    ax,cl            ; if 16 on 8 multiply by 2
  1880.  
  1881.     sub    cx,cx            ; The buffer size is # of bytes, so
  1882.     neg    bh            ; we must convert it to the data size
  1883.     adc    cx,cx
  1884.     shr    ax,cl
  1885.  
  1886.         call    FFAR ptr _ASloadtimer1
  1887. ;
  1888. ; Setup the system interrupt mask (IRQ mask)
  1889. ;
  1890.     mov    dx,IRQ1MASKREG
  1891.     cmp    TheIRQChannel,8     ; 2nd IRQ controller?
  1892.     jl    @F
  1893.     mov    dl,IRQ2MASKREG
  1894.     ;
  1895.     @@:
  1896.     in    al,dx            ; get the mask
  1897.     mov    ah,TheIRQMask
  1898.     not    ah
  1899.     and    al,ah            ; unmask the correct IRQ
  1900.     out    dx,al            ; then let the system know
  1901. ;
  1902. ; Setup the Interrupt Control Register
  1903. ;
  1904.     mov    dx,INTRCTLRST        ; flush any pending interrupts
  1905.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1906.     out    dx,al            ; of the PCM circuitry
  1907.  
  1908.         mov     dx,INTRCTLR
  1909.         xor     dx,[_MVTranslateCode]           ; xlate the board address
  1910.     in    al,dx            ; get the real mask
  1911.     or    al,bICsampbuff        ; interrupt on sample buffer count
  1912.     out    dx,al            ; send it..
  1913.     mov    es:[di._intrctlr],al    ; save it..
  1914. ;
  1915. ; enable the 12/16 bit stuff
  1916. ;
  1917.     test    [_MVHWVersionBits],bMV101 ; 101 chip?
  1918.     jz    sdhpas1_05          ; no, don't touch this...
  1919.  
  1920.     mov    cx,((NOT(bSC216bit+bSC212bit))*256) + bSC216bit+bSC212bit
  1921.     cmp    [SampleSize],1        ; 12 bit?
  1922.     jz    @F
  1923.     mov    cx,((NOT(bSC216bit+bSC212bit))*256) + bSC216bit
  1924.     cmp    [SampleSize],2        ; 16 bit?
  1925.     jz    @F
  1926.     mov    cx,((NOT(bSC216bit+bSC212bit))*256) + 0
  1927.     ;
  1928.     @@:
  1929.     mov    dx,SYSCONFIG2
  1930.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1931.     in    al,dx
  1932.     and    al,ch            ; clear the bits
  1933.     or    al,cl            ; set the appropriate bits
  1934.     out    dx,al
  1935.     ;
  1936.     sdhpas1_05:
  1937. ;
  1938. ; setup the direction, stereo/mono and DMA enable bits
  1939. ;
  1940.     mov    al,bCCmono        ; get the stereo/mono mask bit
  1941.     and    al,[StereoMono]     ; al = bCCmono if in mono mode
  1942.     or    al,[PCMDirection]    ; get the direction bit mask
  1943.     or    al,bCCenapcm        ; enable the PCM state machine
  1944.         mov     dx,CROSSCHANNEL
  1945.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1946.     mov    ah,0fh + bCCdrq     ; get a mask to load non PCM bits
  1947.     and    ah,es:[di._crosschannel]; grab all but PCM/DRQ/MONO/DIRECTION
  1948.     or    al,ah            ; merge the two states
  1949.     xor    al,bCCenapcm        ; disable the PCM bit
  1950.     out    dx,al            ; send to the hardware
  1951.     xor    al,bCCenapcm        ; enable the PCM bit
  1952.     out    dx,al            ; send to the hardware
  1953.     mov    es:[di._crosschannel],al; and save the new state
  1954. ;
  1955. ; Setup the audio filter sample bits
  1956. ;
  1957.     mov    al,es:[di._audiofilt]
  1958.     or    al,(bFIsrate+bFIsbuff)    ; enable the sample count/buff counters
  1959.     mov    dx,AUDIOFILT
  1960.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  1961.     out    dx,al
  1962.     mov    es:[di._audiofilt],al
  1963.  
  1964.         mov     NumberOfInterrupts,0
  1965.  
  1966.         enable                          ; Fly, baby Fly!!!
  1967.  
  1968.     pop    di
  1969.     pop    es
  1970.     ret
  1971.  
  1972. SetupPCMDMAIO    endp
  1973. ;
  1974. ;
  1975. ;---------------------------====< SetupPCMPolledIO >====-----------------------
  1976. ;
  1977. ; SetupPCMPolledIO  --    Setup to read/write to the ADC/DAC in a polled fashion
  1978. ;
  1979.     public    SetupPCMPolledIO
  1980. SetupPCMPolledIO        proc
  1981.     push    es
  1982.     push    di
  1983.     les    di,[mvhwShadowPointer]
  1984. ;
  1985. ; Setup the Sample Timer (T0 & square wave output)
  1986. ;
  1987.     call    _ASloadTimer0
  1988. ;
  1989. ; Setup the Sample Buffer Counter Timer (T1 & rate generator)
  1990. ;
  1991.     mov    ax,1            ; get the count
  1992.     call    FFAR ptr _ASloadtimer1
  1993. ;
  1994. ; Setup the Interrupt Control Register
  1995. ;
  1996.         mov     dx,INTRCTLR
  1997.     xor    dx,[_MVTranslateCode]       ; xlate the board address
  1998.     in    al,dx               ; get the real mask
  1999.     or    al,bICsampbuff+bICsamprate ; enable both sample timer ints
  2000.     out    dx,al               ; send it...
  2001.     mov    es:[di._intrctlr],al       ; save it...
  2002. ;
  2003. ; enable the 16 bit stuff
  2004. ;
  2005.     test    [_MVHWVersionBits],bMV101 ; 101 chip?
  2006.     jz    sphpas1_05          ; no, don't touch this...
  2007.  
  2008.     mov    cx,((NOT(bSC216bit+bSC212bit))*256) + bSC216bit+bSC212bit
  2009.     cmp    [SampleSize],1        ; 12 bit?
  2010.     jz    @F
  2011.     mov    cx,((NOT(bSC216bit+bSC212bit))*256) + bSC216bit
  2012.     cmp    [SampleSize],2        ; 16 bit?
  2013.     jz    @F
  2014.     mov    cx,((NOT(bSC216bit+bSC212bit))*256) + 0
  2015.     ;
  2016.     @@:
  2017.     mov    dx,SYSCONFIG2
  2018.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  2019.     in    al,dx
  2020.     and    al,ch            ; clear the bits
  2021.     or    al,cl            ; set the appropriate bits
  2022.     out    dx,al
  2023.     ;
  2024.     sphpas1_05:
  2025. ;
  2026. ; setup the direction, stereo/mono and DMA enable bits
  2027. ;
  2028.     mov    al,bCCmono        ; get the stereo/mono mask bit
  2029.     and    al,[StereoMono]     ; al = bCCmono if in mono mode
  2030.     or    al,[PCMDirection]    ; get the direction bit mask
  2031.     or    al,bCCenapcm + bCCdrq    ; enable the PCM & set DRQ for NOT mask
  2032.         mov     dx,CROSSCHANNEL
  2033.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  2034.     mov    ah,0fh            ; get a mask to load the non-PCM bits
  2035.     and    ah,es:[di._crosschannel]; grab all but PCM/DRQ/MONO/DIRECTION
  2036.     or    al,ah            ; merge the two states
  2037.     xor    al,bCCenapcm + bCCdrq    ; disable the PCM & DRQ
  2038.     out    dx,al            ; send to the hardware
  2039.     xor    al,bCCenapcm        ; enable the PCM
  2040.     out    dx,al
  2041.     mov    es:[di._crosschannel],al; and save the new state
  2042. ;
  2043. ; Setup the audio filter sample bits to enable sample timer/count
  2044. ;
  2045.     mov    al,es:[di._audiofilt]
  2046.     or    al,(bFIsrate+bFIsbuff)    ; enable the sample timer/counter
  2047.     mov    dx,AUDIOFILT
  2048.     xor    dx,[_MVTranslateCode]    ; xlate the board address
  2049.     out    dx,al
  2050.     mov    es:[di._audiofilt],al
  2051.  
  2052.         sub     ax,ax
  2053.     mov    NumberOfInterrupts,ax
  2054.  
  2055.         enable
  2056.  
  2057.     pop    di
  2058.     pop    es
  2059.     ret
  2060.  
  2061. SetupPCMPolledIO   endp
  2062. ;
  2063. ;
  2064. ;----------------------------====< StartPlaying >====--------------------------
  2065. ;
  2066.     public    StartPlaying
  2067. StartPlaying    proc
  2068. ;
  2069. ; Save the type of setup. It contains the interrupt masks needed
  2070. ;
  2071.     mov    [TypeOfSetup],DMAOUTPUT
  2072.     mov    [PCMDirection],bCCdac    ; bit d6 of interrupt control register
  2073. ;
  2074. ; Select the DMA mode for playing
  2075. ;
  2076.     mov    al,10h            ; auto init bit on 8237 chip
  2077.     and    al,[DMAAutoInit]    ; al may have the auto-init bit
  2078.     or    al,48h            ; merge in the rest of the DMA bits
  2079.     mov    TheDMAMode,al        ; save the mode
  2080. ;
  2081. ; Program the DMA, then our board circuitry to start the interrupts
  2082. ;
  2083.         call    LoadDMA                 ; setup the DMA controller
  2084.     call    SetupPCMDMAIO        ; Setup the MV Hardware
  2085.  
  2086.     mov    StatusWord,1        ; set the global status word
  2087.  
  2088.         ret
  2089.  
  2090. StartPlaying    endp
  2091. ;
  2092. ;
  2093. ;---------------------------====< StartRecording >====-------------------------
  2094. ;
  2095.     public    StartRecording
  2096. StartRecording    proc
  2097. ;
  2098. ; Save the type of setup. It contains the interrupt masks needed
  2099. ;
  2100.     mov    [TypeOfSetup],DMAINPUT
  2101.     mov    [PCMDirection],00h    ; bit d6 of interrupt control register
  2102. ;
  2103. ; Select the DMA mode for recording
  2104. ;
  2105.     mov    al,10h            ; auto init bit on 8237 chip
  2106.     and    al,[DMAAutoInit]    ; al may have the auto-init bit
  2107.     or    al,44h            ; merge in the rest of the DMA bits
  2108.     mov    TheDMAMode,al        ; save the mode
  2109. ;
  2110. ; Program the DMA, then our board circuitry to start the interrupts
  2111. ;
  2112.         call    LoadDMA                 ; setup the DMA controller
  2113.     call    SetupPCMDMAIO        ; Setup the MV Hardware
  2114.  
  2115.     mov    StatusWord,2        ; set the global status word
  2116.         ret
  2117.  
  2118. StartRecording    endp
  2119. ;
  2120. endif    ; PCMOBJ
  2121. if MISC2OBJ
  2122. ;
  2123. ;---------------------====< _unloadirqvector >====---------------
  2124. ;
  2125. ; Restore the original vector
  2126. ;
  2127. ; Entry Conditions:
  2128. ;     dParm1 points to the user routine
  2129. ;
  2130. ; Exit Conditions:
  2131. ;     Nothing
  2132. ;
  2133. ;
  2134.     public    _unloadirqvector
  2135. _unloadirqvector    proc
  2136.     push    es
  2137.  
  2138.         les     ax,OldIRQRoutine
  2139.     mov    bx,es
  2140.     or    bx,ax
  2141.     jz    @F
  2142.  
  2143.     mov    bl,[TheIRQChannel]
  2144.     call    _getirqoffset
  2145.  
  2146.     push    ds
  2147.     sub    cx,cx
  2148.     mov    ds,cx
  2149.  
  2150.         disable
  2151.     mov    ds:[bx+0],ax
  2152.     mov    ds:[bx+2],es
  2153.         enable
  2154.  
  2155.     pop    ds
  2156.  
  2157.         sub     ax,ax
  2158.     mov    wptr [OldIRQRoutine+0],ax
  2159.     mov    wptr [OldIRQRoutine+2],ax
  2160. ;
  2161. @@:
  2162.     pop    es
  2163.     ret
  2164.  
  2165. _unloadirqvector    endp
  2166.  
  2167. endif    ; MISC2OBJ
  2168.  
  2169.  
  2170.