diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 00e995de12..0f2821809b 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -27,9 +27,10 @@ #define INTEL_TYPE_9xx 0x04 #define INTEL_TYPE_83x 0x10 #define INTEL_TYPE_85x 0x20 -#define INTEL_TYPE_915 0x10 +#define INTEL_TYPE_91x 0x10 #define INTEL_TYPE_945 0x20 #define INTEL_TYPE_965 0x40 +#define INTEL_TYPE_G33 0x80 #define DEVICE_NAME "intel_extreme" #define INTEL_ACCELERANT_NAME "intel_extreme.accelerant" @@ -84,6 +85,7 @@ struct intel_shared_info { bool overlay_active; uint32 overlay_token; uint8* physical_overlay_registers; + uint32 overlay_offset; bool hardware_cursor_enabled; sem_id vblank_sem; @@ -138,13 +140,18 @@ struct intel_free_graphics_memory { // PCI bridge memory management #define INTEL_GRAPHICS_MEMORY_CONTROL 0x52 +#define MEMORY_MASK 0x01 #define STOLEN_MEMORY_MASK 0x70 +#define i965_GTT_MASK 0x000e +#define G33_GTT_MASK 0x0300 // models i830 and up #define i830_LOCAL_MEMORY_ONLY 0x10 #define i830_STOLEN_512K 0x20 #define i830_STOLEN_1M 0x30 #define i830_STOLEN_8M 0x40 +#define i830_FRAME_BUFFER_64M 0x01 +#define i830_FRAME_BUFFER_128M 0x00 // models i855 and up #define i855_STOLEN_MEMORY_1M 0x10 @@ -154,6 +161,8 @@ struct intel_free_graphics_memory { #define i855_STOLEN_MEMORY_32M 0x50 #define i855_STOLEN_MEMORY_48M 0x60 #define i855_STOLEN_MEMORY_64M 0x70 +#define i855_STOLEN_MEMORY_128M 0x80 +#define i855_STOLEN_MEMORY_256M 0x90 // graphics page translation table #define INTEL_PAGE_TABLE_CONTROL 0x02020 @@ -163,6 +172,11 @@ struct intel_free_graphics_memory { #define i830_GTT_SIZE 0x20000 #define i965_GTT_BASE 0x80000 // (- 0xfffff) #define i965_GTT_SIZE 0x80000 +#define i965_GTT_128K (2 << 1) +#define i965_GTT_256K (1 << 1) +#define i965_GTT_512K (0 << 1) +#define G33_GTT_1M (1 << 8) +#define G33_GTT_2M (2 << 8) #define GTT_ENTRY_VALID 0x01 #define GTT_ENTRY_LOCAL_MEMORY 0x02 @@ -481,12 +495,21 @@ struct overlay_registers { uint32 _reserved20; + uint32 start_0y; + uint32 start_1y; + uint32 start_0u; + uint32 start_0v; + uint32 start_1u; + uint32 start_1v; + uint32 _reserved21[6]; +#if 0 // (0x70) AWINPOS - alpha blend window position uint32 awinpos; // (0x74) AWINSZ - alpha blend window size uint32 awinsz; uint32 _reserved21[10]; +#endif // (0xa0) FASTHSCALE - fast horizontal downscale (strangely enough, // the next two registers switch the usual Y/RGB vs. UV order) @@ -509,6 +532,10 @@ struct overlay_registers { uint16 horizontal_coefficients_uv[128]; }; +// i965 overlay support is currently realized using its 3D hardware +#define INTEL_i965_OVERLAY_STATE_SIZE 36864 +#define INTEL_i965_3D_CONTEXT_SIZE 32768 + struct hardware_status { uint32 interrupt_status_register; uint32 _reserved0[3]; 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 c6f340fa10..c67d86327c 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/driver.cpp @@ -42,15 +42,16 @@ const struct supported_device { {0x2572, INTEL_TYPE_8xx | INTEL_TYPE_85x, "i865G"}, {0x3582, INTEL_TYPE_8xx | INTEL_TYPE_85x, "i855G"}, -#if 1 - {0x2792, INTEL_TYPE_9xx, "i910"}, - {0x258a, INTEL_TYPE_9xx, "i915"}, - {0x2582, INTEL_TYPE_9xx, "i915G"}, - {0x2592, INTEL_TYPE_9xx, "i915GM"}, - {0x2772, INTEL_TYPE_9xx, "i945G"}, - {0x27a2, INTEL_TYPE_9xx, "i945GM"}, - {0x29a2, INTEL_TYPE_9xx | INTEL_TYPE_965, "i965G"} -#endif + {0x2792, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i910"}, + {0x258a, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i915"}, + {0x2582, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i915G"}, + {0x2592, INTEL_TYPE_9xx | INTEL_TYPE_91x, "i915GM"}, + {0x2772, INTEL_TYPE_9xx | INTEL_TYPE_945, "i945G"}, + {0x27a2, INTEL_TYPE_9xx | INTEL_TYPE_945, "i945GM"}, + {0x29a2, INTEL_TYPE_9xx | INTEL_TYPE_965, "i965G"}, + {0x29b2, INTEL_TYPE_9xx | INTEL_TYPE_G33, "G33G"}, + {0x29c2, INTEL_TYPE_9xx | INTEL_TYPE_G33, "Q35G"}, + {0x29d2, INTEL_TYPE_9xx | INTEL_TYPE_G33, "Q33G"}, }; int32 api_version = B_CUR_DRIVER_API_VERSION; 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 8c878e4e3f..188f118596 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 @@ -104,7 +104,7 @@ static void read_settings(size_t &memorySize, bool &hardwareCursor, bool &ignoreAllocated) { size_t size = 8; // 8 MB - hardwareCursor = true; + hardwareCursor = false; ignoreAllocated = false; void *settings = load_driver_settings("intel_extreme"); @@ -145,6 +145,45 @@ 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; + + // TODO: check if the GTT is really part of the stolen memory + if (info.device_type == (INTEL_TYPE_9xx | 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_9xx | 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_FAMILY_MASK) == INTEL_TYPE_8xx) { + if ((info.device_type & INTEL_TYPE_83x) != 0 + && (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]; + + gttSize = frameBufferSize / 1024; + } // TODO: test with different models! @@ -181,10 +220,16 @@ determine_stolen_memory_size(intel_info &info) 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; + return memorySize - gttSize - 4096; } @@ -352,7 +397,7 @@ intel_extreme_init(intel_info &info) 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, + 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 @@ -386,26 +431,33 @@ intel_extreme_init(intel_info &info) // init graphics memory manager - 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; + AreaKeeper gttMapper; + info.gtt_area = -1; if ((info.device_type & INTEL_TYPE_9xx) != 0) { if ((info.device_type & INTEL_TYPE_GROUP_MASK) == INTEL_TYPE_965) { info.gtt_base = info.registers + i965_GTT_BASE; info.gtt_size = i965_GTT_SIZE; } else { - // TODO: map it in??? - info.gtt_base = (uint8*)info.pci->u.h0.base_register_sizes[3]; - info.gtt_size = i830_GTT_SIZE; - // TODO: for now... + 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... @@ -426,11 +478,23 @@ intel_extreme_init(intel_info &info) secondary.base = info.graphics_memory + secondary.offset; } + // Fix some problems on certain chips (taken from X driver) + // TODO: clean this up + if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) { + dprintf("i965GM/i965GME quirk\n"); + write32(info.registers + 0x6204, (1L << 29)); + } else { + dprintf("i965 quirk\n"); + write32(info.registers + 0x6204, (1L << 29) | (1L << 23)); + } + write32(info.registers + 0x7408, 0x10); + // 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; info.shared_info->registers_area = info.registers_area; @@ -463,8 +527,17 @@ intel_extreme_init(intel_info &info) // setup overlay registers - info.overlay_registers = (overlay_registers *)((uint8 *)info.shared_info - + ROUND_TO_PAGE_SIZE(sizeof(intel_shared_info))); + if (info.device_type == (INTEL_TYPE_9xx | 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))); + } init_overlay_registers(info.overlay_registers); physical_entry physicalEntry; @@ -474,12 +547,11 @@ intel_extreme_init(intel_info &info) // The hardware status page and the cursor memory share one area with // the overlay registers and the shared info - get_memory_map((uint8 *)info.overlay_registers + B_PAGE_SIZE, - B_PAGE_SIZE, &physicalEntry, 1); + 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((uint8 *)info.overlay_registers + 2 * B_PAGE_SIZE, - B_PAGE_SIZE, &physicalEntry, 1); + 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 @@ -537,6 +609,7 @@ intel_extreme_uninit(intel_info &info) mem_destroy(info.memory_manager); delete_area(info.graphics_memory_area); + delete_area(info.gtt_area); delete_area(info.registers_area); delete_area(info.shared_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 e000dc2902..d764b6fa92 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 @@ -26,11 +26,14 @@ struct intel_info { 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;