1/*
2	Copyright (c) 2002, Thomas Kurschel
3
4
5	Part of Radeon accelerant
6
7	Main init/uninit functions
8*/
9
10
11#include "GlobalData.h"
12#include "generic.h"
13
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <string.h>
17#include <unistd.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <sys/ioctl.h>
21#include <malloc.h>
22#include "CP.h"
23
24
25// init data used by both primary and cloned accelerant
26//	the_fd - file descriptor of kernel driver
27//	accelerant_is_clone - if true, this is a cloned accelerant
28static status_t init_common( int the_fd, bool accelerant_is_clone )
29{
30	status_t result;
31	radeon_get_private_data gpd;
32
33	SHOW_FLOW0( 3, "" );
34
35	ai = malloc( sizeof( *ai ));
36	if( ai == NULL )
37		return B_NO_MEMORY;
38
39	memset( ai, 0, sizeof( *ai ));
40
41	ai->accelerant_is_clone = accelerant_is_clone;
42	ai->fd = the_fd;
43
44	// get basic info from driver
45	gpd.magic = RADEON_PRIVATE_DATA_MAGIC;
46
47	result = ioctl( ai->fd, RADEON_GET_PRIVATE_DATA, &gpd, sizeof(gpd) );
48	if (result != B_OK) goto err;
49
50	ai->virtual_card_area = clone_area( "Radeon virtual card", (void **)&ai->vc, B_ANY_ADDRESS,
51		B_READ_AREA | B_WRITE_AREA, gpd.virtual_card_area );
52	if( ai->virtual_card_area < 0 ) {
53		result = ai->virtual_card_area;
54		goto err;
55	}
56	ai->shared_info_area = clone_area( "Radeon shared info", (void **)&ai->si, B_ANY_ADDRESS,
57		B_READ_AREA | B_WRITE_AREA, gpd.shared_info_area );
58	if( ai->shared_info_area < 0 ) {
59		result = ai->shared_info_area;
60		goto err2;
61	}
62
63	ai->regs_area = clone_area( "Radeon regs area", (void **)&ai->regs, B_ANY_ADDRESS,
64		B_READ_AREA | B_WRITE_AREA, ai->si->regs_area );
65	if( ai->regs_area < 0 ) {
66		result = ai->regs_area;
67		goto err3;
68	}
69
70//rud:
71	if( ai->si->memory[mt_PCI].area > 0 ) {
72		ai->mapped_memory[mt_PCI].area = clone_area( "Radeon PCI GART area",
73			(void **)&ai->mapped_memory[mt_PCI].data, B_ANY_ADDRESS,
74			B_READ_AREA | B_WRITE_AREA, ai->si->memory[mt_PCI].area );
75		if( ai->mapped_memory[mt_PCI].area < 0 ) {
76			result = ai->mapped_memory[mt_PCI].area;
77			goto err4;
78		}
79	}
80
81	if( ai->si->memory[mt_AGP].area > 0 ) {
82		ai->mapped_memory[mt_AGP].area = clone_area( "Radeon AGP GART area",
83			(void **)&ai->mapped_memory[mt_AGP].data, B_ANY_ADDRESS,
84			B_READ_AREA | B_WRITE_AREA, ai->si->memory[mt_AGP].area );
85		if( ai->mapped_memory[mt_AGP].area < 0 ) {
86			result = ai->mapped_memory[mt_AGP].area;
87			goto err5;
88		}
89	}
90
91	ai->mapped_memory[mt_nonlocal] = ai->mapped_memory[ai->si->nonlocal_type];
92	ai->mapped_memory[mt_local].data = ai->si->local_mem;
93
94	return B_OK;
95
96err5:
97	if( ai->mapped_memory[mt_PCI].area > 0 )
98		delete_area( ai->mapped_memory[mt_PCI].area );
99err4:
100	delete_area( ai->regs_area );
101err3:
102	delete_area( ai->shared_info_area );
103err2:
104	delete_area( ai->virtual_card_area );
105err:
106	free( ai );
107	return result;
108}
109
110// clean up data common to both primary and cloned accelerant
111static void uninit_common( void )
112{
113	if( !ai->accelerant_is_clone ) {
114		if ( ai->si->acc_dma )
115			Radeon_FreeVirtualCardStateBuffer( ai );
116
117		// the last accelerant should must wait for the card to become quite,
118		// else some nasty command could lunger in some FIFO
119		Radeon_WaitForIdle( ai, false );
120	}
121
122	if( ai->mapped_memory[mt_AGP].area > 0 )
123		delete_area( ai->mapped_memory[mt_AGP].area );
124	if( ai->mapped_memory[mt_PCI].area > 0 )
125		delete_area( ai->mapped_memory[mt_PCI].area );
126	delete_area( ai->regs_area );
127	delete_area( ai->shared_info_area );
128	delete_area( ai->virtual_card_area );
129
130	ai->regs_area = ai->shared_info_area = ai->virtual_card_area = 0;
131
132	ai->regs = 0;
133	ai->si = 0;
134	ai->vc = 0;
135
136	// close the file handle ONLY if we're the clone
137	// (this is what Be tells us ;)
138	if( ai->accelerant_is_clone )
139		close( ai->fd );
140
141	free( ai );
142}
143
144// public function: init primary accelerant
145//	the_fd - file handle of kernel driver
146status_t INIT_ACCELERANT( int the_fd )
147{
148	shared_info *si;
149	virtual_card *vc;
150	status_t result;
151
152	SHOW_FLOW0( 3, "" );
153
154	result = init_common( the_fd, 0 );
155	if (result != B_OK)
156		goto err;
157
158	si = ai->si;
159	vc = ai->vc;
160
161	// init Command Processor
162	/*result = Radeon_InitCP( ai );
163	if( result != B_OK )
164		goto err2;*/
165
166	// this isn't the best place, but has to be done sometime
167	Radeon_ReadSettings( vc );
168
169	// establish connection to TV-Out unit
170	Radeon_DetectTVOut( ai );
171
172	// get all possible information about connected display devices
173	Radeon_DetectDisplays( ai );
174
175	// create list of supported modes
176	result = Radeon_CreateModeList( si );
177	if (result != B_OK)
178		goto err3;
179
180	/* init the shared semaphore */
181	(void)INIT_BEN( si->engine.lock, "Radeon engine" );
182
183	// init engine sync token
184	// (count of issued parameters or commands)
185	si->engine.last_idle = si->engine.count = 0;
186	// set last written count to be very old, so it must be written on first use
187	// (see writeSyncToken)
188	si->engine.written = -1;
189
190	// init overlay
191	si->overlay_mgr.token = 0;
192	si->overlay_mgr.inuse = 0;
193
194	// mark overlay as inactive
195	si->active_overlay.crtc_idx = -1;
196	si->pending_overlay.crtc_idx = -1;
197
198	// reset list of allocated overlays
199	vc->overlay_buffers = NULL;
200
201	// mark engine as having no state
202	//si->cp.active_state_buffer = -1;
203
204	if ( ai->si->acc_dma )
205		Radeon_AllocateVirtualCardStateBuffer( ai );
206
207	// everything else is initialized upon set_display_mode
208	return B_OK;
209
210err3:
211//err2:
212	uninit_common();
213err:
214	return result;
215}
216
217
218// public function: return size of clone info
219ssize_t ACCELERANT_CLONE_INFO_SIZE( void )
220{
221	SHOW_FLOW0( 0, "" );
222
223	// clone info is device name, so return its maximum size
224	return MAX_RADEON_DEVICE_NAME_LENGTH;
225}
226
227
228// public function: return clone info
229//	data - buffer to contain info (allocated by caller)
230void GET_ACCELERANT_CLONE_INFO( void *data )
231{
232	radeon_device_name dn;
233	status_t result;
234
235	SHOW_FLOW0( 0, "" );
236
237	// clone info is device name - ask device driver
238	dn.magic = RADEON_PRIVATE_DATA_MAGIC;
239	dn.name = (char *)data;
240
241	result = ioctl( ai->fd, RADEON_DEVICE_NAME, &dn, sizeof(dn) );
242}
243
244// public function: init cloned accelerant
245//	data - clone info from get_accelerant_clone_info
246status_t CLONE_ACCELERANT( void *data )
247{
248	status_t result;
249	char path[MAXPATHLEN];
250	int fd;
251
252	SHOW_FLOW0( 0, "" );
253
254	// create full device name
255	strcpy(path, "/dev/");
256	strcat(path, (const char *)data);
257
258	// open device; according to Be, permissions aren't important
259	// this will probably change once access right are checked properly
260	fd = open(path, B_READ_WRITE);
261	if( fd < 0 )
262		return errno;
263
264	result = init_common( fd, 1 );
265	if( result != B_OK )
266		goto err1;
267
268	// get (cloned) copy of supported display modes
269	result = ai->mode_list_area = clone_area(
270		"Radeon cloned display_modes", (void **)&ai->mode_list,
271		B_ANY_ADDRESS, B_READ_AREA, ai->si->mode_list_area );
272	if (result < B_OK)
273		goto err2;
274
275	return B_OK;
276
277err2:
278	uninit_common();
279err1:
280	close( fd );
281	return result;
282}
283
284// public function: uninit primary or cloned accelerant
285void UNINIT_ACCELERANT( void )
286{
287	// TBD:
288	// we should put accelerator into stable state first -
289	// on my Laptop, you never can boot Windows/Linux after shutting
290	// down BeOS; if both ports have been used, even the BIOS screen
291	// is completely messed up
292
293	SHOW_FLOW0( 0, "" );
294
295	// cloned accelerants have mode_list cloned, so deleting is OK
296	// primary accelerant owns mode list, so deleting is OK as well
297	delete_area( ai->mode_list_area );
298	ai->mode_list = 0;
299
300	uninit_common();
301}
302
303// public function: get some info about graphics card
304status_t GET_ACCELERANT_DEVICE_INFO( accelerant_device_info *di )
305{
306	SHOW_FLOW0( 0, "" );
307
308	// is there anyone using it?
309
310	// TBD: everything apart from memsize
311	di->version = B_ACCELERANT_VERSION;
312	strcpy( di->name, "Radeon" );
313	strcpy( di->chipset, "Radeon" );
314	strcpy( di->serial_no, "None" );
315
316	di->memory = ai->si->memory[mt_local].size;
317
318	// TBD: is max PLL speed really equal to max DAC speed?
319	di->dac_speed = ai->si->pll.max_pll_freq;
320
321	return B_OK;
322}
323