2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
9 #include <proto/expansion.h>
10 #include <libraries/ahi_sub.h>
11 #include <proto/exec.h>
13 //#include "library.h"
15 #include "interrupt.h"
17 #include "pci_wrapper.h"
19 #define min(a,b) ((a)<(b)?(a):(b))
23 #define CALLHOOK CallHookA
25 #include <clib/alib_protos.h>
29 /******************************************************************************
30 ** Hardware interrupt handler *************************************************
31 ******************************************************************************/
35 CardInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct CardData
* card
)
38 CardInterrupt( struct CardData
* card
)
41 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
46 if ( ( intreq
= INBYTE(card
->iobase
+ CCS_INTR_STATUS
) ) != 0 )
48 //DEBUGPRINTF("INT %x\n", intreq);
50 if (intreq
& CCS_INTR_PLAYREC
)
52 unsigned char mtstatus
= INBYTE(card
->mtbase
+ MT_INTR_STATUS
);
54 if( (mtstatus
& MT_PDMA0
) && AudioCtrl
!= NULL
&& card
->is_playing
)
56 unsigned long diff
= INLONG(card
->mtbase
+ MT_DMAI_PB_ADDRESS
) - (unsigned long) card
->playback_buffer_phys
;
58 OUTBYTE(card
->mtbase
+ MT_INTR_STATUS
, mtstatus
| MT_PDMA0
); // clear interrupt
61 DEBUGPRINTF("MT_PDMA0, diff = %lu, %lu\n", diff, card->current_frames);
66 if (diff
>= card
->current_bytesize
) //card->flip == 0) // just played buf 1
69 card
->current_buffer
= card
->playback_buffer
;
70 card
->spdif_out_current_buffer
= card
->spdif_out_buffer
;
72 else // just played buf 2
75 card
->current_buffer
= (APTR
) ((long) card
->playback_buffer
+ card
->current_bytesize
);
76 card
->spdif_out_current_buffer
= (APTR
) ((long) card
->spdif_out_buffer
+ card
->current_bytesize
/ 2);
79 card
->playback_interrupt_enabled
= FALSE
;
80 CAUSE( &card
->playback_interrupt
);
83 if( ((mtstatus
& MT_RDMA0
) || (mtstatus
& MT_RDMA1
)) && AudioCtrl
!= NULL
&& card
->is_recording
)
85 OUTBYTE(card
->mtbase
+ MT_INTR_STATUS
, mtstatus
| MT_RDMA0
| MT_RDMA1
); // clear interrupt
88 DEBUGPRINTF("MT_RDMA%d\n", mtstatus);
93 if( card
->record_interrupt_enabled
)
95 /* Invoke softint to convert and feed AHI with the new sample data */
97 if (card
->recflip
== 0) // just played buf 1
100 card
->current_record_buffer
= card
->record_buffer
;
101 card
->current_record_buffer_32bit
= card
->record_buffer_32bit
;
103 else // just played buf 2
106 card
->current_record_buffer
= (APTR
) ((long) card
->record_buffer
+ card
->current_record_bytesize_32bit
/ 2);
107 card
->current_record_buffer_32bit
= (APTR
) ((long) card
->record_buffer_32bit
+ card
->current_record_bytesize_32bit
);
110 card
->record_interrupt_enabled
= FALSE
;
111 CAUSE( &card
->record_interrupt
);
115 if( (mtstatus
& MT_DMA_FIFO
) && AudioCtrl
!= NULL
)
117 unsigned char status
= INBYTE(card
->mtbase
+ MT_DMA_UNDERRUN
);
119 //DEBUGPRINTF("FIFO %x\n", status);
120 WriteMask8(card
, card
->mtbase
, MT_INTR_STATUS
, MT_DMA_FIFO
); // clear it
122 OUTBYTE(card
->mtbase
+ MT_DMA_UNDERRUN
, status
);
123 WriteMask8(card
, card
->mtbase
, MT_INTR_MASK
, MT_DMA_FIFO
);
127 OUTBYTE(card
->mtbase
+ MT_INTR_STATUS
, mtstatus
); // clear interrupt
136 /******************************************************************************
137 ** Playback interrupt handler *************************************************
138 ******************************************************************************/
142 PlaybackInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct CardData
* card
)
145 PlaybackInterrupt( struct CardData
* card
)
148 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
150 if( card
->mix_buffer
!= NULL
&& card
->current_buffer
!= NULL
&& card
->is_playing
)
156 LONG
* srclong
, *dstlong
, *spdif_dstlong
, left
, right
;
157 int frames
= card
->current_frames
;
159 skip_mix
= CALLHOOK( AudioCtrl
->ahiac_PreTimerFunc
, (Object
*) AudioCtrl
, 0 );
160 CALLHOOK( AudioCtrl
->ahiac_PlayerFunc
, (Object
*) AudioCtrl
, NULL
);
162 //DEBUGPRINTF("skip_mix = %d\n", skip_mix);
166 CALLHOOK( AudioCtrl
->ahiac_MixerFunc
, (Object
*) AudioCtrl
, card
->mix_buffer
);
169 /* Now translate and transfer to the DMA buffer */
171 src
= card
->mix_buffer
;
173 srclong
= (LONG
*) card
->mix_buffer
;
174 dstlong
= (LONG
*) card
->current_buffer
;
175 spdif_dstlong
= card
->spdif_out_current_buffer
;
178 #if defined(__amigaos4__) || defined(__MORPHOS__)
179 if (AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
183 left
= ((*srclong
& 0xFF000000) >> 24) | ((*srclong
& 0x00FF0000) >> 8) | ((*srclong
& 0x0000FF00) << 8);
184 *dstlong
++ = *spdif_dstlong
++ = left
;
187 right
= ((*srclong
& 0xFF000000) >> 24) | ((*srclong
& 0x00FF0000) >> 8) | ((*srclong
& 0x0000FF00) << 8);
188 *dstlong
++ = *spdif_dstlong
++ = right
;
191 *dstlong
++ = left
; // L & R of 2nd stereo channel that is unused
201 *dstlong
++ = *spdif_dstlong
++ = (*src
& 0xFF00) >> 16; srclong
++;
202 *dstlong
++ = *spdif_dstlong
++ = (*srclong
& 0xFF000000) >> 16; srclong
++;
204 *dstlong
++ = 0; // L & R of 2nd stereo channel that is unused
210 IExec
->CacheClearE(card
->current_buffer
, (ULONG
) dstlong
- (ULONG
) card
->current_buffer
, CACRF_ClearD
);
211 IExec
->CacheClearE(card
->spdif_out_current_buffer
, (ULONG
) spdif_dstlong
- (ULONG
) card
->spdif_out_current_buffer
, CACRF_ClearD
);
214 if (AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
219 *dstlong
++ = *spdif_dstlong
++ = left
;
223 *dstlong
++ = *spdif_dstlong
++ = right
;
226 *dstlong
++ = left
; // L & R of 2nd stereo channel that is unused
236 *dstlong
++ = *spdif_dstlong
++ = (*src
); src
++;
237 *dstlong
++ = *spdif_dstlong
++ = (*src
); src
++;
239 *dstlong
++ = 0; // L & R of 2nd stereo channel that is unused
246 CALLHOOK( AudioCtrl
->ahiac_PostTimerFunc
, (Object
*) AudioCtrl
, 0 );
249 card
->playback_interrupt_enabled
= TRUE
;
253 /******************************************************************************
254 ** Record interrupt handler ***************************************************
255 ******************************************************************************/
259 RecordInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct CardData
* card
)
262 RecordInterrupt( struct CardData
* card
)
265 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
266 int i
= 0, frames
= card
->current_record_bytesize_32bit
/ 4;
268 if (card
->input_is_24bits
)
270 struct AHIRecordMessage rm
=
273 card
->current_record_buffer_32bit
,
274 RECORD_BUFFER_SAMPLES
277 #if defined(__amigaos4__) || defined(__MORPHOS__)
278 long *srclong
= card
->current_record_buffer_32bit
;
282 *srclong
= ((*srclong
& 0x00FF0000) >> 8) | ((*srclong
& 0x0000FF00) << 8) | ((*srclong
& 0x000000FF) << 24);
289 CALLHOOK( AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);
293 struct AHIRecordMessage rm
=
296 card
->current_record_buffer
,
297 RECORD_BUFFER_SAMPLES
300 long *src
= card
->current_record_buffer_32bit
;
301 WORD
* dst
= card
->current_record_buffer
;
303 #if defined(__amigaos4__) || defined(__MORPHOS__)
306 *dst
= ( ( *src
& 0x000000FF ) << 8 ) | ( ( *src
& 0x0000FF00 ) >> 8 );
323 CALLHOOK( AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);
326 card
->record_interrupt_enabled
= TRUE
;