xref: /haiku/src/add-ons/accelerants/ati/accelerant.cpp (revision 17889a8c70dbb3d59c1412f6431968753c767bab)
1 /*
2 	Copyright 2007-2009 Haiku, Inc.  All rights reserved.
3 	Distributed under the terms of the MIT license.
4 
5 	Authors:
6 	Gerald Zajac 2007-2009
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 accelerant.
18 
19 
20 
21 static status_t
22 InitCommon(int fileDesc)
23 {
24 	// Initialization function used by primary and cloned accelerants.
25 
26 	gInfo.deviceFileDesc = fileDesc;
27 
28 	// Get area ID of shared data from driver.
29 
30 	area_id sharedArea;
31 	status_t result = ioctl(gInfo.deviceFileDesc, ATI_GET_SHARED_DATA,
32 		&sharedArea, sizeof(sharedArea));
33 	if (result != B_OK)
34 		return result;
35 
36 	gInfo.sharedInfoArea = clone_area("ATI shared info", (void**)&(gInfo.sharedInfo),
37 		B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, sharedArea);
38 	if (gInfo.sharedInfoArea < 0)
39 		return gInfo.sharedInfoArea;	// sharedInfoArea has error code
40 
41 	gInfo.regsArea = clone_area("ATI regs area", (void**)&(gInfo.regs),
42 		B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gInfo.sharedInfo->regsArea);
43 	if (gInfo.regsArea < 0) {
44 		delete_area(gInfo.sharedInfoArea);
45 		return gInfo.regsArea;		// regsArea has error code
46 	}
47 
48 	// Set pointers to various device specific functions.
49 
50 	if (RAGE128_FAMILY(gInfo.sharedInfo->chipType))
51 		Rage128_SetFunctionPointers();
52 	else if (MACH64_FAMILY(gInfo.sharedInfo->chipType))
53 		Mach64_SetFunctionPointers();
54 	else
55 		return B_ERROR;		// undefined chip type code
56 
57 	return B_OK;
58 }
59 
60 
61 static void
62 UninitCommon(void)
63 {
64 	// This function is used by both primary and cloned accelerants.
65 
66 	delete_area(gInfo.regsArea);
67 	gInfo.regs = 0;
68 
69 	delete_area(gInfo.sharedInfoArea);
70 	gInfo.sharedInfo = 0;
71 }
72 
73 
74 status_t
75 InitAccelerant(int fileDesc)
76 {
77 	// Initialize the accelerant.	fileDesc is the file handle of the device
78 	// (in /dev/graphics) that has been opened by the app_server.
79 
80 	TRACE("Enter InitAccelerant()\n");
81 
82 	gInfo.bAccelerantIsClone = false;		// indicate this is primary accelerant
83 
84 	status_t result = InitCommon(fileDesc);
85 	if (result == B_OK) {
86 		SharedInfo& si = *gInfo.sharedInfo;
87 
88 		TRACE("Vendor ID: 0x%X,  Device ID: 0x%X\n", si.vendorID, si.deviceID);
89 
90 		// Ensure that InitAccelerant is executed just once (copies should be clones)
91 
92 		if (si.bAccelerantInUse) {
93 			result = B_NOT_ALLOWED;
94 		} else {
95 			result = gInfo.ChipInit();	// perform init related to current chip
96 			if (result == B_OK) {
97 				result = si.engineLock.Init("ATI engine lock");
98 				if (result == B_OK) {
99 					if (gInfo.ShowCursor != NULL)
100 						gInfo.ShowCursor(false);
101 
102 					// ensure that this function won't be executed again
103 					// (copies should be clones)
104 					si.bAccelerantInUse = true;
105 				}
106 			}
107 		}
108 
109 		if (result != B_OK)
110 			UninitCommon();
111 	}
112 
113 	TRACE("Leave InitAccelerant(), result: 0x%X\n", result);
114 	return result;
115 }
116 
117 
118 ssize_t
119 AccelerantCloneInfoSize(void)
120 {
121 	// Return the number of bytes required to hold the information required
122 	// to clone the device.  The information is merely the name of the device;
123 	// thus, return the size of the name buffer.
124 
125 	return B_OS_NAME_LENGTH;
126 }
127 
128 
129 void
130 GetAccelerantCloneInfo(void* data)
131 {
132 	// Return the info required to clone the device.  Argument data points to
133 	// a buffer which is the size returned by AccelerantCloneInfoSize().
134 
135 	ioctl(gInfo.deviceFileDesc, ATI_DEVICE_NAME, data, B_OS_NAME_LENGTH);
136 }
137 
138 
139 status_t
140 CloneAccelerant(void* data)
141 {
142 	// Initialize a copy of the accelerant as a clone.  Argument data points to
143 	// a copy of the data which was returned by GetAccelerantCloneInfo().
144 
145 	TRACE("Enter CloneAccelerant()\n");
146 
147 	char path[MAXPATHLEN] = "/dev/";
148 	strcat(path, (const char*)data);
149 
150 	gInfo.deviceFileDesc = open(path, B_READ_WRITE);	// open the device
151 	if (gInfo.deviceFileDesc < 0)
152 		return errno;
153 
154 	gInfo.bAccelerantIsClone = true;
155 
156 	status_t result = InitCommon(gInfo.deviceFileDesc);
157 	if (result != B_OK) {
158 		close(gInfo.deviceFileDesc);
159 		return result;
160 	}
161 
162 	result = gInfo.modeListArea = clone_area("ATI cloned display_modes",
163 		(void**) &gInfo.modeList, B_ANY_ADDRESS, B_READ_AREA,
164 		gInfo.sharedInfo->modeArea);
165 	if (result < 0) {
166 		UninitCommon();
167 		close(gInfo.deviceFileDesc);
168 		return result;
169 	}
170 
171 	TRACE("Leave CloneAccelerant()\n");
172 	return B_OK;
173 }
174 
175 
176 void
177 UninitAccelerant(void)
178 {
179 	delete_area(gInfo.modeListArea);
180 	gInfo.modeList = NULL;
181 
182 	UninitCommon();
183 
184 	if (gInfo.bAccelerantIsClone)
185 		close(gInfo.deviceFileDesc);
186 }
187 
188 
189 sem_id
190 AccelerantRetraceSemaphore(void)
191 {
192 	// Return the semaphore id that will be used to signal that a vertical
193 	// retrace occured.
194 
195 	return B_ERROR;
196 }
197 
198 
199 status_t
200 GetAccelerantDeviceInfo(accelerant_device_info* adi)
201 {
202 	// Get info about the device.
203 
204 	SharedInfo& si = *gInfo.sharedInfo;
205 
206 	adi->version = 1;
207 	strcpy(adi->name, "ATI chipset");
208 	strcpy(adi->serial_no, "unknown");
209 	adi->memory = si.maxFrameBufferSize;
210 	adi->dac_speed = 270;
211 
212 	// If laptop LCD display or flat panel display (ie, DVI interface), set chip
213 	// set name to "VESA" so that Screen Preferences will not show a refresh rate
214 	// since we will be using VESA code to set the video mode.
215 
216 	if (si.displayType == MT_VGA)
217 		strcpy(adi->chipset, si.chipName);
218 	else
219 		strcpy(adi->chipset, "VESA");
220 
221 	return B_OK;
222 }
223