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