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 **)®s, 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