Implemented vblank interrupt and support for the retrace semaphore - not yet
tested, though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17439 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c3b56e03d4
commit
5af5259c38
@ -81,6 +81,8 @@ struct intel_shared_info {
|
||||
uint32 overlay_token;
|
||||
uint8* physical_overlay_registers;
|
||||
|
||||
sem_id vblank_sem;
|
||||
|
||||
uint32 device_type;
|
||||
char device_identifier[32];
|
||||
struct pll_info pll_info;
|
||||
@ -106,6 +108,8 @@ struct intel_info {
|
||||
// allocated memory beyond the "stolen" amount
|
||||
mem_info *memory_manager;
|
||||
|
||||
bool fake_interrupts;
|
||||
|
||||
const char *device_identifier;
|
||||
uint32 device_type;
|
||||
};
|
||||
@ -166,6 +170,7 @@ struct intel_free_graphics_memory {
|
||||
#define i855_STOLEN_MEMORY_48M 0x60
|
||||
#define i855_STOLEN_MEMORY_64M 0x70
|
||||
|
||||
// graphics page translation table
|
||||
#define INTEL_PAGE_TABLE_CONTROL 0x02020
|
||||
#define INTEL_PAGE_TABLE_ERROR 0x02024
|
||||
#define INTEL_HARDWARE_STATUS_PAGE 0x02080
|
||||
@ -173,6 +178,14 @@ struct intel_free_graphics_memory {
|
||||
#define GTT_ENTRY_VALID 0x01
|
||||
#define GTT_ENTRY_LOCAL_MEMORY 0x02
|
||||
|
||||
// interrupts
|
||||
#define INTEL_INTERRUPT_ENABLED 0x020a0
|
||||
#define INTEL_INTERRUPT_IDENTITY 0x020a4
|
||||
#define INTEL_INTERRUPT_MASK 0x020a8
|
||||
#define INTEL_INTERRUPT_STATUS 0x020ac
|
||||
#define INTERRUPT_VBLANK (1 << 7)
|
||||
|
||||
// ring buffer
|
||||
#define INTEL_PRIMARY_RING_BUFFER 0x02030
|
||||
#define INTEL_SECONDARY_RING_BUFFER_0 0x02100
|
||||
#define INTEL_SECONDARY_RING_BUFFER_1 0x02110
|
||||
@ -185,6 +198,7 @@ struct intel_free_graphics_memory {
|
||||
#define INTEL_RING_BUFFER_HEAD_MASK 0x001ffffc
|
||||
#define INTEL_RING_BUFFER_ENABLED 1
|
||||
|
||||
// display
|
||||
#define INTEL_DISPLAY_HTOTAL 0x60000
|
||||
#define INTEL_DISPLAY_HBLANK 0x60004
|
||||
#define INTEL_DISPLAY_HSYNC 0x60008
|
||||
@ -207,6 +221,8 @@ struct intel_free_graphics_memory {
|
||||
|
||||
#define INTEL_DISPLAY_PIPE_CONTROL 0x70008
|
||||
#define DISPLAY_PIPE_ENABLED (1UL << 31)
|
||||
#define INTEL_DISPLAY_PIPE_STATUS 0x70024
|
||||
#define DISPLAY_PIPE_VBLANK_ENABLED (1UL << 17)
|
||||
|
||||
#define INTEL_DISPLAY_PLL 0x06014
|
||||
#define INTEL_DISPLAY_PLL_DIVISOR_0 0x06040
|
||||
@ -238,11 +254,18 @@ struct intel_free_graphics_memory {
|
||||
#define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3)
|
||||
#define DISPLAY_MONITOR_POSITIVE_VSYNC (2UL << 3)
|
||||
|
||||
// cursor
|
||||
#define INTEL_CURSOR_CONTROL 0x70080
|
||||
#define INTEL_CURSOR_BASE 0x70084
|
||||
#define INTEL_CURSOR_POSITION 0x70088
|
||||
#define INTEL_CURSOR_PALETTE 0x70090 // (- 0x7009f)
|
||||
#define INTEL_CURSOR_SIZE 0x700a0
|
||||
#define CURSOR_ENABLED (1UL << 31)
|
||||
#define CURSOR_FORMAT_2_COLORS (0UL << 24)
|
||||
#define CURSOR_FORMAT_3_COLORS (1UL << 24)
|
||||
#define CURSOR_FORMAT_4_COLORS (2UL << 24)
|
||||
#define CURSOR_FORMAT_ARGB (4UL << 24)
|
||||
#define CURSOR_FORMAT_XRGB (5UL << 24)
|
||||
|
||||
// ring buffer commands
|
||||
|
||||
|
@ -298,6 +298,6 @@ sem_id
|
||||
intel_accelerant_retrace_semaphore()
|
||||
{
|
||||
TRACE(("intel_accelerant_retrace_semaphore()\n"));
|
||||
return -1;
|
||||
return gInfo->shared_info->vblank_sem;
|
||||
}
|
||||
|
||||
|
@ -147,6 +147,96 @@ set_gtt_entry(intel_info &info, uint32 offset, uint8 *physicalAddress)
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
release_vblank_sem(intel_info &info)
|
||||
{
|
||||
int32 count;
|
||||
if (get_sem_count(info.shared_info->vblank_sem, &count) == B_OK
|
||||
&& count < 0) {
|
||||
release_sem_etc(info.shared_info->vblank_sem, -count, B_DO_NOT_RESCHEDULE);
|
||||
return B_INVOKE_SCHEDULER;
|
||||
}
|
||||
|
||||
return B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
intel_interrupt_handler(void *data)
|
||||
{
|
||||
intel_info &info = *(intel_info *)data;
|
||||
|
||||
uint32 identity = read32(info.registers + INTEL_INTERRUPT_IDENTITY);
|
||||
if (identity == 0)
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
|
||||
int32 handled = B_HANDLED_INTERRUPT;
|
||||
|
||||
if ((identity & INTERRUPT_VBLANK) != 0) {
|
||||
handled = release_vblank_sem(info);
|
||||
|
||||
// make sure we'll get another one of those
|
||||
write32(info.registers + INTEL_DISPLAY_PIPE_STATUS, DISPLAY_PIPE_VBLANK_ENABLED);
|
||||
write32(info.registers + INTEL_INTERRUPT_IDENTITY, 0);
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
init_interrupt_handler(intel_info &info)
|
||||
{
|
||||
info.shared_info->vblank_sem = create_sem(0, "intel extreme vblank");
|
||||
if (info.shared_info->vblank_sem < B_OK)
|
||||
return;
|
||||
|
||||
status_t status = B_OK;
|
||||
|
||||
// We need to change the owner of the sem to the calling team (usually the
|
||||
// app_server), because userland apps cannot acquire kernel semaphores
|
||||
thread_id thread = find_thread(NULL);
|
||||
thread_info threadInfo;
|
||||
if (get_thread_info(thread, &threadInfo) != B_OK
|
||||
|| set_sem_owner(info.shared_info->vblank_sem, threadInfo.team) != B_OK) {
|
||||
status = B_ERROR;
|
||||
}
|
||||
|
||||
if (status == B_OK
|
||||
&& info.pci->u.h0.interrupt_pin != 0x00 && info.pci->u.h0.interrupt_line != 0xff) {
|
||||
// we've gotten an interrupt line for us to use
|
||||
|
||||
info.fake_interrupts = false;
|
||||
|
||||
status = install_io_interrupt_handler(info.pci->u.h0.interrupt_line,
|
||||
intel_interrupt_handler, (void *)&info, 0);
|
||||
if (status == B_OK) {
|
||||
// enable interrupts - we only want VBLANK interrupts
|
||||
write32(info.registers + INTEL_INTERRUPT_ENABLED, INTERRUPT_VBLANK);
|
||||
write32(info.registers + INTEL_INTERRUPT_MASK, ~INTERRUPT_VBLANK);
|
||||
|
||||
write32(info.registers + INTEL_DISPLAY_PIPE_STATUS,
|
||||
DISPLAY_PIPE_VBLANK_ENABLED);
|
||||
write32(info.registers + INTEL_INTERRUPT_IDENTITY, 0);
|
||||
}
|
||||
}
|
||||
if (status < B_OK) {
|
||||
// there is no interrupt reserved for us, or we couldn't install our interrupt
|
||||
// handler, let's fake the vblank interrupt for our clients using a timer
|
||||
// interrupt
|
||||
info.fake_interrupts = true;
|
||||
|
||||
// TODO: fake interrupts!
|
||||
status = B_ERROR;
|
||||
}
|
||||
|
||||
if (status < B_OK) {
|
||||
delete_sem(info.shared_info->vblank_sem);
|
||||
info.shared_info->vblank_sem = B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -330,6 +420,8 @@ intel_extreme_init(intel_info &info)
|
||||
}
|
||||
info.shared_info->cursor_area = info.cursor_area;
|
||||
|
||||
init_interrupt_handler(info);
|
||||
|
||||
info.cookie_magic = INTEL_COOKIE_MAGIC;
|
||||
// this makes the cookie valid to be used
|
||||
|
||||
@ -344,6 +436,15 @@ intel_extreme_uninit(intel_info &info)
|
||||
{
|
||||
dprintf(DEVICE_NAME": intel_extreme_uninit()\n");
|
||||
|
||||
if (!info.fake_interrupts && info.shared_info->vblank_sem > 0) {
|
||||
// disable interrupt generation
|
||||
write32(info.registers + INTEL_INTERRUPT_ENABLED, 0);
|
||||
write32(info.registers + INTEL_INTERRUPT_MASK, ~0);
|
||||
|
||||
remove_io_interrupt_handler(info.pci->u.h0.interrupt_line,
|
||||
intel_interrupt_handler, &info);
|
||||
}
|
||||
|
||||
mem_destroy(info.memory_manager);
|
||||
|
||||
delete_area(info.graphics_memory_area);
|
||||
|
Loading…
Reference in New Issue
Block a user