revert between 56095 -> 55830 in arch
[AROS.git] / workbench / devs / AHI / Drivers / HDAudio / interrupt.c
blob0af3a8863bfefde38df6237927e62ec7a60761f2
1 /*
2 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
3 http://www.aros.org/license.html
5 Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
6 ANY KIND, either express or implied. See the License for the specific language governing rights and
7 limitations under the License.
9 (C) Copyright xxxx-2009 Davy Wentzler.
10 (C) Copyright 2009-2010 Stephen Jones.
12 The Initial Developer of the Original Code is Davy Wentzler.
14 All Rights Reserved.
17 #include <config.h>
19 #include <proto/expansion.h>
20 #include <libraries/ahi_sub.h>
21 #include <proto/exec.h>
22 #include <stddef.h>
23 #include "library.h"
24 #include "regs.h"
25 #include "interrupt.h"
26 #include "misc.h"
27 #include "pci_wrapper.h"
28 #ifdef __AROS__
29 #include <aros/debug.h>
30 #endif
32 #define min(a,b) ((a)<(b)?(a):(b))
34 int z = 0;
35 ULONG timer = 0; // for demo/test
37 #define TIME_LIMIT 150 // 150 irq's
39 /******************************************************************************
40 ** Hardware interrupt handler *************************************************
41 ******************************************************************************/
44 #ifdef __AMIGAOS4__
45 ULONG
46 CardInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
47 #else
48 ULONG
49 CardInterrupt( struct HDAudioChip* card )
50 #endif
52 ULONG intreq;
53 LONG handled = 0;
54 UBYTE rirb_status;
55 int i;
57 intreq = pci_inl(HD_INTSTS, card);
59 if (intreq & HD_INTCTL_GLOBAL)
61 if (intreq & 0x3fffffff) // stream interrupt
63 // ULONG position;
64 BOOL playback = FALSE;
65 BOOL recording = FALSE;
67 //bug("Stream irq\n");
68 for (i = 0; i < card->nr_of_streams; i++)
70 if (intreq & (1 << card->streams[i].index))
72 // acknowledge stream interrupt
73 pci_outb(0x1C, card->streams[i].sd_reg_offset + HD_SD_OFFSET_STATUS, card);
75 if (i < card->nr_of_input_streams)
77 recording = TRUE;
79 else
81 playback = TRUE;
86 pci_outb(0xFF, HD_INTSTS, card);
88 z++;
89 #ifdef TIME_LIMITED
90 timer++;
92 if (timer > TIME_LIMIT) // stop playback
94 outb_clearbits(HD_SD_CONTROL_STREAM_RUN, card->streams[card->nr_of_input_streams].sd_reg_offset + HD_SD_OFFSET_CONTROL, card);
96 #endif
98 //bug("SIRQ\n");
100 if (playback)
102 // bug("PB\n");
103 // position = pci_inl(card->streams[card->nr_of_input_streams].sd_reg_offset + HD_SD_OFFSET_LINKPOS, card);
105 if (card->flip == 1) //position <= card->current_bytesize + 64)
107 if (card->flip == 0)
109 D(bug("[HDAudio] Lost IRQ!\n"));
111 card->flip = 0;
112 card->current_buffer = card->playback_buffer1;
114 else
116 if (card->flip == 1)
118 D(bug("[HDAudio] Lost IRQ!\n"));
121 card->flip = 1;
122 card->current_buffer = card->playback_buffer2;
125 Cause(&card->playback_interrupt);
128 if (recording)
130 // position = pci_inl(card->streams[0].sd_reg_offset + HD_SD_OFFSET_LINKPOS, card);
132 if (card->recflip == 1) //position <= card->current_record_bytesize + 64)
134 if (card->recflip == 0)
136 D(bug("[HDAudio] Lost rec IRQ!\n"));
138 card->recflip = 0;
139 card->current_record_buffer = card->record_buffer1;
141 else
143 if (card->recflip == 1)
145 D(bug("[HDAudio] Lost rec IRQ!\n"));
148 card->recflip = 1;
149 card->current_record_buffer = card->record_buffer2;
152 Cause(&card->record_interrupt);
156 if (intreq & HD_INTCTL_CIE)
158 //D(bug("[HDAudio] CIE\n"));
159 pci_outb(0x4, HD_INTSTS + 3, card); // only byte access allowed
161 // if (card->is_playing)
162 // D(bug("[HDAudio] CIE irq! rirb is %x, STATESTS = %x\n", pci_inb(HD_RIRBSTS, card), pci_inw(HD_STATESTS, card)));
164 // check for RIRB status
165 rirb_status = pci_inb(HD_RIRBSTS, card);
166 if (rirb_status & 0x5)
168 if (rirb_status & 0x4) // RIRBOIS
170 // D(bug("[HDAudio] RIRB overrun!\n"));
173 if (rirb_status & 0x1) // RINTFL
175 card->rirb_irq++;
177 /*if (card->rirb_irq > 1)
179 D(bug("[HDAudio] IRQ: rirb_irq = %d\n", card->rirb_irq));
181 //D(bug("[HDAudio] RIRB IRQ!\n"));
184 pci_outb(0x5, HD_RIRBSTS, card);
188 handled = 1;
191 return handled;
195 /******************************************************************************
196 ** Playback interrupt handler *************************************************
197 ******************************************************************************/
199 #ifdef __AMIGAOS4__
200 void
201 PlaybackInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
202 #else
203 void
204 PlaybackInterrupt( struct HDAudioChip* card )
205 #endif
207 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
208 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
210 if (card->mix_buffer != NULL && card->current_buffer != NULL && card->is_playing)
212 BOOL skip_mix;
214 int i;
215 LONG* srclong, *dstlong;
216 int frames = card->current_frames;
218 skip_mix = CallHookPkt(AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0);
219 CallHookPkt(AudioCtrl->ahiac_PlayerFunc, (Object*) AudioCtrl, NULL);
221 if (! skip_mix)
223 CallHookPkt(AudioCtrl->ahiac_MixerFunc, (Object*) AudioCtrl, card->mix_buffer);
226 /* Now translate and transfer to the DMA buffer */
227 srclong = (LONG*) card->mix_buffer;
228 dstlong = (LONG*) card->current_buffer;
230 i = frames;
232 if (AudioCtrl->ahiac_Flags & AHIACF_HIFI)
234 while(i > 0)
236 *dstlong++ = *srclong++;
237 *dstlong++ = *srclong++;
239 --i;
242 else
244 while(i > 0)
246 *dstlong++ = (*srclong & 0xFF00) >> 16; srclong++; // tbd
247 *dstlong++ = (*srclong & 0xFF000000) >> 16; srclong++;
249 --i;
253 CallHookPkt(AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0);
258 /******************************************************************************
259 ** Record interrupt handler ***************************************************
260 ******************************************************************************/
262 #ifdef __AMIGAOS4__
263 void
264 RecordInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
265 #else
266 void
267 RecordInterrupt( struct HDAudioChip* card )
268 #endif
270 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
271 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
272 #ifdef __AMIGAOS4__
273 int i = 0;
274 int frames = card->current_record_bytesize / 2;
275 WORD *src = card->current_record_buffer;
276 WORD* dst = card->current_record_buffer;
277 #endif
279 struct AHIRecordMessage rm =
281 AHIST_S16S,
282 card->current_record_buffer,
283 RECORD_BUFFER_SAMPLES
286 #ifdef __AMIGAOS4__
287 while( i < frames )
289 *dst = ( ( *src & 0x00FF ) << 8 ) | ( ( *src & 0xFF00 ) >> 8 );
291 ++i;
292 ++src;
293 ++dst;
295 #else
296 /*while( i < frames )
298 *dst = (*src);
300 ++i;
301 ++src;
302 ++dst;
304 #endif
306 CallHookPkt(AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm);