3 #include <proto/expansion.h>
4 #include <libraries/ahi_sub.h>
5 #include <proto/exec.h>
11 #include "pci_wrapper.h"
13 #include <aros/debug.h>
16 #define min(a,b) ((a)<(b)?(a):(b))
19 ULONG timer
= 0; // for demo/test
21 #define TIME_LIMIT 150 // 150 irq's
23 /******************************************************************************
24 ** Hardware interrupt handler *************************************************
25 ******************************************************************************/
30 CardInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
33 CardInterrupt( struct HDAudioChip
* card
)
36 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
37 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
38 struct PCIDevice
*dev
= (struct PCIDevice
*) card
->pci_dev
;
45 intreq
= pci_inl(HD_INTSTS
, card
);
47 if (intreq
& HD_INTCTL_GLOBAL
)
49 if (intreq
& 0x3fffffff) // stream interrupt
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
)
74 pci_outb(0xFF, HD_INTSTS
, card
);
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
);
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)
100 card
->current_buffer
= card
->playback_buffer1
;
110 card
->current_buffer
= card
->playback_buffer2
;
113 Cause(&card
->playback_interrupt
);
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");
127 card
->current_record_buffer
= card
->record_buffer1
;
131 if (card
->recflip
== 1)
133 bug("Lost rec IRQ!\n");
137 card
->current_record_buffer
= card
->record_buffer2
;
140 Cause(&card
->record_interrupt
);
144 if (intreq
& HD_INTCTL_CIE
)
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
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
);
183 /******************************************************************************
184 ** Playback interrupt handler *************************************************
185 ******************************************************************************/
189 PlaybackInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
192 PlaybackInterrupt( struct HDAudioChip
* card
)
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
)
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
);
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
;
221 if (AudioCtrl
->ahiac_Flags
& AHIACF_HIFI
)
225 *dstlong
++ = *srclong
++;
226 *dstlong
++ = *srclong
++;
235 *dstlong
++ = (*srclong
& 0xFF00) >> 16; srclong
++; // tbd
236 *dstlong
++ = (*srclong
& 0xFF000000) >> 16; srclong
++;
242 CallHookPkt(AudioCtrl
->ahiac_PostTimerFunc
, (Object
*) AudioCtrl
, 0);
247 /******************************************************************************
248 ** Record interrupt handler ***************************************************
249 ******************************************************************************/
253 RecordInterrupt( struct ExceptionContext
*pContext
, struct ExecBase
*SysBase
, struct HDAudioChip
* card
)
256 RecordInterrupt( struct HDAudioChip
* card
)
259 struct AHIAudioCtrlDrv
* AudioCtrl
= card
->audioctrl
;
260 struct DriverBase
* AHIsubBase
= (struct DriverBase
*) card
->ahisubbase
;
262 int frames
= card
->current_record_bytesize
/ 2;
264 struct AHIRecordMessage rm
=
267 card
->current_record_buffer
,
268 RECORD_BUFFER_SAMPLES
271 WORD
*src
= card
->current_record_buffer
;
272 WORD
* dst
= card
->current_record_buffer
;
277 *dst
= ( ( *src
& 0x00FF ) << 8 ) | ( ( *src
& 0xFF00 ) >> 8 );
284 /*while( i < frames )
294 CallHookPkt(AudioCtrl
->ahiac_SamplerFunc
, (Object
*) AudioCtrl
, &rm
);