2 Copyright © 2004-2014, Davy Wentzler. All rights reserved.
3 Copyright © 2014-2016, The AROS Development Team. All rights reserved.
10 #include <proto/expansion.h>
11 #include <libraries/ahi_sub.h>
12 #include <proto/exec.h>
16 #include "interrupt.h"
17 #include "pci_wrapper.h"
19 #define min(a,b) ((a)<(b)?(a):(b))
22 /******************************************************************************
23 ** Hardware interrupt handler *************************************************
24 ******************************************************************************/
27 AROS_INTH1(CardInterrupt
, struct CardData
*, card
)
31 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
36 //DebugPrintF("INT\n");
37 while ( ( intreq
= ( pci_inb(CCS_INTR_STATUS
, card
) ) ) != 0 )
39 //DebugPrintF("INT %x\n", intreq);
41 if (intreq
& CCS_INTR_PRO_MACRO
)
43 unsigned char mtstatus
= pci_inb_mt(MT_INTR_MASK_STATUS
, card
);
45 //DebugPrintF("CCS_INTR_PRO_MACRO, mtstatus = %x\n", mtstatus);
47 if( (mtstatus
& MT_PLAY_STATUS
) && AudioCtrl
!= NULL
)
49 pci_outb_mt(mtstatus
| MT_PLAY_STATUS
, MT_INTR_MASK_STATUS
, card
); // clear interrupt
51 if (card
->flip
== 0) // just played buf 1
54 card
->current_buffer
= card
->playback_buffer
;
56 else // just played buf 2
59 card
->current_buffer
= (APTR
) ((long) card
->playback_buffer
+ card
->current_bytesize
);
62 card
->playback_interrupt_enabled
= FALSE
;
63 Cause( &card
->playback_interrupt
);
66 if( (mtstatus
& MT_REC_STATUS
) && AudioCtrl
!= NULL
)
68 pci_outb_mt(mtstatus
| MT_REC_STATUS
, MT_INTR_MASK_STATUS
, card
); // clear interrupt
69 //DebugPrintF("rec\n");
71 if( card
->record_interrupt_enabled
)
73 const unsigned long diff
= pci_inl_mt(MT_DMA_REC_ADDRESS
, card
) - (unsigned long) card
->record_buffer_32bit_phys
;
75 //DebugPrintF("%lu\n", diff % card->current_record_bytesize_32bit);
77 /* Invoke softint to convert and feed AHI with the new sample data */
79 if (diff
>= card
->current_record_bytesize_32bit
) // just played buf 1
81 if (card
->recflip
== 1)
82 DebugPrintF("A: Missed IRQ!\n");
85 card
->current_record_buffer
= card
->record_buffer
;
86 card
->current_record_buffer_32bit
= card
->record_buffer_32bit
;
88 else // just played buf 2
90 if (card
->recflip
== 0)
91 DebugPrintF("B: Missed IRQ!\n");
94 card
->current_record_buffer
= (APTR
) ((unsigned long) card
->record_buffer
+ card
->current_record_bytesize_target
);
95 card
->current_record_buffer_32bit
= (APTR
) ((unsigned long) card
->record_buffer_32bit
+ card
->current_record_bytesize_32bit
);
97 card
->record_interrupt_enabled
= FALSE
;
98 Cause( &card
->record_interrupt
);
105 DebugPrintF("Oh dear, it's not CCS_INTR_PLAYREC!\n");
117 /******************************************************************************
118 ** Playback interrupt handler *************************************************
119 ******************************************************************************/
121 AROS_INTH1(PlaybackInterrupt
, struct CardData
*, card
)
125 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
126 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
127 BOOL stereo
= (AudioCtrl
->ahiac_Flags
& AHIACF_STEREO
) != 0;
129 if( card
->mix_buffer
!= NULL
&& card
->current_buffer
!= NULL
)
135 LONG
*srclong
, *dstlong
, left
, right
;
136 int frames
= card
->current_frames
;
138 skip_mix
= CallHookPkt( AudioCtrl
->ahiac_PreTimerFunc
, (Object
*) AudioCtrl
, 0 );
139 CallHookPkt( AudioCtrl
->ahiac_PlayerFunc
, (Object
*) AudioCtrl
, NULL
);
141 //DebugPrintF("skip_mix = %d\n", skip_mix);
145 CallHookPkt( AudioCtrl
->ahiac_MixerFunc
, (Object
*) AudioCtrl
, card
->mix_buffer
);
148 /* Now translate and transfer to the DMA buffer */
150 src
= card
->mix_buffer
;
151 srclong
= (LONG
*) card
->mix_buffer
;
152 dstlong
= (LONG
*) card
->current_buffer
;
158 if (AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
160 left
= AROS_LONG2LE(*srclong
++);
162 right
= AROS_LONG2LE(*srclong
++);
168 left
= AROS_LONG2LE(*src
++ << 16);
170 right
= AROS_LONG2LE(*src
++ << 16);
175 *dstlong
++ = left
; // out 1 - 2
190 CacheClearE(card
->current_buffer
, (ULONG
) dstlong
- (ULONG
) card
->current_buffer
, CACRF_ClearD
);
191 CallHookPkt( AudioCtrl
->ahiac_PostTimerFunc
, (Object
*) AudioCtrl
, 0 );
194 card
->playback_interrupt_enabled
= TRUE
;
202 /******************************************************************************
203 ** Record interrupt handler ***************************************************
204 ******************************************************************************/
206 AROS_INTH1(RecordInterrupt
, struct CardData
*, card
)
210 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
211 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
213 struct AHIRecordMessage rm
=
216 card
->current_record_buffer
,
217 RECORD_BUFFER_SAMPLES
220 long *src
= card
->current_record_buffer_32bit
;
221 WORD
* dst
= card
->current_record_buffer
;
222 int i
= 0, frames
= RECORD_BUFFER_SAMPLES
;
224 CacheClearE( card
->current_record_buffer
, card
->current_record_bytesize_target
, CACRF_ClearD
);
225 CacheClearE( card
->current_record_buffer_32bit
, card
->current_record_bytesize_32bit
, CACRF_ClearD
);
229 if (card
->SubType
== PHASE88
|| card
->SubType
== MAUDIO_1010LT
)
231 src
+= card
->input
* 2;
234 *dst
++ = AROS_LE2LONG(*src
++) >> 16;
235 *dst
++ = AROS_LE2LONG(*src
) >> 16;
244 if (card
->input
!= 1)
248 *dst
++ = AROS_LE2LONG(*src
++) >> 16;
249 *dst
++ = AROS_LE2LONG(*src
) >> 16;
262 *dst
++ = AROS_LE2LONG(*src
++) >> 16;
263 *dst
++ = AROS_LE2LONG(*src
) >> 16;
272 CallHookPkt( AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);
273 CacheClearE( card
->current_record_buffer
, card
->current_record_bytesize_target
, CACRF_ClearD
);
274 CacheClearE( card
->current_record_buffer_32bit
, card
->current_record_bytesize_32bit
, CACRF_ClearD
);
276 card
->record_interrupt_enabled
= TRUE
;