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