Port the SB128 code to AROS.
[AROS.git] / workbench / devs / AHI / Drivers / SB128 / interrupt.c
blob017a00293dd59585451ca651860926ef43dee920
1 /*
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.
14 All Rights Reserved.
18 //#include <config.h>
20 #if !defined(__AROS__)
21 #undef __USE_INLINE__
22 #include <proto/expansion.h>
23 #endif
24 #include <libraries/ahi_sub.h>
25 #include <proto/exec.h>
26 #include <stddef.h>
27 #include "library.h"
28 #include "regs.h"
29 #include "interrupt.h"
30 #include "pci_wrapper.h"
31 #ifdef __AROS__
32 #define DEBUG 1
33 #include <aros/debug.h>
34 #define DebugPrintF bug
35 #endif
37 #define min(a,b) ((a)<(b)?(a):(b))
39 unsigned long z = 0;
40 /******************************************************************************
41 ** Hardware interrupt handler *************************************************
42 ******************************************************************************/
45 LONG
46 CardInterrupt( struct SB128_DATA* card )
48 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
49 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
50 struct PCIDevice *dev = (struct PCIDevice * ) card->pci_dev;
52 ULONG intreq;
53 LONG handled = 0;
55 bug("[CMI8738]: %s(card @ 0x%p)\n", __PRETTY_FUNCTION__, card);
57 while (((intreq = (pci_inl(SB128_STATUS, card))) & SB128_INT_PENDING) != 0)
59 if( intreq & SB128_INT_DAC2 && AudioCtrl != NULL )
61 /* Clear interrupt pending bit(s) and re-enable playback interrupts */
62 pci_outl((pci_inl(SB128_SCON, card) & ~SB128_DAC2_INTEN), SB128_SCON, card);
63 pci_outl((pci_inl(SB128_SCON, card) | SB128_DAC2_INTEN), SB128_SCON, card);
65 if (card->flip == 0) /* just played buf 1 */
67 card->flip = 1;
68 card->current_buffer = card->playback_buffer;
70 else /* just played buf 2 */
72 card->flip = 0;
73 card->current_buffer = (APTR) ((unsigned long) card->playback_buffer + card->current_bytesize);
76 card->playback_interrupt_enabled = FALSE;
77 Cause( &card->playback_interrupt );
80 if( intreq & SB128_INT_ADC && AudioCtrl != NULL )
82 /* Clear interrupt pending bit(s) and re-enable record interrupts */
83 pci_outl((pci_inl(SB128_SCON, card) & ~SB128_ADC_INTEN), SB128_SCON, card);
84 pci_outl((pci_inl(SB128_SCON, card) | SB128_ADC_INTEN), SB128_SCON, card);
86 if( card->record_interrupt_enabled )
88 /* Invoke softint to convert and feed AHI with the new sample data */
90 if (card->recflip == 0) /* just filled buf 1 */
92 card->recflip = 1;
93 card->current_record_buffer = card->record_buffer;
95 else /* just filled buf 2 */
97 card->recflip = 0;
98 card->current_record_buffer = (APTR) ((unsigned long) card->record_buffer + card->current_record_bytesize);
100 card->record_interrupt_enabled = FALSE;
101 Cause( &card->record_interrupt );
104 exit:
105 handled = 1;
109 return handled;
113 /******************************************************************************
114 ** Playback interrupt handler *************************************************
115 ******************************************************************************/
117 void
118 PlaybackInterrupt( struct SB128_DATA* card )
120 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
121 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
122 struct PCIDevice *dev = (struct PCIDevice * ) card->pci_dev;
124 if( card->mix_buffer != NULL && card->current_buffer != NULL )
126 BOOL skip_mix;
128 WORD* src;
129 WORD* dst;
130 size_t skip;
131 size_t samples;
132 int i;
134 skip_mix = CallHookPkt( AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0 );
135 CallHookPkt( AudioCtrl->ahiac_PlayerFunc, (Object*) AudioCtrl, NULL );
137 if( ! skip_mix )
139 CallHookPkt( AudioCtrl->ahiac_MixerFunc, (Object*) AudioCtrl, card->mix_buffer );
142 /* Now translate and transfer to the DMA buffer */
144 skip = ( AudioCtrl->ahiac_Flags & AHIACF_HIFI ) ? 2 : 1;
145 samples = card->current_bytesize >> 1;
147 src = card->mix_buffer;
148 dst = card->current_buffer;
150 i = samples;
152 while( i > 0 )
154 *dst = ( ( *src & 0xff ) << 8 ) | ( ( *src & 0xff00 ) >> 8 );
156 src += skip;
157 dst += 1;
159 --i;
162 //Flush cache so that data is completely written to the DMA buffer - Articia hack
163 CacheClearE(card->current_buffer, card->current_bytesize, CACRF_ClearD);
165 CallHookPkt( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 );
167 card->playback_interrupt_enabled = TRUE;
171 /******************************************************************************
172 ** Record interrupt handler ***************************************************
173 ******************************************************************************/
175 void
176 RecordInterrupt( struct SB128_DATA* card )
178 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
179 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
180 struct PCIDevice *dev = (struct PCIDevice * ) card->pci_dev;
182 struct AHIRecordMessage rm =
184 AHIST_S16S,
185 card->current_record_buffer,
186 RECORD_BUFFER_SAMPLES
189 int i = 0, shorts = card->current_record_bytesize / 2;
190 WORD* ptr = card->current_record_buffer;
192 //Invalidate cache so that data read from DMA buffer is correct - Articia hack
193 CacheClearE(card->current_record_buffer, card->current_record_bytesize, CACRF_InvalidateD);
195 while( i < shorts )
197 *ptr = ( ( *ptr & 0xff ) << 8 ) | ( ( *ptr & 0xff00 ) >> 8 );
199 ++i;
200 ++ptr;
203 CallHookPkt( AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm );
205 //Invalidate cache so that data read from DMA buffer is correct - Articia hack
206 CacheClearE(card->current_record_buffer, card->current_record_bytesize, CACRF_InvalidateD);
208 card->record_interrupt_enabled = TRUE;