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
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 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
64static void
65UninitCommon(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
77status_t
78InitAccelerant(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
121ssize_t
122AccelerantCloneInfoSize(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
132void
133GetAccelerantCloneInfo(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
142status_t
143CloneAccelerant(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
179void
180UninitAccelerant(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
192sem_id
193AccelerantRetraceSemaphore(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
202status_t
203GetAccelerantDeviceInfo(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