* Prepared having hardware cursor support; got quite complicated because there
is no good (or reliable) way to retrieve the physical address of "stolen" (by the BIOS) graphics memory. * Implemented allocation of additional graphics memory in case the BIOS was a bit too cheap. We now guarantee 8 MB of memory available to the graphics chip - would be nicer to only allocate that on demand, though. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17433 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c8609aed8c
commit
ccb666bc0e
@ -20,11 +20,11 @@
|
||||
|
||||
#define VENDOR_ID_INTEL 0x8086
|
||||
|
||||
enum {
|
||||
INTEL_TYPE_7xx,
|
||||
INTEL_TYPE_8xx,
|
||||
INTEL_TYPE_9xx,
|
||||
};
|
||||
#define INTEL_TYPE_7xx 0x01
|
||||
#define INTEL_TYPE_8xx 0x02
|
||||
#define INTEL_TYPE_9xx 0x03
|
||||
#define INTEL_TYPE_83x 0x10
|
||||
#define INTEL_TYPE_85x 0x20
|
||||
|
||||
#define DEVICE_NAME "intel_extreme"
|
||||
#define INTEL_ACCELERANT_NAME "intel_extreme.accelerant"
|
||||
@ -64,6 +64,7 @@ struct intel_shared_info {
|
||||
|
||||
area_id registers_area; // area of memory mapped registers
|
||||
uint8 *physical_status_page;
|
||||
area_id cursor_area;
|
||||
uint8 *physical_cursor_memory;
|
||||
area_id graphics_memory_area;
|
||||
uint8 *graphics_memory;
|
||||
@ -94,12 +95,15 @@ struct intel_info {
|
||||
area_id registers_area;
|
||||
struct intel_shared_info *shared_info;
|
||||
area_id shared_area;
|
||||
area_id cursor_area;
|
||||
|
||||
struct overlay_registers *overlay_registers;
|
||||
// update buffer, shares an area with shared_info
|
||||
|
||||
uint8 *graphics_memory;
|
||||
area_id graphics_memory_area;
|
||||
area_id additional_memory_area;
|
||||
// allocated memory beyond the "stolen" amount
|
||||
mem_info *memory_manager;
|
||||
|
||||
const char *device_identifier;
|
||||
@ -162,10 +166,12 @@ struct intel_free_graphics_memory {
|
||||
#define i855_STOLEN_MEMORY_48M 0x60
|
||||
#define i855_STOLEN_MEMORY_64M 0x70
|
||||
|
||||
|
||||
#define INTEL_PAGE_TABLE_CONTROL 0x02020
|
||||
#define INTEL_PAGE_TABLE_ERROR 0x02024
|
||||
#define INTEL_HARDWARE_STATUS_PAGE 0x02080
|
||||
#define INTEL_GTT_BASE 0x10000 // (- 0x2ffff)
|
||||
#define GTT_ENTRY_VALID 0x01
|
||||
#define GTT_ENTRY_LOCAL_MEMORY 0x02
|
||||
|
||||
#define INTEL_PRIMARY_RING_BUFFER 0x02030
|
||||
#define INTEL_SECONDARY_RING_BUFFER_0 0x02100
|
||||
@ -232,6 +238,12 @@ struct intel_free_graphics_memory {
|
||||
#define DISPLAY_MONITOR_POSITIVE_HSYNC (1UL << 3)
|
||||
#define DISPLAY_MONITOR_POSITIVE_VSYNC (2UL << 3)
|
||||
|
||||
#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
|
||||
|
||||
// ring buffer commands
|
||||
|
||||
#define COMMAND_NOOP 0x00
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <syslog.h>
|
||||
|
||||
|
||||
//#define TRACE_ACCELERANT
|
||||
#define TRACE_ACCELERANT
|
||||
#ifdef TRACE_ACCELERANT
|
||||
extern "C" void _sPrintf(const char *format, ...);
|
||||
# define TRACE(x) _sPrintf x
|
||||
@ -128,8 +128,19 @@ init_common(int device, bool isClone)
|
||||
return status;
|
||||
}
|
||||
|
||||
AreaCloner cursorCloner;
|
||||
gInfo->cursor_area = cursorCloner.Clone("intel extreme cursor",
|
||||
(void **)&gInfo->cursor_memory, B_ANY_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA,
|
||||
gInfo->shared_info->cursor_area);
|
||||
if (cursorCloner.InitCheck() < B_OK) {
|
||||
// we can't do a hardware cursor then...
|
||||
gInfo->cursor_memory = NULL;
|
||||
}
|
||||
|
||||
sharedCloner.Keep();
|
||||
regsCloner.Keep();
|
||||
cursorCloner.Keep();
|
||||
|
||||
// The overlay registers, hardware status, and cursor memory share
|
||||
// a single area with the shared_info
|
||||
@ -148,6 +159,7 @@ init_common(int device, bool isClone)
|
||||
static void
|
||||
uninit_common(void)
|
||||
{
|
||||
delete_area(gInfo->cursor_area);
|
||||
delete_area(gInfo->regs_area);
|
||||
delete_area(gInfo->shared_info_area);
|
||||
|
||||
@ -157,7 +169,6 @@ uninit_common(void)
|
||||
gInfo->shared_info = NULL;
|
||||
|
||||
// close the file handle ONLY if we're the clone
|
||||
// (this is what Be tells us ;)
|
||||
if (gInfo->is_clone)
|
||||
close(gInfo->device);
|
||||
|
||||
|
@ -49,6 +49,7 @@ struct accelerant_info {
|
||||
|
||||
hardware_status *status;
|
||||
uint8 *cursor_memory;
|
||||
area_id cursor_area;
|
||||
|
||||
int device;
|
||||
bool is_clone;
|
||||
|
@ -45,7 +45,7 @@ uint32 intel_dpms_mode(void);
|
||||
status_t intel_set_dpms_mode(uint32 flags);
|
||||
|
||||
// cursor
|
||||
status_t intel_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotX,
|
||||
status_t intel_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotY,
|
||||
uint8 *andMask, uint8 *xorMask);
|
||||
void intel_move_cursor(uint16 x, uint16 y);
|
||||
void intel_show_cursor(bool isVisible);
|
||||
|
@ -36,8 +36,8 @@ const struct supported_device {
|
||||
int32 type;
|
||||
const char *name;
|
||||
} kSupportedDevices[] = {
|
||||
{0x2572, INTEL_TYPE_8xx, "i865G"},
|
||||
{0x3582, INTEL_TYPE_8xx, "i855G"},
|
||||
{0x2572, INTEL_TYPE_8xx | INTEL_TYPE_85x, "i865G"},
|
||||
{0x3582, INTEL_TYPE_8xx | INTEL_TYPE_85x, "i855G"},
|
||||
};
|
||||
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION;
|
||||
|
@ -91,6 +91,62 @@ init_overlay_registers(overlay_registers *registers)
|
||||
}
|
||||
|
||||
|
||||
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 = 1024 * 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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return memorySize;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_gtt_entry(intel_info &info, uint32 offset, uint8 *physicalAddress)
|
||||
{
|
||||
write32(info.registers + INTEL_GTT_BASE + (offset >> 10),
|
||||
(uint32)physicalAddress | GTT_ENTRY_VALID);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -107,41 +163,35 @@ intel_extreme_init(intel_info &info)
|
||||
|
||||
memset((void *)info.shared_info, 0, sizeof(intel_shared_info));
|
||||
|
||||
// get chipset info
|
||||
// Determine the amount of "stolen" (ie. reserved by the BIOS) graphics memory
|
||||
// and see if we need to allocate some more.
|
||||
// TODO: introduce a settings value which you can use to cut down the memory
|
||||
// requirements, or make it allocate the memory on demand!
|
||||
|
||||
// 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 = 1024 * 1024;
|
||||
size_t stolenSize = determine_stolen_memory_size(info);
|
||||
dprintf(DEVICE_NAME ": detected %ld MB of stolen memory\n", stolenSize / 1024 / 1024);
|
||||
|
||||
// TODO: this doesn't work like this on anything older than i855
|
||||
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;
|
||||
}
|
||||
dprintf(DEVICE_NAME ": detected %ld MB of stolen memory\n", memorySize / 1024 / 1024);
|
||||
AreaKeeper additionalMemoryCreator;
|
||||
size_t totalSize = max_c(8 * 1024 * 1024, stolenSize);
|
||||
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...
|
||||
info.additional_memory_area = additionalMemoryCreator.Create("intel additional memory",
|
||||
(void **)&additionalMemory, B_ANY_KERNEL_ADDRESS,
|
||||
totalSize - stolenSize, 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[0],
|
||||
memorySize, 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
|
||||
@ -149,7 +199,7 @@ intel_extreme_init(intel_info &info)
|
||||
|
||||
info.graphics_memory_area = graphicsMapper.Map("intel extreme graphics memory",
|
||||
(void *)info.pci->u.h0.base_registers[0],
|
||||
memorySize/*info.pci->u.h0.base_register_sizes[0]*/, B_ANY_KERNEL_BLOCK_ADDRESS,
|
||||
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) {
|
||||
@ -163,9 +213,7 @@ intel_extreme_init(intel_info &info)
|
||||
info.registers_area = mmioMapper.Map("intel extreme mmio",
|
||||
(void *)info.pci->u.h0.base_registers[1],
|
||||
info.pci->u.h0.base_register_sizes[1],
|
||||
B_ANY_KERNEL_BLOCK_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA,
|
||||
(void **)&info.registers);
|
||||
B_ANY_KERNEL_ADDRESS, 0, (void **)&info.registers);
|
||||
if (mmioMapper.InitCheck() < B_OK) {
|
||||
dprintf(DEVICE_NAME ": could not map memory I/O!\n");
|
||||
return info.registers_area;
|
||||
@ -173,8 +221,8 @@ intel_extreme_init(intel_info &info)
|
||||
|
||||
// init graphics memory manager
|
||||
|
||||
info.memory_manager = mem_init("intel extreme memory manager", 0, memorySize, 1024,
|
||||
min_c(memorySize / 1024, 512));
|
||||
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;
|
||||
|
||||
@ -208,7 +256,7 @@ intel_extreme_init(intel_info &info)
|
||||
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 = memorySize;
|
||||
info.shared_info->graphics_memory_size = totalSize;
|
||||
info.shared_info->frame_buffer_offset = 0;
|
||||
info.shared_info->dpms_mode = B_DPMS_ON;
|
||||
info.shared_info->pll_info.reference_frequency = 48000; // 48 kHz
|
||||
@ -245,6 +293,43 @@ intel_extreme_init(intel_info &info)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// We also need to map the cursor memory into the GTT
|
||||
|
||||
// This could also be part of the usual graphics memory, but for some
|
||||
// reason we need its physical address, too - and we only know that of
|
||||
// the additional memory we allocated.
|
||||
// Unfortunately, the GTT is not readable - we would need to compute
|
||||
// the physical location of stolen memory with some heuristics (as it
|
||||
// should be taken from the top of system memory), and hope that the
|
||||
// BIOS adhered to this specification.
|
||||
|
||||
set_gtt_entry(info, totalSize, info.shared_info->physical_cursor_memory);
|
||||
|
||||
AreaKeeper cursorMapper;
|
||||
info.cursor_area = cursorMapper.Map("intel extreme cursor",
|
||||
(void *)(info.shared_info->physical_graphics_memory + totalSize),
|
||||
B_PAGE_SIZE, B_ANY_KERNEL_ADDRESS, 0, (void **)&info.registers);
|
||||
if (cursorMapper.InitCheck() < B_OK) {
|
||||
// we can't do a hardware cursor, then...
|
||||
}
|
||||
info.shared_info->cursor_area = info.cursor_area;
|
||||
|
||||
info.cookie_magic = INTEL_COOKIE_MAGIC;
|
||||
// this makes the cookie valid to be used
|
||||
|
||||
@ -264,5 +349,10 @@ intel_extreme_uninit(intel_info &info)
|
||||
delete_area(info.graphics_memory_area);
|
||||
delete_area(info.registers_area);
|
||||
delete_area(info.shared_area);
|
||||
delete_area(info.cursor_area);
|
||||
|
||||
// we may or may not have allocated additional graphics memory
|
||||
if (info.additional_memory_area >= B_OK)
|
||||
delete_area(info.additional_memory_area);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user