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 return B_ERROR; 159 } 160 161 (void)INIT_BEN( devices->kernel, "Radeon Kernel" ); 162 163 GetDriverSettings(); 164 Radeon_ProbeDevices(); 165 return B_OK; 166 } 167 168 169 // public function: uninit driver 170 void uninit_driver( void ) 171 { 172 SHOW_FLOW0( 3, "" ); 173 DELETE_BEN( devices->kernel ); 174 175 free( devices ); 176 devices = NULL; 177 178 put_module( B_PCI_MODULE_NAME ); 179 /* put the agp module away if it's there */ 180 if (agp_bus) put_module(B_AGP_MODULE_NAME); 181 } 182 183 184 // public function: return list of device names 185 const char **publish_devices( void ) 186 { 187 return (const char **)devices->device_names; 188 } 189 190 191 // public function: find hooks for specific device given its name 192 device_hooks *find_device( const char *name ) 193 { 194 uint32 index; 195 196 // probably, we could always return standard hooks 197 for( index = 0; devices->device_names[index]; ++index ) { 198 if( strcmp( name, devices->device_names[index] ) == 0 ) 199 return &graphics_device_hooks; 200 } 201 202 return NULL; 203 } 204 205 206 // public function: open device 207 static status_t open_hook( const char *name, uint32 flags, void **cookie ) 208 { 209 int32 index = 0; 210 device_info *di; 211 status_t result = B_OK; 212 213 SHOW_FLOW( 3, "name=%s, flags=%ld, cookie=0x%08lx", name, flags, (uint32)cookie ); 214 215 // find device info 216 while( devices->device_names[index] && 217 strcmp(name, devices->device_names[index] ) != 0 ) 218 index++; 219 220 di = &(devices->di[index/2]); 221 222 ACQUIRE_BEN( devices->kernel ); 223 224 if( !di->is_open ) 225 result = Radeon_FirstOpen( di ); 226 227 if( result == B_OK ) { 228 di->is_open++; 229 *cookie = di; 230 } 231 232 RELEASE_BEN( devices->kernel ); 233 234 SHOW_FLOW( 3, "returning 0x%08lx", result ); 235 return result; 236 } 237 238 239 // public function: read from device (denied) 240 static status_t read_hook( void *dev, off_t pos, void *buf, size_t *len ) 241 { 242 *len = 0; 243 return B_NOT_ALLOWED; 244 } 245 246 247 // public function: write to device (denied) 248 static status_t write_hook( void *dev, off_t pos, const void *buf, size_t *len ) 249 { 250 *len = 0; 251 return B_NOT_ALLOWED; 252 } 253 254 255 // public function: close device (ignored, wait for free_hook instead) 256 static status_t close_hook( void *dev ) 257 { 258 return B_NO_ERROR; 259 } 260 261 262 // public function: free device 263 static status_t free_hook( void *dev ) 264 { 265 device_info *di = (device_info *)dev; 266 267 SHOW_FLOW0( 0, "" ); 268 269 ACQUIRE_BEN( devices->kernel ); 270 271 mem_freetag( di->memmgr[mt_local], dev ); 272 273 if( di->memmgr[mt_PCI] ) 274 mem_freetag( di->memmgr[mt_PCI], dev ); 275 276 if( di->memmgr[mt_AGP] ) 277 mem_freetag( di->memmgr[mt_AGP], dev ); 278 279 if( di->is_open == 1 ) 280 Radeon_LastClose( di ); 281 282 di->is_open--; 283 RELEASE_BEN( devices->kernel ); 284 285 return B_OK; 286 } 287 288 289 // public function: ioctl 290 static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len ) 291 { 292 device_info *di = (device_info *)dev; 293 status_t result = B_DEV_INVALID_IOCTL; 294 295 switch (msg) { 296 // needed by app_server to load accelerant 297 case B_GET_ACCELERANT_SIGNATURE: { 298 char *sig = (char *)buf; 299 strcpy(sig, "radeon.accelerant"); 300 result = B_OK; 301 } break; 302 303 // needed to share data between kernel and accelerant 304 case RADEON_GET_PRIVATE_DATA: { 305 radeon_get_private_data *gpd = (radeon_get_private_data *)buf; 306 307 if (gpd->magic == RADEON_PRIVATE_DATA_MAGIC) { 308 gpd->shared_info_area = di->shared_area; 309 gpd->virtual_card_area = di->virtual_card_area; 310 result = B_OK; 311 } 312 } break; 313 314 // needed for cloning 315 case RADEON_DEVICE_NAME: { 316 radeon_device_name *dn = (radeon_device_name *)buf; 317 318 if( dn->magic == RADEON_PRIVATE_DATA_MAGIC ) { 319 strncpy( dn->name, di->name, MAX_RADEON_DEVICE_NAME_LENGTH ); 320 result = B_OK; 321 } 322 } break; 323 324 // graphics mem manager 325 case RADEON_ALLOC_MEM: { 326 radeon_alloc_mem *am = (radeon_alloc_mem *)buf; 327 memory_type_e memory_type; 328 329 if( am->magic != RADEON_PRIVATE_DATA_MAGIC ) 330 break; 331 332 if( am->memory_type > mt_last ) 333 break; 334 335 memory_type = am->memory_type == mt_nonlocal ? di->si->nonlocal_type : am->memory_type; 336 337 result = mem_alloc( di->memmgr[memory_type], am->size, am->global ? 0 : dev, &am->handle, &am->offset ); 338 } break; 339 340 case RADEON_FREE_MEM: { 341 radeon_free_mem *fm = (radeon_free_mem *)buf; 342 memory_type_e memory_type; 343 344 if( fm->magic != RADEON_PRIVATE_DATA_MAGIC ) 345 break; 346 347 if( fm->memory_type > mt_last ) 348 break; 349 350 memory_type = fm->memory_type == mt_nonlocal ? di->si->nonlocal_type : fm->memory_type; 351 352 result = mem_free( di->memmgr[memory_type], fm->handle, fm->global ? 0 : dev ); 353 } break; 354 355 case RADEON_WAITFORIDLE: { 356 radeon_wait_for_idle *wfi = (radeon_wait_for_idle *)buf; 357 358 if( wfi->magic != RADEON_PRIVATE_DATA_MAGIC ) 359 break; 360 361 Radeon_WaitForIdle( di, true, wfi->keep_lock ); 362 result = B_OK; 363 } break; 364 365 case RADEON_WAITFORFIFO: { 366 radeon_wait_for_fifo *wff = (radeon_wait_for_fifo *)buf; 367 368 if( wff->magic != RADEON_PRIVATE_DATA_MAGIC ) 369 break; 370 371 Radeon_WaitForFifo( di, wff->entries ); 372 result = B_OK; 373 } break; 374 375 case RADEON_RESETENGINE: { 376 radeon_no_arg *na = (radeon_no_arg *)buf; 377 378 if( na->magic != RADEON_PRIVATE_DATA_MAGIC ) 379 break; 380 381 ACQUIRE_BEN( di->si->cp.lock ); 382 Radeon_ResetEngine( di ); 383 RELEASE_BEN( di->si->cp.lock ); 384 385 result = B_OK; 386 } break; 387 388 case RADEON_VIPREAD: { 389 radeon_vip_read *vr = (radeon_vip_read *)buf; 390 391 if( vr->magic != RADEON_PRIVATE_DATA_MAGIC ) 392 break; 393 394 result = Radeon_VIPRead( di, vr->channel, vr->address, &vr->data, 395 vr->lock ) ? B_OK : B_ERROR; 396 } break; 397 398 case RADEON_VIPWRITE: { 399 radeon_vip_write *vw = (radeon_vip_write *)buf; 400 401 if( vw->magic != RADEON_PRIVATE_DATA_MAGIC ) 402 break; 403 404 result = Radeon_VIPWrite( di, vw->channel, vw->address, vw->data, 405 vw->lock ) ? B_OK : B_ERROR; 406 } break; 407 408 case RADEON_VIPFIFOREAD: { 409 radeon_vip_fifo_read *vr = (radeon_vip_fifo_read *)buf; 410 411 if( vr->magic != RADEON_PRIVATE_DATA_MAGIC ) 412 break; 413 414 result = Radeon_VIPFifoRead( di, vr->channel, vr->address, vr->count, vr->data, 415 vr->lock ) ? B_OK : B_ERROR; 416 } break; 417 418 case RADEON_VIPFIFOWRITE: { 419 radeon_vip_fifo_write *vw = (radeon_vip_fifo_write *)buf; 420 421 if( vw->magic != RADEON_PRIVATE_DATA_MAGIC ) 422 break; 423 424 result = Radeon_VIPFifoWrite( di, vw->channel, vw->address, vw->count, vw->data, 425 vw->lock ) ? B_OK : B_ERROR; 426 } break; 427 428 case RADEON_FINDVIPDEVICE: { 429 radeon_find_vip_device *fvd = (radeon_find_vip_device *)buf; 430 431 if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC ) 432 break; 433 434 fvd->channel = Radeon_FindVIPDevice( di, fvd->device_id ); 435 result = B_OK; 436 } break; 437 438 439 case RADEON_VIPRESET: { 440 radeon_vip_reset *fvd = (radeon_vip_reset *)buf; 441 442 if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC ) 443 break; 444 445 Radeon_VIPReset( di, fvd->lock ); 446 result = B_OK; 447 } break; 448 449 case RADEON_WAIT_FOR_CAP_IRQ: { 450 radeon_wait_for_cap_irq *wvc = (radeon_wait_for_cap_irq *)buf; 451 452 if( wvc->magic != RADEON_PRIVATE_DATA_MAGIC ) 453 break; 454 455 // restrict wait time to 1 sec to get not stuck here in kernel 456 result = acquire_sem_etc( di->cap_sem, 1, B_RELATIVE_TIMEOUT, 457 min( wvc->timeout, 1000000 )); 458 459 if( result == B_OK ) { 460 cpu_status prev_irq_state = disable_interrupts(); 461 acquire_spinlock( &di->cap_spinlock ); 462 463 wvc->timestamp = di->cap_timestamp; 464 wvc->int_status = di->cap_int_status; 465 wvc->counter = di->cap_counter; 466 467 release_spinlock( &di->cap_spinlock ); 468 restore_interrupts( prev_irq_state ); 469 } 470 } break; 471 472 case RADEON_DMACOPY: { 473 radeon_dma_copy *dc = (radeon_dma_copy *)buf; 474 475 if( dc->magic != RADEON_PRIVATE_DATA_MAGIC ) 476 break; 477 478 result = Radeon_DMACopy( di, dc->src, dc->target, dc->size, dc->lock_mem, dc->contiguous ); 479 } break; 480 481 #ifdef ENABLE_LOGGING 482 #ifdef LOG_INCLUDE_STARTUP 483 // interface to log data 484 case RADEON_GET_LOG_SIZE: 485 *(uint32 *)buf = log_getsize( di->si->log ); 486 result = B_OK; 487 break; 488 489 case RADEON_GET_LOG_DATA: 490 log_getcopy( di->si->log, buf, ((uint32 *)buf)[0] ); 491 result = B_OK; 492 break; 493 #endif 494 #endif 495 } 496 497 if( result == B_DEV_INVALID_IOCTL ) 498 SHOW_ERROR( 3, "Invalid ioctl call: code=0x%lx", msg ); 499 500 return result; 501 } 502