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