xref: /haiku/src/add-ons/kernel/drivers/graphics/intel_extreme/device.cpp (revision faf38d0fc0b16b984be6a34c4c60615d10948452)
1 /*
2  * Copyright 2006-2018, 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 			TRACE("accelerant: %s\n", INTEL_ACCELERANT_NAME);
190 			if (user_strlcpy((char*)buffer, INTEL_ACCELERANT_NAME,
191 					bufferLength) < B_OK)
192 				return B_BAD_ADDRESS;
193 			return B_OK;
194 
195 		// needed to share data between kernel and accelerant
196 		case INTEL_GET_PRIVATE_DATA:
197 		{
198 			intel_get_private_data data;
199 			if (user_memcpy(&data, buffer, sizeof(intel_get_private_data)) < B_OK)
200 				return B_BAD_ADDRESS;
201 
202 			if (data.magic == INTEL_PRIVATE_DATA_MAGIC) {
203 				data.shared_info_area = info->shared_area;
204 				return user_memcpy(buffer, &data,
205 					sizeof(intel_get_private_data));
206 			}
207 			break;
208 		}
209 
210 		// needed for cloning
211 		case INTEL_GET_DEVICE_NAME:
212 			if (user_strlcpy((char* )buffer, gDeviceNames[info->id],
213 					bufferLength) < B_OK)
214 				return B_BAD_ADDRESS;
215 			return B_OK;
216 
217 		// graphics mem manager
218 		case INTEL_ALLOCATE_GRAPHICS_MEMORY:
219 		{
220 			intel_allocate_graphics_memory allocMemory;
221 			if (user_memcpy(&allocMemory, buffer,
222 					sizeof(intel_allocate_graphics_memory)) < B_OK)
223 				return B_BAD_ADDRESS;
224 
225 			if (allocMemory.magic != INTEL_PRIVATE_DATA_MAGIC)
226 				return B_BAD_VALUE;
227 
228 			status_t status = intel_allocate_memory(*info, allocMemory.size,
229 				allocMemory.alignment, allocMemory.flags,
230 				&allocMemory.buffer_base);
231 			if (status == B_OK) {
232 				// copy result
233 				if (user_memcpy(buffer, &allocMemory,
234 						sizeof(intel_allocate_graphics_memory)) < B_OK)
235 					return B_BAD_ADDRESS;
236 			}
237 			return status;
238 		}
239 
240 		case INTEL_FREE_GRAPHICS_MEMORY:
241 		{
242 			intel_free_graphics_memory freeMemory;
243 			if (user_memcpy(&freeMemory, buffer,
244 					sizeof(intel_free_graphics_memory)) < B_OK)
245 				return B_BAD_ADDRESS;
246 
247 			if (freeMemory.magic == INTEL_PRIVATE_DATA_MAGIC)
248 				return intel_free_memory(*info, freeMemory.buffer_base);
249 			break;
250 		}
251 
252 		default:
253 			ERROR("ioctl() unknown message %" B_PRIu32 " (length = %"
254 				B_PRIuSIZE ")\n", op, bufferLength);
255 			break;
256 	}
257 
258 	return B_DEV_INVALID_IOCTL;
259 }
260 
261 
262 static status_t
263 device_read(void* /*data*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
264 {
265 	*_length = 0;
266 	return B_NOT_ALLOWED;
267 }
268 
269 
270 static status_t
271 device_write(void* /*data*/, off_t /*pos*/, const void* /*buffer*/,
272 	size_t* _length)
273 {
274 	*_length = 0;
275 	return B_NOT_ALLOWED;
276 }
277 
278