Patch by Euan Kirkhope:

* Use AGP Bus manager module
* Fixed wrong framebuffer address computation; this should fix bug #1079.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20336 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-03-05 17:06:27 +00:00
parent 96d6092ef6
commit 76b5213f47
7 changed files with 175 additions and 212 deletions
+1 -1
View File
@@ -8,4 +8,4 @@
*/
// current version
#define RADEON_DRIVER_VERSION "Version: 5.1.5.0"
#define RADEON_DRIVER_VERSION "Version: 5.1.6.0"
+163 -202
View File
@@ -7,223 +7,184 @@
AGP fix. Some motherboard BIOSes enable FastWrite even
though the graphics card doesn't support it. Here, we'll
fix that (hopefully it is generic enough).
updated to use AGP_BUS mananager
*/
#include "radeon_driver.h"
// missing PCI definitions
#define PCI_status_cap_list 0x10 /* Support Capability List */
#define PCI_header_type_normal 0
#define PCI_header_type_bridge 1
#define PCI_header_type_cardbus 2
#define PCI_capability_list 0x34 /* Offset of first capability list entry */
#define PCI_cb_capability_list 0x14
#define PCI_cap_list_id 0 /* Capability ID */
#define PCI_cap_id_pm 0x01 /* Power Management */
#define PCI_cap_id_agp 0x02 /* Accelerated Graphics Port */
#define PCI_cap_id_vpd 0x03 /* Vital Product Data */
#define PCI_cap_id_slotid 0x04 /* Slot Identification */
#define PCI_cap_id_msi 0x05 /* Message Signalled Interrupts */
#define PCI_cap_id_chswp 0x06 /* CompactPCI HotSwap */
#define PCI_cap_list_next 1 /* Next capability in the list */
#define PCI_cap_flags 2 /* Capability defined flags (16 bits) */
#define PCI_cap_sizeof 4
#define PCI_agp_status 4 /* Status register */
#define PCI_agp_status_rq_mask 0xff000000 /* Maximum number of requests - 1 */
#define PCI_agp_status_rq_shift 24
#define PCI_agp_status_sba 0x0200 /* Sideband addressing supported */
#define PCI_agp_status_64bit 0x0020 /* 64-bit addressing supported */
#define PCI_agp_status_fw 0x0010 /* FW transfers supported */
#define PCI_agp_status_rate4 0x0004 /* 4x transfer rate supported */
#define PCI_agp_status_rate2 0x0002 /* 2x transfer rate supported */
#define PCI_agp_status_rate1 0x0001 /* 1x transfer rate supported */
#define PCI_agp_command 8 /* Control register */
#define PCI_agp_command_rq_mask 0xff000000 /* Master: Maximum number of requests */
#define PCI_agp_command_rq_shift 24
#define PCI_agp_command_sba 0x0200 /* Sideband addressing enabled */
#define PCI_agp_command_agp 0x0100 /* Allow processing of AGP transactions */
#define PCI_agp_command_64bit 0x0020 /* Allow processing of 64-bit addresses */
#define PCI_agp_command_fw 0x0010 /* Force FW transfers */
#define PCI_agp_command_rate4 0x0004 /* Use 4x rate */
#define PCI_agp_command_rate2 0x0002 /* Use 2x rate */
#define PCI_agp_command_rate1 0x0001 /* Use 1x rate */
// helper macros for easier PCI access
#define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
#define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
// show AGP capabilities
static void show_agp_status( uint32 status )
{
SHOW_FLOW( 3, "Status (%08lx): Max Queue Depth=%ld %s%s%s%s%s%s", status,
(status & PCI_agp_status_rq_mask) >> PCI_agp_status_rq_shift,
(status & PCI_agp_status_sba) != 0 ? "Sideband addressing " : "",
(status & PCI_agp_status_64bit) != 0 ? "64-bit " : "",
(status & PCI_agp_status_fw) != 0 ? "FastWrite " : "",
(status & PCI_agp_status_rate4) != 0 ? "4x " : "",
(status & PCI_agp_status_rate2) != 0 ? "2x " : "",
(status & PCI_agp_status_rate1) != 0 ? "1x " : "" );
}
// show AGP settings
static void show_agp_command( uint32 command )
{
SHOW_FLOW( 3, "Command (%08lx): Queue Depth=%ld %s%s%s%s%s%s%s", command,
(command & PCI_agp_command_rq_mask) >> PCI_agp_command_rq_shift,
(command & PCI_agp_command_sba) != 0 ? "Sideband addressing " : "",
(command & PCI_agp_command_agp) != 0 ? "AGP-Enabled " : "AGP-Disabled ",
(command & PCI_agp_command_64bit) != 0 ? "64-bit " : "",
(command & PCI_agp_command_fw) != 0 ? "FastWrite " : "",
(command & PCI_agp_command_rate4) != 0 ? "4x " : "",
(command & PCI_agp_command_rate2) != 0 ? "2x " : "",
(command & PCI_agp_command_rate1) != 0 ? "1x " : "" );
}
// find PCI capability
int find_capability( pci_info *pcii, uint8 capability )
{
int try_count;
uint16 status;
uint8 pos;
// check whether PCI capabilities are supported at all
status = get_pci( PCI_status, 2 );
if( (status & PCI_status_cap_list) == 0 )
return B_NAME_NOT_FOUND;
SHOW_FLOW0( 3, "Device supports capabilities" );
// get offset of first capability in list
switch( pcii->header_type & PCI_header_type_mask ) {
case PCI_header_type_normal:
case PCI_header_type_bridge:
pos = get_pci( PCI_capability_list, 1 );
break;
case PCI_header_type_cardbus:
pos = get_pci( PCI_cb_capability_list, 1 );
break;
default:
SHOW_FLOW( 3, "Unknown type (%x)", pcii->header_type & PCI_header_type_mask );
return B_ERROR;
}
// search for whished capability in linked list
for( try_count = 48; try_count > 0 && pos >= 0x40; --try_count ) {
uint8 id;
pos &= ~3;
id = get_pci( pos + PCI_cap_list_id, 1 );
if( id == 0xff )
return B_NAME_NOT_FOUND;
if( id == capability ) {
SHOW_FLOW( 3, "Found capability %d", capability );
return pos;
}
SHOW_FLOW( 3, "Ignored capability %d", id );
pos = get_pci( pos + PCI_cap_list_next, 1 );
}
return B_NAME_NOT_FOUND;
}
static void agp_list_info(agp_info ai);
static void agp_list_active(uint32 cmd);
// fix invalid AGP settings
void Radeon_Fix_AGP(void)
void Radeon_Set_AGP( device_info *di, bool enable_agp )
{
long pci_index;
pci_info pci_data, *pcii;
// start with all features enabled, queue depth bits must be 0
uint32 common_caps =
PCI_agp_status_sba | PCI_agp_status_64bit | PCI_agp_status_fw |
PCI_agp_status_rate4 | PCI_agp_status_rate2 | PCI_agp_status_rate1;
uint32 read_queue_depth = PCI_agp_status_rq_mask;
SHOW_FLOW0( 4, "Composing common feature list" );
// only required to make get_pci/set_pci working
pcii = &pci_data;
uint8 agp_index = 0;
agp_info nth_agp_info;
bool found = false;
uint32 agp_cmd;
// find common feature set
for( pci_index = 0;
(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
++pci_index )
/* abort if no agp busmanager found */
if (!agp_bus)
{
int offset;
/*SHOW_FLOW( 3, "Checking bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
pcii->bus, pcii->device, pcii->function,
pcii->vendor_id, pcii->device_id );*/
offset = find_capability( pcii, PCI_cap_id_agp );
if( offset > 0 ) {
uint32 agp_status, agp_command;
agp_status = get_pci( offset + PCI_agp_status, 4 );
agp_command = get_pci( offset + PCI_agp_command, 4 );
SHOW_FLOW( 3, "bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
pcii->bus, pcii->device, pcii->function,
pcii->vendor_id, pcii->device_id );
show_agp_status( agp_status );
show_agp_command( agp_command );
common_caps &= agp_status;
read_queue_depth = min( read_queue_depth, agp_status & PCI_agp_status_rq_mask );
}
SHOW_INFO0(1, "Busmanager not installed.\nWarning Card May hang if AGP Fastwrites are Enabled." );
return;
}
/* contact driver and get a pointer to the registers and shared data */
/* get nth AGP device info */
while((*agp_bus->get_nth_agp_info)(agp_index, &nth_agp_info) == B_NO_ERROR) {
// explicitely enable AGP - it's not part of status register
common_caps |= PCI_agp_command_agp;
/* see if we are this one */
if ((nth_agp_info.device_id == di->pcii.device_id) &&
(nth_agp_info.vendor_id == di->pcii.vendor_id) &&
(nth_agp_info.bus == di->pcii.bus) &&
(nth_agp_info.device == di->pcii.device) &&
(nth_agp_info.function == di->pcii.function))
{
SHOW_INFO0(1, "Found AGP capable device" );
found = true;
// choose fastest transmission speed and disable lower ones
if( (common_caps & PCI_agp_status_rate4) != 0 )
common_caps &= ~(PCI_agp_status_rate2 | PCI_agp_status_rate1);
else if( (common_caps & PCI_agp_status_rate2) != 0 )
common_caps &= ~PCI_agp_status_rate1;
else if( (common_caps & PCI_agp_status_rate1) == 0 )
// no speed found - disable AGP
common_caps &= ~PCI_agp_command_agp;
common_caps |= read_queue_depth;
SHOW_FLOW0( 3, "Combined:" );
show_agp_command( common_caps );
// choose features that all devices support
for( pci_index = 0;
(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
++pci_index )
{
int offset;
/* remember our info */
di->agpi = nth_agp_info;
offset = find_capability( pcii, PCI_cap_id_agp );
if( offset > 0 ) {
SHOW_FLOW( 3, "Modifying bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
pcii->bus, pcii->device, pcii->function,
pcii->vendor_id, pcii->device_id );
/* log capabilities */
agp_list_info(nth_agp_info);
break;
set_pci( offset + PCI_agp_command, 4, common_caps );
}
agp_index++;
}
if (!found) {
if (agp_index != 0) {
SHOW_INFO0(1, "End of AGP capable devices list.");
} else {
SHOW_INFO0(1, "No AGP capable devices found.");
}
return;
}
if (di->settings.force_pci | !enable_agp) {
SHOW_INFO0(1, "Disabling AGP mode...");
/* we want zero agp features enabled */
agp_cmd = 0;
/* write the stuff */
(*agp_bus->enable_agp)(&agp_cmd);
} else {
/* activate AGP mode */
SHOW_INFO0(1, "Activating AGP mode...");
agp_cmd = 0xfffffff7;
/* set agp 3 speed bit is agp is v3 */
if (nth_agp_info.interface.agp_stat & AGP_rate_rev) agp_cmd |= AGP_rate_rev;
/* we want to perma disable fastwrites as they're evil, evil i say */
agp_cmd &= ~AGP_FW;
/* write the stuff */
(*agp_bus->enable_agp)(&agp_cmd);
}
/* list mode now activated,
* make sure we have the correct speed scheme for logging */
agp_list_active(nth_agp_info.interface.agp_cmd |
(nth_agp_info.interface.agp_stat & AGP_rate_rev));
}
static void agp_list_info(agp_info ai)
{
/*
list device
*/
if (ai.class_base == PCI_display) {
SHOW_INFO(4, "Device is a graphics card, subclass ID is $%02x", ai.class_sub);
} else {
SHOW_INFO(4, "Device is a hostbridge, subclass ID is $%02x", ai.class_sub);
}
SHOW_INFO(4, "Vendor ID $%04x", ai.vendor_id);
SHOW_INFO(4, "Device ID $%04x", ai.device_id);
SHOW_INFO(4, "Bus %d, device %d, function %d", ai.bus, ai.device, ai.function);
/*
list capabilities
*/
SHOW_INFO(4, "This device supports AGP specification %ld.%ld;",
((ai.interface.agp_cap_id & AGP_rev_major) >> AGP_rev_major_shift),
((ai.interface.agp_cap_id & AGP_rev_minor) >> AGP_rev_minor_shift));
/* the AGP devices determine AGP speed scheme version used on power-up/reset */
if (!(ai.interface.agp_stat & AGP_rate_rev))
{
/* AGP 2.0 scheme applies */
if (ai.interface.agp_stat & AGP_2_1x)
SHOW_INFO0(4, "AGP 2.0 1x mode is available");
if (ai.interface.agp_stat & AGP_2_2x)
SHOW_INFO0(4, "AGP 2.0 2x mode is available");
if (ai.interface.agp_stat & AGP_2_4x)
SHOW_INFO0(41, "AGP 2.0 4x mode is available");
}
else
{
/* AGP 3.0 scheme applies */
if (ai.interface.agp_stat & AGP_3_4x)
SHOW_INFO0(4, "AGP 3.0 4x mode is available");
if (ai.interface.agp_stat & AGP_3_8x)
SHOW_INFO0(4, "AGP 3.0 8x mode is available");
}
if (ai.interface.agp_stat & AGP_FW) SHOW_INFO0(4, "Fastwrite transfers are supported");
if (ai.interface.agp_stat & AGP_SBA) SHOW_INFO0(4, "Sideband adressing is supported");
SHOW_INFO(1, "%ld queued AGP requests can be handled.",
((ai.interface.agp_stat & AGP_RQ) >> AGP_RQ_shift) + 1);
/*
list current settings,
make sure we have the correct speed scheme for logging
*/
agp_list_active(ai.interface.agp_cmd | (ai.interface.agp_stat & AGP_rate_rev));
}
static void agp_list_active(uint32 cmd)
{
SHOW_INFO0(4, "listing settings now in use:");
if (!(cmd & AGP_rate_rev)) {
/* AGP 2.0 scheme applies */
if (cmd & AGP_2_1x)
SHOW_INFO0(2,"AGP 2.0 1x mode is set");
if (cmd & AGP_2_2x)
SHOW_INFO0(2,"AGP 2.0 2x mode is set");
if (cmd & AGP_2_4x)
SHOW_INFO0(2,"AGP 2.0 4x mode is set");
} else {
/* AGP 3.0 scheme applies */
if (cmd & AGP_3_4x)
SHOW_INFO0(2,"AGP 3.0 4x mode is set");
if (cmd & AGP_3_8x)
SHOW_INFO0(2,"AGP 3.0 8x mode is set");
}
if (cmd & AGP_FW) {
SHOW_INFO0(2, "Fastwrite transfers are enabled");
} else {
SHOW_INFO0(2, "Fastwrite transfers are disabled");
}
if (cmd & AGP_SBA) SHOW_INFO0(4, "Sideband adressing is enabled");
SHOW_INFO(4, "Max. AGP queued request depth is set to %ld",
(((cmd & AGP_RQ) >> AGP_RQ_shift) + 1));
if (cmd & AGP_enable)
SHOW_INFO0(2, "The AGP interface is enabled.");
else
SHOW_INFO0(2, "The AGP interface is disabled.");
}
@@ -148,6 +148,9 @@ status_t init_driver( void )
if( get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK )
return B_ERROR;
/* get a handle for the agp bus if it exists */
get_module(B_AGP_MODULE_NAME, (module_info **)&agp_bus);
/* driver private data */
devices = (radeon_devices *)calloc( 1, sizeof( radeon_devices ));
if( devices == NULL ) {
@@ -173,6 +176,8 @@ void uninit_driver( void )
devices = NULL;
put_module( B_PCI_MODULE_NAME );
/* put the agp module away if it's there */
if (agp_bus) put_module(B_AGP_MODULE_NAME);
}
@@ -16,3 +16,4 @@ int debug_level_error = 4;
radeon_devices *devices;
pci_module_info *pci_bus;
agp_module_info *agp_bus;
@@ -374,8 +374,7 @@ status_t Radeon_FirstOpen( device_info *di )
di->memmgr[mt_AGP] = NULL;
// fix AGP settings for IGP chipset
if( di->asic == rt_rs100 || di->asic == rt_rs200 || di->asic == rt_rs300)
Radeon_Fix_AGP();
Radeon_Set_AGP( di, !di->settings.force_pci ); // disable AGP
if ( di->acc_dma )
{
@@ -39,7 +39,6 @@ static uint32 getTopOfRam()
static void Radeon_SetupMCAddresses_Direct( device_info *di )
{
shared_info *si = di->si;
uint32 mc_fb_location;
uint32 aper0 = INREG( di->regs, RADEON_CONFIG_APER_0_BASE );
// bug in asics mean memory must be aligned to memory size...
@@ -47,13 +46,9 @@ static void Radeon_SetupMCAddresses_Direct( device_info *di )
aper0 &= ~( di->local_mem_size - 1 );
}
mc_fb_location = ( aper0 >> 16 ) ||
(aper0 + di->local_mem_size - 1 ) & 0xffff0000;
// set address range of video memory;
// use the same addresses the CPU sees
si->memory[mt_local].virtual_addr_start = mc_fb_location;
si->memory[mt_local].virtual_addr_start = aper0;
si->memory[mt_local].virtual_size = di->local_mem_size;
// PCI GART has no corresponding CPU address space, so we must find an unused
@@ -158,6 +158,7 @@ typedef struct device_info {
radeon_settings settings; // overrides read from radeon.settings
pci_info pcii;
agp_info agpi;
char name[MAX_RADEON_DEVICE_NAME_LENGTH];
char video_name[MAX_RADEON_DEVICE_NAME_LENGTH];
} device_info;
@@ -174,6 +175,7 @@ typedef struct {
extern pci_module_info *pci_bus;
extern agp_module_info *agp_bus;
extern radeon_devices *devices;
@@ -206,7 +208,7 @@ void Radeon_CleanupIRQ( device_info *di );
// agp.c
void Radeon_Fix_AGP(void);
void Radeon_Set_AGP( device_info *di, bool enable_agp );
// mem_controller.c