xref: /haiku/src/add-ons/accelerants/framebuffer/accelerant.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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
22 extern "C" void _sPrintf(const char *format, ...);
23 #	define TRACE(x) _sPrintf x
24 #else
25 #	define TRACE(x) ;
26 #endif
27 
28 
29 struct 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 */
38 static status_t
39 init_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(). */
74 static void
75 uninit_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 */
94 status_t
95 framebuffer_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 
113 ssize_t
114 framebuffer_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 
121 void
122 framebuffer_get_accelerant_clone_info(void *info)
123 {
124 	ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH);
125 }
126 
127 
128 status_t
129 framebuffer_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 
155 err2:
156 	uninit_common();
157 err1:
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 */
166 void
167 framebuffer_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 
179 status_t
180 framebuffer_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 
197 sem_id
198 framebuffer_accelerant_retrace_semaphore()
199 {
200 	return -1;
201 }
202 
203