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