xref: /haiku/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp (revision 5e7964b0a929555415798dea3373db9ac4611caa)
1 /*
2  * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include "driver.h"
11 #include "device.h"
12 #include "intel_extreme.h"
13 #include "utility.h"
14 
15 #include <OS.h>
16 #include <KernelExport.h>
17 #include <Drivers.h>
18 #include <PCI.h>
19 #include <SupportDefs.h>
20 #include <graphic_driver.h>
21 #include <image.h>
22 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 
27 #define DEBUG_COMMANDS
28 
29 #define TRACE_DEVICE
30 #ifdef TRACE_DEVICE
31 #	define TRACE(x...) dprintf("intel_extreme: " x)
32 #else
33 #	define TRACE(x) ;
34 #endif
35 
36 #define ERROR(x...) dprintf("intel_extreme: " x)
37 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
38 
39 
40 /* device hooks prototypes */
41 
42 static status_t device_open(const char* name, uint32 flags, void** _cookie);
43 static status_t device_close(void* data);
44 static status_t device_free(void* data);
45 static status_t device_ioctl(void* data, uint32 opcode, void* buffer,
46 	size_t length);
47 static status_t device_read(void* data, off_t offset, void* buffer,
48 	size_t* length);
49 static status_t device_write(void* data, off_t offset, const void* buffer,
50 	size_t* length);
51 
52 
53 device_hooks gDeviceHooks = {
54 	device_open,
55 	device_close,
56 	device_free,
57 	device_ioctl,
58 	device_read,
59 	device_write,
60 	NULL,
61 	NULL,
62 	NULL,
63 	NULL
64 };
65 
66 
67 #ifdef DEBUG_COMMANDS
68 static int
69 getset_register(int argc, char** argv)
70 {
71 	if (argc < 2 || argc > 3) {
72 		kprintf("usage: %s <register> [set-to-value]\n", argv[0]);
73 		return 0;
74 	}
75 
76 	uint32 reg = parse_expression(argv[1]);
77 	uint32 value = 0;
78 	bool set = argc == 3;
79 	if (set)
80 		value = parse_expression(argv[2]);
81 
82 	kprintf("intel_extreme register %#" B_PRIx32 "\n", reg);
83 
84 	intel_info &info = *gDeviceInfo[0];
85 	uint32 oldValue = read32(info, reg);
86 
87 	kprintf("  %svalue: %#" B_PRIx32 " (%" B_PRIu32 ")\n", set ? "old " : "",
88 		oldValue, oldValue);
89 
90 	if (set) {
91 		write32(info, reg, value);
92 
93 		value = read32(info, reg);
94 		kprintf("  new value: %#" B_PRIx32 " (%" B_PRIu32 ")\n", value, value);
95 	}
96 
97 	return 0;
98 }
99 #endif	// DEBUG_COMMANDS
100 
101 
102 //	#pragma mark - Device Hooks
103 
104 
105 static status_t
106 device_open(const char* name, uint32 /*flags*/, void** _cookie)
107 {
108 	CALLED();
109 	int32 id;
110 
111 	// find accessed device
112 	{
113 		char* thisName;
114 
115 		// search for device name
116 		for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
117 			if (!strcmp(name, thisName))
118 				break;
119 		}
120 		if (!thisName)
121 			return B_BAD_VALUE;
122 	}
123 
124 	intel_info* info = gDeviceInfo[id];
125 
126 	mutex_lock(&gLock);
127 
128 	if (info->open_count == 0) {
129 		// This device hasn't been initialized yet, so we
130 		// allocate needed resources and initialize the structure
131 		info->init_status = intel_extreme_init(*info);
132 		if (info->init_status == B_OK) {
133 #ifdef DEBUG_COMMANDS
134 			add_debugger_command("ie_reg", getset_register,
135 				"dumps or sets the specified intel_extreme register");
136 #endif
137 		}
138 	}
139 
140 	if (info->init_status == B_OK) {
141 		info->open_count++;
142 		*_cookie = info;
143 	} else
144 		ERROR("%s: initialization failed!\n", __func__);
145 
146 	mutex_unlock(&gLock);
147 
148 	return info->init_status;
149 }
150 
151 
152 static status_t
153 device_close(void* /*data*/)
154 {
155 	CALLED();
156 	return B_OK;
157 }
158 
159 
160 static status_t
161 device_free(void* data)
162 {
163 	struct intel_info* info = (intel_info*)data;
164 
165 	mutex_lock(&gLock);
166 
167 	if (info->open_count-- == 1) {
168 		// release info structure
169 		info->init_status = B_NO_INIT;
170 		intel_extreme_uninit(*info);
171 
172 #ifdef DEBUG_COMMANDS
173 		remove_debugger_command("ie_reg", getset_register);
174 #endif
175 	}
176 
177 	mutex_unlock(&gLock);
178 	return B_OK;
179 }
180 
181 
182 static status_t
183 device_ioctl(void* data, uint32 op, void* buffer, size_t bufferLength)
184 {
185 	struct intel_info* info = (intel_info*)data;
186 
187 	switch (op) {
188 		case B_GET_ACCELERANT_SIGNATURE:
189 			strcpy((char*)buffer, INTEL_ACCELERANT_NAME);
190 			TRACE("accelerant: %s\n", INTEL_ACCELERANT_NAME);
191 			return B_OK;
192 
193 		// needed to share data between kernel and accelerant
194 		case INTEL_GET_PRIVATE_DATA:
195 		{
196 			intel_get_private_data* data = (intel_get_private_data* )buffer;
197 
198 			if (data->magic == INTEL_PRIVATE_DATA_MAGIC) {
199 				data->shared_info_area = info->shared_area;
200 				return B_OK;
201 			}
202 			break;
203 		}
204 
205 		// needed for cloning
206 		case INTEL_GET_DEVICE_NAME:
207 #ifdef __HAIKU__
208 			if (user_strlcpy((char* )buffer, gDeviceNames[info->id],
209 					B_PATH_NAME_LENGTH) < B_OK)
210 				return B_BAD_ADDRESS;
211 #else
212 			strncpy((char* )buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH);
213 			((char* )buffer)[B_PATH_NAME_LENGTH - 1] = '\0';
214 #endif
215 			return B_OK;
216 
217 		// graphics mem manager
218 		case INTEL_ALLOCATE_GRAPHICS_MEMORY:
219 		{
220 			intel_allocate_graphics_memory allocMemory;
221 #ifdef __HAIKU__
222 			if (user_memcpy(&allocMemory, buffer,
223 					sizeof(intel_allocate_graphics_memory)) < B_OK)
224 				return B_BAD_ADDRESS;
225 #else
226 			memcpy(&allocMemory, buffer,
227 				sizeof(intel_allocate_graphics_memory));
228 #endif
229 
230 			if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC)
231 				return B_BAD_VALUE;
232 
233 			status_t status = intel_allocate_memory(*info, allocMemory.size,
234 				allocMemory.alignment, allocMemory.flags,
235 				&allocMemory.buffer_base);
236 			if (status == B_OK) {
237 				// copy result
238 #ifdef __HAIKU__
239 				if (user_memcpy(buffer, &allocMemory,
240 						sizeof(intel_allocate_graphics_memory)) < B_OK)
241 					return B_BAD_ADDRESS;
242 #else
243 				memcpy(buffer, &allocMemory,
244 					sizeof(intel_allocate_graphics_memory));
245 #endif
246 			}
247 			return status;
248 		}
249 
250 		case INTEL_FREE_GRAPHICS_MEMORY:
251 		{
252 			intel_free_graphics_memory freeMemory;
253 #ifdef __HAIKU__
254 			if (user_memcpy(&freeMemory, buffer,
255 					sizeof(intel_free_graphics_memory)) < B_OK)
256 				return B_BAD_ADDRESS;
257 #else
258 			memcpy(&freeMemory, buffer, sizeof(intel_free_graphics_memory));
259 #endif
260 
261 			if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC)
262 				return intel_free_memory(*info, freeMemory.buffer_base);
263 			break;
264 		}
265 
266 		default:
267 			ERROR("ioctl() unknown message %" B_PRIu32 " (length = %"
268 				B_PRIuSIZE ")\n", op, bufferLength);
269 			break;
270 	}
271 
272 	return B_DEV_INVALID_IOCTL;
273 }
274 
275 
276 static status_t
277 device_read(void* /*data*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
278 {
279 	*_length = 0;
280 	return B_NOT_ALLOWED;
281 }
282 
283 
284 static status_t
285 device_write(void* /*data*/, off_t /*pos*/, const void* /*buffer*/,
286 	size_t* _length)
287 {
288 	*_length = 0;
289 	return B_NOT_ALLOWED;
290 }
291 
292