Temporarily disabled interrupt handling: this fixes a strange symptom that happen
on stippi's and my laptop when connected to a power outlet (no interrupts arrive anymore but timer interrupts). Need to investigate this a bit more... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16553 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,101 +1,107 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2002-2004, Thomas Kurschel
|
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Copyright 2002-2004, Thomas Kurschel
|
||||||
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Interrupt handling. Currently, none of this is used
|
||||||
Part of Radeon kernel driver
|
* as I haven't got the HW spec.
|
||||||
|
*/
|
||||||
Interrupt handling. Currently, none of this is used
|
|
||||||
as I haven't got the HW spec.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "radeon_driver.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "mmio.h"
|
#include "mmio.h"
|
||||||
|
#include "radeon_driver.h"
|
||||||
#include "rbbm_regs.h"
|
#include "rbbm_regs.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
// disable all interrupts
|
|
||||||
static void
|
/** Disable all interrupts */
|
||||||
Radeon_DisableIRQ( device_info *di )
|
|
||||||
|
static void
|
||||||
|
Radeon_DisableIRQ(device_info *di)
|
||||||
{
|
{
|
||||||
OUTREG( di->regs, RADEON_GEN_INT_CNTL, 0 );
|
OUTREG(di->regs, RADEON_GEN_INT_CNTL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// interrupt worker routine
|
/** Interrupt worker routine
|
||||||
// handles standard interrupts, i.e. VBI and DMA
|
* handles standard interrupts, i.e. VBI and DMA
|
||||||
static uint32
|
*/
|
||||||
Radeon_ThreadInterruptWork( vuint8 *regs, device_info *di, uint32 int_status )
|
|
||||||
|
static uint32
|
||||||
|
Radeon_ThreadInterruptWork(vuint8 *regs, device_info *di, uint32 int_status)
|
||||||
{
|
{
|
||||||
shared_info *si = di->si;
|
shared_info *si = di->si;
|
||||||
uint32 handled = B_HANDLED_INTERRUPT;
|
uint32 handled = B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
if( (int_status & RADEON_CRTC_VBLANK_STAT) != 0 &&
|
if ((int_status & RADEON_CRTC_VBLANK_STAT) != 0
|
||||||
si->crtc[0].vblank >= 0 )
|
&& si->crtc[0].vblank >= 0) {
|
||||||
{
|
|
||||||
int32 blocked;
|
int32 blocked;
|
||||||
|
|
||||||
++di->vbi_count[0];
|
++di->vbi_count[0];
|
||||||
|
|
||||||
if( (get_sem_count( si->crtc[0].vblank, &blocked ) == B_OK) && (blocked < 0) ) {
|
if (get_sem_count(si->crtc[0].vblank, &blocked ) == B_OK && blocked < 0) {
|
||||||
release_sem_etc( si->crtc[0].vblank, -blocked, B_DO_NOT_RESCHEDULE );
|
release_sem_etc(si->crtc[0].vblank, -blocked, B_DO_NOT_RESCHEDULE);
|
||||||
handled = B_INVOKE_SCHEDULER;
|
handled = B_INVOKE_SCHEDULER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (int_status & RADEON_CRTC2_VBLANK_STAT) != 0 &&
|
if ((int_status & RADEON_CRTC2_VBLANK_STAT) != 0
|
||||||
si->crtc[1].vblank >= 0 )
|
&& si->crtc[1].vblank >= 0) {
|
||||||
{
|
|
||||||
int32 blocked;
|
int32 blocked;
|
||||||
|
|
||||||
++di->vbi_count[1];
|
++di->vbi_count[1];
|
||||||
|
|
||||||
if( (get_sem_count( si->crtc[1].vblank, &blocked ) == B_OK) && (blocked < 0) ) {
|
if (get_sem_count(si->crtc[1].vblank, &blocked) == B_OK && blocked < 0) {
|
||||||
release_sem_etc( si->crtc[1].vblank, -blocked, B_DO_NOT_RESCHEDULE );
|
release_sem_etc(si->crtc[1].vblank, -blocked, B_DO_NOT_RESCHEDULE);
|
||||||
handled = B_INVOKE_SCHEDULER;
|
handled = B_INVOKE_SCHEDULER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( (int_status & RADEON_VIDDMA_STAT ) != 0 ) {
|
if ((int_status & RADEON_VIDDMA_STAT) != 0) {
|
||||||
release_sem_etc( di->dma_sem, 1, B_DO_NOT_RESCHEDULE );
|
release_sem_etc(di->dma_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||||
handled = B_INVOKE_SCHEDULER;
|
handled = B_INVOKE_SCHEDULER;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Capture interrupt handler
|
#if 0
|
||||||
|
/** Capture interrupt handler */
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
Radeon_HandleCaptureInterrupt( vuint8 *regs, device_info *di, uint32 cap_status )
|
Radeon_HandleCaptureInterrupt(vuint8 *regs, device_info *di, uint32 cap_status)
|
||||||
{
|
{
|
||||||
int32 blocked;
|
int32 blocked;
|
||||||
uint32 handled = B_HANDLED_INTERRUPT;
|
uint32 handled = B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
cpu_status prev_irq_state = disable_interrupts();
|
cpu_status prev_irq_state = disable_interrupts();
|
||||||
acquire_spinlock( &di->cap_spinlock );
|
acquire_spinlock(&di->cap_spinlock);
|
||||||
|
|
||||||
++di->cap_counter;
|
++di->cap_counter;
|
||||||
di->cap_int_status = cap_status;
|
di->cap_int_status = cap_status;
|
||||||
di->cap_timestamp = system_time();
|
di->cap_timestamp = system_time();
|
||||||
|
|
||||||
release_spinlock( &di->cap_spinlock );
|
release_spinlock(&di->cap_spinlock);
|
||||||
restore_interrupts( prev_irq_state );
|
restore_interrupts(prev_irq_state);
|
||||||
|
|
||||||
// don't release if semaphore count is positive, i.e. notifications are piling up
|
// don't release if semaphore count is positive, i.e. notifications are piling up
|
||||||
if( (get_sem_count( di->cap_sem, &blocked ) == B_OK) && (blocked <= 0) ) {
|
if (get_sem_count(di->cap_sem, &blocked) == B_OK && blocked <= 0) {
|
||||||
release_sem_etc( di->cap_sem, 1, B_DO_NOT_RESCHEDULE );
|
release_sem_etc(di->cap_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||||
handled = B_INVOKE_SCHEDULER;
|
handled = B_INVOKE_SCHEDULER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// acknowledge IRQ
|
// acknowledge IRQ
|
||||||
OUTREG( regs, RADEON_CAP_INT_STATUS, cap_status );
|
OUTREG(regs, RADEON_CAP_INT_STATUS, cap_status);
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main interrupt handler
|
|
||||||
|
/** Main interrupt handler */
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
Radeon_Interrupt(void *data)
|
Radeon_Interrupt(void *data)
|
||||||
{
|
{
|
||||||
@@ -105,43 +111,46 @@ Radeon_Interrupt(void *data)
|
|||||||
int32 full_int_status, int_status;
|
int32 full_int_status, int_status;
|
||||||
|
|
||||||
// read possible IRQ reasons, ignoring any masked IRQs
|
// read possible IRQ reasons, ignoring any masked IRQs
|
||||||
full_int_status = INREG( regs, RADEON_GEN_INT_STATUS );
|
full_int_status = INREG(regs, RADEON_GEN_INT_STATUS);
|
||||||
int_status = full_int_status & INREG( regs, RADEON_GEN_INT_CNTL );
|
int_status = full_int_status & INREG(regs, RADEON_GEN_INT_CNTL);
|
||||||
|
|
||||||
if( int_status != 0 ) {
|
if (int_status != 0) {
|
||||||
++di->interrupt_count;
|
++di->interrupt_count;
|
||||||
|
|
||||||
handled = Radeon_ThreadInterruptWork( regs, di, int_status );
|
handled = Radeon_ThreadInterruptWork(regs, di, int_status);
|
||||||
|
|
||||||
// acknowledge IRQ
|
// acknowledge IRQ
|
||||||
OUTREG( regs, RADEON_GEN_INT_STATUS, int_status );
|
OUTREG(regs, RADEON_GEN_INT_STATUS, int_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// capture interrupt have no mask in GEN_INT_CNTL register;
|
// capture interrupt have no mask in GEN_INT_CNTL register;
|
||||||
// probably, ATI wanted to make capture interrupt control independant of main control
|
// probably, ATI wanted to make capture interrupt control independant of main control
|
||||||
if( (full_int_status & RADEON_CAP0_INT_ACTIVE) != 0 ) {
|
if ((full_int_status & RADEON_CAP0_INT_ACTIVE) != 0) {
|
||||||
int32 cap_status;
|
int32 cap_status;
|
||||||
|
|
||||||
// same as before: only regard enabled IRQ reasons
|
|
||||||
cap_status = INREG( regs, RADEON_CAP_INT_STATUS );
|
|
||||||
cap_status &= INREG( regs, RADEON_CAP_INT_CNTL );
|
|
||||||
|
|
||||||
if( cap_status != 0 ) {
|
// same as before: only regard enabled IRQ reasons
|
||||||
|
cap_status = INREG(regs, RADEON_CAP_INT_STATUS);
|
||||||
|
cap_status &= INREG(regs, RADEON_CAP_INT_CNTL);
|
||||||
|
|
||||||
|
if (cap_status != 0) {
|
||||||
int32 cap_handled;
|
int32 cap_handled;
|
||||||
|
|
||||||
cap_handled = Radeon_HandleCaptureInterrupt( regs, di, cap_status );
|
cap_handled = Radeon_HandleCaptureInterrupt(regs, di, cap_status);
|
||||||
|
|
||||||
if( cap_handled == B_INVOKE_SCHEDULER || handled == B_INVOKE_SCHEDULER )
|
if (cap_handled == B_INVOKE_SCHEDULER || handled == B_INVOKE_SCHEDULER)
|
||||||
handled = B_INVOKE_SCHEDULER;
|
handled = B_INVOKE_SCHEDULER;
|
||||||
else if( cap_handled == B_HANDLED_INTERRUPT )
|
else if (cap_handled == B_HANDLED_INTERRUPT)
|
||||||
handled = B_HANDLED_INTERRUPT;
|
handled = B_HANDLED_INTERRUPT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int32 timer_interrupt_func( timer *te )
|
|
||||||
|
static int32
|
||||||
|
timer_interrupt_func(timer *te)
|
||||||
{
|
{
|
||||||
bigtime_t now = system_time();
|
bigtime_t now = system_time();
|
||||||
/* get the pointer to the device we're handling this time */
|
/* get the pointer to the device we're handling this time */
|
||||||
@@ -152,30 +161,35 @@ static int32 timer_interrupt_func( timer *te )
|
|||||||
int32 result = B_HANDLED_INTERRUPT;
|
int32 result = B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
/* are we suppoesed to handle interrupts still? */
|
/* are we suppoesed to handle interrupts still? */
|
||||||
if( !di->shutdown_virtual_irq ) {
|
if (!di->shutdown_virtual_irq) {
|
||||||
/* reschedule with same period by default */
|
/* reschedule with same period by default */
|
||||||
bigtime_t when = si->refresh_period;
|
bigtime_t when = si->refresh_period;
|
||||||
timer *to;
|
timer *to;
|
||||||
|
|
||||||
/* if interrupts are "enabled", do our thing */
|
/* if interrupts are "enabled", do our thing */
|
||||||
if( si->enable_virtual_irq ) {
|
if (si->enable_virtual_irq) {
|
||||||
/* insert code to sync to interrupts here */
|
/* insert code to sync to interrupts here */
|
||||||
if (!vbl_status) {
|
if (!vbl_status) {
|
||||||
when -= si->blank_period - 4;
|
when -= si->blank_period - 4;
|
||||||
}
|
}
|
||||||
/* do the things we do when we notice a vertical retrace */
|
/* do the things we do when we notice a vertical retrace */
|
||||||
result = Radeon_ThreadInterruptWork( regs, di,
|
result = Radeon_ThreadInterruptWork(regs, di,
|
||||||
RADEON_CRTC_VBLANK_STAT |
|
RADEON_CRTC_VBLANK_STAT
|
||||||
(di->num_crtc > 1 ? RADEON_CRTC2_VBLANK_STAT : 0 ));
|
| (di->num_crtc > 1 ? RADEON_CRTC2_VBLANK_STAT : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pick the "other" timer */
|
/* pick the "other" timer */
|
||||||
to = (timer *)&(di->ti_a);
|
to = (timer *)&di->ti_a;
|
||||||
if (to == te) to = (timer *)&(di->ti_b);
|
if (to == te)
|
||||||
|
to = (timer *)&di->ti_b;
|
||||||
|
|
||||||
/* our guess as to when we should be back */
|
/* our guess as to when we should be back */
|
||||||
((timer_info *)to)->when_target = now + when;
|
((timer_info *)to)->when_target = now + when;
|
||||||
|
|
||||||
/* reschedule the interrupt */
|
/* reschedule the interrupt */
|
||||||
add_timer(to, timer_interrupt_func, ((timer_info *)to)->when_target, B_ONE_SHOT_ABSOLUTE_TIMER);
|
add_timer(to, timer_interrupt_func, ((timer_info *)to)->when_target,
|
||||||
|
B_ONE_SHOT_ABSOLUTE_TIMER);
|
||||||
|
|
||||||
/* remember the currently active timer */
|
/* remember the currently active timer */
|
||||||
di->current_timer = (timer_info *)to;
|
di->current_timer = (timer_info *)to;
|
||||||
}
|
}
|
||||||
@@ -184,142 +198,150 @@ static int32 timer_interrupt_func( timer *te )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// setup IRQ handlers.
|
/** Setup IRQ handlers.
|
||||||
// includes an VBI emulator via a timer (according to sample code),
|
* Includes an VBI emulator via a timer (according to sample code),
|
||||||
// though this makes sense for one CRTC only
|
* though this makes sense for one CRTC only.
|
||||||
|
*/
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Radeon_SetupIRQ( device_info *di, char *buffer )
|
Radeon_SetupIRQ(device_info *di, char *buffer)
|
||||||
{
|
{
|
||||||
shared_info *si = di->si;
|
shared_info *si = di->si;
|
||||||
status_t result;
|
status_t result;
|
||||||
thread_id thid;
|
thread_id thid;
|
||||||
thread_info thinfo;
|
thread_info thinfo;
|
||||||
|
|
||||||
sprintf( buffer, "%04X_%04X_%02X%02X%02X VBI 1",
|
sprintf(buffer, "%04X_%04X_%02X%02X%02X VBI 1",
|
||||||
di->pcii.vendor_id, di->pcii.device_id,
|
di->pcii.vendor_id, di->pcii.device_id,
|
||||||
di->pcii.bus, di->pcii.device, di->pcii.function );
|
di->pcii.bus, di->pcii.device, di->pcii.function);
|
||||||
si->crtc[0].vblank = create_sem( 0, buffer );
|
si->crtc[0].vblank = create_sem(0, buffer);
|
||||||
if( si->crtc[0].vblank < 0 ) {
|
if (si->crtc[0].vblank < 0) {
|
||||||
result = si->crtc[0].vblank;
|
result = si->crtc[0].vblank;
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
si->crtc[1].vblank = 0;
|
si->crtc[1].vblank = 0;
|
||||||
|
|
||||||
if( di->num_crtc > 1 ) {
|
if (di->num_crtc > 1) {
|
||||||
sprintf( buffer, "%04X_%04X_%02X%02X%02X VBI 2",
|
sprintf(buffer, "%04X_%04X_%02X%02X%02X VBI 2",
|
||||||
di->pcii.vendor_id, di->pcii.device_id,
|
di->pcii.vendor_id, di->pcii.device_id,
|
||||||
di->pcii.bus, di->pcii.device, di->pcii.function );
|
di->pcii.bus, di->pcii.device, di->pcii.function);
|
||||||
si->crtc[1].vblank = create_sem( 0, buffer );
|
si->crtc[1].vblank = create_sem(0, buffer);
|
||||||
if( si->crtc[1].vblank < 0 ) {
|
if (si->crtc[1].vblank < 0) {
|
||||||
result = si->crtc[1].vblank;
|
result = si->crtc[1].vblank;
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf( buffer, "%04X_%04X_%02X%02X%02X Cap I",
|
sprintf(buffer, "%04X_%04X_%02X%02X%02X Cap I",
|
||||||
di->pcii.vendor_id, di->pcii.device_id,
|
di->pcii.vendor_id, di->pcii.device_id,
|
||||||
di->pcii.bus, di->pcii.device, di->pcii.function );
|
di->pcii.bus, di->pcii.device, di->pcii.function);
|
||||||
di->cap_sem = create_sem( 0, buffer );
|
di->cap_sem = create_sem(0, buffer);
|
||||||
if( di->cap_sem < 0 ) {
|
if (di->cap_sem < 0) {
|
||||||
result = di->cap_sem;
|
result = di->cap_sem;
|
||||||
goto err3;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
di->cap_spinlock = 0;
|
di->cap_spinlock = 0;
|
||||||
|
|
||||||
sprintf( buffer, "%04X_%04X_%02X%02X%02X DMA I",
|
sprintf(buffer, "%04X_%04X_%02X%02X%02X DMA I",
|
||||||
di->pcii.vendor_id, di->pcii.device_id,
|
di->pcii.vendor_id, di->pcii.device_id,
|
||||||
di->pcii.bus, di->pcii.device, di->pcii.function );
|
di->pcii.bus, di->pcii.device, di->pcii.function);
|
||||||
di->dma_sem = create_sem( 0, buffer );
|
di->dma_sem = create_sem(0, buffer);
|
||||||
if( di->dma_sem < 0 ) {
|
if (di->dma_sem < 0) {
|
||||||
result = di->dma_sem;
|
result = di->dma_sem;
|
||||||
goto err4;
|
goto err4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* change the owner of the semaphores to the opener's team */
|
/* change the owner of the semaphores to the opener's team */
|
||||||
/* this is required because apps can't aquire kernel semaphores */
|
/* this is required because apps can't aquire kernel semaphores */
|
||||||
thid = find_thread(NULL);
|
thid = find_thread(NULL);
|
||||||
get_thread_info(thid, &thinfo);
|
get_thread_info(thid, &thinfo);
|
||||||
set_sem_owner(si->crtc[0].vblank, thinfo.team);
|
set_sem_owner(si->crtc[0].vblank, thinfo.team);
|
||||||
if( di->num_crtc > 1 )
|
if (di->num_crtc > 1)
|
||||||
set_sem_owner(si->crtc[1].vblank, thinfo.team);
|
set_sem_owner(si->crtc[1].vblank, thinfo.team);
|
||||||
//set_sem_owner(di->cap_sem, thinfo.team);
|
//set_sem_owner(di->cap_sem, thinfo.team);
|
||||||
|
|
||||||
/* disable all interrupts */
|
/* disable all interrupts */
|
||||||
Radeon_DisableIRQ( di );
|
Radeon_DisableIRQ(di);
|
||||||
|
|
||||||
/* if we're faking interrupts */
|
/* if we're faking interrupts */
|
||||||
if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){
|
if (di->pcii.u.h0.interrupt_pin == 0x00 || di->pcii.u.h0.interrupt_line == 0xff) {
|
||||||
SHOW_INFO0( 3, "We like to fake IRQ" );
|
SHOW_INFO0( 3, "We like to fake IRQ" );
|
||||||
/* fake some kind of interrupt with a timer */
|
/* fake some kind of interrupt with a timer */
|
||||||
di->shutdown_virtual_irq = false;
|
di->shutdown_virtual_irq = false;
|
||||||
si->refresh_period = 16666; /* fake 60Hz to start */
|
si->refresh_period = 16666; /* fake 60Hz to start */
|
||||||
si->blank_period = si->refresh_period / 20;
|
si->blank_period = si->refresh_period / 20;
|
||||||
|
|
||||||
di->ti_a.di = di; /* refer to ourself */
|
di->ti_a.di = di; /* refer to ourself */
|
||||||
di->ti_b.di = di;
|
di->ti_b.di = di;
|
||||||
di->current_timer = &(di->ti_a);
|
di->current_timer = &di->ti_a;
|
||||||
|
|
||||||
/* program the first timer interrupt, and it will handle the rest */
|
/* program the first timer interrupt, and it will handle the rest */
|
||||||
result = add_timer((timer *)(di->current_timer), timer_interrupt_func,
|
result = add_timer((timer *)(di->current_timer), timer_interrupt_func,
|
||||||
si->refresh_period, B_ONE_SHOT_RELATIVE_TIMER);
|
si->refresh_period, B_ONE_SHOT_RELATIVE_TIMER);
|
||||||
if( result != B_OK )
|
if (result != B_OK)
|
||||||
goto err5;
|
goto err5;
|
||||||
} else {
|
} else {
|
||||||
/* otherwise install our interrupt handler */
|
/* otherwise install our interrupt handler */
|
||||||
result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line,
|
dprintf("radeon: real interrupt handling disabled\n");
|
||||||
Radeon_Interrupt, (void *)di, 0);
|
#if 0
|
||||||
if( result != B_OK )
|
result = install_io_interrupt_handler(di->pcii.u.h0.interrupt_line,
|
||||||
goto err5;
|
Radeon_Interrupt, (void *)di, 0);
|
||||||
|
if (result != B_OK)
|
||||||
|
goto err5;
|
||||||
|
|
||||||
SHOW_INFO( 3, "installed IRQ @ %d", di->pcii.u.h0.interrupt_line );
|
SHOW_INFO(3, "installed IRQ @ %d", di->pcii.u.h0.interrupt_line);
|
||||||
}
|
#endif
|
||||||
|
}
|
||||||
return B_OK;
|
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
err5:
|
err5:
|
||||||
delete_sem( di->dma_sem );
|
delete_sem(di->dma_sem);
|
||||||
err4:
|
err4:
|
||||||
delete_sem( di->cap_sem );
|
delete_sem(di->cap_sem);
|
||||||
err3:
|
err3:
|
||||||
if( di->num_crtc > 1 )
|
if (di->num_crtc > 1)
|
||||||
delete_sem( si->crtc[1].vblank );
|
delete_sem(si->crtc[1].vblank);
|
||||||
err2:
|
err2:
|
||||||
delete_sem( si->crtc[0].vblank );
|
delete_sem(si->crtc[0].vblank);
|
||||||
err1:
|
err1:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// clean-up interrupt handling
|
/** Clean-up interrupt handling */
|
||||||
|
|
||||||
void
|
void
|
||||||
Radeon_CleanupIRQ( device_info *di )
|
Radeon_CleanupIRQ(device_info *di)
|
||||||
{
|
{
|
||||||
shared_info *si = di->si;
|
shared_info *si = di->si;
|
||||||
|
|
||||||
Radeon_DisableIRQ( di );
|
|
||||||
|
|
||||||
/* if we were faking the interrupts */
|
|
||||||
if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){
|
|
||||||
/* stop our interrupt faking thread */
|
|
||||||
di->shutdown_virtual_irq = true;
|
|
||||||
/* cancel the timer */
|
|
||||||
/* we don't know which one is current, so cancel them both and ignore any error */
|
|
||||||
cancel_timer((timer *)&(di->ti_a));
|
|
||||||
cancel_timer((timer *)&(di->ti_b));
|
|
||||||
} else {
|
|
||||||
/* remove interrupt handler */
|
|
||||||
remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, Radeon_Interrupt, di);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete_sem( si->crtc[0].vblank );
|
Radeon_DisableIRQ(di);
|
||||||
|
|
||||||
if( di->num_crtc > 1 )
|
#if 0
|
||||||
delete_sem( si->crtc[1].vblank );
|
/* if we were faking the interrupts */
|
||||||
|
if ((di->pcii.u.h0.interrupt_pin == 0x00) || (di->pcii.u.h0.interrupt_line == 0xff)){
|
||||||
delete_sem( di->cap_sem );
|
/* stop our interrupt faking thread */
|
||||||
delete_sem( di->dma_sem );
|
di->shutdown_virtual_irq = true;
|
||||||
|
/* cancel the timer */
|
||||||
|
/* we don't know which one is current, so cancel them both and ignore any error */
|
||||||
|
cancel_timer((timer *)&(di->ti_a));
|
||||||
|
cancel_timer((timer *)&(di->ti_b));
|
||||||
|
} else {
|
||||||
|
/* remove interrupt handler */
|
||||||
|
remove_io_interrupt_handler(di->pcii.u.h0.interrupt_line, Radeon_Interrupt, di);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
delete_sem(si->crtc[0].vblank);
|
||||||
|
|
||||||
|
if (di->num_crtc > 1)
|
||||||
|
delete_sem(si->crtc[1].vblank);
|
||||||
|
|
||||||
|
delete_sem(di->cap_sem);
|
||||||
|
delete_sem(di->dma_sem);
|
||||||
|
|
||||||
di->cap_sem = si->crtc[1].vblank = si->crtc[0].vblank = 0;
|
di->cap_sem = si->crtc[1].vblank = si->crtc[0].vblank = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user