xref: /haiku/src/add-ons/accelerants/vesa/accelerant.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
1 /*
2  * Copyright 2005, 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 <syslog.h>
14 
15 
16 //#define TRACE_ACCELERANT
17 #ifdef TRACE_ACCELERANT
18 extern "C" void _sPrintf(const char *format, ...);
19 #	define TRACE(x) _sPrintf x
20 #else
21 #	define TRACE(x) ;
22 #endif
23 
24 
25 struct accelerant_info *gInfo;
26 
27 
28 class AreaCloner {
29 	public:
30 		AreaCloner();
31 		~AreaCloner();
32 
33 		area_id Clone(const char *name, void **_address, uint32 spec,
34 					uint32 protection, area_id sourceArea);
35 		status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; }
36 		void Keep();
37 
38 	private:
39 		area_id	fArea;
40 };
41 
42 
43 AreaCloner::AreaCloner()
44 	:
45 	fArea(-1)
46 {
47 }
48 
49 
50 AreaCloner::~AreaCloner()
51 {
52 	if (fArea >= B_OK)
53 		delete_area(fArea);
54 }
55 
56 
57 area_id
58 AreaCloner::Clone(const char *name, void **_address, uint32 spec,
59 	uint32 protection, area_id sourceArea)
60 {
61 	fArea = clone_area(name, _address, spec, protection, sourceArea);
62 	return fArea;
63 }
64 
65 
66 void
67 AreaCloner::Keep()
68 {
69 	fArea = -1;
70 }
71 
72 
73 //	#pragma mark -
74 
75 
76 /** This is the common accelerant_info initializer. It is called by
77  *	both, the first accelerant and all clones.
78  */
79 
80 static status_t
81 init_common(int device, bool isClone)
82 {
83 	// initialize global accelerant info structure
84 
85 	gInfo = (accelerant_info *)malloc(sizeof(accelerant_info));
86 	if (gInfo == NULL)
87 		return B_NO_MEMORY;
88 
89 	memset(gInfo, 0, sizeof(accelerant_info));
90 
91 	gInfo->is_clone = isClone;
92 	gInfo->device = device;
93 
94 	// get basic info from driver
95 
96 	area_id sharedArea;
97 	if (ioctl(device, VESA_GET_PRIVATE_DATA, &sharedArea, sizeof(area_id)) != 0) {
98 		free(gInfo);
99 		return B_ERROR;
100 	}
101 
102 	AreaCloner sharedCloner;
103 	gInfo->shared_info_area = sharedCloner.Clone("vesa shared info",
104 								(void **)&gInfo->shared_info, B_ANY_ADDRESS,
105 								B_READ_AREA | B_WRITE_AREA,
106 								sharedArea);
107 	status_t status = sharedCloner.InitCheck();
108 	if (status < B_OK) {
109 		free(gInfo);
110 		return status;
111 	}
112 
113 	sharedCloner.Keep();
114 	return B_OK;
115 }
116 
117 
118 /** Cleans up everything done by a successful init_common().
119  */
120 
121 static void
122 uninit_common(void)
123 {
124 	delete_area(gInfo->shared_info_area);
125 	gInfo->shared_info_area = -1;
126 	gInfo->shared_info = NULL;
127 
128 	// close the file handle ONLY if we're the clone
129 	// (this is what Be tells us ;)
130 	if (gInfo->is_clone)
131 		close(gInfo->device);
132 
133 	free(gInfo);
134 }
135 
136 
137 //	#pragma mark -
138 //	public accelerant functions
139 
140 
141 /** init primary accelerant */
142 
143 status_t
144 vesa_init_accelerant(int device)
145 {
146 	TRACE(("vesa_init_accelerant()\n"));
147 
148 	status_t status = init_common(device, false);
149 	if (status != B_OK)
150 		return status;
151 
152 	status = create_mode_list();
153 	if (status != B_OK) {
154 		uninit_common();
155 		return status;
156 	}
157 
158 	return B_OK;
159 }
160 
161 
162 ssize_t
163 vesa_accelerant_clone_info_size(void)
164 {
165 	// clone info is device name, so return its maximum size
166 	return B_PATH_NAME_LENGTH;
167 }
168 
169 
170 void
171 vesa_get_accelerant_clone_info(void *info)
172 {
173 	ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH);
174 }
175 
176 
177 status_t
178 vesa_clone_accelerant(void *info)
179 {
180 	TRACE(("vesa_clone_accelerant()\n"));
181 
182 	// create full device name
183 	char path[MAXPATHLEN];
184 	strcpy(path, "/dev/");
185 	strcat(path, (const char *)info);
186 
187 	int fd = open(path, B_READ_WRITE);
188 	if (fd < 0)
189 		return fd;
190 
191 	status_t status = init_common(fd, true);
192 	if (status != B_OK)
193 		goto err1;
194 
195 	// get read-only clone of supported display modes
196 	status = gInfo->mode_list_area = clone_area(
197 		"vesa cloned modes", (void **)&gInfo->mode_list,
198 		B_ANY_ADDRESS, B_READ_AREA, gInfo->shared_info->mode_list_area);
199 	if (status < B_OK)
200 		goto err2;
201 
202 	return B_OK;
203 
204 err2:
205 	uninit_common();
206 err1:
207 	close(fd);
208 	return status;
209 }
210 
211 
212 /** This function is called for both, the primary accelerant and all of
213  *	its clones.
214  */
215 
216 void
217 vesa_uninit_accelerant(void)
218 {
219 	TRACE(("vesa_uninit_accelerant()\n"));
220 
221 	// delete accelerant instance data
222 	delete_area(gInfo->mode_list_area);
223 	gInfo->mode_list = NULL;
224 
225 	uninit_common();
226 }
227 
228 
229 status_t
230 vesa_get_accelerant_device_info(accelerant_device_info *info)
231 {
232 	info->version = B_ACCELERANT_VERSION;
233 	strcpy(info->name, "VESA Driver");
234 	strcpy(info->chipset, "VESA");
235 		// ToDo: provide some more insight here...
236 	strcpy(info->serial_no, "None");
237 
238 #if 0
239 	info->memory = ???
240 	info->dac_speed = ???
241 #endif
242 
243 	return B_OK;
244 }
245 
246 
247 sem_id
248 vesa_accelerant_retrace_semaphore()
249 {
250 	return -1;
251 }
252 
253