xref: /haiku/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp (revision 002f37b0cca92e4cf72857c72ac95db5a8b09615)
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 %#lx\n", reg);
83 
84 	intel_info &info = *gDeviceInfo[0];
85 	uint32 oldValue = read32(info, reg);
86 
87 	kprintf("  %svalue: %#lx (%lu)\n", set ? "old " : "", oldValue, oldValue);
88 
89 	if (set) {
90 		write32(info, reg, value);
91 
92 		value = read32(info, reg);
93 		kprintf("  new value: %#lx (%lu)\n", value, value);
94 	}
95 
96 	return 0;
97 }
98 #endif	// DEBUG_COMMANDS
99 
100 
101 //	#pragma mark - Device Hooks
102 
103 
104 static status_t
105 device_open(const char* name, uint32 /*flags*/, void** _cookie)
106 {
107 	CALLED();
108 	int32 id;
109 
110 	// find accessed device
111 	{
112 		char* thisName;
113 
114 		// search for device name
115 		for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
116 			if (!strcmp(name, thisName))
117 				break;
118 		}
119 		if (!thisName)
120 			return B_BAD_VALUE;
121 	}
122 
123 	intel_info* info = gDeviceInfo[id];
124 
125 	mutex_lock(&gLock);
126 
127 	if (info->open_count == 0) {
128 		// This device hasn't been initialized yet, so we
129 		// allocate needed resources and initialize the structure
130 		info->init_status = intel_extreme_init(*info);
131 		if (info->init_status == B_OK) {
132 #ifdef DEBUG_COMMANDS
133 			add_debugger_command("ie_reg", getset_register,
134 				"dumps or sets the specified intel_extreme register");
135 #endif
136 		}
137 	}
138 
139 	if (info->init_status == B_OK) {
140 		info->open_count++;
141 		*_cookie = info;
142 	} else
143 		ERROR("%s: initialization failed!\n", __func__);
144 
145 	mutex_unlock(&gLock);
146 
147 	return info->init_status;
148 }
149 
150 
151 static status_t
152 device_close(void* /*data*/)
153 {
154 	CALLED();
155 	return B_OK;
156 }
157 
158 
159 static status_t
160 device_free(void* data)
161 {
162 	struct intel_info* info = (intel_info*)data;
163 
164 	mutex_lock(&gLock);
165 
166 	if (info->open_count-- == 1) {
167 		// release info structure
168 		info->init_status = B_NO_INIT;
169 		intel_extreme_uninit(*info);
170 
171 #ifdef DEBUG_COMMANDS
172 		remove_debugger_command("ie_reg", getset_register);
173 #endif
174 	}
175 
176 	mutex_unlock(&gLock);
177 	return B_OK;
178 }
179 
180 
181 static status_t
182 device_ioctl(void* data, uint32 op, void* buffer, size_t bufferLength)
183 {
184 	struct intel_info* info = (intel_info*)data;
185 
186 	switch (op) {
187 		case B_GET_ACCELERANT_SIGNATURE:
188 			strcpy((char*)buffer, INTEL_ACCELERANT_NAME);
189 			TRACE("accelerant: %s\n", INTEL_ACCELERANT_NAME);
190 			return B_OK;
191 
192 		// needed to share data between kernel and accelerant
193 		case INTEL_GET_PRIVATE_DATA:
194 		{
195 			intel_get_private_data* data = (intel_get_private_data* )buffer;
196 
197 			if (data->magic == INTEL_PRIVATE_DATA_MAGIC) {
198 				data->shared_info_area = info->shared_area;
199 				return B_OK;
200 			}
201 			break;
202 		}
203 
204 		// needed for cloning
205 		case INTEL_GET_DEVICE_NAME:
206 #ifdef __HAIKU__
207 			if (user_strlcpy((char* )buffer, gDeviceNames[info->id],
208 					B_PATH_NAME_LENGTH) < B_OK)
209 				return B_BAD_ADDRESS;
210 #else
211 			strncpy((char* )buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH);
212 			((char* )buffer)[B_PATH_NAME_LENGTH - 1] = '\0';
213 #endif
214 			return B_OK;
215 
216 		// graphics mem manager
217 		case INTEL_ALLOCATE_GRAPHICS_MEMORY:
218 		{
219 			intel_allocate_graphics_memory allocMemory;
220 #ifdef __HAIKU__
221 			if (user_memcpy(&allocMemory, buffer,
222 					sizeof(intel_allocate_graphics_memory)) < B_OK)
223 				return B_BAD_ADDRESS;
224 #else
225 			memcpy(&allocMemory, buffer,
226 				sizeof(intel_allocate_graphics_memory));
227 #endif
228 
229 			if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC)
230 				return B_BAD_VALUE;
231 
232 			status_t status = intel_allocate_memory(*info, allocMemory.size,
233 				allocMemory.alignment, allocMemory.flags,
234 				&allocMemory.buffer_base);
235 			if (status == B_OK) {
236 				// copy result
237 #ifdef __HAIKU__
238 				if (user_memcpy(buffer, &allocMemory,
239 						sizeof(intel_allocate_graphics_memory)) < B_OK)
240 					return B_BAD_ADDRESS;
241 #else
242 				memcpy(buffer, &allocMemory,
243 					sizeof(intel_allocate_graphics_memory));
244 #endif
245 			}
246 			return status;
247 		}
248 
249 		case INTEL_FREE_GRAPHICS_MEMORY:
250 		{
251 			intel_free_graphics_memory freeMemory;
252 #ifdef __HAIKU__
253 			if (user_memcpy(&freeMemory, buffer,
254 					sizeof(intel_free_graphics_memory)) < B_OK)
255 				return B_BAD_ADDRESS;
256 #else
257 			memcpy(&freeMemory, buffer, sizeof(intel_free_graphics_memory));
258 #endif
259 
260 			if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC)
261 				return intel_free_memory(*info, freeMemory.buffer_base);
262 			break;
263 		}
264 
265 		default:
266 			ERROR("ioctl() unknown message %ld (length = %ld)\n", op,
267 				bufferLength);
268 			break;
269 	}
270 
271 	return B_DEV_INVALID_IOCTL;
272 }
273 
274 
275 static status_t
276 device_read(void* /*data*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
277 {
278 	*_length = 0;
279 	return B_NOT_ALLOWED;
280 }
281 
282 
283 static status_t
284 device_write(void* /*data*/, off_t /*pos*/, const void* /*buffer*/,
285 	size_t* _length)
286 {
287 	*_length = 0;
288 	return B_NOT_ALLOWED;
289 }
290 
291