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
22int32	api_version = 2;
23
24
25static status_t open_hook(const char *name, uint32 flags, void **cookie);
26static status_t close_hook(void *dev);
27static status_t free_hook(void *dev);
28static status_t read_hook(void *dev, off_t pos, void *buf, size_t *len);
29static status_t write_hook(void *dev, off_t pos, const void *buf, size_t *len);
30static status_t control_hook(void *dev, uint32 msg, void *buf, size_t len);
31
32
33static 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
46radeon_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
60radeon_settings current_settings;
61
62static void
63GetDriverSettings(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
134status_t
135init_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
145status_t
146init_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
173void
174uninit_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
188const char **
189publish_devices(void)
190{
191	return (const char **)devices->device_names;
192}
193
194
195device_hooks *
196find_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
213static status_t
214open_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
248static status_t
249read_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)
257static status_t
258write_hook(void *dev, off_t pos, const void *buf, size_t *len)
259{
260	*len = 0;
261	return B_NOT_ALLOWED;
262}
263
264
265static status_t
266close_hook(void *dev)
267{
268	return B_NO_ERROR;
269}
270
271
272static status_t
273free_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
299static status_t
300control_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