xref: /haiku/src/add-ons/accelerants/intel_810/accelerant.cpp (revision 07b33113a3b3a0e3ace703c48d1ac39faad2c6c0)
1 /*
2  * Copyright 2007-2012 Haiku, Inc.  All rights reserved.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		Gerald Zajac
7  */
8 
9 
10 #include "accelerant.h"
11 
12 #include <errno.h>
13 #include <string.h>
14 #include <unistd.h>
15 
16 
17 AccelerantInfo gInfo;	// global data used by source files of accelerant
18 
19 static uint32 videoValue;
20 
21 
22 static int32
23 SuppressArtifacts(void* dataPtr)
24 {
25 	// The Intel 810 & 815 video chips create annoying artifacts which are
26 	// most noticeable when the cursor is moved by itself or the user goes up
27 	// and down through a menu.  However, if a large number of video memory
28 	// locations are accessed frequently like when the GLTeapot demo is
29 	// running, the artifacts are greatly suppressed.  Thus, that is the reason
30 	// why this function accesses a large number of video memory locations
31 	// frequently.  Note that the accessed memory locations are at the end of
32 	// the video memory.  This is because some artifacts still occur at the
33 	// top of the screen if the accessed memory is at the beginning of the
34 	// video memory.
35 
36 	// Note that this function will reduce the general performance of a
37 	// computer somewhat, but it is much less of a hit than if double
38 	// buffering was used for the video.  Base on the frame rate of the
39 	// the GLTeapot demo, it is less than a 10% reduction.
40 
41 	SharedInfo& si = *((SharedInfo*)dataPtr);
42 
43 	while (true) {
44 		uint32* src = ((uint32*)(si.videoMemAddr)) + si.videoMemSize / 4 - 1;
45 		uint32 count = 65000;
46 
47 		while (count-- > 0)
48 			videoValue = *src--;
49 
50 		snooze(30000);		// sleep for 30 msec
51 	}
52 
53 	return 0;
54 }
55 
56 
57 static status_t
58 InitCommon(int fileDesc)
59 {
60 	// Initialization function used by primary and cloned accelerants.
61 
62 	gInfo.deviceFileDesc = fileDesc;
63 
64 	// Get area ID of shared data from driver.
65 
66 	area_id sharedArea;
67 	status_t result = ioctl(gInfo.deviceFileDesc, INTEL_GET_SHARED_DATA,
68 		&sharedArea, sizeof(sharedArea));
69 	if (result != B_OK)
70 		return result;
71 
72 	gInfo.sharedInfoArea = clone_area("i810 shared info",
73 		(void**)&(gInfo.sharedInfo), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA,
74 		sharedArea);
75 	if (gInfo.sharedInfoArea < 0)
76 		return gInfo.sharedInfoArea; // sharedInfoArea has error code
77 
78 	gInfo.regsArea = clone_area("i810 regs area", (void**)&(gInfo.regs),
79 		B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gInfo.sharedInfo->regsArea);
80 	if (gInfo.regsArea < 0) {
81 		delete_area(gInfo.sharedInfoArea);
82 		return gInfo.regsArea; // regsArea has error code
83 	}
84 
85 	return B_OK;
86 }
87 
88 
89 static void
90 UninitCommon(void)
91 {
92 	// This function is used by both primary and cloned accelerants.
93 
94 	delete_area(gInfo.regsArea);
95 	gInfo.regs = 0;
96 
97 	delete_area(gInfo.sharedInfoArea);
98 	gInfo.sharedInfo = 0;
99 }
100 
101 
102 status_t
103 InitAccelerant(int fileDesc)
104 {
105 	// Initialize the accelerant.	fileDesc is the file handle of the device
106 	// (in /dev/graphics) that has been opened by the app_server.
107 
108 	TRACE("Enter InitAccelerant()\n");
109 
110 	gInfo.bAccelerantIsClone = false;	// indicate this is primary accelerant
111 
112 	status_t result = InitCommon(fileDesc);
113 	if (result == B_OK) {
114 		SharedInfo& si = *gInfo.sharedInfo;
115 
116 		TRACE("Vendor ID: 0x%X,  Device ID: 0x%X\n", si.vendorID, si.deviceID);
117 
118 		// Ensure that InitAccelerant is executed just once (copies should be
119 		// clones)
120 
121 		if (si.bAccelerantInUse) {
122 			result = B_NOT_ALLOWED;
123 		} else {
124 			result = I810_Init();	// perform init related to current chip
125 			if (result == B_OK) {
126 				result = si.engineLock.Init("i810 engine lock");
127 				if (result == B_OK) {
128 					// Ensure that this function won't be executed again
129 					// (copies should be clones)
130 					si.bAccelerantInUse = true;
131 
132 					thread_id threadID = spawn_thread(SuppressArtifacts,
133 						"SuppressArtifacts_Thread", B_DISPLAY_PRIORITY,
134 						gInfo.sharedInfo);
135 					result = resume_thread(threadID);
136 				}
137 			}
138 		}
139 
140 		if (result != B_OK)
141 			UninitCommon();
142 	}
143 
144 	TRACE("Leave InitAccelerant(), result: 0x%X\n", result);
145 	return result;
146 }
147 
148 
149 ssize_t
150 AccelerantCloneInfoSize(void)
151 {
152 	// Return the number of bytes required to hold the information required
153 	// to clone the device.  The information is merely the name of the device;
154 	// thus, return the size of the name buffer.
155 
156 	return B_OS_NAME_LENGTH;
157 }
158 
159 
160 void
161 GetAccelerantCloneInfo(void* data)
162 {
163 	// Return the info required to clone the device.  Argument data points to
164 	// a buffer which is the size returned by AccelerantCloneInfoSize().
165 
166 	ioctl(gInfo.deviceFileDesc, INTEL_DEVICE_NAME, data, B_OS_NAME_LENGTH);
167 }
168 
169 
170 status_t
171 CloneAccelerant(void* data)
172 {
173 	// Initialize a copy of the accelerant as a clone.  Argument data points to
174 	// a copy of the data which was returned by GetAccelerantCloneInfo().
175 
176 	TRACE("Enter CloneAccelerant()\n");
177 
178 	char path[MAXPATHLEN] = "/dev/";
179 	strcat(path, (const char*)data);
180 
181 	gInfo.deviceFileDesc = open(path, B_READ_WRITE);	// open the device
182 	if (gInfo.deviceFileDesc < 0)
183 		return errno;
184 
185 	gInfo.bAccelerantIsClone = true;
186 
187 	status_t result = InitCommon(gInfo.deviceFileDesc);
188 	if (result != B_OK) {
189 		close(gInfo.deviceFileDesc);
190 		return result;
191 	}
192 
193 	result = gInfo.modeListArea = clone_area("i810 cloned display_modes",
194 		(void**) &gInfo.modeList, B_ANY_ADDRESS, B_READ_AREA,
195 		gInfo.sharedInfo->modeArea);
196 	if (result < 0) {
197 		UninitCommon();
198 		close(gInfo.deviceFileDesc);
199 		return result;
200 	}
201 
202 	TRACE("Leave CloneAccelerant()\n");
203 	return B_OK;
204 }
205 
206 
207 void
208 UninitAccelerant(void)
209 {
210 	delete_area(gInfo.modeListArea);
211 	gInfo.modeList = NULL;
212 
213 	UninitCommon();
214 
215 	if (gInfo.bAccelerantIsClone)
216 		close(gInfo.deviceFileDesc);
217 }
218 
219 
220 status_t
221 GetAccelerantDeviceInfo(accelerant_device_info* adi)
222 {
223 	// Get info about the device.
224 
225 	SharedInfo& si = *gInfo.sharedInfo;
226 
227 	adi->version = 1;
228 	strcpy(adi->name, "Intel 810/815 chipset");
229 	strcpy(adi->chipset, si.chipName);
230 	strcpy(adi->serial_no, "unknown");
231 	adi->memory = si.maxFrameBufferSize;
232 	adi->dac_speed = 270;
233 
234 	return B_OK;
235 }
236