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