- Set a default PCM volume so that something can be heard when driver is
[AROS.git] / workbench / devs / AHI / Drivers / HDAudio / interrupt.c
bloba2e9446afb892c005c1cc211126808778bd7cef2
1 #include <config.h>
3 #include <proto/expansion.h>
4 #include <libraries/ahi_sub.h>
5 #include <proto/exec.h>
6 #include <stddef.h>
7 #include "library.h"
8 #include "regs.h"
9 #include "interrupt.h"
10 #include "misc.h"
11 #include "pci_wrapper.h"
12 #ifdef __AROS__
13 #include <aros/debug.h>
14 #endif
16 #define min(a,b) ((a)<(b)?(a):(b))
18 int z = 0;
19 ULONG timer = 0; // for demo/test
21 #define TIME_LIMIT 150 // 150 irq's
23 /******************************************************************************
24 ** Hardware interrupt handler *************************************************
25 ******************************************************************************/
28 #ifdef __AMIGAOS4__
29 ULONG
30 CardInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
31 #else
32 ULONG
33 CardInterrupt( struct HDAudioChip* card )
34 #endif
36 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
37 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
38 struct PCIDevice *dev = (struct PCIDevice *) card->pci_dev;
40 ULONG intreq, status;
41 LONG handled = 0;
42 UBYTE rirb_status;
43 int i;
45 intreq = pci_inl(HD_INTSTS, card);
47 if (intreq & HD_INTCTL_GLOBAL)
49 if (intreq & 0x3fffffff) // stream interrupt
51 ULONG position;
52 BOOL playback = FALSE;
53 BOOL recording = FALSE;
55 //bug("Stream irq\n");
56 for (i = 0; i < card->nr_of_streams; i++)
58 if (intreq & (1 << card->streams[i].index))
60 // acknowledge stream interrupt
61 pci_outb(0x1C, card->streams[i].sd_reg_offset + HD_SD_OFFSET_STATUS, card);
63 if (i < card->nr_of_input_streams)
65 recording = TRUE;
67 else
69 playback = TRUE;
74 pci_outb(0xFF, HD_INTSTS, card);
76 z++;
77 #ifdef TIME_LIMITED
78 timer++;
80 if (timer > TIME_LIMIT) // stop playback
82 outb_clearbits(HD_SD_CONTROL_STREAM_RUN, card->streams[card->nr_of_input_streams].sd_reg_offset + HD_SD_OFFSET_CONTROL, card);
84 #endif
86 //bug("SIRQ\n");
88 if (playback)
90 // bug("PB\n");
91 position = pci_inl(card->streams[card->nr_of_input_streams].sd_reg_offset + HD_SD_OFFSET_LINKPOS, card);
93 if (card->flip == 1) //position <= card->current_bytesize + 64)
95 if (card->flip == 0)
97 bug("Lost IRQ!\n");
99 card->flip = 0;
100 card->current_buffer = card->playback_buffer1;
102 else
104 if (card->flip == 1)
106 bug("Lost IRQ!\n");
109 card->flip = 1;
110 card->current_buffer = card->playback_buffer2;
113 Cause(&card->playback_interrupt);
116 if (recording)
118 position = pci_inl(card->streams[0].sd_reg_offset + HD_SD_OFFSET_LINKPOS, card);
120 if (card->recflip == 1) //position <= card->current_record_bytesize + 64)
122 if (card->recflip == 0)
124 bug("Lost rec IRQ!\n");
126 card->recflip = 0;
127 card->current_record_buffer = card->record_buffer1;
129 else
131 if (card->recflip == 1)
133 bug("Lost rec IRQ!\n");
136 card->recflip = 1;
137 card->current_record_buffer = card->record_buffer2;
140 Cause(&card->record_interrupt);
144 if (intreq & HD_INTCTL_CIE)
146 //bug("CIE\n");
147 pci_outb(0x4, HD_INTSTS + 3, card); // only byte access allowed
149 // if (card->is_playing)
150 // bug("CIE irq! rirb is %x, STATESTS = %x\n", pci_inb(HD_RIRBSTS, card), pci_inw(HD_STATESTS, card));
152 // check for RIRB status
153 rirb_status = pci_inb(HD_RIRBSTS, card);
154 if (rirb_status & 0x5)
156 if (rirb_status & 0x4) // RIRBOIS
158 // bug("RIRB overrun!\n");
161 if (rirb_status & 0x1) // RINTFL
163 card->rirb_irq++;
165 /*if (card->rirb_irq > 1)
167 bug("IRQ: rirb_irq = %d\n", card->rirb_irq);
169 //bug("RIRB IRQ!\n");
172 pci_outb(0x5, HD_RIRBSTS, card);
176 handled = 1;
179 return handled;
183 /******************************************************************************
184 ** Playback interrupt handler *************************************************
185 ******************************************************************************/
187 #ifdef __AMIGAOS4__
188 void
189 PlaybackInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
190 #else
191 void
192 PlaybackInterrupt( struct HDAudioChip* card )
193 #endif
195 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
196 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
198 if (card->mix_buffer != NULL && card->current_buffer != NULL && card->is_playing)
200 BOOL skip_mix;
202 WORD* src;
203 int i;
204 LONG* srclong, *dstlong, left, right;
205 int frames = card->current_frames;
207 skip_mix = CallHookPkt(AudioCtrl->ahiac_PreTimerFunc, (Object*) AudioCtrl, 0);
208 CallHookPkt(AudioCtrl->ahiac_PlayerFunc, (Object*) AudioCtrl, NULL);
210 if (! skip_mix)
212 CallHookPkt(AudioCtrl->ahiac_MixerFunc, (Object*) AudioCtrl, card->mix_buffer);
215 /* Now translate and transfer to the DMA buffer */
216 srclong = (LONG*) card->mix_buffer;
217 dstlong = (LONG*) card->current_buffer;
219 i = frames;
221 if (AudioCtrl->ahiac_Flags & AHIACF_HIFI)
223 while(i > 0)
225 *dstlong++ = *srclong++;
226 *dstlong++ = *srclong++;
228 --i;
231 else
233 while(i > 0)
235 *dstlong++ = (*srclong & 0xFF00) >> 16; srclong++; // tbd
236 *dstlong++ = (*srclong & 0xFF000000) >> 16; srclong++;
238 --i;
242 CallHookPkt(AudioCtrl->ahiac_PostTimerFunc, (Object*) AudioCtrl, 0);
247 /******************************************************************************
248 ** Record interrupt handler ***************************************************
249 ******************************************************************************/
251 #ifdef __AMIGAOS4__
252 void
253 RecordInterrupt( struct ExceptionContext *pContext, struct ExecBase *SysBase, struct HDAudioChip* card )
254 #else
255 void
256 RecordInterrupt( struct HDAudioChip* card )
257 #endif
259 struct AHIAudioCtrlDrv* AudioCtrl = card->audioctrl;
260 struct DriverBase* AHIsubBase = (struct DriverBase*) card->ahisubbase;
261 int i = 0;
262 int frames = card->current_record_bytesize / 2;
264 struct AHIRecordMessage rm =
266 AHIST_S16S,
267 card->current_record_buffer,
268 RECORD_BUFFER_SAMPLES
271 WORD *src = card->current_record_buffer;
272 WORD* dst = card->current_record_buffer;
274 #ifdef __AMIGAOS4__
275 while( i < frames )
277 *dst = ( ( *src & 0x00FF ) << 8 ) | ( ( *src & 0xFF00 ) >> 8 );
279 ++i;
280 ++src;
281 ++dst;
283 #else
284 /*while( i < frames )
286 *dst = (*src);
288 ++i;
289 ++src;
290 ++dst;
292 #endif
294 CallHookPkt(AudioCtrl->ahiac_SamplerFunc, (Object*) AudioCtrl, &rm);