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 "mmio.h" 18 #include "version.h" 19 20 // tell the kernel what revision of the driver API we support 21 int32 api_version = 2; 22 23 24 static status_t open_hook( const char *name, uint32 flags, void **cookie ); 25 static status_t close_hook( void *dev ); 26 static status_t free_hook( void *dev ); 27 static status_t read_hook( void *dev, off_t pos, void *buf, size_t *len ); 28 static status_t write_hook( void *dev, off_t pos, const void *buf, size_t *len ); 29 static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len ); 30 31 32 static device_hooks graphics_device_hooks = { 33 open_hook, 34 close_hook, 35 free_hook, 36 control_hook, 37 read_hook, 38 write_hook, 39 NULL, 40 NULL, 41 NULL, 42 NULL 43 }; 44 45 46 // public function: check whether there is *any* supported hardware 47 status_t init_hardware( void ) 48 { 49 SHOW_INFO0( 0, RADEON_DRIVER_VERSION ); 50 if( Radeon_CardDetect() == B_OK ) 51 return B_OK; 52 else 53 return B_ERROR; 54 } 55 56 57 // public function: init driver 58 status_t init_driver( void ) 59 { 60 SHOW_FLOW0( 3, "" ); 61 62 if( get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK ) 63 return B_ERROR; 64 65 /* driver private data */ 66 devices = (radeon_devices *)calloc( 1, sizeof( radeon_devices )); 67 if( devices == NULL ) { 68 put_module(B_PCI_MODULE_NAME); 69 return B_ERROR; 70 } 71 72 (void)INIT_BEN( devices->kernel, "Radeon Kernel" ); 73 74 Radeon_ProbeDevices(); 75 return B_OK; 76 } 77 78 79 // public function: uninit driver 80 void uninit_driver( void ) 81 { 82 SHOW_FLOW0( 3, "" ); 83 DELETE_BEN( devices->kernel ); 84 85 free( devices ); 86 devices = NULL; 87 88 put_module( B_PCI_MODULE_NAME ); 89 } 90 91 92 // public function: return list of device names 93 const char **publish_devices( void ) 94 { 95 return (const char **)devices->device_names; 96 } 97 98 99 // public function: find hooks for specific device given its name 100 device_hooks *find_device( const char *name ) 101 { 102 uint32 index; 103 104 // probably, we could always return standard hooks 105 for( index = 0; devices->device_names[index]; ++index ) { 106 if( strcmp( name, devices->device_names[index] ) == 0 ) 107 return &graphics_device_hooks; 108 } 109 110 return NULL; 111 } 112 113 114 // public function: open device 115 static status_t open_hook( const char *name, uint32 flags, void **cookie ) 116 { 117 int32 index = 0; 118 device_info *di; 119 status_t result = B_OK; 120 121 SHOW_FLOW( 3, "name=%s, flags=%ld, cookie=0x%08lx", name, flags, (uint32)cookie ); 122 123 // find device info 124 while( devices->device_names[index] && 125 strcmp(name, devices->device_names[index] ) != 0 ) 126 index++; 127 128 di = &(devices->di[index/2]); 129 130 ACQUIRE_BEN( devices->kernel ); 131 132 if( !di->is_open ) 133 result = Radeon_FirstOpen( di ); 134 135 if( result == B_OK ) { 136 di->is_open++; 137 *cookie = di; 138 } 139 140 RELEASE_BEN( devices->kernel ); 141 142 SHOW_FLOW( 3, "returning 0x%08lx", result ); 143 return result; 144 } 145 146 147 // public function: read from device (denied) 148 static status_t read_hook( void *dev, off_t pos, void *buf, size_t *len ) 149 { 150 *len = 0; 151 return B_NOT_ALLOWED; 152 } 153 154 155 // public function: write to device (denied) 156 static status_t write_hook( void *dev, off_t pos, const void *buf, size_t *len ) 157 { 158 *len = 0; 159 return B_NOT_ALLOWED; 160 } 161 162 163 // public function: close device (ignored, wait for free_hook instead) 164 static status_t close_hook( void *dev ) 165 { 166 return B_NO_ERROR; 167 } 168 169 170 // public function: free device 171 static status_t free_hook( void *dev ) 172 { 173 device_info *di = (device_info *)dev; 174 175 SHOW_FLOW0( 0, "" ); 176 177 ACQUIRE_BEN( devices->kernel ); 178 179 mem_freetag( di->memmgr[mt_local], dev ); 180 181 if( di->memmgr[mt_PCI] ) 182 mem_freetag( di->memmgr[mt_PCI], dev ); 183 184 if( di->memmgr[mt_AGP] ) 185 mem_freetag( di->memmgr[mt_AGP], dev ); 186 187 if( di->is_open == 1 ) 188 Radeon_LastClose( di ); 189 190 di->is_open--; 191 RELEASE_BEN( devices->kernel ); 192 193 return B_OK; 194 } 195 196 197 // public function: ioctl 198 static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len ) 199 { 200 device_info *di = (device_info *)dev; 201 status_t result = B_DEV_INVALID_IOCTL; 202 203 switch (msg) { 204 // needed by app_server to load accelerant 205 case B_GET_ACCELERANT_SIGNATURE: { 206 char *sig = (char *)buf; 207 strcpy(sig, "radeon.accelerant"); 208 result = B_OK; 209 } break; 210 211 // needed to share data between kernel and accelerant 212 case RADEON_GET_PRIVATE_DATA: { 213 radeon_get_private_data *gpd = (radeon_get_private_data *)buf; 214 215 if (gpd->magic == RADEON_PRIVATE_DATA_MAGIC) { 216 gpd->shared_info_area = di->shared_area; 217 gpd->virtual_card_area = di->virtual_card_area; 218 result = B_OK; 219 } 220 } break; 221 222 // needed for cloning 223 case RADEON_DEVICE_NAME: { 224 radeon_device_name *dn = (radeon_device_name *)buf; 225 226 if( dn->magic == RADEON_PRIVATE_DATA_MAGIC ) { 227 strncpy( dn->name, di->name, MAX_RADEON_DEVICE_NAME_LENGTH ); 228 result = B_OK; 229 } 230 } break; 231 232 // graphics mem manager 233 case RADEON_ALLOC_MEM: { 234 radeon_alloc_mem *am = (radeon_alloc_mem *)buf; 235 memory_type_e memory_type; 236 237 if( am->magic != RADEON_PRIVATE_DATA_MAGIC ) 238 break; 239 240 if( am->memory_type > mt_last ) 241 break; 242 243 memory_type = am->memory_type == mt_nonlocal ? di->si->nonlocal_type : am->memory_type; 244 245 result = mem_alloc( di->memmgr[memory_type], am->size, am->global ? 0 : dev, &am->handle, &am->offset ); 246 } break; 247 248 case RADEON_FREE_MEM: { 249 radeon_free_mem *fm = (radeon_free_mem *)buf; 250 memory_type_e memory_type; 251 252 if( fm->magic != RADEON_PRIVATE_DATA_MAGIC ) 253 break; 254 255 if( fm->memory_type > mt_last ) 256 break; 257 258 memory_type = fm->memory_type == mt_nonlocal ? di->si->nonlocal_type : fm->memory_type; 259 260 result = mem_free( di->memmgr[memory_type], fm->handle, fm->global ? 0 : dev ); 261 } break; 262 263 case RADEON_WAITFORIDLE: { 264 radeon_wait_for_idle *wfi = (radeon_wait_for_idle *)buf; 265 266 if( wfi->magic != RADEON_PRIVATE_DATA_MAGIC ) 267 break; 268 269 Radeon_WaitForIdle( di, true, wfi->keep_lock ); 270 result = B_OK; 271 } break; 272 273 case RADEON_RESETENGINE: { 274 radeon_no_arg *na = (radeon_no_arg *)buf; 275 276 if( na->magic != RADEON_PRIVATE_DATA_MAGIC ) 277 break; 278 279 ACQUIRE_BEN( di->si->cp.lock ); 280 Radeon_ResetEngine( di ); 281 RELEASE_BEN( di->si->cp.lock ); 282 283 result = B_OK; 284 } break; 285 286 case RADEON_VIPREAD: { 287 radeon_vip_read *vr = (radeon_vip_read *)buf; 288 289 if( vr->magic != RADEON_PRIVATE_DATA_MAGIC ) 290 break; 291 292 result = Radeon_VIPRead( di, vr->channel, vr->address, &vr->data, 293 vr->lock ) ? B_OK : B_ERROR; 294 } break; 295 296 case RADEON_VIPWRITE: { 297 radeon_vip_write *vw = (radeon_vip_write *)buf; 298 299 if( vw->magic != RADEON_PRIVATE_DATA_MAGIC ) 300 break; 301 302 result = Radeon_VIPWrite( di, vw->channel, vw->address, vw->data, 303 vw->lock ) ? B_OK : B_ERROR; 304 } break; 305 306 case RADEON_FINDVIPDEVICE: { 307 radeon_find_vip_device *fvd = (radeon_find_vip_device *)buf; 308 309 if( fvd->magic != RADEON_PRIVATE_DATA_MAGIC ) 310 break; 311 312 fvd->channel = Radeon_FindVIPDevice( di, fvd->device_id ); 313 result = B_OK; 314 } break; 315 316 case RADEON_WAIT_FOR_CAP_IRQ: { 317 radeon_wait_for_cap_irq *wvc = (radeon_wait_for_cap_irq *)buf; 318 319 if( wvc->magic != RADEON_PRIVATE_DATA_MAGIC ) 320 break; 321 322 // restrict wait time to 1 sec to get not stuck here in kernel 323 result = acquire_sem_etc( di->cap_sem, 1, B_RELATIVE_TIMEOUT, 324 min( wvc->timeout, 1000000 )); 325 326 if( result == B_OK ) { 327 cpu_status prev_irq_state = disable_interrupts(); 328 acquire_spinlock( &di->cap_spinlock ); 329 330 wvc->timestamp = di->cap_timestamp; 331 wvc->int_status = di->cap_int_status; 332 wvc->counter = di->cap_counter; 333 334 release_spinlock( &di->cap_spinlock ); 335 restore_interrupts( prev_irq_state ); 336 } 337 } break; 338 339 case RADEON_DMACOPY: { 340 radeon_dma_copy *dc = (radeon_dma_copy *)buf; 341 342 if( dc->magic != RADEON_PRIVATE_DATA_MAGIC ) 343 break; 344 345 result = Radeon_DMACopy( di, dc->src, dc->target, dc->size, dc->lock_mem, dc->contiguous ); 346 } break; 347 348 #ifdef ENABLE_LOGGING 349 #ifdef LOG_INCLUDE_STARTUP 350 // interface to log data 351 case RADEON_GET_LOG_SIZE: 352 *(uint32 *)buf = log_getsize( di->si->log ); 353 result = B_OK; 354 break; 355 356 case RADEON_GET_LOG_DATA: 357 log_getcopy( di->si->log, buf, ((uint32 *)buf)[0] ); 358 result = B_OK; 359 break; 360 #endif 361 #endif 362 } 363 364 if( result == B_DEV_INVALID_IOCTL ) 365 SHOW_ERROR( 3, "Invalid ioctl call: code=0x%lx", msg ); 366 367 return result; 368 } 369