xref: /haiku/src/add-ons/accelerants/skeleton/InitAccelerant.c (revision 9da04493a9afe8fc3039dc1d7c9488b071ba7310)
168353368SRudolf Cornelissen /*
268353368SRudolf Cornelissen 	Copyright 1999, Be Incorporated.   All Rights Reserved.
368353368SRudolf Cornelissen 	This file may be used under the terms of the Be Sample Code License.
468353368SRudolf Cornelissen 
568353368SRudolf Cornelissen 	Other authors:
668353368SRudolf Cornelissen 	Mark Watson,
768353368SRudolf Cornelissen 	Rudolf Cornelissen 10/2002-7/2004.
868353368SRudolf Cornelissen */
968353368SRudolf Cornelissen 
1068353368SRudolf Cornelissen #define MODULE_BIT 0x00800000
1168353368SRudolf Cornelissen 
1268353368SRudolf Cornelissen #include <string.h>
1368353368SRudolf Cornelissen #include <unistd.h>
1468353368SRudolf Cornelissen #include "acc_std.h"
1568353368SRudolf Cornelissen 
1668353368SRudolf Cornelissen static status_t init_common(int the_fd);
1768353368SRudolf Cornelissen 
1868353368SRudolf Cornelissen /* Initialization code shared between primary and cloned accelerants */
init_common(int the_fd)1968353368SRudolf Cornelissen static status_t init_common(int the_fd) {
2068353368SRudolf Cornelissen 	status_t result;
219d063f00SRudolf Cornelissen 	eng_get_private_data gpd;
2268353368SRudolf Cornelissen 
2368353368SRudolf Cornelissen 	// LOG not available from here to next LOG: NULL si
2468353368SRudolf Cornelissen 
2568353368SRudolf Cornelissen 	/* memorize the file descriptor */
2668353368SRudolf Cornelissen 	fd = the_fd;
2768353368SRudolf Cornelissen 	/* set the magic number so the driver knows we're for real */
28bf1feef8SRudolf Cornelissen 	gpd.magic = SKEL_PRIVATE_DATA_MAGIC;
2968353368SRudolf Cornelissen 	/* contact driver and get a pointer to the registers and shared data */
30bf1feef8SRudolf Cornelissen 	result = ioctl(fd, ENG_GET_PRIVATE_DATA, &gpd, sizeof(gpd));
3168353368SRudolf Cornelissen 	if (result != B_OK) goto error0;
3268353368SRudolf Cornelissen 
3368353368SRudolf Cornelissen 	/* clone the shared area for our use */
3468353368SRudolf Cornelissen 	shared_info_area = clone_area(DRIVER_PREFIX " shared", (void **)&si, B_ANY_ADDRESS,
3568353368SRudolf Cornelissen 		B_READ_AREA | B_WRITE_AREA, gpd.shared_info_area);
3668353368SRudolf Cornelissen 	if (shared_info_area < 0) {
3768353368SRudolf Cornelissen 			result = shared_info_area;
3868353368SRudolf Cornelissen 			goto error0;
3968353368SRudolf Cornelissen 	}
4068353368SRudolf Cornelissen 	// LOG is now available, si !NULL
4168353368SRudolf Cornelissen 	LOG(4,("init_common: logmask 0x%08x, memory %dMB, hardcursor %d, usebios %d, switchhead %d, force_pci %d\n",
4268353368SRudolf Cornelissen 		si->settings.logmask, si->settings.memory, si->settings.hardcursor, si->settings.usebios, si->settings.switchhead, si->settings.force_pci));
4368353368SRudolf Cornelissen 	LOG(4,("init_common: dumprom %d, unhide_fw %d, pgm_panel %d\n",
4468353368SRudolf Cornelissen 		si->settings.dumprom, si->settings.unhide_fw, si->settings.pgm_panel));
4568353368SRudolf Cornelissen 
4668353368SRudolf Cornelissen  	/*Check for R4.5.0 and if it is running, use work around*/
4768353368SRudolf Cornelissen  	{
4868353368SRudolf Cornelissen  		if (si->use_clone_bugfix)
4968353368SRudolf Cornelissen  		{
5068353368SRudolf Cornelissen  			/*check for R4.5.0 bug and attempt to work around*/
5168353368SRudolf Cornelissen  			LOG(2,("InitACC: Found R4.5.0 bug - attempting to work around\n"));
5268353368SRudolf Cornelissen  			regs = si->clone_bugfix_regs;
5368353368SRudolf Cornelissen  		}
5468353368SRudolf Cornelissen  		else
5568353368SRudolf Cornelissen  		{
5668353368SRudolf Cornelissen 			/* clone the memory mapped registers for our use  - does not work on <4.5.2 (but is better this way)*/
5768353368SRudolf Cornelissen 			regs_area = clone_area(DRIVER_PREFIX " regs", (void **)&regs, B_ANY_ADDRESS,
5868353368SRudolf Cornelissen 				B_READ_AREA | B_WRITE_AREA, si->regs_area);
5968353368SRudolf Cornelissen 			if (regs_area < 0) {
6068353368SRudolf Cornelissen 				result = regs_area;
6168353368SRudolf Cornelissen 				goto error1;
6268353368SRudolf Cornelissen 			}
6368353368SRudolf Cornelissen  		}
6468353368SRudolf Cornelissen  	}
6568353368SRudolf Cornelissen 
6668353368SRudolf Cornelissen 	/*FIXME - print dma addresses*/
6768353368SRudolf Cornelissen 	//LOG(4,("DMA_virtual:%x\tDMA_physical:%x\tDMA_area:%x\n",si->dma_buffer,si->dma_buffer_pci,si->dma_buffer_area));
6868353368SRudolf Cornelissen 
6968353368SRudolf Cornelissen 	/* all done */
7068353368SRudolf Cornelissen 	goto error0;
7168353368SRudolf Cornelissen 
7268353368SRudolf Cornelissen error1:
7368353368SRudolf Cornelissen 	delete_area(shared_info_area);
7468353368SRudolf Cornelissen error0:
7568353368SRudolf Cornelissen 	return result;
7668353368SRudolf Cornelissen }
7768353368SRudolf Cornelissen 
7868353368SRudolf Cornelissen /* Clean up code shared between primary and cloned accelrants */
uninit_common(void)7968353368SRudolf Cornelissen static void uninit_common(void) {
8068353368SRudolf Cornelissen 	/* release the memory mapped registers */
8168353368SRudolf Cornelissen 	delete_area(regs_area);
8268353368SRudolf Cornelissen 	/* a little cheap paranoia */
8368353368SRudolf Cornelissen 	regs = 0;
8468353368SRudolf Cornelissen 	/* release our copy of the shared info from the kernel driver */
8568353368SRudolf Cornelissen 	delete_area(shared_info_area);
8668353368SRudolf Cornelissen 	/* more cheap paranoia */
8768353368SRudolf Cornelissen 	si = 0;
8868353368SRudolf Cornelissen }
8968353368SRudolf Cornelissen 
9068353368SRudolf Cornelissen /*
9168353368SRudolf Cornelissen Initialize the accelerant.  the_fd is the file handle of the device (in
9268353368SRudolf Cornelissen /dev/graphics) that has been opened by the app_server (or some test harness).
9368353368SRudolf Cornelissen We need to determine if the kernel driver and the accelerant are compatible.
9468353368SRudolf Cornelissen If they are, get the accelerant ready to handle other hook functions and
9568353368SRudolf Cornelissen report success or failure.
9668353368SRudolf Cornelissen */
INIT_ACCELERANT(int the_fd)9768353368SRudolf Cornelissen status_t INIT_ACCELERANT(int the_fd) {
9868353368SRudolf Cornelissen 	status_t result;
9968353368SRudolf Cornelissen 	int pointer_reservation; //mem reserved for pointer
10068353368SRudolf Cornelissen 	int cnt; 				 //used for iteration through the overlay buffers
10168353368SRudolf Cornelissen 
10268353368SRudolf Cornelissen 	if (0) {
10368353368SRudolf Cornelissen 		time_t now = time (NULL);
10468353368SRudolf Cornelissen 		// LOG not available from here to next LOG: NULL si
10568353368SRudolf Cornelissen 		MSG(("INIT_ACCELERANT: %s", ctime (&now)));
10668353368SRudolf Cornelissen 	}
10768353368SRudolf Cornelissen 
10868353368SRudolf Cornelissen 	/* note that we're the primary accelerant (accelerantIsClone is global) */
10968353368SRudolf Cornelissen 	accelerantIsClone = 0;
11068353368SRudolf Cornelissen 
11168353368SRudolf Cornelissen 	/* do the initialization common to both the primary and the clones */
11268353368SRudolf Cornelissen 	result = init_common(the_fd);
11368353368SRudolf Cornelissen 
11468353368SRudolf Cornelissen 	/* bail out if the common initialization failed */
11568353368SRudolf Cornelissen 	if (result != B_OK) goto error0;
11668353368SRudolf Cornelissen 	// LOG now available: !NULL si
11768353368SRudolf Cornelissen 
11868353368SRudolf Cornelissen 	/* call the device specific init code */
119886dbf81SRudolf Cornelissen 	result = eng_general_powerup();
12068353368SRudolf Cornelissen 
12168353368SRudolf Cornelissen 	/* bail out if it failed */
12268353368SRudolf Cornelissen 	if (result != B_OK) goto error1;
12368353368SRudolf Cornelissen 
12468353368SRudolf Cornelissen 	/*
12568353368SRudolf Cornelissen 	Now would be a good time to figure out what video modes your card supports.
12668353368SRudolf Cornelissen 	We'll place the list of modes in another shared area so all of the copies
12768353368SRudolf Cornelissen 	of the driver can see them.  The primary copy of the accelerant (ie the one
12868353368SRudolf Cornelissen 	initialized with this routine) will own the "one true copy" of the list.
12968353368SRudolf Cornelissen 	Everybody else get's a read-only clone.
13068353368SRudolf Cornelissen 	*/
13168353368SRudolf Cornelissen 	result = create_mode_list();
13268353368SRudolf Cornelissen 	if (result != B_OK)
13368353368SRudolf Cornelissen 	{
13468353368SRudolf Cornelissen 		goto error1;
13568353368SRudolf Cornelissen 	}
13668353368SRudolf Cornelissen 
13768353368SRudolf Cornelissen 	/*
13868353368SRudolf Cornelissen 	Put the cursor at the start of the frame buffer.
13968353368SRudolf Cornelissen 	Nvidia cursor is 32x32 16 color? takes up 4096 bytes of RAM.
14068353368SRudolf Cornelissen 	*/
14168353368SRudolf Cornelissen 	/* Initialize the rest of the cursor information while we're here */
14268353368SRudolf Cornelissen 	si->cursor.width = 16;
14368353368SRudolf Cornelissen 	si->cursor.height = 16;
14468353368SRudolf Cornelissen 	si->cursor.hot_x = 0;
14568353368SRudolf Cornelissen 	si->cursor.hot_y = 0;
14668353368SRudolf Cornelissen 	si->cursor.x = 0;
14768353368SRudolf Cornelissen 	si->cursor.y = 0;
14868353368SRudolf Cornelissen 	si->cursor.dh_right = false;
14968353368SRudolf Cornelissen 
15068353368SRudolf Cornelissen 	/*
15168353368SRudolf Cornelissen 	Put the frame buffer immediately following the cursor data. We store this
15268353368SRudolf Cornelissen 	info in a frame_buffer_config structure to make it convienient to return
15368353368SRudolf Cornelissen 	to the app_server later.
15468353368SRudolf Cornelissen 	*/
15568353368SRudolf Cornelissen 	pointer_reservation = 0;
15668353368SRudolf Cornelissen 	/* Nvidia hardcursor needs 2kB space */
15768353368SRudolf Cornelissen 	if (si->settings.hardcursor) pointer_reservation = 2048;
15868353368SRudolf Cornelissen 
15968353368SRudolf Cornelissen 	si->fbc.frame_buffer = (void *)((char *)si->framebuffer+pointer_reservation);
16068353368SRudolf Cornelissen 	si->fbc.frame_buffer_dma = (void *)((char *)si->framebuffer_pci+pointer_reservation);
16168353368SRudolf Cornelissen 
16268353368SRudolf Cornelissen 	/* count of issued parameters or commands */
16368353368SRudolf Cornelissen 	si->engine.last_idle = si->engine.count = 0;
16468353368SRudolf Cornelissen 	INIT_BEN(si->engine.lock);
16568353368SRudolf Cornelissen 
16668353368SRudolf Cornelissen 	INIT_BEN(si->overlay.lock);
16768353368SRudolf Cornelissen 	for (cnt = 0; cnt < MAXBUFFERS; cnt++)
16868353368SRudolf Cornelissen 	{
16968353368SRudolf Cornelissen 		/* make sure overlay buffers are 'marked' as being free */
17068353368SRudolf Cornelissen 		si->overlay.myBuffer[cnt].buffer = NULL;
17168353368SRudolf Cornelissen 		si->overlay.myBuffer[cnt].buffer_dma = NULL;
17268353368SRudolf Cornelissen 	}
17368353368SRudolf Cornelissen 	/* make sure overlay unit is 'marked' as being free */
17468353368SRudolf Cornelissen 	si->overlay.myToken = NULL;
17568353368SRudolf Cornelissen 
176886dbf81SRudolf Cornelissen 	/* note that overlay is not in use (for eng_bes_move_overlay()) */
17768353368SRudolf Cornelissen 	si->overlay.active = false;
17868353368SRudolf Cornelissen 
17968353368SRudolf Cornelissen 	/* bail out if something failed */
18068353368SRudolf Cornelissen 	if (result != B_OK) goto error1;
18168353368SRudolf Cornelissen 
18268353368SRudolf Cornelissen 	/* initialise various cursor stuff */
18368353368SRudolf Cornelissen 	head1_cursor_init();
18468353368SRudolf Cornelissen 	if (si->ps.secondary_head) head2_cursor_init();
18568353368SRudolf Cornelissen 
18668353368SRudolf Cornelissen 	/* ensure cursor state */
18768353368SRudolf Cornelissen 	head1_cursor_hide();
18868353368SRudolf Cornelissen 	if (si->ps.secondary_head) head2_cursor_hide();
18968353368SRudolf Cornelissen 
19068353368SRudolf Cornelissen 	/* a winner! */
19168353368SRudolf Cornelissen 	result = B_OK;
19268353368SRudolf Cornelissen 	goto error0;
19368353368SRudolf Cornelissen 
19468353368SRudolf Cornelissen error1:
19568353368SRudolf Cornelissen 	/*
19668353368SRudolf Cornelissen 	Initialization failed after init_common() succeeded, so we need to clean
19768353368SRudolf Cornelissen 	up before quiting.
19868353368SRudolf Cornelissen 	*/
19968353368SRudolf Cornelissen 	uninit_common();
20068353368SRudolf Cornelissen 
20168353368SRudolf Cornelissen error0:
20268353368SRudolf Cornelissen 	return result;
20368353368SRudolf Cornelissen }
20468353368SRudolf Cornelissen 
20568353368SRudolf Cornelissen /*
20668353368SRudolf Cornelissen Return the number of bytes required to hold the information required
20768353368SRudolf Cornelissen to clone the device.
20868353368SRudolf Cornelissen */
ACCELERANT_CLONE_INFO_SIZE(void)20968353368SRudolf Cornelissen ssize_t ACCELERANT_CLONE_INFO_SIZE(void) {
21068353368SRudolf Cornelissen 	/*
21168353368SRudolf Cornelissen 	Since we're passing the name of the device as the only required
21268353368SRudolf Cornelissen 	info, return the size of the name buffer
21368353368SRudolf Cornelissen 	*/
214bf1feef8SRudolf Cornelissen 	return B_OS_NAME_LENGTH; // apsed, was MAX_ENG_DEVICE_NAME_LENGTH;
21568353368SRudolf Cornelissen }
21668353368SRudolf Cornelissen 
21768353368SRudolf Cornelissen 
21868353368SRudolf Cornelissen /*
21968353368SRudolf Cornelissen Return the info required to clone the device.  void *data points to
22068353368SRudolf Cornelissen a buffer at least ACCELERANT_CLONE_INFO_SIZE() bytes in length.
22168353368SRudolf Cornelissen */
GET_ACCELERANT_CLONE_INFO(void * data)22268353368SRudolf Cornelissen void GET_ACCELERANT_CLONE_INFO(void *data) {
2239d063f00SRudolf Cornelissen 	eng_device_name dn;
22468353368SRudolf Cornelissen 	status_t result;
22568353368SRudolf Cornelissen 
22668353368SRudolf Cornelissen 	/* call the kernel driver to get the device name */
227bf1feef8SRudolf Cornelissen 	dn.magic = SKEL_PRIVATE_DATA_MAGIC;
22868353368SRudolf Cornelissen 	/* store the returned info directly into the passed buffer */
22968353368SRudolf Cornelissen 	dn.name = (char *)data;
230bf1feef8SRudolf Cornelissen 	result = ioctl(fd, ENG_DEVICE_NAME, &dn, sizeof(dn));
23168353368SRudolf Cornelissen }
23268353368SRudolf Cornelissen 
23368353368SRudolf Cornelissen /*
23468353368SRudolf Cornelissen Initialize a copy of the accelerant as a clone.  void *data points to
23568353368SRudolf Cornelissen a copy of the data returned by GET_ACCELERANT_CLONE_INFO().
23668353368SRudolf Cornelissen */
CLONE_ACCELERANT(void * data)23768353368SRudolf Cornelissen status_t CLONE_ACCELERANT(void *data) {
23868353368SRudolf Cornelissen 	status_t result;
23968353368SRudolf Cornelissen 	char path[MAXPATHLEN];
24068353368SRudolf Cornelissen 
24168353368SRudolf Cornelissen 	/* the data is the device name */
24268353368SRudolf Cornelissen 	/* Note: the R4 graphics driver kit is in error here (missing trailing '/') */
24368353368SRudolf Cornelissen 	strcpy(path, "/dev/");
24468353368SRudolf Cornelissen 	strcat(path, (const char *)data);
24568353368SRudolf Cornelissen 	/* open the device, the permissions aren't important */
24668353368SRudolf Cornelissen 	fd = open(path, B_READ_WRITE);
24768353368SRudolf Cornelissen 	if (fd < 0)
24868353368SRudolf Cornelissen 	{
24968353368SRudolf Cornelissen 		/* we can't use LOG because we didn't get the shared_info struct.. */
25068353368SRudolf Cornelissen 		char     fname[64];
25168353368SRudolf Cornelissen 		FILE    *myhand = NULL;
25268353368SRudolf Cornelissen 
25368353368SRudolf Cornelissen 		sprintf (fname, "/boot/home/" DRIVER_PREFIX ".accelerant.0.log");
25468353368SRudolf Cornelissen 		myhand=fopen(fname,"a+");
25568353368SRudolf Cornelissen 		fprintf(myhand, "CLONE_ACCELERANT: couldn't open kerneldriver %s! Aborting.\n", path);
25668353368SRudolf Cornelissen 		fclose(myhand);
25768353368SRudolf Cornelissen 
25868353368SRudolf Cornelissen 		/* abort with resultcode from open attempt on kerneldriver */
259*9da04493SJérôme Duval 		result = errno;
26068353368SRudolf Cornelissen 		goto error0;
26168353368SRudolf Cornelissen 	}
26268353368SRudolf Cornelissen 
26368353368SRudolf Cornelissen 	/* note that we're a clone accelerant */
26468353368SRudolf Cornelissen 	accelerantIsClone = 1;
26568353368SRudolf Cornelissen 
26668353368SRudolf Cornelissen 	/* call the shared initialization code */
26768353368SRudolf Cornelissen 	result = init_common(fd);
26868353368SRudolf Cornelissen 
26968353368SRudolf Cornelissen 	/* setup CRTC and DAC functions access */
27068353368SRudolf Cornelissen 	setup_virtualized_heads(si->crtc_switch_mode);
27168353368SRudolf Cornelissen 
27268353368SRudolf Cornelissen 	/* bail out if the common initialization failed */
27368353368SRudolf Cornelissen 	if (result != B_OK) goto error1;
27468353368SRudolf Cornelissen 
27568353368SRudolf Cornelissen 	/* get shared area for display modes */
27668353368SRudolf Cornelissen 	result = my_mode_list_area = clone_area(
27768353368SRudolf Cornelissen 		DRIVER_PREFIX " cloned display_modes",
27868353368SRudolf Cornelissen 		(void **)&my_mode_list,
27968353368SRudolf Cornelissen 		B_ANY_ADDRESS,
28068353368SRudolf Cornelissen 		B_READ_AREA,
28168353368SRudolf Cornelissen 		si->mode_area
28268353368SRudolf Cornelissen 	);
28368353368SRudolf Cornelissen 	if (result < B_OK) goto error2;
28468353368SRudolf Cornelissen 
28568353368SRudolf Cornelissen 	/* all done */
28668353368SRudolf Cornelissen 	LOG(4,("CLONE_ACCELERANT: cloning was succesfull.\n"));
28768353368SRudolf Cornelissen 
28868353368SRudolf Cornelissen 	result = B_OK;
28968353368SRudolf Cornelissen 	goto error0;
29068353368SRudolf Cornelissen 
29168353368SRudolf Cornelissen error2:
29268353368SRudolf Cornelissen 	/* free up the areas we cloned */
29368353368SRudolf Cornelissen 	uninit_common();
29468353368SRudolf Cornelissen error1:
29568353368SRudolf Cornelissen 	/* close the device we opened */
29668353368SRudolf Cornelissen 	close(fd);
29768353368SRudolf Cornelissen error0:
29868353368SRudolf Cornelissen 	return result;
29968353368SRudolf Cornelissen }
30068353368SRudolf Cornelissen 
UNINIT_ACCELERANT(void)30168353368SRudolf Cornelissen void UNINIT_ACCELERANT(void)
30268353368SRudolf Cornelissen {
30368353368SRudolf Cornelissen 	if (accelerantIsClone)
30468353368SRudolf Cornelissen 	{
30568353368SRudolf Cornelissen 		LOG(4,("UNINIT_ACCELERANT: shutting down clone accelerant.\n"));
30668353368SRudolf Cornelissen 	}
30768353368SRudolf Cornelissen 	else
30868353368SRudolf Cornelissen 	{
30968353368SRudolf Cornelissen 		LOG(4,("UNINIT_ACCELERANT: shutting down primary accelerant.\n"));
31068353368SRudolf Cornelissen 
31168353368SRudolf Cornelissen 		/* delete benaphores ONLY if we are the primary accelerant */
31268353368SRudolf Cornelissen 		DELETE_BEN(si->engine.lock);
31368353368SRudolf Cornelissen 		DELETE_BEN(si->overlay.lock);
31468353368SRudolf Cornelissen 	}
31568353368SRudolf Cornelissen 
31668353368SRudolf Cornelissen 	/* free our mode list area */
31768353368SRudolf Cornelissen 	delete_area(my_mode_list_area);
31868353368SRudolf Cornelissen 	/* paranoia */
31968353368SRudolf Cornelissen 	my_mode_list = 0;
32068353368SRudolf Cornelissen 	/* release our cloned data */
32168353368SRudolf Cornelissen 	uninit_common();
32268353368SRudolf Cornelissen 	/* close the file handle ONLY if we're the clone */
32368353368SRudolf Cornelissen 	if (accelerantIsClone) close(fd);
32468353368SRudolf Cornelissen }
325