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