1 /* 2 Copyright (c) 2002, Thomas Kurschel 3 4 5 Part of Radeon kernel driver 6 7 DevFS interface 8 */ 9 10 #include "radeon_driver.h" 11 12 #include <OS.h> 13 #include <malloc.h> 14 #include <graphic_driver.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include "AGP.h" 18 #include "mmio.h" 19 #include "version.h" 20 #include <driver_settings.h> 21 #include <stdlib.h> // for strtoXX 22 23 // tell the kernel what revision of the driver API we support 24 int32 api_version = 2; 25 26 27 static status_t open_hook( const char *name, uint32 flags, void **cookie ); 28 static status_t close_hook( void *dev ); 29 static status_t free_hook( void *dev ); 30 static status_t read_hook( void *dev, off_t pos, void *buf, size_t *len ); 31 static status_t write_hook( void *dev, off_t pos, const void *buf, size_t *len ); 32 static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len ); 33 34 35 static device_hooks graphics_device_hooks = { 36 open_hook, 37 close_hook, 38 free_hook, 39 control_hook, 40 read_hook, 41 write_hook, 42 NULL, 43 NULL, 44 NULL, 45 NULL 46 }; 47 48 radeon_settings def_settings = { // see comments in radeon.settings 49 2, // loginfo 50 2, // logflow 51 2, // logerror 52 false, // switchhead 53 false, // force_lcd 54 true, // dynamic_clocks 55 true, // force_pci 56 false, // unhide_fw 57 false, // acc_dma 58 false, // acc_mmio 59 true, // acc_wb 60 }; 61 62 radeon_settings current_settings; 63 64 static void GetDriverSettings(void) 65 { 66 67 void *settings_handle = NULL; 68 69 SHOW_FLOW0( 1, "" ); 70 71 // init settings to defaults; 72 current_settings = def_settings; 73 74 // get driver/accelerant settings, apsed 75 settings_handle = load_driver_settings ("radeon.settings"); 76 if (settings_handle != NULL) { 77 const char *item; 78 char *end; 79 uint32 value; 80 81 item = get_driver_parameter (settings_handle, "loginfo", "2", "2"); 82 value = strtoul (item, &end, 0); 83 if (*end == '\0' && value <= 4) { 84 current_settings.loginfo = value; 85 SHOW_INFO( 1, "Log Info Level now %ld/4", value ); 86 } 87 88 item = get_driver_parameter (settings_handle, "logflow", "2", "2"); 89 value = strtoul (item, &end, 0); 90 if (*end == '\0' && value <= 4) { 91 current_settings.logflow = value; 92 SHOW_INFO( 1, "Log Flow Level now %ld/4", value ); 93 } 94 95 item = get_driver_parameter (settings_handle, "logerror", "2", "2"); 96 value = strtoul (item, &end, 0); 97 if (*end == '\0' && value <= 4) { 98 current_settings.logerror = value; 99 SHOW_INFO( 1, "Log Error Level now %ld/4", value ); 100 } 101 102 current_settings.switchhead = get_driver_boolean_parameter (settings_handle, "switchhead", false, false); 103 current_settings.force_lcd = get_driver_boolean_parameter (settings_handle, "force_lcd", false, false); 104 current_settings.dynamic_clocks = get_driver_boolean_parameter (settings_handle, "dynamic_clocks", true, true); 105 current_settings.force_pci = get_driver_boolean_parameter (settings_handle, "force_pci", true, true); 106 current_settings.unhide_fastwrites = get_driver_boolean_parameter (settings_handle, "unhide_fw", false, false); 107 current_settings.force_acc_dma = get_driver_boolean_parameter (settings_handle, "force_acc_dma", false, false); 108 current_settings.force_acc_mmio = get_driver_boolean_parameter (settings_handle, "force_acc_mmio", false, false); 109 current_settings.acc_writeback = get_driver_boolean_parameter (settings_handle, "acc_writeback", false, false); 110 111 if ( current_settings.switchhead != def_settings.switchhead ) 112 SHOW_INFO0( 1, "Switch Head = True" ); 113 if ( current_settings.force_lcd != def_settings.force_lcd ) 114 SHOW_INFO0( 1, "Force LCD ON" ); 115 if ( current_settings.dynamic_clocks != def_settings.dynamic_clocks ) 116 SHOW_INFO0( 1, "Mobility Power Saving Disabled (Dynamic Clocks)" ); 117 if ( current_settings.force_pci != def_settings.force_pci ) 118 SHOW_INFO0( 1, "Force PCI = True" ); 119 if ( current_settings.unhide_fastwrites != def_settings.unhide_fastwrites ) 120 SHOW_INFO0( 1, "use Fastwrites ON" ); 121 if ( current_settings.force_acc_dma != def_settings.force_acc_dma ) 122 SHOW_INFO0( 1, "DMA ACC Enabled" ); 123 if ( current_settings.force_acc_mmio != def_settings.force_acc_mmio ) 124 SHOW_INFO0( 1, "DMA ACC Disabled" ); 125 if ( current_settings.acc_writeback != def_settings.acc_writeback ) 126 SHOW_INFO0( 1, "DMA WriteBack Disabled" ); 127 128 unload_driver_settings (settings_handle); 129 } 130 } 131 132 // public function: check whether there is *any* supported hardware 133 status_t init_hardware( void ) 134 { 135 SHOW_INFO0( 0, RADEON_DRIVER_VERSION ); 136 if( Radeon_CardDetect() == B_OK ) 137 return B_OK; 138 else 139 return B_ERROR; 140 } 141 142 143 // public function: init driver 144 status_t init_driver( void ) 145 { 146 SHOW_FLOW0( 3, "" ); 147 148 if( get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK ) 149 return B_ERROR; 150 151 /* get a handle for the agp bus if it exists */ 152 get_module(B_AGP_MODULE_NAME, (module_info **)&agp_bus); 153 154 /* driver private data */ 155 devices = (radeon_devices *)calloc( 1, sizeof( radeon_devices )); 156 if( devices == NULL ) { 157 put_module(B_PCI_MODULE_NAME); 158 if (agp_bus != NULL) 159 put_module(B_AGP_MODULE_NAME); 160 return B_ERROR; 161 } 162 163 (void)INIT_BEN( devices->kernel, "Radeon Kernel" ); 164 165 GetDriverSettings(); 166 Radeon_ProbeDevices(); 167 return B_OK; 168 } 169 170 171 // public function: uninit driver 172 void uninit_driver( void ) 173 { 174 SHOW_FLOW0( 3, "" ); 175 DELETE_BEN( devices->kernel ); 176 177 free( devices ); 178 devices = NULL; 179 180 put_module( B_PCI_MODULE_NAME ); 181 /* put the agp module away if it's there */ 182 if (agp_bus) 183 put_module(B_AGP_MODULE_NAME); 184 } 185 186 187 // public function: return list of device names 188 const char **publish_devices( void ) 189 { 190 return (const char **)devices->device_names; 191 } 192 193 194 // public function: find hooks for specific device given its name 195 device_hooks *find_device( const char *name ) 196 { 197 uint32 index; 198 199 // probably, we could always return standard hooks 200 for( index = 0; devices->device_names[index]; ++index ) { 201 if( strcmp( name, devices->device_names[index] ) == 0 ) 202 return &graphics_device_hooks; 203 } 204 205 return NULL; 206 } 207 208 209 // public function: open device 210 static status_t open_hook( const char *name, uint32 flags, void **cookie ) 211 { 212 int32 index = 0; 213 device_info *di; 214 status_t result = B_OK; 215 216 SHOW_FLOW( 3, "name=%s, flags=%ld, cookie=0x%08lx", name, flags, (uint32)cookie ); 217 218 // find device info 219 while( devices->device_names[index] && 220 strcmp(name, devices->device_names[index] ) != 0 ) 221 index++; 222 223 di = &(devices->di[index/2]); 224 225 ACQUIRE_BEN( devices->kernel ); 226 227 if( !di->is_open ) 228 result = Radeon_FirstOpen( di ); 229 230 if( result == B_OK ) { 231 di->is_open++; 232 *cookie = di; 233 } 234 235 RELEASE_BEN( devices->kernel ); 236 237 SHOW_FLOW( 3, "returning 0x%08lx", result ); 238 return result; 239 } 240 241 242 // public function: read from device (denied) 243 static status_t read_hook( void *dev, off_t pos, void *buf, size_t *len ) 244 { 245 *len = 0; 246 return B_NOT_ALLOWED; 247 } 248 249 250 // public function: write to device (denied) 251 static status_t write_hook( void *dev, off_t pos, const void *buf, size_t *len ) 252 { 253 *len = 0; 254 return B_NOT_ALLOWED; 255 } 256 257 258 // public function: close device (ignored, wait for free_hook instead) 259 static status_t close_hook( void *dev ) 260 { 261 return B_NO_ERROR; 262 } 263 264 265 // public function: free device 266 static status_t free_hook( void *dev ) 267 { 268 device_info *di = (device_info *)dev; 269 270 SHOW_FLOW0( 0, "" ); 271 272 ACQUIRE_BEN( devices->kernel ); 273 274 mem_freetag( di->memmgr[mt_local], dev ); 275 276 if( di->memmgr[mt_PCI] ) 277 mem_freetag( di->memmgr[mt_PCI], dev ); 278 279 if( di->memmgr[mt_AGP] ) 280 mem_freetag( di->memmgr[mt_AGP], dev ); 281 282 if( di->is_open == 1 ) 283 Radeon_LastClose( di ); 284 285 di->is_open--; 286 RELEASE_BEN( devices->kernel ); 287 288 return B_OK; 289 } 290 291 292 // public function: ioctl 293 static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len ) 294 { 295 device_info *di = (device_info *)dev; 296 status_t result = B_DEV_INVALID_IOCTL; 297 298 switch (msg) { 299 // needed by app_server to load accelerant 300 case B_GET_ACCELERANT_SIGNATURE: { 301 char *sig = (char *)buf; 302 strcpy(sig, "radeon.accelerant"); 303 result = B_OK; 304 } break; 305 306 // needed to share data between kernel and accelerant 307 case RADEON_GET_PRIVATE_DATA: { 308 radeon_get_private_data *gpd = (radeon_get_private_data *)buf; 309 310 if (gpd->magic == RADEON_PRIVATE_DATA_MAGIC) { 311 gpd->shared_info_area = di->shared_area; 312 gpd->virtual_card_area = di->virtual_card_area; 313 result = B_OK; 314 } 315 } break; 316 317 // needed for cloning 318 case RADEON_DEVICE_NAME: { 319 radeon_device_name *dn = (radeon_device_name *)buf; 320 321 if( dn->magic == RADEON_PRIVATE_DATA_MAGIC ) { 322 strncpy( dn->name, di->name, MAX_RADEON_DEVICE_NAME_LENGTH ); 323 result = B_OK; 324 } 325 } break; 326 327 // graphics mem manager 328 case RADEON_ALLOC_MEM: { 329 radeon_alloc_mem *am = (radeon_alloc_mem *)buf; 330 memory_type_e memory_type; 331 332 if( am->magic != RADEON_PRIVATE_DATA_MAGIC ) 333 break; 334 335 if( am->memory_type > mt_last ) 336 break; 337 338 memory_type = am->memory_type == mt_nonlocal ? di->si->nonlocal_type : am->memory_type; 339 340 result = mem_alloc( di->memmgr[memory_type], am->size, am->global ? 0 : dev, &am->handle, &am->offset ); 341 } break; 342 343 case RADEON_FREE_MEM: { 344 radeon_free_mem *fm = (radeon_free_mem *)buf; 345 memory_type_e memory_type; 346 347 if( fm->magic != RADEON_PRIVATE_DATA_MAGIC ) 348 break; 349 350 if( fm->memory_type > mt_last ) 351 break; 352 353 memory_type = fm->memory_type == mt_nonlocal ? di->si->nonlocal_type : fm->memory_type; 354 355 result = mem_free( di->memmgr[memory_type], fm->handle, fm->global ? 0 : dev ); 356 } break; 357 358 case RADEON_WAITFORIDLE: { 359 radeon_wait_for_idle *wfi = (radeon_wait_for_idle *)buf; 360 361 if( wfi->magic != RADEON_PRIVATE_DATA_MAGIC ) 362 break; 363 364 Radeon_WaitForIdle( di, true, wfi->keep_lock ); 365 result = B_OK; 366 } break; 367 368 case RADEON_WAITFORFIFO: { 369 radeon_wait_for_fifo *wff = (radeon_wait_for_fifo *)buf; 370 371 if( wff->magic != RADEON_PRIVATE_DATA_MAGIC ) 372 break; 373 374 Radeon_WaitForFifo( di, wff->entries ); 375 result = B_OK; 376 } break; 377 378 case RADEON_RESETENGINE: { 379 radeon_no_arg *na = (radeon_no_arg *)buf; 380 381 if( na->magic != RADEON_PRIVATE_DATA_MAGIC ) 382 break; 383 384 ACQUIRE_BEN( di->si->cp.lock ); 385 Radeon_ResetEngine( di ); 386 RELEASE_BEN( di->si->cp.lock ); 387 388 result = B_OK; 389 } break; 390 391 case RADEON_VIPREAD: { 392 radeon_vip_read *vr = (radeon_vip_read *)buf; 393 394 if( vr->magic != RADEON_PRIVATE_DATA_MAGIC ) 395 break; 396 397 result = Radeon_VIPRead( di, vr->channel, vr->address, &vr->data, 398 vr->lock ) ? B_OK : B_ERROR; 399 } break; 400 401 case RADEON_VIPWRITE: { 402 radeon_vip_write *vw = (radeon_vip_write *)buf; 403 404 if( vw->magic != RADEON_PRIVATE_DATA_MAGIC ) 405 break; 406 407 result = Radeon_VIPWrite( di, vw->channel, vw->address, vw->data, 408 vw->lock ) ? B_OK : B_ERROR; 409 } break; 410 411 case RADEON_VIPFIFOREAD: { 412 radeon_vip_fifo_read *vr = (radeon_vip_fifo_read *)buf; 413 414 if( vr->magic != RADEON_PRIVATE_DATA_MAGIC ) 415 break; 416 417 result = Radeon_VIPFifoRead( di, vr->channel, vr->address, vr->count, vr->data, 418 vr->lock ) ? B_OK : B_ERROR; 419 } break; 420 421 case RADEON_VIPFIFOWRITE: { 422 radeon_vip_fifo_write *vw = (radeon_vip_fifo_write *)buf; 423 424 if( vw->magic != RADEON_PRIVATE_DATA_MAGIC ) 425 break; 426 427 result = Radeon_VIPFifoWrite( di, vw->channel, vw->address, vw->count, vw->data, 428 vw->lock ) ? B_OK : B_ERROR; 429 } break; 430 431 case RADEON_FINDVIPDEVICE: { 432 radeon_find_vip_device *fvd = (radeon_find_vip_device *)buf; 433 434 if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC ) 435 break; 436 437 fvd->channel = Radeon_FindVIPDevice( di, fvd->device_id ); 438 result = B_OK; 439 } break; 440 441 442 case RADEON_VIPRESET: { 443 radeon_vip_reset *fvd = (radeon_vip_reset *)buf; 444 445 if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC ) 446 break; 447 448 Radeon_VIPReset( di, fvd->lock ); 449 result = B_OK; 450 } break; 451 452 case RADEON_WAIT_FOR_CAP_IRQ: { 453 radeon_wait_for_cap_irq *wvc = (radeon_wait_for_cap_irq *)buf; 454 455 if( wvc->magic != RADEON_PRIVATE_DATA_MAGIC ) 456 break; 457 458 // restrict wait time to 1 sec to get not stuck here in kernel 459 result = acquire_sem_etc( di->cap_sem, 1, B_RELATIVE_TIMEOUT, 460 min( wvc->timeout, 1000000 )); 461 462 if( result == B_OK ) { 463 cpu_status prev_irq_state = disable_interrupts(); 464 acquire_spinlock( &di->cap_spinlock ); 465 466 wvc->timestamp = di->cap_timestamp; 467 wvc->int_status = di->cap_int_status; 468 wvc->counter = di->cap_counter; 469 470 release_spinlock( &di->cap_spinlock ); 471 restore_interrupts( prev_irq_state ); 472 } 473 } break; 474 475 case RADEON_DMACOPY: { 476 radeon_dma_copy *dc = (radeon_dma_copy *)buf; 477 478 if( dc->magic != RADEON_PRIVATE_DATA_MAGIC ) 479 break; 480 481 result = Radeon_DMACopy( di, dc->src, dc->target, dc->size, dc->lock_mem, dc->contiguous ); 482 } break; 483 484 #ifdef ENABLE_LOGGING 485 #ifdef LOG_INCLUDE_STARTUP 486 // interface to log data 487 case RADEON_GET_LOG_SIZE: 488 *(uint32 *)buf = log_getsize( di->si->log ); 489 result = B_OK; 490 break; 491 492 case RADEON_GET_LOG_DATA: 493 log_getcopy( di->si->log, buf, ((uint32 *)buf)[0] ); 494 result = B_OK; 495 break; 496 #endif 497 #endif 498 } 499 500 if( result == B_DEV_INVALID_IOCTL ) 501 SHOW_ERROR( 3, "Invalid ioctl call: code=0x%lx", msg ); 502 503 return result; 504 } 505