From 1c34b9b1f5e168501f89a270233457e04aa1b16b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 29 Jan 2008 08:55:36 +0000 Subject: [PATCH] Work in progress (might not work for you yet): * Now uses the AGP GART module for memory management. This greatly simplifies the memory handling, and memory is now actually allocated on demand, instead of a fixed size (stolen memory is not freed, though). * The Intel GART module should now also work with older chipsets. * No longer remove the GTT size from the stolen memory; this appears to have been a mistake in the X driver. Not sure about the BIOS popup yet. * The AGP module (in combination with the Intel GART module) is now mandatory to use the Intel driver. * Removed now superfluous settings (like memory size). Only enabling/disabling the hardware cursor is still supported. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23781 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../graphics/intel_extreme/intel_extreme.h | 29 +- .../accelerants/intel_extreme/accelerant.cpp | 20 +- .../accelerants/intel_extreme/accelerant.h | 15 +- .../accelerants/intel_extreme/commands.h | 2 +- .../accelerants/intel_extreme/cursor.cpp | 4 +- .../accelerants/intel_extreme/engine.cpp | 8 +- .../accelerants/intel_extreme/hooks.cpp | 6 +- .../accelerants/intel_extreme/memory.cpp | 22 +- .../accelerants/intel_extreme/mode.cpp | 24 +- .../accelerants/intel_extreme/overlay.cpp | 43 ++- .../kernel/busses/agp_gart/intel_gart.cpp | 30 +- .../drivers/graphics/intel_extreme/device.cpp | 12 +- .../drivers/graphics/intel_extreme/driver.cpp | 19 +- .../drivers/graphics/intel_extreme/driver.h | 1 + .../graphics/intel_extreme/intel_extreme.cpp | 355 ++++-------------- .../intel_extreme/intel_extreme_private.h | 21 +- 16 files changed, 208 insertions(+), 403 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index c997830bfc..fc0f990f5b 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -11,8 +11,6 @@ #include "lock.h" -#include - #include #include #include @@ -46,7 +44,6 @@ struct pll_info { struct ring_buffer { struct lock lock; uint32 register_base; - uint32 handle; uint32 offset; uint32 size; uint32 position; @@ -66,13 +63,13 @@ struct intel_shared_info { uint32 dpms_mode; area_id registers_area; // area of memory mapped registers - uint8 *physical_status_page; - uint8 *physical_cursor_memory; - area_id graphics_memory_area; + uint8 *status_page; + addr_t physical_status_page; uint8 *graphics_memory; - uint8 *physical_graphics_memory; + addr_t physical_graphics_memory; uint32 graphics_memory_size; + addr_t frame_buffer; uint32 frame_buffer_offset; struct lock accelerant_lock; @@ -84,12 +81,14 @@ struct intel_shared_info { int32 overlay_channel_used; bool overlay_active; uint32 overlay_token; - uint8* physical_overlay_registers; + addr_t physical_overlay_registers; uint32 overlay_offset; bool hardware_cursor_enabled; sem_id vblank_sem; + uint8 *cursor_memory; + addr_t physical_cursor_memory; uint32 cursor_buffer_offset; uint32 cursor_format; bool cursor_visible; @@ -125,14 +124,15 @@ struct intel_get_private_data { struct intel_allocate_graphics_memory { uint32 magic; uint32 size; - uint32 buffer_offset; - uint32 handle; + uint32 alignment; + uint32 flags; + uint32 buffer_base; }; // free graphics memory struct intel_free_graphics_memory { uint32 magic; - uint32 handle; + uint32 buffer_base; }; //---------------------------------------------------------- @@ -540,6 +540,13 @@ struct overlay_registers { #define INTEL_i965_OVERLAY_STATE_SIZE 36864 #define INTEL_i965_3D_CONTEXT_SIZE 32768 +inline bool +intel_uses_physical_overlay(intel_shared_info &info) +{ + return info.device_type != INTEL_TYPE_G33; +} + + struct hardware_status { uint32 interrupt_status_register; uint32 _reserved0[3]; diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index bc3494d06c..dce761d7c6 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -18,6 +18,8 @@ #include #include +#include + #define TRACE_ACCELERANT #ifdef TRACE_ACCELERANT @@ -133,17 +135,17 @@ init_common(int device, bool isClone) // The overlay registers, hardware status, and cursor memory share // a single area with the shared_info - gInfo->overlay_registers = (struct overlay_registers *)((uint8 *)gInfo->shared_info - + ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info))); - gInfo->status = (hardware_status *)((uint8 *)gInfo->overlay_registers + B_PAGE_SIZE); - - if (gInfo->shared_info->hardware_cursor_enabled) - gInfo->cursor_memory = (uint8 *)gInfo->overlay_registers + 2 * B_PAGE_SIZE; + gInfo->overlay_registers = (struct overlay_registers *) + (gInfo->shared_info->graphics_memory + + gInfo->shared_info->overlay_offset); if (gInfo->shared_info->device_type == INTEL_TYPE_965) { // allocate some extra memory for the 3D context - intel_allocate_memory(INTEL_i965_3D_CONTEXT_SIZE, gInfo->context_handle, - gInfo->context_offset); + if (intel_allocate_memory(INTEL_i965_3D_CONTEXT_SIZE, + B_APERTURE_NON_RESERVED, gInfo->context_base) == B_OK) { + gInfo->context_offset = gInfo->context_base + - (addr_t)gInfo->shared_info->graphics_memory; + } } return B_OK; @@ -154,7 +156,7 @@ init_common(int device, bool isClone) static void uninit_common(void) { - intel_free_memory(gInfo->context_handle); + intel_free_memory(gInfo->context_base); delete_area(gInfo->regs_area); delete_area(gInfo->shared_info_area); diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index c4db067ea7..c068b5d8c2 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -17,9 +17,9 @@ struct overlay { overlay_buffer buffer; - uint32 buffer_handle; + addr_t buffer_base; uint32 buffer_offset; - uint32 state_handle; + addr_t state_base; uint32 state_offset; }; @@ -40,8 +40,6 @@ struct accelerant_info { display_mode *mode_list; // cloned list of standard display modes area_id mode_list_area; - uint32 frame_buffer_handle; - struct overlay_registers *overlay_registers; overlay *current_overlay; overlay_view last_overlay_view; @@ -50,14 +48,11 @@ struct accelerant_info { uint32 last_vertical_overlay_scale; uint32 overlay_position_buffer_offset; - hardware_status *status; - uint8 *cursor_memory; - edid1_info edid_info; bool has_edid; // limited 3D support for overlay on i965 - uint32 context_handle; + addr_t context_base; uint32 context_offset; bool context_set; @@ -101,7 +96,7 @@ extern void set_frame_buffer_base(void); extern status_t create_mode_list(void); // memory.cpp -extern void intel_free_memory(uint32 handle); -extern status_t intel_allocate_memory(size_t size, uint32& handle, uint32& offset); +extern void intel_free_memory(uint32 base); +extern status_t intel_allocate_memory(size_t size, uint32 flags, uint32 &base); #endif /* INTEL_EXTREME_ACCELERANT_H */ diff --git a/src/add-ons/accelerants/intel_extreme/commands.h b/src/add-ons/accelerants/intel_extreme/commands.h index 3b5965f66f..f0b04f15a1 100644 --- a/src/add-ons/accelerants/intel_extreme/commands.h +++ b/src/add-ons/accelerants/intel_extreme/commands.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: diff --git a/src/add-ons/accelerants/intel_extreme/cursor.cpp b/src/add-ons/accelerants/intel_extreme/cursor.cpp index 96d8cef2c5..bb2e8ffacb 100644 --- a/src/add-ons/accelerants/intel_extreme/cursor.cpp +++ b/src/add-ons/accelerants/intel_extreme/cursor.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -33,7 +33,7 @@ intel_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotY, // transparent, for 0x3 it inverts the background, so only the first // two palette entries will be used (since we're using the 2 color mode). - uint8 *data = gInfo->cursor_memory; + uint8 *data = gInfo->shared_info->cursor_memory; uint8 byteWidth = (width + 7) / 8; for (int32 y = 0; y < height; y++) { diff --git a/src/add-ons/accelerants/intel_extreme/engine.cpp b/src/add-ons/accelerants/intel_extreme/engine.cpp index dd514990c9..1d8e21c9b2 100644 --- a/src/add-ons/accelerants/intel_extreme/engine.cpp +++ b/src/add-ons/accelerants/intel_extreme/engine.cpp @@ -97,11 +97,11 @@ QueueCommands::PutOverlayFlip(uint32 mode, bool updateCoefficients) Write(COMMAND_OVERLAY_FLIP | mode); uint32 registers; - if (gInfo->shared_info->overlay_offset != 0) { - // G33 does not need a physical address for the overlay registers + // G33 does not need a physical address for the overlay registers + if (intel_uses_physical_overlay(*gInfo->shared_info)) + registers = gInfo->shared_info->physical_overlay_registers; + else registers = gInfo->shared_info->overlay_offset; - } else - registers = (uint32)gInfo->shared_info->physical_overlay_registers; Write(registers | (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0)); } diff --git a/src/add-ons/accelerants/intel_extreme/hooks.cpp b/src/add-ons/accelerants/intel_extreme/hooks.cpp index 341598437f..9688585ddc 100644 --- a/src/add-ons/accelerants/intel_extreme/hooks.cpp +++ b/src/add-ons/accelerants/intel_extreme/hooks.cpp @@ -67,13 +67,13 @@ get_accelerant_hook(uint32 feature, void *data) /* cursor managment */ case B_SET_CURSOR_SHAPE: - if (gInfo->cursor_memory != NULL) + if (gInfo->shared_info->cursor_memory != NULL) return (void*)intel_set_cursor_shape; case B_MOVE_CURSOR: - if (gInfo->cursor_memory != NULL) + if (gInfo->shared_info->cursor_memory != NULL) return (void*)intel_move_cursor; case B_SHOW_CURSOR: - if (gInfo->cursor_memory != NULL) + if (gInfo->shared_info->cursor_memory != NULL) return (void*)intel_show_cursor; return NULL; diff --git a/src/add-ons/accelerants/intel_extreme/memory.cpp b/src/add-ons/accelerants/intel_extreme/memory.cpp index 31e977356e..1f2a705f42 100644 --- a/src/add-ons/accelerants/intel_extreme/memory.cpp +++ b/src/add-ons/accelerants/intel_extreme/memory.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -24,32 +24,34 @@ extern "C" void _sPrintf(const char *format, ...); void -intel_free_memory(uint32 handle) +intel_free_memory(uint32 base) { - if (!handle) + if (base == 0) return; intel_free_graphics_memory freeMemory; freeMemory.magic = INTEL_PRIVATE_DATA_MAGIC; - freeMemory.handle = handle; + freeMemory.buffer_base = base; - ioctl(gInfo->device, INTEL_FREE_GRAPHICS_MEMORY, &freeMemory, sizeof(freeMemory)); + ioctl(gInfo->device, INTEL_FREE_GRAPHICS_MEMORY, &freeMemory, + sizeof(freeMemory)); } status_t -intel_allocate_memory(size_t size, uint32& handle, uint32& offset) +intel_allocate_memory(size_t size, uint32 flags, uint32 &base) { intel_allocate_graphics_memory allocMemory; allocMemory.magic = INTEL_PRIVATE_DATA_MAGIC; allocMemory.size = size; + allocMemory.alignment = 0; + allocMemory.flags = flags; - if (ioctl(gInfo->device, INTEL_ALLOCATE_GRAPHICS_MEMORY, &allocMemory, sizeof(allocMemory)) < 0) + if (ioctl(gInfo->device, INTEL_ALLOCATE_GRAPHICS_MEMORY, &allocMemory, + sizeof(allocMemory)) < 0) return errno; - handle = allocMemory.handle; - offset = allocMemory.buffer_offset; - + base = allocMemory.buffer_base; return B_OK; } diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index 359ee48e42..5ed6fb9853 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -417,16 +417,17 @@ if (first) { // free old and allocate new frame buffer in graphics memory - intel_free_memory(gInfo->frame_buffer_handle); + intel_free_memory(sharedInfo.frame_buffer); - uint32 offset; - if (intel_allocate_memory(bytesPerRow * target.virtual_height, - gInfo->frame_buffer_handle, offset) < B_OK) { + uint32 base; + if (intel_allocate_memory(bytesPerRow * target.virtual_height, 0, + base) < B_OK) { // oh, how did that happen? Unfortunately, there is no really good way back if (intel_allocate_memory(sharedInfo.current_mode.virtual_height - * sharedInfo.bytes_per_row, gInfo->frame_buffer_handle, - offset) == B_OK) { - sharedInfo.frame_buffer_offset = offset; + * sharedInfo.bytes_per_row, 0, base) == B_OK) { + sharedInfo.frame_buffer = base; + sharedInfo.frame_buffer_offset = base + - (addr_t)sharedInfo.graphics_memory; set_frame_buffer_base(); } @@ -434,9 +435,9 @@ if (first) { } // clear frame buffer before using it - memset(sharedInfo.graphics_memory + offset, 0, - bytesPerRow * target.virtual_height); - sharedInfo.frame_buffer_offset = offset; + memset((uint8 *)base, 0, bytesPerRow * target.virtual_height); + sharedInfo.frame_buffer = base; + sharedInfo.frame_buffer_offset = base - (addr_t)sharedInfo.graphics_memory; // make sure VGA display is disabled write32(INTEL_VGA_DISPLAY_CONTROL, VGA_DISPLAY_DISABLED); @@ -673,7 +674,8 @@ intel_get_frame_buffer_config(frame_buffer_config *config) uint32 offset = gInfo->shared_info->frame_buffer_offset; config->frame_buffer = gInfo->shared_info->graphics_memory + offset; - config->frame_buffer_dma = gInfo->shared_info->physical_graphics_memory + offset; + config->frame_buffer_dma + = (uint8 *)gInfo->shared_info->physical_graphics_memory + offset; config->bytes_per_row = gInfo->shared_info->bytes_per_row; return B_OK; diff --git a/src/add-ons/accelerants/intel_extreme/overlay.cpp b/src/add-ons/accelerants/intel_extreme/overlay.cpp index a0d543df6a..c2bcc2bcd8 100644 --- a/src/add-ons/accelerants/intel_extreme/overlay.cpp +++ b/src/add-ons/accelerants/intel_extreme/overlay.cpp @@ -18,6 +18,8 @@ #include #include +#include + //#define TRACE_OVERLAY #ifdef TRACE_OVERLAY @@ -42,8 +44,7 @@ struct phase_coefficient { }; -/*! - Splits the coefficient floating point value into the 3 components +/*! Splits the coefficient floating point value into the 3 components sign, mantissa, and exponent. */ static bool @@ -179,8 +180,8 @@ update_coefficients(int32 taps, double filterCutOff, bool horizontal, bool isY, static void -set_color_key(uint8 red, uint8 green, uint8 blue, - uint8 redMask, uint8 greenMask, uint8 blueMask) +set_color_key(uint8 red, uint8 green, uint8 blue, uint8 redMask, + uint8 greenMask, uint8 blueMask) { overlay_registers *registers = gInfo->overlay_registers; @@ -224,7 +225,8 @@ set_color_key(const overlay_window *window) static void update_overlay(bool updateCoefficients) { - if (!gInfo->shared_info->overlay_active) + if (!gInfo->shared_info->overlay_active + || gInfo->shared_info->device_type == INTEL_TYPE_965) return; QueueCommands queue(gInfo->shared_info->secondary_ring_buffer); @@ -245,7 +247,8 @@ update_overlay(bool updateCoefficients) static void show_overlay(void) { - if (gInfo->shared_info->overlay_active) + if (gInfo->shared_info->overlay_active + || gInfo->shared_info->device_type == INTEL_TYPE_965) return; gInfo->shared_info->overlay_active = true; @@ -260,7 +263,8 @@ show_overlay(void) static void hide_overlay(void) { - if (!gInfo->shared_info->overlay_active) + if (!gInfo->shared_info->overlay_active + || gInfo->shared_info->device_type == INTEL_TYPE_965) return; overlay_registers *registers = gInfo->overlay_registers; @@ -364,7 +368,7 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width, buffer->bytes_per_row = (width * bytesPerPixel + 0x3f) & ~0x3f; status_t status = intel_allocate_memory(buffer->bytes_per_row * height, - overlay->buffer_handle, overlay->buffer_offset); + 0, overlay->buffer_base); if (status < B_OK) { free(overlay); return NULL; @@ -372,18 +376,22 @@ intel_allocate_overlay_buffer(color_space colorSpace, uint16 width, if (sharedInfo.device_type == INTEL_TYPE_965) { status = intel_allocate_memory(INTEL_i965_OVERLAY_STATE_SIZE, - overlay->state_handle, overlay->state_offset); + B_APERTURE_NON_RESERVED, overlay->state_base); if (status < B_OK) { - intel_free_memory(overlay->buffer_handle); + intel_free_memory(overlay->buffer_base); free(overlay); return NULL; } - } else - overlay->state_handle = 0; - buffer->buffer = gInfo->shared_info->graphics_memory - + overlay->buffer_offset; - buffer->buffer_dma = gInfo->shared_info->physical_graphics_memory + overlay->state_offset = overlay->state_base + - (addr_t)gInfo->shared_info->graphics_memory; + } + + overlay->buffer_offset = overlay->buffer_base + - (addr_t)gInfo->shared_info->graphics_memory; + + buffer->buffer = (uint8 *)overlay->buffer_base; + buffer->buffer_dma = (uint8 *)gInfo->shared_info->physical_graphics_memory + overlay->buffer_offset; TRACE(("allocated overlay buffer: handle=%x, offset=%x, address=%x, " @@ -406,8 +414,9 @@ intel_release_overlay_buffer(const overlay_buffer *buffer) if (gInfo->current_overlay == overlay) hide_overlay(); - intel_free_memory(overlay->buffer_handle); - intel_free_memory(overlay->state_handle); + intel_free_memory(overlay->buffer_base); + if (gInfo->shared_info->device_type == INTEL_TYPE_965) + intel_free_memory(overlay->state_base); free(overlay); return B_OK; diff --git a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp index 902235322e..7f0aa7007b 100644 --- a/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp +++ b/src/add-ons/kernel/busses/agp_gart/intel_gart.cpp @@ -127,30 +127,28 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) break; } } else { -#if 0 // older models have the GTT as large as their frame buffer mapping // TODO: check if the i9xx version works with the i8xx chips as well size_t frameBufferSize = 0; - if ((info.device_type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_8xx) { - if ((info.device_type & INTEL_TYPE_83x) != 0 + if ((info.type & INTEL_TYPE_8xx) != 0) { + if (info.type == INTEL_TYPE_83x && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) frameBufferSize = 64 << 20; else frameBufferSize = 128 << 20; - } else if ((info.device_type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) - frameBufferSize = info.pci->u.h0.base_register_sizes[2]; + } else if ((info.type & INTEL_TYPE_9xx) != 0) + frameBufferSize = info.display.u.h0.base_register_sizes[2]; gttSize = frameBufferSize / 1024; -#endif } -#if 0 // TODO: test with different models! - if (info.device_type == (INTEL_TYPE_8xx | INTEL_TYPE_83x)) { + if (info.type == INTEL_TYPE_83x) { switch (memoryConfig & STOLEN_MEMORY_MASK) { case i830_LOCAL_MEMORY_ONLY: // TODO: determine its size! + dprintf("intel_gart: getting local memory size not implemented.\n"); break; case i830_STOLEN_512K: memorySize >>= 1; @@ -159,10 +157,8 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) memorySize *= 8; break; } - } else if (info.device_type == (INTEL_TYPE_8xx | INTEL_TYPE_85x) - || (info.device_type & INTEL_TYPE_FAMILY_MASK) == INTEL_TYPE_9xx) -#endif - { + } else if (info.type == INTEL_TYPE_85x + || (info.type & INTEL_TYPE_9xx) != 0) { switch (memoryConfig & STOLEN_MEMORY_MASK) { case i855_STOLEN_MEMORY_4M: memorySize *= 4; @@ -191,7 +187,9 @@ determine_memory_sizes(intel_info &info, size_t >tSize, size_t &stolenSize) } } - stolenSize = memorySize - gttSize - 4096; + // TODO: this is probably wrong after all (taken from X driver) + // the stolen memory does not host the GTT! + stolenSize = memorySize /*- gttSize - 4096*/; } @@ -272,7 +270,11 @@ dprintf("GTT base %lx, size %lu, entries %lu, stolen %lu\n", info.gtt_physical_b info.aperture_physical_base = info.display.u.h0.base_registers[fbIndex]; info.aperture_stolen_size = stolenSize; if (info.aperture_size == 0) - info.aperture_size = info.display.u.h0.base_register_sizes[0]; + info.aperture_size = info.display.u.h0.base_register_sizes[fbIndex]; + + dprintf("intel_gart: detected %ld MB of stolen memory, aperture size %ld " + "MB, GTT size %ld KB\n", stolenSize >> 20, info.aperture_size >> 20, + gttSize >> 10); AreaKeeper apertureMapper; info.aperture_area = apertureMapper.Map("intel graphics aperture", diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp index eba4594935..3dfe9ace0a 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -222,8 +222,9 @@ device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength) if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC) return B_BAD_VALUE; - status_t status = mem_alloc(info->memory_manager, allocMemory.size, info, - &allocMemory.handle, &allocMemory.buffer_offset); + status_t status = intel_allocate_memory(*info, allocMemory.size, + allocMemory.alignment, allocMemory.flags, + (addr_t *)&allocMemory.buffer_base); if (status == B_OK) { // copy result #ifdef __HAIKU__ @@ -231,7 +232,8 @@ device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength) sizeof(intel_allocate_graphics_memory)) < B_OK) return B_BAD_ADDRESS; #else - memcpy(buffer, &allocMemory, sizeof(intel_allocate_graphics_memory)); + memcpy(buffer, &allocMemory, + sizeof(intel_allocate_graphics_memory)); #endif } return status; @@ -249,7 +251,7 @@ device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength) #endif if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC) - return mem_free(info->memory_manager, freeMemory.handle, info); + return intel_free_memory(*info, freeMemory.buffer_base); break; } diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp index c57b6eb84e..e8ac336578 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -132,13 +132,19 @@ init_driver(void) return status; } - status = init_lock(&gLock, "intel extreme ksync"); - if (status < B_OK) { + status = get_module(B_AGP_GART_MODULE_NAME, (module_info **)&gGART); + if (status != B_OK) { + TRACE((DEVICE_NAME ": AGP GART module unavailable\n")); put_module(B_PCI_MODULE_NAME); return status; } - get_module(B_AGP_GART_MODULE_NAME, (module_info **)&gGART); + status = init_lock(&gLock, "intel extreme ksync"); + if (status < B_OK) { + put_module(B_AGP_GART_MODULE_NAME); + put_module(B_PCI_MODULE_NAME); + return status; + } // find devices @@ -185,6 +191,7 @@ init_driver(void) dprintf(DEVICE_NAME ": (%ld) %s, revision = 0x%x\n", found, kSupportedDevices[type].name, info->revision); + found++; } @@ -192,8 +199,7 @@ init_driver(void) if (found == 0) { uninit_lock(&gLock); - if (gGART != NULL) - put_module(B_AGP_GART_MODULE_NAME); + put_module(B_AGP_GART_MODULE_NAME); put_module(B_PCI_MODULE_NAME); return ENODEV; } @@ -216,8 +222,7 @@ uninit_driver(void) free(name); } - if (gGART != NULL) - put_module(B_AGP_GART_MODULE_NAME); + put_module(B_AGP_GART_MODULE_NAME); put_module(B_PCI_MODULE_NAME); } diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h index 846766fb51..57208dbe4f 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.h @@ -28,6 +28,7 @@ extern char *gDeviceNames[]; extern intel_info *gDeviceInfo[]; extern pci_module_info *gPCI; +extern agp_gart_module_info *gGART; extern struct lock gLock; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index eeb8103931..ecab58ff28 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -42,142 +42,17 @@ init_overlay_registers(overlay_registers *registers) static void -read_settings(size_t &memorySize, bool &hardwareCursor, bool &ignoreAllocated) +read_settings(bool &hardwareCursor) { - size_t size = 8; // 8 MB hardwareCursor = false; - ignoreAllocated = false; void *settings = load_driver_settings("intel_extreme"); if (settings != NULL) { - size_t specified = 0; - const char *string = get_driver_parameter(settings, - "graphics_memory_size", "0", "0"); - if (string != NULL) - specified = atoi(string); - hardwareCursor = get_driver_boolean_parameter(settings, "hardware_cursor", true, true); - ignoreAllocated = get_driver_boolean_parameter(settings, - "ignore_bios_allocated_memory", false, false); - unload_driver_settings(settings); - - if (specified != 0) { - // take the next power of two - size_t desired = 1; - while (desired < specified) { - desired *= 2; - } - - if (desired < 128) - size = desired; - } } - - memorySize = size << 20; -} - - -static size_t -determine_stolen_memory_size(intel_info &info) -{ - // read stolen memory from the PCI configuration of the PCI bridge - uint16 memoryConfig = gPCI->read_pci_config(0, 0, 0, INTEL_GRAPHICS_MEMORY_CONTROL, 2); - size_t memorySize = 1 << 20; // 1 MB - size_t gttSize = 0; - - if (info.device_type == INTEL_TYPE_965) { - switch (memoryConfig & i965_GTT_MASK) { - case i965_GTT_128K: - gttSize = 128 << 10; - break; - case i965_GTT_256K: - gttSize = 256 << 10; - break; - case i965_GTT_512K: - gttSize = 512 << 10; - break; - } - } else if (info.device_type == INTEL_TYPE_G33) { - switch (memoryConfig & G33_GTT_MASK) { - case G33_GTT_1M: - gttSize = 1 << 20; - break; - case G33_GTT_2M: - gttSize = 2 << 20; - break; - } - } else { - // older models have the GTT as large as their frame buffer mapping - // TODO: check if the i9xx version works with the i8xx chips as well - size_t frameBufferSize = 0; - if ((info.device_type & INTEL_TYPE_8xx) != 0) { - if (info.device_type == INTEL_TYPE_83x - && (memoryConfig & MEMORY_MASK) == i830_FRAME_BUFFER_64M) - frameBufferSize = 64 << 20; - else - frameBufferSize = 128 << 20; - } else if ((info.device_type & INTEL_TYPE_9xx) != 0) - frameBufferSize = info.pci->u.h0.base_register_sizes[2]; - - gttSize = frameBufferSize / 1024; - } - - // TODO: test with different models! - - if (info.device_type == INTEL_TYPE_83x) { - switch (memoryConfig & STOLEN_MEMORY_MASK) { - case i830_LOCAL_MEMORY_ONLY: - // TODO: determine its size! - break; - case i830_STOLEN_512K: - memorySize >>= 1; - break; - case i830_STOLEN_8M: - memorySize *= 8; - break; - } - } else if (info.device_type == INTEL_TYPE_85x - || (info.device_type & INTEL_TYPE_9xx) != 0) { - switch (memoryConfig & STOLEN_MEMORY_MASK) { - case i855_STOLEN_MEMORY_4M: - memorySize *= 4; - break; - case i855_STOLEN_MEMORY_8M: - memorySize *= 8; - break; - case i855_STOLEN_MEMORY_16M: - memorySize *= 16; - break; - case i855_STOLEN_MEMORY_32M: - memorySize *= 32; - break; - case i855_STOLEN_MEMORY_48M: - memorySize *= 48; - break; - case i855_STOLEN_MEMORY_64M: - memorySize *= 64; - break; - case i855_STOLEN_MEMORY_128M: - memorySize *= 128; - break; - case i855_STOLEN_MEMORY_256M: - memorySize *= 256; - break; - } - } - - return memorySize - gttSize - 4096; -} - - -static void -set_gtt_entry(intel_info &info, uint32 offset, uint8 *physicalAddress) -{ - write32(info.gtt_base + (offset >> GTT_PAGE_SHIFT), - (uint32)physicalAddress | GTT_ENTRY_VALID); } @@ -211,7 +86,8 @@ intel_interrupt_handler(void *data) handled = release_vblank_sem(info); // make sure we'll get another one of those - write32(info.registers + INTEL_DISPLAY_A_PIPE_STATUS, DISPLAY_PIPE_VBLANK_STATUS); + write32(info.registers + INTEL_DISPLAY_A_PIPE_STATUS, + DISPLAY_PIPE_VBLANK_STATUS); } // setting the bit clears it! @@ -239,8 +115,8 @@ init_interrupt_handler(intel_info &info) status = B_ERROR; } - if (status == B_OK - && info.pci->u.h0.interrupt_pin != 0x00 && info.pci->u.h0.interrupt_line != 0xff) { + 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; @@ -250,7 +126,8 @@ init_interrupt_handler(intel_info &info) if (status == B_OK) { // enable interrupts - we only want VBLANK interrupts write16(info.registers + INTEL_INTERRUPT_ENABLED, - read16(info.registers + INTEL_INTERRUPT_ENABLED) | INTERRUPT_VBLANK); + read16(info.registers + INTEL_INTERRUPT_ENABLED) + | INTERRUPT_VBLANK); write16(info.registers + INTEL_INTERRUPT_MASK, ~INTERRUPT_VBLANK); write32(info.registers + INTEL_DISPLAY_A_PIPE_STATUS, @@ -259,9 +136,9 @@ init_interrupt_handler(intel_info &info) } } 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 + // 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! @@ -278,16 +155,39 @@ init_interrupt_handler(intel_info &info) // #pragma mark - +status_t +intel_free_memory(intel_info &info, addr_t offset) +{ + return gGART->deallocate_memory(info.aperture, info.aperture_base + offset); +} + + +status_t +intel_allocate_memory(intel_info &info, size_t size, size_t alignment, + uint32 flags, addr_t *_base, addr_t *_physicalBase) +{ + return gGART->allocate_memory(info.aperture, size, alignment, + flags, _base, _physicalBase); +} + + status_t intel_extreme_init(intel_info &info) { + info.aperture = gGART->map_aperture(info.pci->bus, info.pci->device, + info.pci->function, 0, &info.aperture_base); + if (info.aperture < B_OK) + return info.aperture; + AreaKeeper sharedCreator; info.shared_area = sharedCreator.Create("intel extreme shared info", (void **)&info.shared_info, B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info)) + 3 * B_PAGE_SIZE, B_FULL_LOCK, 0); - if (info.shared_area < B_OK) + if (info.shared_area < B_OK) { + gGART->unmap_aperture(info.aperture); return info.shared_area; + } memset((void *)info.shared_info, 0, sizeof(intel_shared_info)); @@ -302,67 +202,23 @@ intel_extreme_init(intel_info &info) // evaluate driver settings, if any - bool ignoreBIOSAllocated; bool hardwareCursor; - size_t totalSize; - read_settings(totalSize, hardwareCursor, ignoreBIOSAllocated); - - // Determine the amount of "stolen" (ie. reserved by the BIOS) graphics memory - // and see if we need to allocate some more. - // TODO: make it allocate the memory on demand! - - size_t stolenSize = ignoreBIOSAllocated ? 0 : determine_stolen_memory_size(info); - totalSize = max_c(totalSize, stolenSize); - - dprintf(DEVICE_NAME ": detected %ld MB of stolen memory, reserving %ld MB total\n", - stolenSize >> 20, totalSize >> 20); - - AreaKeeper additionalMemoryCreator; - uint8 *additionalMemory; - - if (stolenSize < totalSize) { - // Every device should have at least 8 MB - we could also allocate them - // on demand only, but we're lazy here... - // TODO: overlay seems to have problem when the memory pages are too - // far spreaded - that's why we're using B_CONTIGUOUS for now. - info.additional_memory_area = additionalMemoryCreator.Create("intel additional memory", - (void **)&additionalMemory, B_ANY_KERNEL_ADDRESS, - totalSize - stolenSize, B_CONTIGUOUS /*B_FULL_LOCK*/, 0); - if (info.additional_memory_area < B_OK) - return info.additional_memory_area; - } else - info.additional_memory_area = B_ERROR; - - // map frame buffer, try to map it write combined - - AreaKeeper graphicsMapper; - info.graphics_memory_area = graphicsMapper.Map("intel extreme graphics memory", - (void *)info.pci->u.h0.base_registers[fbIndex], - totalSize, B_ANY_KERNEL_BLOCK_ADDRESS /*| B_MTR_WC*/, - B_READ_AREA | B_WRITE_AREA, (void **)&info.graphics_memory); - if (graphicsMapper.InitCheck() < B_OK) { - // try again without write combining - dprintf(DEVICE_NAME ": enabling write combined mode failed.\n"); - - info.graphics_memory_area = graphicsMapper.Map("intel extreme graphics memory", - (void *)info.pci->u.h0.base_registers[fbIndex], - totalSize/*info.pci->u.h0.base_register_sizes[0]*/, B_ANY_KERNEL_BLOCK_ADDRESS, - B_READ_AREA | B_WRITE_AREA, (void **)&info.graphics_memory); - } - if (graphicsMapper.InitCheck() < B_OK) { - dprintf(DEVICE_NAME ": could not map frame buffer!\n"); - return info.graphics_memory_area; - } + read_settings(hardwareCursor); // memory mapped I/O + // TODO: registers are mapped twice (by us and intel_gart), maybe we + // can share it between the drivers + AreaKeeper mmioMapper; info.registers_area = mmioMapper.Map("intel extreme mmio", (void *)info.pci->u.h0.base_registers[mmioIndex], info.pci->u.h0.base_register_sizes[mmioIndex], - B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA /*0*/, (void **)&info.registers); + B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, + (void **)&info.registers); if (mmioMapper.InitCheck() < B_OK) { dprintf(DEVICE_NAME ": could not map memory I/O!\n"); + gGART->unmap_aperture(info.aperture); return info.registers_area; } @@ -370,53 +226,24 @@ intel_extreme_init(intel_info &info) set_pci_config(info.pci, PCI_command, 2, get_pci_config(info.pci, PCI_command, 2) | PCI_command_io | PCI_command_memory | PCI_command_master); - // init graphics memory manager - - AreaKeeper gttMapper; - info.gtt_area = -1; - - if ((info.device_type & INTEL_TYPE_9xx) != 0) { - if (info.device_type == INTEL_TYPE_965) { - info.gtt_base = info.registers + i965_GTT_BASE; - info.gtt_size = i965_GTT_SIZE; - } else { - info.gtt_area = gttMapper.Map("intel extreme gtt", - (void *)info.pci->u.h0.base_registers[3], totalSize / 1024, - B_ANY_KERNEL_ADDRESS, 0, (void **)&info.gtt_base); - if (gttMapper.InitCheck() < B_OK) { - dprintf(DEVICE_NAME ": could not map GTT area!\n"); - return info.gtt_area; - } - info.gtt_size = totalSize / 1024; - } - } else { - info.gtt_base = info.registers + i830_GTT_BASE; - info.gtt_size = i830_GTT_SIZE; - } - - info.memory_manager = mem_init("intel extreme memory manager", 0, totalSize, 1024, - min_c(totalSize / 1024, 512)); - if (info.memory_manager == NULL) - return B_NO_MEMORY; - // reserve ring buffer memory (currently, this memory is placed in // the graphics memory), but this could bring us problems with // write combining... ring_buffer &primary = info.shared_info->primary_ring_buffer; - if (mem_alloc(info.memory_manager, 4 * B_PAGE_SIZE, &info, - &primary.handle, &primary.offset) == B_OK) { + if (intel_allocate_memory(info, 4 * B_PAGE_SIZE, 0, 0, + (addr_t *)&primary.base) == B_OK) { primary.register_base = INTEL_PRIMARY_RING_BUFFER; primary.size = 4 * B_PAGE_SIZE; - primary.base = info.graphics_memory + primary.offset; + primary.offset = (addr_t)primary.base - info.aperture_base; } ring_buffer &secondary = info.shared_info->secondary_ring_buffer; - if (mem_alloc(info.memory_manager, B_PAGE_SIZE, &info, - &secondary.handle, &secondary.offset) == B_OK) { + if (intel_allocate_memory(info, B_PAGE_SIZE, 0, 0, + (addr_t *)&secondary.base) == B_OK) { secondary.register_base = INTEL_SECONDARY_RING_BUFFER_0; secondary.size = B_PAGE_SIZE; - secondary.base = info.graphics_memory + secondary.offset; + secondary.offset = (addr_t)secondary.base - info.aperture_base; } // Fix some problems on certain chips (taken from X driver) @@ -432,18 +259,16 @@ intel_extreme_init(intel_info &info) // no errors, so keep areas and mappings sharedCreator.Detach(); - additionalMemoryCreator.Detach(); - graphicsMapper.Detach(); mmioMapper.Detach(); - gttMapper.Detach(); - info.shared_info->graphics_memory_area = info.graphics_memory_area; + aperture_info apertureInfo; + gGART->get_aperture_info(info.aperture, &apertureInfo); + info.shared_info->registers_area = info.registers_area; - info.shared_info->graphics_memory = info.graphics_memory; - info.shared_info->physical_graphics_memory = (uint8 *)info.pci->u.h0.base_registers[0]; - - info.shared_info->graphics_memory_size = totalSize; - info.shared_info->frame_buffer_offset = 0; + info.shared_info->graphics_memory = (uint8 *)info.aperture_base; + info.shared_info->physical_graphics_memory = apertureInfo.physical_base; + info.shared_info->graphics_memory_size = apertureInfo.size; + info.shared_info->frame_buffer = 0; info.shared_info->dpms_mode = B_DPMS_ON; if ((info.device_type & INTEL_TYPE_9xx) != 0) { @@ -468,62 +293,26 @@ intel_extreme_init(intel_info &info) // setup overlay registers - if (info.device_type == INTEL_TYPE_G33) { - if (mem_alloc(info.memory_manager, B_PAGE_SIZE, &info, - &info.overlay_handle, &info.overlay_offset) == B_OK) { - info.overlay_registers = (overlay_registers *)(info.graphics_memory - + info.overlay_offset); - info.shared_info->overlay_offset = info.overlay_offset; - } - } else { - info.overlay_registers = (overlay_registers *)((uint8 *)info.shared_info - + ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info))); + if (intel_allocate_memory(info, B_PAGE_SIZE, 0, B_APERTURE_NEED_PHYSICAL, + (addr_t *)&info.overlay_registers, + &info.shared_info->physical_overlay_registers) == B_OK) { + info.shared_info->overlay_offset = (addr_t)info.overlay_registers + - info.aperture_base; } + init_overlay_registers(info.overlay_registers); - physical_entry physicalEntry; - get_memory_map(info.overlay_registers, sizeof(overlay_registers), &physicalEntry, 1); - info.shared_info->physical_overlay_registers = (uint8 *)physicalEntry.address; + // Allocate hardware status page and the cursor memory - // The hardware status page and the cursor memory share one area with - // the overlay registers and the shared info - - uint8 *base = (uint8 *)info.shared_info + ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info)); - get_memory_map(base + B_PAGE_SIZE, B_PAGE_SIZE, &physicalEntry, 1); - info.shared_info->physical_status_page = (uint8 *)physicalEntry.address; - - get_memory_map(base + 2 * B_PAGE_SIZE, B_PAGE_SIZE, &physicalEntry, 1); - info.shared_info->physical_cursor_memory = (uint8 *)physicalEntry.address; - - // setup the GTT to point to include the additional memory - - if (stolenSize < totalSize) { - for (size_t offset = stolenSize; offset < totalSize;) { - physical_entry physicalEntry; - get_memory_map(additionalMemory + offset - stolenSize, - totalSize - offset, &physicalEntry, 1); - - for (size_t i = 0; i < physicalEntry.size; i += B_PAGE_SIZE) { - set_gtt_entry(info, offset + i, (uint8 *)physicalEntry.address + i); - } - - offset += physicalEntry.size; - } + if (intel_allocate_memory(info, B_PAGE_SIZE, 0, B_APERTURE_NEED_PHYSICAL, + (addr_t *)info.shared_info->status_page, + &info.shared_info->physical_status_page) == B_OK) { + // TODO: set status page } - - // We also need to map the cursor memory into the GTT - - info.shared_info->hardware_cursor_enabled = hardwareCursor; if (hardwareCursor) { - // This could also be part of the usual graphics memory, but since we - // need to make sure it's not in the graphics local memory (and I don't - // even know yet how to determine that a chip has local memory...), we - // keep the current strategy and put it into the shared area. - // Unfortunately, the GTT is not readable until it has been written into - // the double buffered register set; we cannot get its original contents. - - set_gtt_entry(info, totalSize, info.shared_info->physical_cursor_memory); - info.shared_info->cursor_buffer_offset = totalSize; + intel_allocate_memory(info, B_PAGE_SIZE, 0, B_APERTURE_NEED_PHYSICAL, + (addr_t *)&info.shared_info->cursor_memory, + &info.shared_info->physical_cursor_memory); } init_interrupt_handler(info); @@ -547,15 +336,9 @@ intel_extreme_uninit(intel_info &info) intel_interrupt_handler, &info); } - mem_destroy(info.memory_manager); + gGART->unmap_aperture(info.aperture); - delete_area(info.graphics_memory_area); - delete_area(info.gtt_area); delete_area(info.registers_area); delete_area(info.shared_area); - - // we may or may not have allocated additional graphics memory - if (info.additional_memory_area >= B_OK) - delete_area(info.additional_memory_area); } diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h index d764b6fa92..f51a7a154f 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2008, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -9,6 +9,7 @@ #define INTEL_EXTREME_PRIVATE_H +#include #include #include @@ -21,24 +22,14 @@ struct intel_info { status_t init_status; int32 id; pci_info *pci; + addr_t aperture_base; + aperture_id aperture; uint8 *registers; area_id registers_area; struct intel_shared_info *shared_info; area_id shared_area; - uint32 overlay_handle; - uint32 overlay_offset; struct overlay_registers *overlay_registers; - // update buffer, shares an area with shared_info - - uint8 *gtt_base; - size_t gtt_size; - area_id gtt_area; - uint8 *graphics_memory; - area_id graphics_memory_area; - area_id additional_memory_area; - // allocated memory beyond the "stolen" amount - mem_info *memory_manager; bool fake_interrupts; @@ -46,6 +37,10 @@ struct intel_info { uint32 device_type; }; +extern status_t intel_free_memory(intel_info &info, addr_t offset); +extern status_t intel_allocate_memory(intel_info &info, size_t size, + size_t alignment, uint32 flags, addr_t *_offset, + addr_t *_physicalBase = NULL); extern status_t intel_extreme_init(intel_info &info); extern void intel_extreme_uninit(intel_info &info);