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