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
)
52 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
53 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
54 struct PCIDevice
*dev
= (struct PCIDevice
*) card
->pci_dev
;
61 intreq
= pci_inl(HD_INTSTS
, card
);
63 if (intreq
& HD_INTCTL_GLOBAL
)
65 if (intreq
& 0x3fffffff) // stream interrupt
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
)
90 pci_outb(0xFF, HD_INTSTS
, card
);
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
);
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)
113 D(bug("[HDAudio] Lost IRQ!\n"));
116 card
->current_buffer
= card
->playback_buffer1
;
122 D(bug("[HDAudio] Lost IRQ!\n"));
126 card
->current_buffer
= card
->playback_buffer2
;
129 Cause(&card
->playback_interrupt
);
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"));
143 card
->current_record_buffer
= card
->record_buffer1
;
147 if (card
->recflip
== 1)
149 D(bug("[HDAudio] Lost rec IRQ!\n"));
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
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
);
199 /******************************************************************************
200 ** Playback interrupt handler *************************************************
201 ******************************************************************************/
205 PlaybackInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
208 PlaybackInterrupt( struct HDAudioChip
* card
)
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
)
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
);
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
;
237 if (AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
241 *dstlong
++ = *srclong
++;
242 *dstlong
++ = *srclong
++;
251 *dstlong
++ = (*srclong
& 0xFF00) >> 16; srclong
++; // tbd
252 *dstlong
++ = (*srclong
& 0xFF000000) >> 16; srclong
++;
258 CallHookPkt(AudioCtrl
->ahiac_PostTimerFunc
, (Object
*) AudioCtrl
, 0);
263 /******************************************************************************
264 ** Record interrupt handler ***************************************************
265 ******************************************************************************/
269 RecordInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
272 RecordInterrupt( struct HDAudioChip
* card
)
275 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
276 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
278 int frames
= card
->current_record_bytesize
/ 2;
280 struct AHIRecordMessage rm
=
283 card
->current_record_buffer
,
284 RECORD_BUFFER_SAMPLES
287 WORD
*src
= card
->current_record_buffer
;
288 WORD
* dst
= card
->current_record_buffer
;
293 *dst
= ( ( *src
& 0x00FF ) << 8 ) | ( ( *src
& 0xFF00 ) >> 8 );
300 /*while( i < frames )
310 CallHookPkt(AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);