xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/driver.c (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
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