1 /*
2 * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "device.h"
8
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include <Drivers.h>
13 #include <graphic_driver.h>
14 #include <image.h>
15 #include <KernelExport.h>
16 #include <OS.h>
17 #include <PCI.h>
18 #include <SupportDefs.h>
19
20 #include <vesa.h>
21
22 #include "driver.h"
23 #include "utility.h"
24 #include "vesa_info.h"
25 #include "vesa_private.h"
26 #include "vga.h"
27
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 static status_t
device_open(const char * name,uint32 flags,void ** _cookie)38 device_open(const char* name, uint32 flags, void** _cookie)
39 {
40 int id;
41
42 // find accessed device
43 char* thisName;
44
45 // search for device name
46 for (id = 0; (thisName = gDeviceNames[id]) != NULL; id++) {
47 if (!strcmp(name, thisName))
48 break;
49 }
50 if (thisName == NULL)
51 return B_BAD_VALUE;
52
53 vesa_info* info = gDeviceInfo[id];
54
55 mutex_lock(&gLock);
56
57 status_t status = B_OK;
58
59 if (info->open_count == 0) {
60 // this device has been opened for the first time, so
61 // we allocate needed resources and initialize the structure
62 if (status == B_OK)
63 status = vesa_init(*info);
64 if (status == B_OK)
65 info->id = id;
66 }
67
68 if (status == B_OK) {
69 info->open_count++;
70 *_cookie = info;
71 }
72
73 mutex_unlock(&gLock);
74 return status;
75 }
76
77
78 static status_t
device_close(void * cookie)79 device_close(void* cookie)
80 {
81 return B_OK;
82 }
83
84
85 static status_t
device_free(void * cookie)86 device_free(void* cookie)
87 {
88 struct vesa_info* info = (vesa_info*)cookie;
89
90 mutex_lock(&gLock);
91
92 if (info->open_count-- == 1) {
93 // release info structure
94 vesa_uninit(*info);
95 }
96
97 mutex_unlock(&gLock);
98 return B_OK;
99 }
100
101
102 static status_t
device_ioctl(void * cookie,uint32 msg,void * buffer,size_t bufferLength)103 device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength)
104 {
105 struct vesa_info* info = (vesa_info*)cookie;
106
107 switch (msg) {
108 case B_GET_ACCELERANT_SIGNATURE:
109 dprintf(DEVICE_NAME ": acc: %s\n", VESA_ACCELERANT_NAME);
110 if (user_strlcpy((char*)buffer, VESA_ACCELERANT_NAME,
111 B_FILE_NAME_LENGTH) < B_OK)
112 return B_BAD_ADDRESS;
113
114 return B_OK;
115
116 // needed to share data between kernel and accelerant
117 case VESA_GET_PRIVATE_DATA:
118 return user_memcpy(buffer, &info->shared_area, sizeof(area_id));
119
120 // needed for cloning
121 case VESA_GET_DEVICE_NAME:
122 if (user_strlcpy((char*)buffer, gDeviceNames[info->id],
123 B_PATH_NAME_LENGTH) < B_OK)
124 return B_BAD_ADDRESS;
125
126 return B_OK;
127
128 case VESA_SET_DISPLAY_MODE:
129 {
130 if (bufferLength != sizeof(uint32))
131 return B_BAD_VALUE;
132
133 uint32 mode;
134 if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK)
135 return B_BAD_ADDRESS;
136
137 return vesa_set_display_mode(*info, mode);
138 }
139
140 case VESA_SET_CUSTOM_DISPLAY_MODE:
141 {
142 if (bufferLength != sizeof(display_mode))
143 return B_BAD_VALUE;
144
145 if (info->shared_info->bios_type == kUnknownBiosType)
146 return B_NOT_ALLOWED;
147
148 display_mode mode;
149 if (user_memcpy(&mode, buffer, sizeof(display_mode)) != B_OK)
150 return B_BAD_ADDRESS;
151
152 return vesa_set_custom_display_mode(*info, mode);
153 }
154
155 case VESA_GET_DPMS_MODE:
156 {
157 if (bufferLength != sizeof(uint32))
158 return B_BAD_VALUE;
159
160 uint32 mode;
161 status_t status = vesa_get_dpms_mode(*info, mode);
162 if (status != B_OK)
163 return status;
164
165 return user_memcpy(buffer, &mode, sizeof(mode));
166 }
167
168 case VESA_SET_DPMS_MODE:
169 {
170 if (bufferLength != sizeof(uint32))
171 return B_BAD_VALUE;
172
173 uint32 mode;
174 if (user_memcpy(&mode, buffer, sizeof(uint32)) != B_OK)
175 return B_BAD_ADDRESS;
176
177 return vesa_set_dpms_mode(*info, mode);
178 }
179
180 case VESA_SET_INDEXED_COLORS:
181 {
182 color_space space
183 = (color_space)info->shared_info->current_mode.space;
184 if (space != B_GRAY8 && space != B_CMAP8)
185 return B_ERROR;
186
187 vesa_set_indexed_colors_args args;
188 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
189 return B_BAD_ADDRESS;
190
191 status_t status = B_NOT_SUPPORTED;
192 if (space != B_GRAY8) {
193 status = vesa_set_indexed_colors(*info, args.first, args.colors,
194 args.count);
195 }
196
197 // Try VGA as a fallback
198 if (status != B_OK && (info->vbe_capabilities
199 & CAPABILITY_NOT_VGA_COMPATIBLE) == 0) {
200 return vga_set_indexed_colors(args.first, args.colors,
201 args.count);
202 }
203
204 return status;
205 }
206
207 case VGA_PLANAR_BLIT:
208 {
209 if (info->shared_info->current_mode.space != B_GRAY8
210 || (info->vbe_capabilities
211 & CAPABILITY_NOT_VGA_COMPATIBLE) != 0)
212 return B_NOT_SUPPORTED;
213
214 vga_planar_blit_args args;
215 if (user_memcpy(&args, buffer, sizeof(args)) != B_OK)
216 return B_BAD_ADDRESS;
217
218 return vga_planar_blit(info->shared_info, args.source,
219 args.source_bytes_per_row, args.left, args.top,
220 args.right, args.bottom);
221 }
222
223 default:
224 TRACE((DEVICE_NAME ": ioctl() unknown message %ld (length = %lu)\n",
225 msg, bufferLength));
226 break;
227 }
228
229 return B_DEV_INVALID_IOCTL;
230 }
231
232
233 static status_t
device_read(void *,off_t,void *,size_t * _length)234 device_read(void* /*cookie*/, off_t /*pos*/, void* /*buffer*/, size_t* _length)
235 {
236 *_length = 0;
237 return B_NOT_ALLOWED;
238 }
239
240
241 static status_t
device_write(void *,off_t,const void *,size_t * _length)242 device_write(void* /*cookie*/, off_t /*pos*/, const void* /*buffer*/,
243 size_t* _length)
244 {
245 *_length = 0;
246 return B_NOT_ALLOWED;
247 }
248
249
250 device_hooks gDeviceHooks = {
251 device_open,
252 device_close,
253 device_free,
254 device_ioctl,
255 device_read,
256 device_write,
257 NULL,
258 NULL,
259 NULL,
260 NULL
261 };
262