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
InitCommon(int fileDesc)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
UninitCommon(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
InitAccelerant(int fileDesc)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
AccelerantCloneInfoSize(void)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
GetAccelerantCloneInfo(void * data)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
CloneAccelerant(void * data)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
UninitAccelerant(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
AccelerantRetraceSemaphore(void)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
GetAccelerantDeviceInfo(accelerant_device_info * adi)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