xref: /haiku/src/add-ons/accelerants/neomagic/InitAccelerant.c (revision cba34fecc417ab0af63105226966ef9efc5b0eee)
1 /*
2 	Copyright 1999, Be Incorporated.   All Rights Reserved.
3 	This file may be used under the terms of the Be Sample Code License.
4 
5 	Other authors:
6 	Mark Watson,
7 	Rudolf Cornelissen 10/2002-12/2003.
8 */
9 
10 #define MODULE_BIT 0x00800000
11 
12 #include <string.h>
13 #include "acc_std.h"
14 
15 /* defined in ProposeDisplayMode.c */
16 extern status_t create_mode_list(void);
17 
18 static status_t init_common(int the_fd);
19 
20 /* Initialization code shared between primary and cloned accelerants */
21 static status_t init_common(int the_fd) {
22 	status_t result;
23 	mn_get_private_data gpd;
24 
25 	// LOG not available from here to next LOG: NULL si
26 
27 	/* memorize the file descriptor */
28 	fd = the_fd;
29 	/* set the magic number so the driver knows we're for real */
30 	gpd.magic = MN_PRIVATE_DATA_MAGIC;
31 	/* contact driver and get a pointer to the registers and shared data */
32 	result = ioctl(fd, MN_GET_PRIVATE_DATA, &gpd, sizeof(gpd));
33 	if (result != B_OK) goto error0;
34 
35 	/* clone the shared area for our use */
36 	shared_info_area = clone_area(DRIVER_PREFIX " shared", (void **)&si, B_ANY_ADDRESS,
37 		B_READ_AREA | B_WRITE_AREA, gpd.shared_info_area);
38 	if (shared_info_area < 0) {
39 			result = shared_info_area;
40 			goto error0;
41 	}
42 	// LOG is now available, si !NULL
43 	LOG(4,("init_common: logmask 0x%08x, memory %dMB, hardcursor %d, usebios %d\n",
44 		si->settings.logmask, si->settings.memory, si->settings.hardcursor, si->settings.usebios));
45 
46  	/*Check for R4.5.0 and if it is running, use work around*/
47  	{
48  		if (si->use_clone_bugfix)
49  		{
50  			/*check for R4.5.0 bug and attempt to work around*/
51  			LOG(2,("InitACC: Found R4.5.0 bug - attempting to work around\n"));
52  			regs = si->clone_bugfix_regs;
53  			regs2 = si->clone_bugfix_regs2;
54  		}
55  		else
56  		{
57 			/* clone the memory mapped registers for our use  - does not work on <4.5.2 (but is better this way)*/
58 			regs_area = clone_area(DRIVER_PREFIX " regs", (void **)&regs, B_ANY_ADDRESS,
59 				B_READ_AREA | B_WRITE_AREA, si->regs_area);
60 			if (regs_area < 0)
61 			{
62 				result = regs_area;
63 				goto error1;
64 			}
65 			else
66 			{
67 				regs2_area = clone_area(DRIVER_PREFIX " regs2", (void **)&regs2, B_ANY_ADDRESS,
68 				B_READ_AREA | B_WRITE_AREA, si->regs2_area);
69 				if (regs2_area < 0)
70 				{
71 					result = regs2_area;
72 					goto error2;
73 				}
74 			}
75  		}
76  	}
77 
78 	/*FIXME - print dma addresses*/
79 	//LOG(4,("DMA_virtual:%x\tDMA_physical:%x\tDMA_area:%x\n",si->dma_buffer,si->dma_buffer_pci,si->dma_buffer_area));
80 
81 	/* all done */
82 	goto error0;
83 
84 error2:
85 	delete_area(regs_area);
86 error1:
87 	delete_area(shared_info_area);
88 error0:
89 	return result;
90 }
91 
92 /* Clean up code shared between primary and cloned accelrants */
93 static void uninit_common(void) {
94 	/* release the memory mapped registers */
95 	delete_area(regs2_area);
96 	delete_area(regs_area);
97 	/* a little cheap paranoia */
98 	regs = 0;
99 	regs2 = 0;
100 	/* release our copy of the shared info from the kernel driver */
101 	delete_area(shared_info_area);
102 	/* more cheap paranoia */
103 	si = 0;
104 }
105 
106 /*
107 Initialize the accelerant.  the_fd is the file handle of the device (in
108 /dev/graphics) that has been opened by the app_server (or some test harness).
109 We need to determine if the kernel driver and the accelerant are compatible.
110 If they are, get the accelerant ready to handle other hook functions and
111 report success or failure.
112 */
113 status_t INIT_ACCELERANT(int the_fd) {
114 	status_t result;
115 	int pointer_reservation; //mem reserved for pointer
116 	int cnt; 				 //used for iteration through the overlay buffers
117 
118 	if (1) {
119 		time_t now = time (NULL);
120 		// LOG not available from here to next LOG: NULL si
121 		MSG(("INIT_ACCELERANT: %s", ctime (&now)));
122 	}
123 
124 	/* note that we're the primary accelerant (accelerantIsClone is global) */
125 	accelerantIsClone = 0;
126 
127 	/* do the initialization common to both the primary and the clones */
128 	result = init_common(the_fd);
129 
130 	/* bail out if the common initialization failed */
131 	if (result != B_OK) goto error0;
132 	// LOG now available: !NULL si
133 
134 	/* call the device specific init code */
135 	result = mn_general_powerup();
136 
137 	/* bail out if it failed */
138 	if (result != B_OK) goto error1;
139 
140 	/*
141 	Now would be a good time to figure out what video modes your card supports.
142 	We'll place the list of modes in another shared area so all of the copies
143 	of the driver can see them.  The primary copy of the accelerant (ie the one
144 	initialized with this routine) will own the "one true copy" of the list.
145 	Everybody else get's a read-only clone.
146 	*/
147 	result = create_mode_list();
148 	if (result != B_OK)
149 	{
150 		goto error1;
151 	}
152 
153 	/*
154 	Put the cursor at the start of the frame buffer.  The typical 64x64 4 color
155 	(black, white, transparent, inverse) takes up 1024 bytes of RAM.
156 	*/
157 	/* Initialize the rest of the cursor information while we're here */
158 	si->cursor.width = 16;
159 	si->cursor.height = 16;
160 	si->cursor.hot_x = 0;
161 	si->cursor.hot_y = 0;
162 	si->cursor.x = 0;
163 	si->cursor.y = 0;
164 
165 	/*
166 	Put the frame buffer immediately following the cursor data. We store this
167 	info in a frame_buffer_config structure to make it convienient to return
168 	to the app_server later.
169 	*/
170 	pointer_reservation = 0;
171 	if (si->settings.hardcursor) pointer_reservation = si->ps.curmem_size;
172 
173 	si->fbc.frame_buffer = (void *)((char *)si->framebuffer+pointer_reservation);
174 	si->fbc.frame_buffer_dma = (void *)((char *)si->framebuffer_pci+pointer_reservation);
175 
176 	/* count of issued parameters or commands */
177 	si->engine.last_idle = si->engine.count = 0;
178 	INIT_BEN(si->engine.lock);
179 
180 	INIT_BEN(si->overlay.lock);
181 	for (cnt = 0; cnt < MAXBUFFERS; cnt++)
182 	{
183 		/* make sure overlay buffers are 'marked' as being free */
184 		si->overlay.myBuffer[cnt].buffer = NULL;
185 		si->overlay.myBuffer[cnt].buffer_dma = NULL;
186 	}
187 	/* make sure overlay unit is 'marked' as being free */
188 	si->overlay.myToken = NULL;
189 
190 	/* bail out if something failed */
191 	if (result != B_OK) goto error1;
192 
193 	/* initialise various cursor stuff*/
194 	mn_crtc_cursor_init();
195 
196 	/* ensure cursor state */
197 	SHOW_CURSOR(false);
198 
199 	/* a winner! */
200 	result = B_OK;
201 	goto error0;
202 
203 error1:
204 	/*
205 	Initialization failed after init_common() succeeded, so we need to clean
206 	up before quiting.
207 	*/
208 	uninit_common();
209 
210 error0:
211 	return result;
212 }
213 
214 /*
215 Return the number of bytes required to hold the information required
216 to clone the device.
217 */
218 ssize_t ACCELERANT_CLONE_INFO_SIZE(void) {
219 	/*
220 	Since we're passing the name of the device as the only required
221 	info, return the size of the name buffer
222 	*/
223 	return B_OS_NAME_LENGTH; // apsed, was MAX_mn_DEVICE_NAME_LENGTH;
224 }
225 
226 
227 /*
228 Return the info required to clone the device.  void *data points to
229 a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length.
230 */
231 void GET_ACCELERANT_CLONE_INFO(void *data) {
232 	mn_device_name dn;
233 	status_t result;
234 
235 	/* call the kernel driver to get the device name */
236 	dn.magic = MN_PRIVATE_DATA_MAGIC;
237 	/* store the returned info directly into the passed buffer */
238 	dn.name = (char *)data;
239 	result = ioctl(fd, MN_DEVICE_NAME, &dn, sizeof(dn));
240 }
241 
242 /*
243 Initialize a copy of the accelerant as a clone.  void *data points to
244 a copy of the data returned by GET_ACCELERANT_CLONE_INFO().
245 */
246 status_t CLONE_ACCELERANT(void *data) {
247 	status_t result;
248 	char path[MAXPATHLEN];
249 
250 	/* the data is the device name */
251 	/* Note: the R4 graphics driver kit is in error here (missing trailing '/') */
252 	strcpy(path, "/dev/");
253 	strcat(path, (const char *)data);
254 	/* open the device, the permissions aren't important */
255 	fd = open(path, B_READ_WRITE);
256 	if (fd < 0) {
257 		result = fd;
258 		goto error0;
259 	}
260 
261 	/* note that we're a clone accelerant */
262 	accelerantIsClone = 1;
263 
264 	/* call the shared initialization code */
265 	result = init_common(fd);
266 
267 	/* bail out if the common initialization failed */
268 	if (result != B_OK) goto error1;
269 
270 	/* get shared area for display modes */
271 	result = my_mode_list_area = clone_area(
272 		DRIVER_PREFIX " cloned display_modes",
273 		(void **)&my_mode_list,
274 		B_ANY_ADDRESS,
275 		B_READ_AREA,
276 		si->mode_area
277 	);
278 	if (result < B_OK) goto error2;
279 
280 	/* all done */
281 	LOG(4,("CLONE_ACCELERANT: cloning was succesfull.\n"));
282 
283 	result = B_OK;
284 	goto error0;
285 
286 error2:
287 	/* free up the areas we cloned */
288 	uninit_common();
289 error1:
290 	/* close the device we opened */
291 	close(fd);
292 error0:
293 	return result;
294 }
295 
296 void UNINIT_ACCELERANT(void)
297 {
298 	if (accelerantIsClone)
299 		LOG(4,("UNINIT_ACCELERANT: shutting down clone accelerant.\n"));
300 	else
301 		LOG(4,("UNINIT_ACCELERANT: shutting down primary accelerant.\n"));
302 
303 	/*delete benaphore*/
304 	DELETE_BEN(si->engine.lock);
305 	DELETE_BEN(si->overlay.lock);
306 	/* free our mode list area */
307 	delete_area(my_mode_list_area);
308 	/* paranoia */
309 	my_mode_list = 0;
310 	/* release our cloned data */
311 	uninit_common();
312 	/* close the file handle ONLY if we're the clone */
313 	if (accelerantIsClone) close(fd);
314 }
315