xref: /haiku/src/add-ons/accelerants/3dfx/accelerant.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
1 /*
2  * Copyright 2007-2010 Haiku, Inc.  All rights reserved.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		Gerald Zajac
7  */
8 
9 #include "accelerant.h"
10 
11 #include <errno.h>
12 #include <string.h>
13 #include <unistd.h>
14 
15 
16 
17 AccelerantInfo gInfo;		// global data used by various source files of
18 							// accelerant.
19 
20 
21 
22 static status_t
23 InitCommon(int fileDesc)
24 {
25 	// Initialization function used by primary and cloned accelerants.
26 
27 	gInfo.deviceFileDesc = fileDesc;
28 
29 	// Get area ID of shared data from driver.
30 
31 	area_id sharedArea;
32 	status_t result = ioctl(gInfo.deviceFileDesc, TDFX_GET_SHARED_DATA,
33 		&sharedArea, sizeof(sharedArea));
34 	if (result != B_OK)
35 		return result;
36 
37 	gInfo.sharedInfoArea = clone_area("3DFX shared info",
38 		(void**)&(gInfo.sharedInfo), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA,
39 		 sharedArea);
40 	if (gInfo.sharedInfoArea < 0)
41 		return gInfo.sharedInfoArea;	// sharedInfoArea has error code
42 
43 	gInfo.regsArea = clone_area("3DFX regs area", (void**)&(gInfo.regs),
44 		B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gInfo.sharedInfo->regsArea);
45 	if (gInfo.regsArea < 0) {
46 		delete_area(gInfo.sharedInfoArea);
47 		return gInfo.regsArea;		// regsArea has error code
48 	}
49 
50 	return B_OK;
51 }
52 
53 
54 static void
55 UninitCommon(void)
56 {
57 	// This function is used by both primary and cloned accelerants.
58 
59 	delete_area(gInfo.regsArea);
60 	gInfo.regs = 0;
61 
62 	delete_area(gInfo.sharedInfoArea);
63 	gInfo.sharedInfo = 0;
64 }
65 
66 
67 status_t
68 InitAccelerant(int fileDesc)
69 {
70 	// Initialize the accelerant.	fileDesc is the file handle of the device
71 	// (in /dev/graphics) that has been opened by the app_server.
72 
73 	TRACE("Enter InitAccelerant()\n");
74 
75 	gInfo.bAccelerantIsClone = false;		// indicate this is primary accelerant
76 
77 	status_t result = InitCommon(fileDesc);
78 	if (result == B_OK) {
79 		SharedInfo& si = *gInfo.sharedInfo;
80 
81 		TRACE("Vendor ID: 0x%X,  Device ID: 0x%X\n", si.vendorID, si.deviceID);
82 
83 		// Ensure that InitAccelerant is executed just once (copies should be clones)
84 
85 		if (si.bAccelerantInUse) {
86 			result = B_NOT_ALLOWED;
87 		} else {
88 			result = TDFX_Init();	// perform init related to current chip
89 			if (result == B_OK) {
90 				result = si.engineLock.Init("3DFX engine lock");
91 				if (result == B_OK)
92 					result = si.overlayLock.Init("3DFX overlay lock");
93 				if (result == B_OK) {
94 					TDFX_ShowCursor(false);
95 
96 					// ensure that this function won't be executed again
97 					// (copies should be clones)
98 					si.bAccelerantInUse = true;
99 				}
100 			}
101 		}
102 
103 		if (result != B_OK)
104 			UninitCommon();
105 	}
106 
107 	TRACE("Leave InitAccelerant(), result: 0x%X\n", result);
108 	return result;
109 }
110 
111 
112 ssize_t
113 AccelerantCloneInfoSize(void)
114 {
115 	// Return the number of bytes required to hold the information required
116 	// to clone the device.  The information is merely the name of the device;
117 	// thus, return the size of the name buffer.
118 
119 	return B_OS_NAME_LENGTH;
120 }
121 
122 
123 void
124 GetAccelerantCloneInfo(void* data)
125 {
126 	// Return the info required to clone the device.  Argument data points to
127 	// a buffer which is the size returned by AccelerantCloneInfoSize().
128 
129 	ioctl(gInfo.deviceFileDesc, TDFX_DEVICE_NAME, data, B_OS_NAME_LENGTH);
130 }
131 
132 
133 status_t
134 CloneAccelerant(void* data)
135 {
136 	// Initialize a copy of the accelerant as a clone.  Argument data points to
137 	// a copy of the data which was returned by GetAccelerantCloneInfo().
138 
139 	TRACE("Enter CloneAccelerant()\n");
140 
141 	char path[MAXPATHLEN] = "/dev/";
142 	strcat(path, (const char*)data);
143 
144 	gInfo.deviceFileDesc = open(path, B_READ_WRITE);	// open the device
145 	if (gInfo.deviceFileDesc < 0)
146 		return errno;
147 
148 	gInfo.bAccelerantIsClone = true;
149 
150 	status_t result = InitCommon(gInfo.deviceFileDesc);
151 	if (result != B_OK) {
152 		close(gInfo.deviceFileDesc);
153 		return result;
154 	}
155 
156 	result = gInfo.modeListArea = clone_area("3DFX cloned display_modes",
157 		(void**) &gInfo.modeList, B_ANY_ADDRESS, B_READ_AREA,
158 		gInfo.sharedInfo->modeArea);
159 	if (result < 0) {
160 		UninitCommon();
161 		close(gInfo.deviceFileDesc);
162 		return result;
163 	}
164 
165 	TRACE("Leave CloneAccelerant()\n");
166 	return B_OK;
167 }
168 
169 
170 void
171 UninitAccelerant(void)
172 {
173 	delete_area(gInfo.modeListArea);
174 	gInfo.modeList = NULL;
175 
176 	UninitCommon();
177 
178 	if (gInfo.bAccelerantIsClone)
179 		close(gInfo.deviceFileDesc);
180 }
181 
182 
183 status_t
184 GetAccelerantDeviceInfo(accelerant_device_info* adi)
185 {
186 	// Get info about the device.
187 
188 	SharedInfo& si = *gInfo.sharedInfo;
189 
190 	adi->version = 1;
191 	strcpy(adi->name, "3dfx chipset");
192 	strcpy(adi->chipset, si.chipName);
193 	strcpy(adi->serial_no, "unknown");
194 	adi->memory = si.maxFrameBufferSize;
195 	adi->dac_speed = 270;
196 
197 	return B_OK;
198 }
199