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