add placeholder for classic magicmenu pull-down-on-titlebar behaviour when using...
[AROS.git] / workbench / devs / AHI / Drivers / HDAudio / interrupt.c
blob311763e881d082f09347b2313139b429715b0459
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 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
53 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
54 struct PCIDevice *dev = (struct PCIDevice *) card->pci_dev;
56 ULONG intreq, status;
57 LONG handled = 0;
58 UBYTE rirb_status;
59 int i;
61 intreq = pci_inl(HD_INTSTS, card);
63 if (intreq & HD_INTCTL_GLOBAL)
65 if (intreq & 0x3fffffff) // stream interrupt
67 ULONG position;
68 BOOL playback = FALSE;
69 BOOL recording = FALSE;
71 //bug("Stream irq\n");
72 for (i = 0; i < card->nr_of_streams; i++)
74 if (intreq & (1 << card->streams[i].index))
76 // acknowledge stream interrupt
77 pci_outb(0x1C, card->streams[i].sd_reg_offset + HD_SD_OFFSET_STATUS, card);
79 if (i < card->nr_of_input_streams)
81 recording = TRUE;
83 else
85 playback = TRUE;
90 pci_outb(0xFF, HD_INTSTS, card);
92 z++;
93 #ifdef TIME_LIMITED
94 timer++;
96 if (timer > TIME_LIMIT) // stop playback
98 outb_clearbits(HD_SD_CONTROL_STREAM_RUN, card->streams[card->nr_of_input_streams].sd_reg_offset + HD_SD_OFFSET_CONTROL, card);
100 #endif
102 //bug("SIRQ\n");
104 if (playback)
106 // bug("PB\n");
107 position = pci_inl(card->streams[card->nr_of_input_streams].sd_reg_offset + HD_SD_OFFSET_LINKPOS, card);
109 if (card->flip == 1) //position <= card->current_bytesize + 64)
111 if (card->flip == 0)
113 D(bug("[HDAudio] Lost IRQ!\n"));
115 card->flip = 0;
116 card->current_buffer = card->playback_buffer1;
118 else
120 if (card->flip == 1)
122 D(bug("[HDAudio] Lost IRQ!\n"));
125 card->flip = 1;
126 card->current_buffer = card->playback_buffer2;
129 Cause(&card->playback_interrupt);
132 if (recording)
134 position = pci_inl(card->streams[0].sd_reg_offset + HD_SD_OFFSET_LINKPOS, card);
136 if (card->recflip == 1) //position <= card->current_record_bytesize + 64)
138 if (card->recflip == 0)
140 D(bug("[HDAudio] Lost rec IRQ!\n"));
142 card->recflip = 0;
143 card->current_record_buffer = card->record_buffer1;
145 else
147 if (card->recflip == 1)
149 D(bug("[HDAudio] Lost rec IRQ!\n"));
152 card->recflip = 1;
153 card->current_record_buffer = card->record_buffer2;
156 Cause(&card->record_interrupt);
160 if (intreq & HD_INTCTL_CIE)
162 //D(bug("[HDAudio] CIE\n"));
163 pci_outb(0x4, HD_INTSTS + 3, card); // only byte access allowed
165 // if (card->is_playing)
166 // D(bug("[HDAudio] CIE irq! rirb is %x, STATESTS = %x\n", pci_inb(HD_RIRBSTS, card), pci_inw(HD_STATESTS, card)));
168 // check for RIRB status
169 rirb_status = pci_inb(HD_RIRBSTS, card);
170 if (rirb_status & 0x5)
172 if (rirb_status & 0x4) // RIRBOIS
174 // D(bug("[HDAudio] RIRB overrun!\n"));
177 if (rirb_status & 0x1) // RINTFL
179 card->rirb_irq++;
181 /*if (card->rirb_irq > 1)
183 D(bug("[HDAudio] IRQ: rirb_irq = %d\n", card->rirb_irq));
185 //D(bug("[HDAudio] RIRB IRQ!\n"));
188 pci_outb(0x5, HD_RIRBSTS, card);
192 handled = 1;
195 return handled;
199 /******************************************************************************
200 ** Playback interrupt handler *************************************************
201 ******************************************************************************/
203 #ifdef __AMIGAOS4__
204 void
205 PlaybackInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
206 #else
207 void
208 PlaybackInterrupt( struct HDAudioChip* card )
209 #endif
211 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
212 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
214 if (card->mix_buffer != NULL && card->current_buffer != NULL && card->is_playing)
216 BOOL skip_mix;
218 WORD* src;
219 int i;
220 LONG* srclong, *dstlong, left, right;
221 int frames = card->current_frames;
223 skip_mix = CallHookPkt(AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0);
224 CallHookPkt(AudioCtrl->ahiac_PlayerFunc, (Object*) AudioCtrl, NULL);
226 if (! skip_mix)
228 CallHookPkt(AudioCtrl->ahiac_MixerFunc, (Object*) AudioCtrl, card->mix_buffer);
231 /* Now translate and transfer to the DMA buffer */
232 srclong = (LONG*) card->mix_buffer;
233 dstlong = (LONG*) card->current_buffer;
235 i = frames;
237 if (AudioCtrl->ahiac_Flags & AHIACF_HIFI)
239 while(i > 0)
241 *dstlong++ = *srclong++;
242 *dstlong++ = *srclong++;
244 --i;
247 else
249 while(i > 0)
251 *dstlong++ = (*srclong & 0xFF00) >> 16; srclong++; // tbd
252 *dstlong++ = (*srclong & 0xFF000000) >> 16; srclong++;
254 --i;
258 CallHookPkt(AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0);
263 /******************************************************************************
264 ** Record interrupt handler ***************************************************
265 ******************************************************************************/
267 #ifdef __AMIGAOS4__
268 void
269 RecordInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
270 #else
271 void
272 RecordInterrupt( struct HDAudioChip* card )
273 #endif
275 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
276 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
277 int i = 0;
278 int frames = card->current_record_bytesize / 2;
280 struct AHIRecordMessage rm =
282 AHIST_S16S,
283 card->current_record_buffer,
284 RECORD_BUFFER_SAMPLES
287 WORD *src = card->current_record_buffer;
288 WORD* dst = card->current_record_buffer;
290 #ifdef __AMIGAOS4__
291 while( i < frames )
293 *dst = ( ( *src & 0x00FF ) << 8 ) | ( ( *src & 0xFF00 ) >> 8 );
295 ++i;
296 ++src;
297 ++dst;
299 #else
300 /*while( i < frames )
302 *dst = (*src);
304 ++i;
305 ++src;
306 ++dst;
308 #endif
310 CallHookPkt(AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm);