Remove the interrupt register block. These aren't actually identitiy mapped
(they are actually reversed), so introduce a find_reg() inline function to map such regs individually instead. Should fix interrupt storms on SandyBridge. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42870 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
// We encode the register block into the value and extract/translate it when
|
// We encode the register block into the value and extract/translate it when
|
||||||
// actually accessing.
|
// actually accessing.
|
||||||
#define REGISTER_BLOCK_COUNT 7
|
#define REGISTER_BLOCK_COUNT 6
|
||||||
#define REGISTER_BLOCK_SHIFT 24
|
#define REGISTER_BLOCK_SHIFT 24
|
||||||
#define REGISTER_BLOCK_MASK 0xff000000
|
#define REGISTER_BLOCK_MASK 0xff000000
|
||||||
#define REGISTER_REGISTER_MASK 0x00ffffff
|
#define REGISTER_REGISTER_MASK 0x00ffffff
|
||||||
@@ -69,15 +69,13 @@
|
|||||||
#define REGISTER_REGISTER(x) (x & REGISTER_REGISTER_MASK)
|
#define REGISTER_REGISTER(x) (x & REGISTER_REGISTER_MASK)
|
||||||
|
|
||||||
#define REGS_FLAT (0 << REGISTER_BLOCK_SHIFT)
|
#define REGS_FLAT (0 << REGISTER_BLOCK_SHIFT)
|
||||||
#define REGS_INTERRUPT (1 << REGISTER_BLOCK_SHIFT)
|
#define REGS_NORTH_SHARED (1 << REGISTER_BLOCK_SHIFT)
|
||||||
#define REGS_NORTH_SHARED (2 << REGISTER_BLOCK_SHIFT)
|
#define REGS_NORTH_PIPE_AND_PORT (2 << REGISTER_BLOCK_SHIFT)
|
||||||
#define REGS_NORTH_PIPE_AND_PORT (3 << REGISTER_BLOCK_SHIFT)
|
#define REGS_NORTH_PLANE_CONTROL (3 << REGISTER_BLOCK_SHIFT)
|
||||||
#define REGS_NORTH_PLANE_CONTROL (4 << REGISTER_BLOCK_SHIFT)
|
#define REGS_SOUTH_SHARED (4 << REGISTER_BLOCK_SHIFT)
|
||||||
#define REGS_SOUTH_SHARED (5 << REGISTER_BLOCK_SHIFT)
|
#define REGS_SOUTH_TRANSCODER_PORT (5 << REGISTER_BLOCK_SHIFT)
|
||||||
#define REGS_SOUTH_TRANSCODER_PORT (6 << REGISTER_BLOCK_SHIFT)
|
|
||||||
|
|
||||||
// register blocks for (G)MCH/ICH based platforms
|
// register blocks for (G)MCH/ICH based platforms
|
||||||
#define MCH_INTERRUPT_REGISTER_BASE 0x020a0
|
|
||||||
#define MCH_SHARED_REGISTER_BASE 0x00000
|
#define MCH_SHARED_REGISTER_BASE 0x00000
|
||||||
#define MCH_PIPE_AND_PORT_REGISTER_BASE 0x60000
|
#define MCH_PIPE_AND_PORT_REGISTER_BASE 0x60000
|
||||||
#define MCH_PLANE_CONTROL_REGISTER_BASE 0x70000
|
#define MCH_PLANE_CONTROL_REGISTER_BASE 0x70000
|
||||||
@@ -88,7 +86,6 @@
|
|||||||
// to a PCH based one, that means anything that used to communicate via (G)MCH
|
// to a PCH based one, that means anything that used to communicate via (G)MCH
|
||||||
// registers needs to use different ones on PCH based platforms (Ironlake and
|
// registers needs to use different ones on PCH based platforms (Ironlake and
|
||||||
// up, SandyBridge, etc.).
|
// up, SandyBridge, etc.).
|
||||||
#define PCH_DE_INTERRUPT_REGISTER_BASE 0x44000
|
|
||||||
#define PCH_NORTH_SHARED_REGISTER_BASE 0x40000
|
#define PCH_NORTH_SHARED_REGISTER_BASE 0x40000
|
||||||
#define PCH_NORTH_PIPE_AND_PORT_REGISTER_BASE 0x60000
|
#define PCH_NORTH_PIPE_AND_PORT_REGISTER_BASE 0x60000
|
||||||
#define PCH_NORTH_PLANE_CONTROL_REGISTER_BASE 0x70000
|
#define PCH_NORTH_PLANE_CONTROL_REGISTER_BASE 0x70000
|
||||||
@@ -338,13 +335,18 @@ struct intel_free_graphics_memory {
|
|||||||
#define INTEL_RING_BUFFER_ENABLED 1
|
#define INTEL_RING_BUFFER_ENABLED 1
|
||||||
|
|
||||||
// interrupts
|
// interrupts
|
||||||
#define INTEL_INTERRUPT_ENABLED (0x0000 | REGS_INTERRUPT)
|
#define INTEL_INTERRUPT_ENABLED 0x02a0
|
||||||
#define INTEL_INTERRUPT_IDENTITY (0x0004 | REGS_INTERRUPT)
|
#define INTEL_INTERRUPT_IDENTITY 0x02a4
|
||||||
#define INTEL_INTERRUPT_MASK (0x0008 | REGS_INTERRUPT)
|
#define INTEL_INTERRUPT_MASK 0x02a8
|
||||||
#define INTEL_INTERRUPT_STATUS (0x000c | REGS_INTERRUPT)
|
#define INTEL_INTERRUPT_STATUS 0x02ac
|
||||||
#define INTERRUPT_VBLANK_PIPEA (1 << 7)
|
#define INTERRUPT_VBLANK_PIPEA (1 << 7)
|
||||||
#define INTERRUPT_VBLANK_PIPEB (1 << 5)
|
#define INTERRUPT_VBLANK_PIPEB (1 << 5)
|
||||||
// TODO: verify that these are actually different on older versions
|
|
||||||
|
// PCH interrupts
|
||||||
|
#define PCH_INTERRUPT_STATUS 0x44000
|
||||||
|
#define PCH_INTERRUPT_MASK 0x44004
|
||||||
|
#define PCH_INTERRUPT_IDENTITY 0x44008
|
||||||
|
#define PCH_INTERRUPT_ENABLED 0x4400c
|
||||||
#define PCH_INTERRUPT_VBLANK_PIPEA (1 << 7)
|
#define PCH_INTERRUPT_VBLANK_PIPEA (1 << 7)
|
||||||
#define PCH_INTERRUPT_VBLANK_PIPEB (1 << 15)
|
#define PCH_INTERRUPT_VBLANK_PIPEB (1 << 15)
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ intel_interrupt_handler(void* data)
|
|||||||
{
|
{
|
||||||
intel_info &info = *(intel_info*)data;
|
intel_info &info = *(intel_info*)data;
|
||||||
|
|
||||||
uint16 identity = read16(info, INTEL_INTERRUPT_IDENTITY);
|
uint16 identity = read16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY));
|
||||||
if (identity == 0)
|
if (identity == 0)
|
||||||
return B_UNHANDLED_INTERRUPT;
|
return B_UNHANDLED_INTERRUPT;
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ intel_interrupt_handler(void* data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setting the bit clears it!
|
// setting the bit clears it!
|
||||||
write16(info, INTEL_INTERRUPT_IDENTITY, identity);
|
write16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY), identity);
|
||||||
|
|
||||||
return handled;
|
return handled;
|
||||||
}
|
}
|
||||||
@@ -142,7 +142,7 @@ init_interrupt_handler(intel_info &info)
|
|||||||
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
|
write32(info, INTEL_DISPLAY_B_PIPE_STATUS,
|
||||||
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
|
DISPLAY_PIPE_VBLANK_STATUS | DISPLAY_PIPE_VBLANK_ENABLED);
|
||||||
|
|
||||||
write16(info, INTEL_INTERRUPT_IDENTITY, ~0);
|
write16(info, find_reg(info, INTEL_INTERRUPT_IDENTITY), ~0);
|
||||||
|
|
||||||
// enable interrupts - we only want VBLANK interrupts
|
// enable interrupts - we only want VBLANK interrupts
|
||||||
bool hasPCH = info.device_type.HasPlatformControlHub();
|
bool hasPCH = info.device_type.HasPlatformControlHub();
|
||||||
@@ -150,9 +150,8 @@ init_interrupt_handler(intel_info &info)
|
|||||||
? (PCH_INTERRUPT_VBLANK_PIPEA | PCH_INTERRUPT_VBLANK_PIPEB)
|
? (PCH_INTERRUPT_VBLANK_PIPEA | PCH_INTERRUPT_VBLANK_PIPEB)
|
||||||
: (INTERRUPT_VBLANK_PIPEA | INTERRUPT_VBLANK_PIPEB);
|
: (INTERRUPT_VBLANK_PIPEA | INTERRUPT_VBLANK_PIPEB);
|
||||||
|
|
||||||
write16(info, INTEL_INTERRUPT_ENABLED,
|
write16(info, find_reg(info, INTEL_INTERRUPT_ENABLED), enable);
|
||||||
read16(info, INTEL_INTERRUPT_ENABLED) | enable);
|
write16(info, find_reg(info, INTEL_INTERRUPT_MASK), ~enable);
|
||||||
write16(info, INTEL_INTERRUPT_MASK, ~enable);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
@@ -250,8 +249,6 @@ intel_extreme_init(intel_info &info)
|
|||||||
// setup the register blocks for the different architectures
|
// setup the register blocks for the different architectures
|
||||||
if (info.device_type.HasPlatformControlHub()) {
|
if (info.device_type.HasPlatformControlHub()) {
|
||||||
// PCH based platforms (IronLake and up)
|
// PCH based platforms (IronLake and up)
|
||||||
blocks[REGISTER_BLOCK(REGS_INTERRUPT)]
|
|
||||||
= PCH_DE_INTERRUPT_REGISTER_BASE;
|
|
||||||
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]
|
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]
|
||||||
= PCH_NORTH_SHARED_REGISTER_BASE;
|
= PCH_NORTH_SHARED_REGISTER_BASE;
|
||||||
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]
|
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]
|
||||||
@@ -264,8 +261,6 @@ intel_extreme_init(intel_info &info)
|
|||||||
= PCH_SOUTH_TRANSCODER_AND_PORT_REGISTER_BASE;
|
= PCH_SOUTH_TRANSCODER_AND_PORT_REGISTER_BASE;
|
||||||
} else {
|
} else {
|
||||||
// (G)MCH/ICH based platforms
|
// (G)MCH/ICH based platforms
|
||||||
blocks[REGISTER_BLOCK(REGS_INTERRUPT)]
|
|
||||||
= MCH_INTERRUPT_REGISTER_BASE;
|
|
||||||
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]
|
blocks[REGISTER_BLOCK(REGS_NORTH_SHARED)]
|
||||||
= MCH_SHARED_REGISTER_BASE;
|
= MCH_SHARED_REGISTER_BASE;
|
||||||
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]
|
blocks[REGISTER_BLOCK(REGS_NORTH_PIPE_AND_PORT)]
|
||||||
@@ -401,8 +396,8 @@ intel_extreme_uninit(intel_info &info)
|
|||||||
|
|
||||||
if (!info.fake_interrupts && info.shared_info->vblank_sem > 0) {
|
if (!info.fake_interrupts && info.shared_info->vblank_sem > 0) {
|
||||||
// disable interrupt generation
|
// disable interrupt generation
|
||||||
write16(info, INTEL_INTERRUPT_ENABLED, 0);
|
write16(info, find_reg(info, INTEL_INTERRUPT_ENABLED), 0);
|
||||||
write16(info, INTEL_INTERRUPT_MASK, ~0);
|
write16(info, find_reg(info, INTEL_INTERRUPT_MASK), ~0);
|
||||||
|
|
||||||
remove_io_interrupt_handler(info.pci->u.h0.interrupt_line,
|
remove_io_interrupt_handler(info.pci->u.h0.interrupt_line,
|
||||||
intel_interrupt_handler, &info);
|
intel_interrupt_handler, &info);
|
||||||
|
|||||||
@@ -39,6 +39,34 @@ struct intel_info {
|
|||||||
DeviceType device_type;
|
DeviceType device_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static inline uint32
|
||||||
|
find_reg(const intel_info& info, uint32 target)
|
||||||
|
{
|
||||||
|
if (REGISTER_BLOCK(target) != REGS_FLAT) {
|
||||||
|
panic("find_reg is only supposed to be used for unrouped registers\n");
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.device_type.HasPlatformControlHub())
|
||||||
|
return target;
|
||||||
|
|
||||||
|
#define RETURN_REG(x) case INTEL_##x: return PCH_##x;
|
||||||
|
|
||||||
|
switch (target) {
|
||||||
|
RETURN_REG(INTERRUPT_ENABLED)
|
||||||
|
RETURN_REG(INTERRUPT_IDENTITY)
|
||||||
|
RETURN_REG(INTERRUPT_MASK)
|
||||||
|
RETURN_REG(INTERRUPT_STATUS)
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef RETURN_REG;
|
||||||
|
|
||||||
|
panic("find_reg didn't have any matching register\n");
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern status_t intel_free_memory(intel_info& info, addr_t offset);
|
extern status_t intel_free_memory(intel_info& info, addr_t offset);
|
||||||
extern status_t intel_allocate_memory(intel_info& info, size_t size,
|
extern status_t intel_allocate_memory(intel_info& info, size_t size,
|
||||||
size_t alignment, uint32 flags, addr_t* _offset,
|
size_t alignment, uint32 flags, addr_t* _offset,
|
||||||
|
|||||||
Reference in New Issue
Block a user