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