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.
19 #include <proto/expansion.h>
20 #include <libraries/ahi_sub.h>
21 #include <proto/exec.h>
25 #include "interrupt.h"
27 #include "pci_wrapper.h"
29 #include <aros/debug.h>
32 #define min(a,b) ((a)<(b)?(a):(b))
35 ULONG timer
= 0; // for demo/test
37 #define TIME_LIMIT 150 // 150 irq's
39 /******************************************************************************
40 ** Hardware interrupt handler *************************************************
41 ******************************************************************************/
46 CardInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
49 CardInterrupt( struct HDAudioChip
* card
)
57 intreq
= pci_inl(HD_INTSTS
, card
);
59 if (intreq
& HD_INTCTL_GLOBAL
)
61 if (intreq
& 0x3fffffff) // stream interrupt
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
)
86 pci_outb(0xFF, HD_INTSTS
, card
);
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
);
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)
109 D(bug("[HDAudio] Lost IRQ!\n"));
112 card
->current_buffer
= card
->playback_buffer1
;
118 D(bug("[HDAudio] Lost IRQ!\n"));
122 card
->current_buffer
= card
->playback_buffer2
;
125 Cause(&card
->playback_interrupt
);
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"));
139 card
->current_record_buffer
= card
->record_buffer1
;
143 if (card
->recflip
== 1)
145 D(bug("[HDAudio] Lost rec IRQ!\n"));
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
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
);
195 /******************************************************************************
196 ** Playback interrupt handler *************************************************
197 ******************************************************************************/
201 PlaybackInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
204 PlaybackInterrupt( struct HDAudioChip
* card
)
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
)
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
);
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
;
232 if (AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
236 *dstlong
++ = *srclong
++;
237 *dstlong
++ = *srclong
++;
246 *dstlong
++ = (*srclong
& 0xFF00) >> 16; srclong
++; // tbd
247 *dstlong
++ = (*srclong
& 0xFF000000) >> 16; srclong
++;
253 CallHookPkt(AudioCtrl
->ahiac_PostTimerFunc
, (Object
*) AudioCtrl
, 0);
258 /******************************************************************************
259 ** Record interrupt handler ***************************************************
260 ******************************************************************************/
264 RecordInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
267 RecordInterrupt( struct HDAudioChip
* card
)
270 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
271 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
274 int frames
= card
->current_record_bytesize
/ 2;
275 WORD
*src
= card
->current_record_buffer
;
276 WORD
* dst
= card
->current_record_buffer
;
279 struct AHIRecordMessage rm
=
282 card
->current_record_buffer
,
283 RECORD_BUFFER_SAMPLES
289 *dst
= ( ( *src
& 0x00FF ) << 8 ) | ( ( *src
& 0xFF00 ) >> 8 );
296 /*while( i < frames )
306 CallHookPkt(AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);