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
17AccelerantInfo gInfo;		// global data used by various source files of accelerant.
18
19
20
21static status_t
22InitCommon(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
61static void
62UninitCommon(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
74status_t
75InitAccelerant(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
118ssize_t
119AccelerantCloneInfoSize(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
129void
130GetAccelerantCloneInfo(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
139status_t
140CloneAccelerant(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
176void
177UninitAccelerant(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
189sem_id
190AccelerantRetraceSemaphore(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
199status_t
200GetAccelerantDeviceInfo(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