3 The contents of this file are subject to the AROS Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
4 http://www.aros.org/license.html
6 Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
7 ANY KIND, either express or implied. See the License for the specific language governing rights and
8 limitations under the License.
10 The Original Code is (C) Copyright 2004-2011 Ross Vumbaca.
12 The Initial Developer of the Original Code is Ross Vumbaca.
21 #include <proto/expansion.h>
22 #include <libraries/ahi_sub.h>
23 #include <proto/exec.h>
27 #include "interrupt.h"
29 #define min(a,b) ((a)<(b)?(a):(b))
32 /******************************************************************************
33 ** Hardware interrupt handler *************************************************
34 ******************************************************************************/
38 CardInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct CardData
* card
)
40 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
41 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
42 struct PCIDevice
*dev
= (struct PCIDevice
* ) card
->pci_dev
;
46 while (((intreq
= (dev
->InLong(card
->iobase
+ SB128_STATUS
))) & SB128_INT_PENDING
) != 0)
48 if( intreq
& SB128_INT_DAC2
&& AudioCtrl
!= NULL
)
50 /* Clear interrupt pending bit(s) and re-enable playback interrupts */
51 dev
->OutLong(card
->iobase
+ SB128_SCON
, (dev
->InLong(card
->iobase
+ SB128_SCON
) & ~SB128_DAC2_INTEN
));
52 dev
->OutLong(card
->iobase
+ SB128_SCON
, (dev
->InLong(card
->iobase
+ SB128_SCON
) | SB128_DAC2_INTEN
));
54 if (card
->flip
== 0) /* just played buf 1 */
57 card
->current_buffer
= card
->playback_buffer
;
59 else /* just played buf 2 */
62 card
->current_buffer
= (APTR
) ((unsigned long) card
->playback_buffer
+ card
->current_bytesize
);
65 card
->playback_interrupt_enabled
= FALSE
;
66 IExec
->Cause( &card
->playback_interrupt
);
69 if( intreq
& SB128_INT_ADC
&& AudioCtrl
!= NULL
)
71 /* Clear interrupt pending bit(s) and re-enable record interrupts */
72 dev
->OutLong(card
->iobase
+ SB128_SCON
, (dev
->InLong(card
->iobase
+ SB128_SCON
) & ~SB128_ADC_INTEN
));
73 dev
->OutLong(card
->iobase
+ SB128_SCON
, (dev
->InLong(card
->iobase
+ SB128_SCON
) | SB128_ADC_INTEN
));
75 if( card
->record_interrupt_enabled
)
77 /* Invoke softint to convert and feed AHI with the new sample data */
79 if (card
->recflip
== 0) /* just filled buf 1 */
82 card
->current_record_buffer
= card
->record_buffer
;
84 else /* just filled buf 2 */
87 card
->current_record_buffer
= (APTR
) ((unsigned long) card
->record_buffer
+ card
->current_record_bytesize
);
89 card
->record_interrupt_enabled
= FALSE
;
90 IExec
->Cause( &card
->record_interrupt
);
102 /******************************************************************************
103 ** Playback interrupt handler *************************************************
104 ******************************************************************************/
107 PlaybackInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct CardData
* card
)
109 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
110 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
111 struct PCIDevice
*dev
= (struct PCIDevice
* ) card
->pci_dev
;
113 if( card
->mix_buffer
!= NULL
&& card
->current_buffer
!= NULL
)
123 skip_mix
= IUtility
->CallHookPkt( AudioCtrl
->ahiac_PreTimerFunc
, (Object
*) AudioCtrl
, 0 );
124 IUtility
->CallHookPkt( AudioCtrl
->ahiac_PlayerFunc
, (Object
*) AudioCtrl
, NULL
);
128 IUtility
->CallHookPkt( AudioCtrl
->ahiac_MixerFunc
, (Object
*) AudioCtrl
, card
->mix_buffer
);
131 /* Now translate and transfer to the DMA buffer */
133 skip
= ( AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
) ? 2 : 1;
134 samples
= card
->current_bytesize
>> 1;
136 src
= card
->mix_buffer
;
137 dst
= card
->current_buffer
;
143 *dst
= ( ( *src
& 0xff ) << 8 ) | ( ( *src
& 0xff00 ) >> 8 );
151 //Flush cache so that data is completely written to the DMA buffer - Articia hack
152 IExec
->CacheClearE(card
->current_buffer
, card
->current_bytesize
, CACRF_ClearD
);
154 IUtility
->CallHookPkt( AudioCtrl
->ahiac_PostTimerFunc
, (Object
*) AudioCtrl
, 0 );
156 card
->playback_interrupt_enabled
= TRUE
;
160 /******************************************************************************
161 ** Record interrupt handler ***************************************************
162 ******************************************************************************/
165 RecordInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct CardData
* card
)
167 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
168 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
169 struct PCIDevice
*dev
= (struct PCIDevice
* ) card
->pci_dev
;
171 struct AHIRecordMessage rm
=
174 card
->current_record_buffer
,
175 RECORD_BUFFER_SAMPLES
178 int i
= 0, shorts
= card
->current_record_bytesize
/ 2;
179 WORD
* ptr
= card
->current_record_buffer
;
181 //Invalidate cache so that data read from DMA buffer is correct - Articia hack
182 IExec
->CacheClearE(card
->current_record_buffer
, card
->current_record_bytesize
, CACRF_InvalidateD
);
186 *ptr
= ( ( *ptr
& 0xff ) << 8 ) | ( ( *ptr
& 0xff00 ) >> 8 );
192 IUtility
->CallHookPkt( AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);
194 //Invalidate cache so that data read from DMA buffer is correct - Articia hack
195 IExec
->CacheClearE(card
->current_record_buffer
, card
->current_record_bytesize
, CACRF_InvalidateD
);
197 card
->record_interrupt_enabled
= TRUE
;