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 // current version
#define RADEON_DRIVER_VERSION "Version: 5.1.5.0" #define RADEON_DRIVER_VERSION "Version: 5.1.6.0"
+161 -200
View File
@@ -7,223 +7,184 @@
AGP fix. Some motherboard BIOSes enable FastWrite even AGP fix. Some motherboard BIOSes enable FastWrite even
though the graphics card doesn't support it. Here, we'll though the graphics card doesn't support it. Here, we'll
fix that (hopefully it is generic enough). fix that (hopefully it is generic enough).
updated to use AGP_BUS mananager
*/ */
#include "radeon_driver.h" #include "radeon_driver.h"
static void agp_list_info(agp_info ai);
// missing PCI definitions static void agp_list_active(uint32 cmd);
#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;
}
// fix invalid AGP settings // fix invalid AGP settings
void Radeon_Fix_AGP(void) void Radeon_Set_AGP( device_info *di, bool enable_agp )
{ {
long pci_index; uint8 agp_index = 0;
pci_info pci_data, *pcii; agp_info nth_agp_info;
bool found = false;
uint32 agp_cmd;
// start with all features enabled, queue depth bits must be 0 /* abort if no agp busmanager found */
uint32 common_caps = if (!agp_bus)
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;
// find common feature set
for( pci_index = 0;
(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
++pci_index )
{ {
int offset; SHOW_INFO0(1, "Busmanager not installed.\nWarning Card May hang if AGP Fastwrites are Enabled." );
return;
/*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 );
}
} }
// explicitely enable AGP - it's not part of status register /* contact driver and get a pointer to the registers and shared data */
common_caps |= PCI_agp_command_agp; /* get nth AGP device info */
while((*agp_bus->get_nth_agp_info)(agp_index, &nth_agp_info) == B_NO_ERROR) {
// choose fastest transmission speed and disable lower ones /* see if we are this one */
if( (common_caps & PCI_agp_status_rate4) != 0 ) if ((nth_agp_info.device_id == di->pcii.device_id) &&
common_caps &= ~(PCI_agp_status_rate2 | PCI_agp_status_rate1); (nth_agp_info.vendor_id == di->pcii.vendor_id) &&
else if( (common_caps & PCI_agp_status_rate2) != 0 ) (nth_agp_info.bus == di->pcii.bus) &&
common_caps &= ~PCI_agp_status_rate1; (nth_agp_info.device == di->pcii.device) &&
else if( (common_caps & PCI_agp_status_rate1) == 0 ) (nth_agp_info.function == di->pcii.function))
// no speed found - disable AGP {
common_caps &= ~PCI_agp_command_agp; SHOW_INFO0(1, "Found AGP capable device" );
found = true;
common_caps |= read_queue_depth; /* remember our info */
di->agpi = nth_agp_info;
SHOW_FLOW0( 3, "Combined:" ); /* log capabilities */
show_agp_command( common_caps ); agp_list_info(nth_agp_info);
// choose features that all devices support break;
for( pci_index = 0;
(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
++pci_index )
{
int offset;
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 );
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 ) if( get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK )
return B_ERROR; 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 */ /* driver private data */
devices = (radeon_devices *)calloc( 1, sizeof( radeon_devices )); devices = (radeon_devices *)calloc( 1, sizeof( radeon_devices ));
if( devices == NULL ) { if( devices == NULL ) {
@@ -173,6 +176,8 @@ void uninit_driver( void )
devices = NULL; devices = NULL;
put_module( B_PCI_MODULE_NAME ); 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; radeon_devices *devices;
pci_module_info *pci_bus; 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; di->memmgr[mt_AGP] = NULL;
// fix AGP settings for IGP chipset // fix AGP settings for IGP chipset
if( di->asic == rt_rs100 || di->asic == rt_rs200 || di->asic == rt_rs300) Radeon_Set_AGP( di, !di->settings.force_pci ); // disable AGP
Radeon_Fix_AGP();
if ( di->acc_dma ) if ( di->acc_dma )
{ {
@@ -39,7 +39,6 @@ static uint32 getTopOfRam()
static void Radeon_SetupMCAddresses_Direct( device_info *di ) static void Radeon_SetupMCAddresses_Direct( device_info *di )
{ {
shared_info *si = di->si; shared_info *si = di->si;
uint32 mc_fb_location;
uint32 aper0 = INREG( di->regs, RADEON_CONFIG_APER_0_BASE ); uint32 aper0 = INREG( di->regs, RADEON_CONFIG_APER_0_BASE );
// bug in asics mean memory must be aligned to memory size... // 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 ); aper0 &= ~( di->local_mem_size - 1 );
} }
mc_fb_location = ( aper0 >> 16 ) ||
(aper0 + di->local_mem_size - 1 ) & 0xffff0000;
// set address range of video memory; // set address range of video memory;
// use the same addresses the CPU sees // 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; si->memory[mt_local].virtual_size = di->local_mem_size;
// PCI GART has no corresponding CPU address space, so we must find an unused // 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 radeon_settings settings; // overrides read from radeon.settings
pci_info pcii; pci_info pcii;
agp_info agpi;
char name[MAX_RADEON_DEVICE_NAME_LENGTH]; char name[MAX_RADEON_DEVICE_NAME_LENGTH];
char video_name[MAX_RADEON_DEVICE_NAME_LENGTH]; char video_name[MAX_RADEON_DEVICE_NAME_LENGTH];
} device_info; } device_info;
@@ -174,6 +175,7 @@ typedef struct {
extern pci_module_info *pci_bus; extern pci_module_info *pci_bus;
extern agp_module_info *agp_bus;
extern radeon_devices *devices; extern radeon_devices *devices;
@@ -206,7 +208,7 @@ void Radeon_CleanupIRQ( device_info *di );
// agp.c // agp.c
void Radeon_Fix_AGP(void); void Radeon_Set_AGP( device_info *di, bool enable_agp );
// mem_controller.c // mem_controller.c