/*
Copyright (c) 2002, Thomas Kurschel
Part of Radeon kernel driver
DevFS interface
*/
#include "radeon_driver.h"
#include <OS.h>
#include <malloc.h>
#include <graphic_driver.h>
#include <stdio.h>
#include <string.h>
#include "AGP.h"
#include "mmio.h"
#include "version.h"
#include <driver_settings.h>
#include <stdlib.h> // for strtoXX
// tell the kernel what revision of the driver API we support
int32 api_version = 2;
static status_t open_hook(const char *name, uint32 flags, void **cookie);
static status_t close_hook(void *dev);
static status_t free_hook(void *dev);
static status_t read_hook(void *dev, off_t pos, void *buf, size_t *len);
static status_t write_hook(void *dev, off_t pos, const void *buf, size_t *len);
static status_t control_hook(void *dev, uint32 msg, void *buf, size_t len);
static device_hooks graphics_device_hooks = {
open_hook,
close_hook,
free_hook,
control_hook,
read_hook,
write_hook,
NULL,
NULL,
NULL,
NULL
};
radeon_settings def_settings = { // see comments in radeon.settings
2, // loginfo
2, // logflow
2, // logerror
false, // switchhead
false, // force_lcd
true, // dynamic_clocks
true, // force_pci
false, // unhide_fw
false, // acc_dma
false, // acc_mmio
true, // acc_wb
};
radeon_settings current_settings;
static void
GetDriverSettings(void)
{
void *settings_handle = NULL;
SHOW_FLOW0( 1, "" );
// init settings to defaults;
current_settings = def_settings;
// get driver/accelerant settings, apsed
settings_handle = load_driver_settings ("radeon.settings");
if (settings_handle != NULL) {
const char *item;
char *end;
uint32 value;
item = get_driver_parameter (settings_handle, "loginfo", "2", "2");
value = strtoul (item, &end, 0);
if (*end == '\0' && value <= 4) {
current_settings.loginfo = value;
SHOW_INFO( 1, "Log Info Level now %ld/4", value );
}
item = get_driver_parameter (settings_handle, "logflow", "2", "2");
value = strtoul (item, &end, 0);
if (*end == '\0' && value <= 4) {
current_settings.logflow = value;
SHOW_INFO( 1, "Log Flow Level now %ld/4", value );
}
item = get_driver_parameter (settings_handle, "logerror", "2", "2");
value = strtoul (item, &end, 0);
if (*end == '\0' && value <= 4) {
current_settings.logerror = value;
SHOW_INFO( 1, "Log Error Level now %ld/4", value );
}
current_settings.switchhead = get_driver_boolean_parameter (settings_handle, "switchhead", false, false);
current_settings.force_lcd = get_driver_boolean_parameter (settings_handle, "force_lcd", false, false);
current_settings.dynamic_clocks = get_driver_boolean_parameter (settings_handle, "dynamic_clocks", true, true);
current_settings.force_pci = get_driver_boolean_parameter (settings_handle, "force_pci", true, true);
current_settings.unhide_fastwrites = get_driver_boolean_parameter (settings_handle, "unhide_fw", false, false);
current_settings.force_acc_dma = get_driver_boolean_parameter (settings_handle, "force_acc_dma", false, false);
current_settings.force_acc_mmio = get_driver_boolean_parameter (settings_handle, "force_acc_mmio", false, false);
current_settings.acc_writeback = get_driver_boolean_parameter (settings_handle, "acc_writeback", false, false);
if ( current_settings.switchhead != def_settings.switchhead )
SHOW_INFO0( 1, "Switch Head = True" );
if ( current_settings.force_lcd != def_settings.force_lcd )
SHOW_INFO0( 1, "Force LCD ON" );
if ( current_settings.dynamic_clocks != def_settings.dynamic_clocks )
SHOW_INFO0( 1, "Mobility Power Saving Disabled (Dynamic Clocks)" );
if ( current_settings.force_pci != def_settings.force_pci )
SHOW_INFO0( 1, "Force PCI = True" );
if ( current_settings.unhide_fastwrites != def_settings.unhide_fastwrites )
SHOW_INFO0( 1, "use Fastwrites ON" );
if ( current_settings.force_acc_dma != def_settings.force_acc_dma )
SHOW_INFO0( 1, "DMA ACC Enabled" );
if ( current_settings.force_acc_mmio != def_settings.force_acc_mmio )
SHOW_INFO0( 1, "DMA ACC Disabled" );
if ( current_settings.acc_writeback != def_settings.acc_writeback )
SHOW_INFO0( 1, "DMA WriteBack Disabled" );
unload_driver_settings (settings_handle);
}
}
// #pragma mark - driver API
status_t
init_hardware(void)
{
SHOW_INFO0(0, RADEON_DRIVER_VERSION);
if (Radeon_CardDetect() == B_OK)
return B_OK;
return B_ERROR;
}
status_t
init_driver(void)
{
SHOW_FLOW0(3, "");
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_GART_MODULE_NAME, (module_info **)&sAGP);
/* driver private data */
devices = (radeon_devices *)calloc(1, sizeof(radeon_devices));
if (devices == NULL) {
put_module(B_PCI_MODULE_NAME);
if (sAGP != NULL)
put_module(B_AGP_GART_MODULE_NAME);
return B_ERROR;
}
(void)INIT_BEN(devices->kernel, "Radeon Kernel");
GetDriverSettings();
Radeon_ProbeDevices();
return B_OK;
}
void
uninit_driver(void)
{
SHOW_FLOW0(3, "");
DELETE_BEN(devices->kernel);
free(devices);
devices = NULL;
put_module(B_PCI_MODULE_NAME);
if (sAGP)
put_module(B_AGP_GART_MODULE_NAME);
}
const char **
publish_devices(void)
{
return (const char **)devices->device_names;
}
device_hooks *
find_device(const char *name)
{
uint32 index;
// probably, we could always return standard hooks
for (index = 0; devices->device_names[index]; ++index) {
if (strcmp(name, devices->device_names[index]) == 0)
return &graphics_device_hooks;
}
return NULL;
}
// #pragma mark - device API
static status_t
open_hook(const char *name, uint32 flags, void **cookie)
{
int32 index = 0;
device_info *di;
status_t result = B_OK;
SHOW_FLOW( 3, "name=%s, flags=%ld, cookie=0x%08lx", name, flags, (uint32)cookie );
// find device info
while (devices->device_names[index]
&& strcmp(name, devices->device_names[index]) != 0) {
index++;
}
di = &(devices->di[index / 2]);
ACQUIRE_BEN(devices->kernel);
if (!di->is_open)
result = Radeon_FirstOpen(di);
if (result == B_OK) {
di->is_open++;
*cookie = di;
}
RELEASE_BEN(devices->kernel);
SHOW_FLOW(3, "returning 0x%08lx", result);
return result;
}
static status_t
read_hook(void *dev, off_t pos, void *buf, size_t *len)
{
*len = 0;
return B_NOT_ALLOWED;
}
// public function: write to device (denied)
static status_t
write_hook(void *dev, off_t pos, const void *buf, size_t *len)
{
*len = 0;
return B_NOT_ALLOWED;
}
static status_t
close_hook(void *dev)
{
return B_NO_ERROR;
}
static status_t
free_hook(void *dev)
{
device_info *di = (device_info *)dev;
SHOW_FLOW0( 0, "" );
ACQUIRE_BEN( devices->kernel );
mem_freetag( di->memmgr[mt_local], dev );
if( di->memmgr[mt_PCI] )
mem_freetag( di->memmgr[mt_PCI], dev );
if( di->memmgr[mt_AGP] )
mem_freetag( di->memmgr[mt_AGP], dev );
if( di->is_open == 1 )
Radeon_LastClose( di );
di->is_open--;
RELEASE_BEN( devices->kernel );
return B_OK;
}
static status_t
control_hook(void *dev, uint32 msg, void *buf, size_t len)
{
device_info *di = (device_info *)dev;
status_t result = B_DEV_INVALID_IOCTL;
switch (msg) {
// needed by app_server to load accelerant
case B_GET_ACCELERANT_SIGNATURE: {
char *sig = (char *)buf;
strcpy(sig, "radeon.accelerant");
result = B_OK;
} break;
// needed to share data between kernel and accelerant
case RADEON_GET_PRIVATE_DATA: {
radeon_get_private_data *gpd = (radeon_get_private_data *)buf;
if (gpd->magic == RADEON_PRIVATE_DATA_MAGIC) {
gpd->shared_info_area = di->shared_area;
gpd->virtual_card_area = di->virtual_card_area;
result = B_OK;
}
} break;
// needed for cloning
case RADEON_DEVICE_NAME: {
radeon_device_name *dn = (radeon_device_name *)buf;
if( dn->magic == RADEON_PRIVATE_DATA_MAGIC ) {
strncpy( dn->name, di->name, MAX_RADEON_DEVICE_NAME_LENGTH );
result = B_OK;
}
} break;
// graphics mem manager
case RADEON_ALLOC_MEM: {
radeon_alloc_mem *am = (radeon_alloc_mem *)buf;
memory_type_e memory_type;
if( am->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
if( am->memory_type > mt_last )
break;
memory_type = am->memory_type == mt_nonlocal ? di->si->nonlocal_type : am->memory_type;
result = mem_alloc( di->memmgr[memory_type], am->size, am->global ? 0 : dev, &am->handle, &am->offset );
} break;
case RADEON_FREE_MEM: {
radeon_free_mem *fm = (radeon_free_mem *)buf;
memory_type_e memory_type;
if( fm->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
if( fm->memory_type > mt_last )
break;
memory_type = fm->memory_type == mt_nonlocal ? di->si->nonlocal_type : fm->memory_type;
result = mem_free( di->memmgr[memory_type], fm->handle, fm->global ? 0 : dev );
} break;
case RADEON_WAITFORIDLE: {
radeon_wait_for_idle *wfi = (radeon_wait_for_idle *)buf;
if( wfi->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
Radeon_WaitForIdle( di, true, wfi->keep_lock );
result = B_OK;
} break;
case RADEON_WAITFORFIFO: {
radeon_wait_for_fifo *wff = (radeon_wait_for_fifo *)buf;
if( wff->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
Radeon_WaitForFifo( di, wff->entries );
result = B_OK;
} break;
case RADEON_RESETENGINE: {
radeon_no_arg *na = (radeon_no_arg *)buf;
if( na->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
ACQUIRE_BEN( di->si->cp.lock );
Radeon_ResetEngine( di );
RELEASE_BEN( di->si->cp.lock );
result = B_OK;
} break;
case RADEON_VIPREAD: {
radeon_vip_read *vr = (radeon_vip_read *)buf;
if( vr->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
result = Radeon_VIPRead( di, vr->channel, vr->address, &vr->data,
vr->lock ) ? B_OK : B_ERROR;
} break;
case RADEON_VIPWRITE: {
radeon_vip_write *vw = (radeon_vip_write *)buf;
if( vw->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
result = Radeon_VIPWrite( di, vw->channel, vw->address, vw->data,
vw->lock ) ? B_OK : B_ERROR;
} break;
case RADEON_VIPFIFOREAD: {
radeon_vip_fifo_read *vr = (radeon_vip_fifo_read *)buf;
if( vr->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
result = Radeon_VIPFifoRead( di, vr->channel, vr->address, vr->count, vr->data,
vr->lock ) ? B_OK : B_ERROR;
} break;
case RADEON_VIPFIFOWRITE: {
radeon_vip_fifo_write *vw = (radeon_vip_fifo_write *)buf;
if( vw->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
result = Radeon_VIPFifoWrite( di, vw->channel, vw->address, vw->count, vw->data,
vw->lock ) ? B_OK : B_ERROR;
} break;
case RADEON_FINDVIPDEVICE: {
radeon_find_vip_device *fvd = (radeon_find_vip_device *)buf;
if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
fvd->channel = Radeon_FindVIPDevice( di, fvd->device_id );
result = B_OK;
} break;
case RADEON_VIPRESET: {
radeon_vip_reset *fvd = (radeon_vip_reset *)buf;
if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
Radeon_VIPReset( di, fvd->lock );
result = B_OK;
} break;
case RADEON_WAIT_FOR_CAP_IRQ: {
radeon_wait_for_cap_irq *wvc = (radeon_wait_for_cap_irq *)buf;
if( wvc->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
// restrict wait time to 1 sec to get not stuck here in kernel
result = acquire_sem_etc( di->cap_sem, 1, B_RELATIVE_TIMEOUT,
min( wvc->timeout, 1000000 ));
if( result == B_OK ) {
cpu_status prev_irq_state = disable_interrupts();
acquire_spinlock( &di->cap_spinlock );
wvc->timestamp = di->cap_timestamp;
wvc->int_status = di->cap_int_status;
wvc->counter = di->cap_counter;
release_spinlock( &di->cap_spinlock );
restore_interrupts( prev_irq_state );
}
} break;
case RADEON_DMACOPY: {
radeon_dma_copy *dc = (radeon_dma_copy *)buf;
if( dc->magic != RADEON_PRIVATE_DATA_MAGIC )
break;
result = Radeon_DMACopy( di, dc->src, dc->target, dc->size, dc->lock_mem, dc->contiguous );
} break;
#ifdef ENABLE_LOGGING
#ifdef LOG_INCLUDE_STARTUP
// interface to log data
case RADEON_GET_LOG_SIZE:
*(uint32 *)buf = log_getsize( di->si->log );
result = B_OK;
break;
case RADEON_GET_LOG_DATA:
log_getcopy( di->si->log, buf, ((uint32 *)buf)[0] );
result = B_OK;
break;
#endif
#endif
}
if( result == B_DEV_INVALID_IOCTL )
SHOW_ERROR( 3, "Invalid ioctl call: code=0x%lx", msg );
return result;
}
↑ V576 Incorrect format. Consider checking the fourth actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the fourth actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the fifth actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the sixth actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the fourth actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the fourth actual argument of the 'dprintf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the fourth actual argument of the 'dprintf' function. The memsize type argument is expected.