xref: /haiku/src/add-ons/accelerants/vesa/accelerant.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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
21 extern "C" void _sPrintf(const char *format, ...);
22 #	define TRACE(x) _sPrintf x
23 #else
24 #	define TRACE(x) ;
25 #endif
26 
27 
28 struct 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 */
37 static status_t
38 init_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(). */
76 static void
77 uninit_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 */
96 status_t
97 vesa_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 
117 ssize_t
118 vesa_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 
125 void
126 vesa_get_accelerant_clone_info(void *info)
127 {
128 	ioctl(gInfo->device, VESA_GET_DEVICE_NAME, info, B_PATH_NAME_LENGTH);
129 }
130 
131 
132 status_t
133 vesa_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 
159 err2:
160 	uninit_common();
161 err1:
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 */
170 void
171 vesa_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 
183 status_t
184 vesa_get_accelerant_device_info(accelerant_device_info *info)
185 {
186 	info->version = B_ACCELERANT_VERSION;
187 	strcpy(info->name, "VESA Driver");
188 	strcpy(info->chipset, "VESA");
189 		// ToDo: provide some more insight here...
190 	strcpy(info->serial_no, "None");
191 
192 #if 0
193 	info->memory = ???
194 	info->dac_speed = ???
195 #endif
196 
197 	return B_OK;
198 }
199 
200 
201 sem_id
202 vesa_accelerant_retrace_semaphore()
203 {
204 	return -1;
205 }
206 
207