xref: /haiku/src/add-ons/accelerants/vesa/accelerant.cpp (revision 6011ce6c7495e4e707bd33b12a7e22d66c710aad)
1 /*
2  * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Copyright 2016-207, 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))
58 			!= 0) {
59 		free(gInfo);
60 		return B_ERROR;
61 	}
62 
63 	AreaDeleter sharedDeleter(clone_area("vesa shared info",
64 		(void **)&gInfo->shared_info, B_ANY_ADDRESS,
65 		B_READ_AREA | B_WRITE_AREA, sharedArea));
66 	status_t status = gInfo->shared_info_area = sharedDeleter.Get();
67 	if (status < B_OK)
68 		return status;
69 
70 	if (gInfo->shared_info->vesa_mode_count == 0)
71 		gInfo->vesa_modes = NULL;
72 	else
73 		gInfo->vesa_modes = (vesa_mode *)((uint8 *)gInfo->shared_info
74 			+ gInfo->shared_info->vesa_mode_offset);
75 
76 	infoDeleter.Detach();
77 	sharedDeleter.Detach();
78 	return B_OK;
79 }
80 
81 
82 /*!	Cleans up everything done by a successful init_common(). */
83 static void
84 uninit_common(void)
85 {
86 	delete_area(gInfo->shared_info_area);
87 	gInfo->shared_info_area = -1;
88 	gInfo->shared_info = NULL;
89 
90 	// close the file handle ONLY if we're the clone
91 	// (this is what Be tells us ;)
92 	if (gInfo->is_clone)
93 		close(gInfo->device);
94 
95 	free(gInfo);
96 }
97 
98 
99 //	#pragma mark - public accelerant functions
100 
101 
102 /*!	Init primary accelerant */
103 status_t
104 vesa_init_accelerant(int device)
105 {
106 	TRACE(("vesa_init_accelerant()\n"));
107 
108 	status_t status = init_common(device, false);
109 	if (status != B_OK)
110 		return status;
111 
112 	status = create_mode_list();
113 	if (status != B_OK) {
114 		uninit_common();
115 		return status;
116 	}
117 
118 	// Initialize current mode completely from the mode list
119 	vesa_propose_display_mode(&gInfo->shared_info->current_mode, NULL, NULL);
120 	return B_OK;
121 }
122 
123 
124 ssize_t
125 vesa_accelerant_clone_info_size(void)
126 {
127 	// clone info is device name, so return its maximum size
128 	return B_PATH_NAME_LENGTH;
129 }
130 
131 
132 void
133 vesa_get_accelerant_clone_info(void *info)
134 {
135 	ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH);
136 }
137 
138 
139 status_t
140 vesa_clone_accelerant(void *info)
141 {
142 	TRACE(("vesa_clone_accelerant()\n"));
143 
144 	// create full device name
145 	char path[MAXPATHLEN];
146 	strcpy(path, "/dev/");
147 	strcat(path, (const char *)info);
148 
149 	int fd = open(path, B_READ_WRITE);
150 	if (fd < 0)
151 		return errno;
152 
153 	status_t status = init_common(fd, true);
154 	if (status != B_OK)
155 		goto err1;
156 
157 	// get read-only clone of supported display modes
158 	status = gInfo->mode_list_area = clone_area(
159 		"vesa cloned modes", (void **)&gInfo->mode_list,
160 		B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area);
161 	if (status < B_OK)
162 		goto err2;
163 
164 	return B_OK;
165 
166 err2:
167 	uninit_common();
168 err1:
169 	close(fd);
170 	return status;
171 }
172 
173 
174 /*!	This function is called for both, the primary accelerant and all of
175 	its clones.
176 */
177 void
178 vesa_uninit_accelerant(void)
179 {
180 	TRACE(("vesa_uninit_accelerant()\n"));
181 
182 	// delete accelerant instance data
183 	delete_area(gInfo->mode_list_area);
184 	gInfo->mode_list = NULL;
185 
186 	uninit_common();
187 }
188 
189 
190 status_t
191 vesa_get_accelerant_device_info(accelerant_device_info *info)
192 {
193 	info->version = B_ACCELERANT_VERSION;
194 
195 	// TODO: provide some more insight here...
196 	if (gInfo->vesa_modes != NULL) {
197 		strcpy(info->name, "VESA driver");
198 		strcpy(info->chipset, "VESA");
199 	} else {
200 		strcpy(info->name, "Framebuffer");
201 		strcpy(info->chipset, "");
202 	}
203 
204 	strcpy(info->serial_no, "None");
205 
206 #if 0
207 	info->memory = ???
208 	info->dac_speed = ???
209 #endif
210 
211 	return B_OK;
212 }
213 
214 
215 sem_id
216 vesa_accelerant_retrace_semaphore()
217 {
218 	return -1;
219 }
220 
221