revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Drivers / VIA-AC97 / interrupt.c
blob34b6ab7a8a903ef3d94f947f17516b21c49d43c7
1 /*
2 Copyright © 2005-2013, Davy Wentzler. All rights reserved.
3 Copyright © 2010-2016, The AROS Development Team. All rights reserved.
4 $Id$
5 */
7 #include <config.h>
9 #undef __USE_INLINE__
10 #include <proto/expansion.h>
11 #include <libraries/ahi_sub.h>
12 #include <proto/exec.h>
13 #include <stddef.h>
14 #include "library.h"
15 #include "regs.h"
16 #include "interrupt.h"
17 #include "misc.h"
18 #include "hwaccess.h"
19 #include "pci_wrapper.h"
21 #define min(a,b) ((a)<(b)?(a):(b))
23 /******************************************************************************
24 ** Hardware interrupt handler *************************************************
25 ******************************************************************************/
28 #ifdef __amigaos4__
29 LONG CardInterrupt(struct ExceptionContext *pContext,
30 struct ExecBase *SysBase, struct CardData* card)
31 #else
32 LONG CardInterrupt(struct CardData* card)
33 #endif
35 #ifdef __amigaos4__
36 struct PCIDevice *dev = (struct PCIDevice * ) card->pci_dev;
37 #endif
39 ULONG intreq;
40 LONG handled = 0;
42 intreq = pci_inl(VIA_REG_SGD_SHADOW, card);
44 //DebugPrintF("INT %lx\n", intreq);
45 if( intreq & 0x33 )
47 unsigned char play_status = pci_inb(VIA_REG_OFFSET_STATUS, card),
48 rec_status = pci_inb(VIA_REG_OFFSET_STATUS + RECORD, card);
50 play_status &= (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED);
52 if (play_status)
54 pci_outb(play_status, VIA_REG_OFFSET_STATUS, card);
56 if (play_status & VIA_REG_STAT_FLAG)
58 card->flip = 0;
59 card->current_buffer = card->playback_buffer1;
61 else if (play_status & VIA_REG_STAT_EOL)
63 card->flip = 1;
64 card->current_buffer = card->playback_buffer2;
67 card->playback_interrupt_enabled = FALSE;
68 Cause( &card->playback_interrupt );
71 rec_status &= (VIA_REG_STAT_EOL|VIA_REG_STAT_FLAG|VIA_REG_STAT_STOPPED);
72 if (rec_status)
74 //DebugPrintF("REC!\n");
75 pci_outb(rec_status, VIA_REG_OFFSET_STATUS + RECORD, card);
77 if (rec_status & VIA_REG_STAT_FLAG)
79 card->flip = 0;
80 card->current_record_buffer = card->record_buffer1;
82 else if (rec_status & VIA_REG_STAT_EOL)
84 card->flip = 1;
85 card->current_record_buffer = card->record_buffer2;
88 card->record_interrupt_enabled = FALSE;
89 Cause( &card->record_interrupt );
92 handled = 1;
95 return handled;
99 /******************************************************************************
100 ** Playback interrupt handler *************************************************
101 ******************************************************************************/
103 #ifdef __amigaos4__
104 void PlaybackInterrupt(struct ExceptionContext *pContext,
105 struct ExecBase *SysBase, struct CardData* card)
106 #else
107 void PlaybackInterrupt(struct CardData* card)
108 #endif
110 struct AHIAudioCtrlDrv* AudioCtrl;
111 struct DriverBase* AHIsubBase;
113 if (card == NULL)
114 return;
116 AudioCtrl = card->audioctrl;
117 AHIsubBase = (struct DriverBase*) card->ahisubbase;
119 if( card->mix_buffer != NULL && card->current_buffer != NULL)
121 BOOL skip_mix;
123 WORD* src;
124 WORD* dst;
125 size_t skip;
126 size_t samples;
127 int i;
129 skip_mix = CallHookPkt( AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0 );
130 CallHookPkt( AudioCtrl->ahiac_PlayerFunc, (Object*) AudioCtrl, NULL );
132 //DebugPrintF("skip_mix = %d\n", skip_mix);
134 if( ! skip_mix )
136 CallHookPkt( AudioCtrl->ahiac_MixerFunc, (Object*) AudioCtrl, card->mix_buffer );
139 /* Now translate and transfer to the DMA buffer */
142 skip = ( AudioCtrl->ahiac_Flags & AHIACF_HIFI ) ? 2 : 1;
143 samples = card->current_bytesize >> 1;
145 src = card->mix_buffer;
146 #if !defined(__amigaos4__) && !AROS_BIG_ENDIAN
147 if(skip == 2)
148 src++;
149 #endif
150 dst = card->current_buffer;
152 i = samples;
154 while( i > 0 )
156 #ifdef __amigaos4__
157 *dst = ( ( *src & 0xff ) << 8 ) | ( ( *src & 0xff00 ) >> 8 );
158 #else
159 *dst = AROS_WORD2LE(*src);
160 #endif
161 src += skip;
162 dst += 1;
164 --i;
167 CacheClearE( card->current_buffer, (ULONG) dst - (ULONG) card->current_buffer, CACRF_ClearD );
168 CallHookPkt( AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0 );
171 card->playback_interrupt_enabled = TRUE;
175 /******************************************************************************
176 ** Record interrupt handler ***************************************************
177 ******************************************************************************/
179 #ifdef __amigaos4__
180 void RecordInterrupt(struct ExceptionContext *pContext,
181 struct ExecBase *SysBase, struct CardData* card)
182 #else
183 void RecordInterrupt(struct CardData* card)
184 #endif
186 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
187 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
189 struct AHIRecordMessage rm =
191 AHIST_S16S,
192 card->current_record_buffer,
193 RECORD_BUFFER_SAMPLES
196 int i = 0, shorts = card->current_record_bytesize / 2;
197 WORD* ptr = card->current_record_buffer;
200 while( i < shorts )
202 #if defined(__AMIGAOS4__) || AROS_BIG_ENDIAN
203 *ptr = ( ( *ptr & 0xff ) << 8 ) | ( ( *ptr & 0xff00 ) >> 8 );
204 #endif
205 ++i;
206 ++ptr;
209 CallHookPkt( AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm );
211 card->record_interrupt_enabled = TRUE;