1/*
2 * Copyright 2005-2008, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "accelerant_protos.h"
8#include "accelerant.h"
9
10#include <stdlib.h>
11#include <string.h>
12#include <unistd.h>
13#include <errno.h>
14#include <syslog.h>
15
16#include <AutoDeleterOS.h>
17
18
19//#define TRACE_ACCELERANT
20#ifdef TRACE_ACCELERANT
21extern "C" void _sPrintf(const char *format, ...);
22#	define TRACE(x) _sPrintf x
23#else
24#	define TRACE(x) ;
25#endif
26
27
28struct accelerant_info *gInfo;
29
30
31//	#pragma mark -
32
33
34/*!	This is the common accelerant_info initializer. It is called by
35	both, the first accelerant and all clones.
36*/
37static status_t
38init_common(int device, bool isClone)
39{
40	// initialize global accelerant info structure
41
42	gInfo = (accelerant_info *)malloc(sizeof(accelerant_info));
43	MemoryDeleter infoDeleter(gInfo);
44	if (gInfo == NULL)
45		return B_NO_MEMORY;
46
47	memset(gInfo, 0, sizeof(accelerant_info));
48
49	gInfo->is_clone = isClone;
50	gInfo->device = device;
51	gInfo->current_mode = UINT16_MAX;
52
53	// get basic info from driver
54
55	area_id sharedArea;
56	if (ioctl(device, VESA_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0)
57		return B_ERROR;
58
59	AreaDeleter sharedDeleter(clone_area("vesa shared info",
60		(void **)&gInfo->shared_info, B_ANY_ADDRESS,
61		B_READ_AREA | B_WRITE_AREA, sharedArea));
62	status_t status = gInfo->shared_info_area = sharedDeleter.Get();
63	if (status < B_OK)
64		return status;
65
66	gInfo->vesa_modes = (vesa_mode *)((uint8 *)gInfo->shared_info
67		+ gInfo->shared_info->vesa_mode_offset);
68
69	infoDeleter.Detach();
70	sharedDeleter.Detach();
71	return B_OK;
72}
73
74
75/*!	Cleans up everything done by a successful init_common(). */
76static void
77uninit_common(void)
78{
79	delete_area(gInfo->shared_info_area);
80	gInfo->shared_info_area = -1;
81	gInfo->shared_info = NULL;
82
83	// close the file handle ONLY if we're the clone
84	// (this is what Be tells us ;)
85	if (gInfo->is_clone)
86		close(gInfo->device);
87
88	free(gInfo);
89}
90
91
92//	#pragma mark - public accelerant functions
93
94
95/*!	Init primary accelerant */
96status_t
97vesa_init_accelerant(int device)
98{
99	TRACE(("vesa_init_accelerant()\n"));
100
101	status_t status = init_common(device, false);
102	if (status != B_OK)
103		return status;
104
105	status = create_mode_list();
106	if (status != B_OK) {
107		uninit_common();
108		return status;
109	}
110
111	// Initialize current mode completely from the mode list
112	vesa_propose_display_mode(&gInfo->shared_info->current_mode, NULL, NULL);
113	return B_OK;
114}
115
116
117ssize_t
118vesa_accelerant_clone_info_size(void)
119{
120	// clone info is device name, so return its maximum size
121	return B_PATH_NAME_LENGTH;
122}
123
124
125void
126vesa_get_accelerant_clone_info(void *info)
127{
128	ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH);
129}
130
131
132status_t
133vesa_clone_accelerant(void *info)
134{
135	TRACE(("vesa_clone_accelerant()\n"));
136
137	// create full device name
138	char path[MAXPATHLEN];
139	strcpy(path, "/dev/");
140	strcat(path, (const char *)info);
141
142	int fd = open(path, B_READ_WRITE);
143	if (fd < 0)
144		return errno;
145
146	status_t status = init_common(fd, true);
147	if (status != B_OK)
148		goto err1;
149
150	// get read-only clone of supported display modes
151	status = gInfo->mode_list_area = clone_area(
152		"vesa cloned modes", (void **)&gInfo->mode_list,
153		B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area);
154	if (status < B_OK)
155		goto err2;
156
157	return B_OK;
158
159err2:
160	uninit_common();
161err1:
162	close(fd);
163	return status;
164}
165
166
167/*!	This function is called for both, the primary accelerant and all of
168	its clones.
169*/
170void
171vesa_uninit_accelerant(void)
172{
173	TRACE(("vesa_uninit_accelerant()\n"));
174
175	// delete accelerant instance data
176	delete_area(gInfo->mode_list_area);
177	gInfo->mode_list = NULL;
178
179	uninit_common();
180}
181
182
183status_t
184vesa_get_accelerant_device_info(accelerant_device_info *info)
185{
186	info->version = B_ACCELERANT_VERSION;
187
188	strcpy(info->name, "VESA driver");
189	if (gInfo->shared_info->name[0] != '\0') {
190		strlcpy(info->chipset, gInfo->shared_info->name, 32);
191	} else {
192		switch (gInfo->shared_info->bios_type) {
193			case kIntelBiosType:
194				strcpy(info->chipset, "Intel");
195				break;
196			case kNVidiaBiosType:
197				strcpy(info->chipset, "nVidia");
198				break;
199			case kAtomBiosType1:
200			case kAtomBiosType2:
201				strcpy(info->chipset, "AMD/ATI Atombios");
202				break;
203			default:
204				strcpy(info->chipset, "Generic VESA");
205				break;
206		}
207	}
208	strcpy(info->serial_no, "None");
209
210	info->memory = gInfo->shared_info->vram_size;
211#if 0
212	info->dac_speed = ???
213#endif
214
215	return B_OK;
216}
217
218
219sem_id
220vesa_accelerant_retrace_semaphore()
221{
222	return -1;
223}
224
225