1/*
2 * Copyright 2007-2010 Haiku, Inc.  All rights reserved.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 *		Gerald Zajac
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
18							// accelerant.
19
20
21
22static status_t
23InitCommon(int fileDesc)
24{
25	// Initialization function used by primary and cloned accelerants.
26
27	gInfo.deviceFileDesc = fileDesc;
28
29	// Get area ID of shared data from driver.
30
31	area_id sharedArea;
32	status_t result = ioctl(gInfo.deviceFileDesc, TDFX_GET_SHARED_DATA,
33		&sharedArea, sizeof(sharedArea));
34	if (result != B_OK)
35		return result;
36
37	gInfo.sharedInfoArea = clone_area("3DFX shared info",
38		(void**)&(gInfo.sharedInfo), B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA,
39		 sharedArea);
40	if (gInfo.sharedInfoArea < 0)
41		return gInfo.sharedInfoArea;	// sharedInfoArea has error code
42
43	gInfo.regsArea = clone_area("3DFX regs area", (void**)&(gInfo.regs),
44		B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, gInfo.sharedInfo->regsArea);
45	if (gInfo.regsArea < 0) {
46		delete_area(gInfo.sharedInfoArea);
47		return gInfo.regsArea;		// regsArea has error code
48	}
49
50	return B_OK;
51}
52
53
54static void
55UninitCommon(void)
56{
57	// This function is used by both primary and cloned accelerants.
58
59	delete_area(gInfo.regsArea);
60	gInfo.regs = 0;
61
62	delete_area(gInfo.sharedInfoArea);
63	gInfo.sharedInfo = 0;
64}
65
66
67status_t
68InitAccelerant(int fileDesc)
69{
70	// Initialize the accelerant.	fileDesc is the file handle of the device
71	// (in /dev/graphics) that has been opened by the app_server.
72
73	TRACE("Enter InitAccelerant()\n");
74
75	gInfo.bAccelerantIsClone = false;		// indicate this is primary accelerant
76
77	status_t result = InitCommon(fileDesc);
78	if (result == B_OK) {
79		SharedInfo& si = *gInfo.sharedInfo;
80
81		TRACE("Vendor ID: 0x%X,  Device ID: 0x%X\n", si.vendorID, si.deviceID);
82
83		// Ensure that InitAccelerant is executed just once (copies should be clones)
84
85		if (si.bAccelerantInUse) {
86			result = B_NOT_ALLOWED;
87		} else {
88			result = TDFX_Init();	// perform init related to current chip
89			if (result == B_OK) {
90				result = si.engineLock.Init("3DFX engine lock");
91				if (result == B_OK)
92					result = si.overlayLock.Init("3DFX overlay lock");
93				if (result == B_OK) {
94					TDFX_ShowCursor(false);
95
96					// ensure that this function won't be executed again
97					// (copies should be clones)
98					si.bAccelerantInUse = true;
99				}
100			}
101		}
102
103		if (result != B_OK)
104			UninitCommon();
105	}
106
107	TRACE("Leave InitAccelerant(), result: 0x%X\n", result);
108	return result;
109}
110
111
112ssize_t
113AccelerantCloneInfoSize(void)
114{
115	// Return the number of bytes required to hold the information required
116	// to clone the device.  The information is merely the name of the device;
117	// thus, return the size of the name buffer.
118
119	return B_OS_NAME_LENGTH;
120}
121
122
123void
124GetAccelerantCloneInfo(void* data)
125{
126	// Return the info required to clone the device.  Argument data points to
127	// a buffer which is the size returned by AccelerantCloneInfoSize().
128
129	ioctl(gInfo.deviceFileDesc, TDFX_DEVICE_NAME, data, B_OS_NAME_LENGTH);
130}
131
132
133status_t
134CloneAccelerant(void* data)
135{
136	// Initialize a copy of the accelerant as a clone.  Argument data points to
137	// a copy of the data which was returned by GetAccelerantCloneInfo().
138
139	TRACE("Enter CloneAccelerant()\n");
140
141	char path[MAXPATHLEN] = "/dev/";
142	strcat(path, (const char*)data);
143
144	gInfo.deviceFileDesc = open(path, B_READ_WRITE);	// open the device
145	if (gInfo.deviceFileDesc < 0)
146		return errno;
147
148	gInfo.bAccelerantIsClone = true;
149
150	status_t result = InitCommon(gInfo.deviceFileDesc);
151	if (result != B_OK) {
152		close(gInfo.deviceFileDesc);
153		return result;
154	}
155
156	result = gInfo.modeListArea = clone_area("3DFX cloned display_modes",
157		(void**) &gInfo.modeList, B_ANY_ADDRESS, B_READ_AREA,
158		gInfo.sharedInfo->modeArea);
159	if (result < 0) {
160		UninitCommon();
161		close(gInfo.deviceFileDesc);
162		return result;
163	}
164
165	TRACE("Leave CloneAccelerant()\n");
166	return B_OK;
167}
168
169
170void
171UninitAccelerant(void)
172{
173	delete_area(gInfo.modeListArea);
174	gInfo.modeList = NULL;
175
176	UninitCommon();
177
178	if (gInfo.bAccelerantIsClone)
179		close(gInfo.deviceFileDesc);
180}
181
182
183status_t
184GetAccelerantDeviceInfo(accelerant_device_info* adi)
185{
186	// Get info about the device.
187
188	SharedInfo& si = *gInfo.sharedInfo;
189
190	adi->version = 1;
191	strcpy(adi->name, "3dfx chipset");
192	strcpy(adi->chipset, si.chipName);
193	strcpy(adi->serial_no, "unknown");
194	adi->memory = si.maxFrameBufferSize;
195	adi->dac_speed = 270;
196
197	return B_OK;
198}
199