xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon_hd/device.cpp (revision d3ff06683af390a4c2e83b69177e0a2eb76679bc)
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 "radeon_hd.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("radeon_hd: " x)
32 #else
33 #	define TRACE(x...) ;
34 #endif
35 
36 #define ERROR(x...) dprintf("radeon_hd: " x)
37 
38 
39 /* device hooks prototypes */
40 
41 static status_t device_open(const char *name, uint32 flags, void **_cookie);
42 static status_t device_close(void *data);
43 static status_t device_free(void *data);
44 static status_t device_ioctl(void *data, uint32 opcode,
45 	void *buffer, size_t length);
46 static status_t device_read(void *data, off_t offset,
47 	void *buffer, size_t *length);
48 static status_t device_write(void *data, off_t offset,
49 	const void *buffer, size_t *length);
50 
51 
52 device_hooks gDeviceHooks = {
53 	device_open,
54 	device_close,
55 	device_free,
56 	device_ioctl,
57 	device_read,
58 	device_write,
59 	NULL,
60 	NULL,
61 	NULL,
62 	NULL
63 };
64 
65 
66 #ifdef DEBUG_COMMANDS
67 static int
68 getset_register(int argc, char **argv)
69 {
70 	if (argc < 2 || argc > 3) {
71 		kprintf("usage: %s <register> [set-to-value]\n", argv[0]);
72 		return 0;
73 	}
74 
75 	uint32 reg = parse_expression(argv[1]);
76 	uint32 value = 0;
77 	bool set = argc == 3;
78 	if (set)
79 		value = parse_expression(argv[2]);
80 
81 	kprintf("radeon_hd register %#lx\n", reg);
82 
83 	radeon_info &info = *gDeviceInfo[0];
84 	uint32 oldValue = read32(info.registers + reg);
85 
86 	kprintf("  %svalue: %#lx (%lu)\n", set ? "old " : "", oldValue, oldValue);
87 
88 	if (set) {
89 		write32(info.registers + reg, value);
90 
91 		value = read32(info.registers + reg);
92 		kprintf("  new value: %#lx (%lu)\n", value, value);
93 	}
94 
95 	return 0;
96 }
97 #endif	// DEBUG_COMMANDS
98 
99 
100 //	#pragma mark - Device Hooks
101 
102 
103 static status_t
104 device_open(const char *name, uint32 /*flags*/, void **_cookie)
105 {
106 	TRACE("%s: open(name = %s)\n", __func__, name);
107 	int32 id;
108 
109 	// find accessed device
110 	{
111 		char *thisName;
112 
113 		// search for device name
114 		for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
115 			if (!strcmp(name, thisName))
116 				break;
117 		}
118 		if (!thisName)
119 			return B_BAD_VALUE;
120 	}
121 
122 	radeon_info *info = gDeviceInfo[id];
123 
124 	mutex_lock(&gLock);
125 
126 	if (info->open_count == 0) {
127 		// this device has been opened for the first time, so
128 		// we allocate needed resources and initialize the structure
129 		info->init_status = radeon_hd_init(*info);
130 		if (info->init_status == B_OK) {
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("%s: close\n", __func__);
148 	return B_OK;
149 }
150 
151 
152 static status_t
153 device_free(void *data)
154 {
155 	struct radeon_info *info = (radeon_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 		radeon_hd_uninit(*info);
163 	}
164 	mutex_unlock(&gLock);
165 	return B_OK;
166 }
167 
168 
169 static status_t
170 device_ioctl(void *data, uint32 op, void *buffer, size_t bufferLength)
171 {
172 	struct radeon_info *info = (radeon_info *)data;
173 
174 	switch (op) {
175 		case B_GET_ACCELERANT_SIGNATURE:
176 			strcpy((char *)buffer, RADEON_ACCELERANT_NAME);
177 			TRACE("%s: accelerant: %s\n", __func__, RADEON_ACCELERANT_NAME);
178 			return B_OK;
179 
180 		// needed to share data between kernel and accelerant
181 		case RADEON_GET_PRIVATE_DATA:
182 		{
183 			radeon_get_private_data *data = (radeon_get_private_data *)buffer;
184 
185 			if (data->magic == RADEON_PRIVATE_DATA_MAGIC) {
186 				data->shared_info_area = info->shared_area;
187 				return B_OK;
188 			}
189 			break;
190 		}
191 
192 		// needed for cloning
193 		case RADEON_GET_DEVICE_NAME:
194 #ifdef __HAIKU__
195 			if (user_strlcpy((char *)buffer, gDeviceNames[info->id],
196 					B_PATH_NAME_LENGTH) < B_OK)
197 				return B_BAD_ADDRESS;
198 #else
199 			strncpy((char *)buffer, gDeviceNames[info->id], B_PATH_NAME_LENGTH);
200 			((char *)buffer)[B_PATH_NAME_LENGTH - 1] = '\0';
201 #endif
202 			return B_OK;
203 
204 		default:
205 			TRACE("%s: ioctl() unknown message %ld (length = %ld)\n",
206 				__func__, op, bufferLength);
207 			break;
208 	}
209 
210 	return B_DEV_INVALID_IOCTL;
211 }
212 
213 
214 static status_t
215 device_read(void */*data*/, off_t /*pos*/,
216 	void */*buffer*/, size_t *_length)
217 {
218 	*_length = 0;
219 	return B_NOT_ALLOWED;
220 }
221 
222 
223 static status_t
224 device_write(void */*data*/, off_t /*pos*/,
225 	const void */*buffer*/, size_t *_length)
226 {
227 	*_length = 0;
228 	return B_NOT_ALLOWED;
229 }
230 
231