vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / accelerants / ati / accelerant.cpp
blob0497134612c1466019ba29e2c2a335682661cfdc
1 /*
2 Copyright 2007-2009 Haiku, Inc. All rights reserved.
3 Distributed under the terms of the MIT license.
5 Authors:
6 Gerald Zajac 2007-2009
7 */
9 #include "accelerant.h"
11 #include <errno.h>
12 #include <string.h>
13 #include <unistd.h>
17 AccelerantInfo gInfo; // global data used by various source files of accelerant.
21 static status_t
22 InitCommon(int fileDesc)
24 // Initialization function used by primary and cloned accelerants.
26 gInfo.deviceFileDesc = fileDesc;
28 // Get area ID of shared data from driver.
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;
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
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
48 // Set pointers to various device specific functions.
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
57 return B_OK;
61 static void
62 UninitCommon(void)
64 // This function is used by both primary and cloned accelerants.
66 delete_area(gInfo.regsArea);
67 gInfo.regs = 0;
69 delete_area(gInfo.sharedInfoArea);
70 gInfo.sharedInfo = 0;
74 status_t
75 InitAccelerant(int fileDesc)
77 // Initialize the accelerant. fileDesc is the file handle of the device
78 // (in /dev/graphics) that has been opened by the app_server.
80 TRACE("Enter InitAccelerant()\n");
82 gInfo.bAccelerantIsClone = false; // indicate this is primary accelerant
84 status_t result = InitCommon(fileDesc);
85 if (result == B_OK) {
86 SharedInfo& si = *gInfo.sharedInfo;
88 TRACE("Vendor ID: 0x%X, Device ID: 0x%X\n", si.vendorID, si.deviceID);
90 // Ensure that InitAccelerant is executed just once (copies should be clones)
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);
102 // ensure that this function won't be executed again
103 // (copies should be clones)
104 si.bAccelerantInUse = true;
109 if (result != B_OK)
110 UninitCommon();
113 TRACE("Leave InitAccelerant(), result: 0x%X\n", result);
114 return result;
118 ssize_t
119 AccelerantCloneInfoSize(void)
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.
125 return B_OS_NAME_LENGTH;
129 void
130 GetAccelerantCloneInfo(void* data)
132 // Return the info required to clone the device. Argument data points to
133 // a buffer which is the size returned by AccelerantCloneInfoSize().
135 ioctl(gInfo.deviceFileDesc, ATI_DEVICE_NAME, data, B_OS_NAME_LENGTH);
139 status_t
140 CloneAccelerant(void* data)
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().
145 TRACE("Enter CloneAccelerant()\n");
147 char path[MAXPATHLEN] = "/dev/";
148 strcat(path, (const char*)data);
150 gInfo.deviceFileDesc = open(path, B_READ_WRITE); // open the device
151 if (gInfo.deviceFileDesc < 0)
152 return errno;
154 gInfo.bAccelerantIsClone = true;
156 status_t result = InitCommon(gInfo.deviceFileDesc);
157 if (result != B_OK) {
158 close(gInfo.deviceFileDesc);
159 return result;
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;
171 TRACE("Leave CloneAccelerant()\n");
172 return B_OK;
176 void
177 UninitAccelerant(void)
179 delete_area(gInfo.modeListArea);
180 gInfo.modeList = NULL;
182 UninitCommon();
184 if (gInfo.bAccelerantIsClone)
185 close(gInfo.deviceFileDesc);
189 sem_id
190 AccelerantRetraceSemaphore(void)
192 // Return the semaphore id that will be used to signal that a vertical
193 // retrace occured.
195 return B_ERROR;
199 status_t
200 GetAccelerantDeviceInfo(accelerant_device_info* adi)
202 // Get info about the device.
204 SharedInfo& si = *gInfo.sharedInfo;
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;
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.
216 if (si.displayType == MT_VGA)
217 strcpy(adi->chipset, si.chipName);
218 else
219 strcpy(adi->chipset, "VESA");
221 return B_OK;