xref: /haiku/src/add-ons/accelerants/radeon/InitAccelerant.c (revision 1a76488fc88584bf66b9751d7fb9b6527ac20d87)
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_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 
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 		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
146 status_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 
210 err3:
211 //err2:
212 	uninit_common();
213 err:
214 	return result;
215 }
216 
217 
218 // public function: return size of clone info
219 ssize_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)
230 void 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
246 status_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 
277 err2:
278 	uninit_common();
279 err1:
280 	close( fd );
281 	return result;
282 }
283 
284 // public function: uninit primary or cloned accelerant
285 void 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
304 status_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