VirtualBox

source: vbox/trunk/src/VBox/Additions/haiku/VBoxVideo/driver/driver.cpp@ 46001

Last change on this file since 46001 was 46001, checked in by vboxsync, 12 years ago

header fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.1 KB
Line 
1/* $Id: driver.cpp 46001 2013-05-13 07:11:05Z vboxsync $ */
2/** @file
3 * VBoxVideo driver, Haiku Guest Additions, implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*
19 * This code is based on:
20 *
21 * VirtualBox Guest Additions for Haiku.
22 * Copyright (c) 2011 Mike Smith <[email protected]>
23 * François Revol <[email protected]>
24 *
25 * Permission is hereby granted, free of charge, to any person
26 * obtaining a copy of this software and associated documentation
27 * files (the "Software"), to deal in the Software without
28 * restriction, including without limitation the rights to use,
29 * copy, modify, merge, publish, distribute, sublicense, and/or sell
30 * copies of the Software, and to permit persons to whom the
31 * Software is furnished to do so, subject to the following
32 * conditions:
33 *
34 * The above copyright notice and this permission notice shall be
35 * included in all copies or substantial portions of the Software.
36 *
37 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
38 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
39 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
40 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
41 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
42 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
43 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
44 * OTHER DEALINGS IN THE SOFTWARE.
45 */
46
47/*******************************************************************************
48* Header Files *
49*******************************************************************************/
50#include <KernelExport.h>
51#include <PCI.h>
52#include <malloc.h>
53#include <stdio.h>
54#include <string.h>
55#include <graphic_driver.h>
56#include <VBoxGuest-haiku.h>
57#include <VBox/VBoxVideoGuest.h>
58#include "../common/VBoxVideo_common.h"
59
60#define VENDOR_ID 0x80ee
61#define DEVICE_ID 0xbeef
62#define DRIVER_NAME "VBoxVideoDriver"
63#define DEVICE_FORMAT "vd_%04X_%04X_%02X%02X%02X"
64
65/** @todo r=ramshankar: pretty sure IPRT has something for page rounding,
66 * replace with IPRT version later. */
67#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
68
69#define ENABLE_DEBUG_TRACE
70
71#undef TRACE
72#ifdef ENABLE_DEBUG_TRACE
73#define TRACE(x...) dprintf("VBoxVideo: " x)
74#else
75#define TRACE(x...) ;
76#endif
77
78int32 api_version = B_CUR_DRIVER_API_VERSION; // revision of driver API we support
79
80extern "C" status_t vm_set_area_memory_type(area_id id, phys_addr_t physicalBase, uint32 type);
81
82struct Benaphore
83{
84 sem_id sem;
85 int32 count;
86
87 status_t Init(const char *name)
88 {
89 count = 0;
90 sem = create_sem(0, name);
91 return sem < 0 ? sem : B_OK;
92 }
93
94 status_t Acquire()
95 {
96 if (atomic_add(&count, 1) > 0)
97 return acquire_sem(sem);
98 return B_OK;
99 }
100
101 status_t Release()
102 {
103 if (atomic_add(&count, -1) > 1)
104 return release_sem(sem);
105 return B_OK;
106 }
107
108 void Delete()
109 {
110 delete_sem(sem);
111 }
112};
113
114struct DeviceInfo
115{
116 uint32 openCount; /* Count of how many times device has been opened */
117 uint32 flags; /* Device flags */
118 area_id sharedArea; /* Area shared between driver and all accelerants */
119 SharedInfo *sharedInfo; /* Pointer to shared info area memory */
120 pci_info pciInfo; /* Copy of pci info for this device */
121 char name[B_OS_NAME_LENGTH]; /* Name of device */
122};
123
124/*******************************************************************************
125* Internal Functions *
126*******************************************************************************/
127status_t device_open(const char *name, uint32 flags, void **cookie);
128status_t device_close(void *dev);
129status_t device_free(void *dev);
130status_t device_read(void *dev, off_t pos, void *buf, size_t *len);
131status_t device_write(void *dev, off_t pos, const void *buf, size_t *len);
132status_t device_ioctl(void *dev, uint32 msg, void *buf, size_t len);
133static uint32 get_color_space_for_depth(uint32 depth);
134
135/*******************************************************************************
136* Globals *
137*******************************************************************************/
138/* At most one virtual video card ever appears, no reason for this to be an array */
139static DeviceInfo gDeviceInfo;
140static char *gDeviceNames[2] = { gDeviceInfo.name, NULL };
141static bool gCanHasDevice = false; /* is the device present? */
142static Benaphore gLock;
143static pci_module_info *gPCI;
144
145static device_hooks gDeviceHooks =
146{
147 device_open,
148 device_close,
149 device_free,
150 device_ioctl,
151 device_read,
152 device_write,
153 NULL, /* select */
154 NULL, /* deselect */
155 NULL, /* read_pages */
156 NULL /* write_pages */
157};
158
159
160status_t init_hardware()
161{
162 LogFlowFunc(("init_hardware\n"));
163
164 status_t err = get_module(VBOXGUEST_MODULE_NAME, (module_info **)&g_VBoxGuest);
165 if (err == B_OK)
166 {
167 err = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
168 if (err == B_OK)
169 return B_OK;
170
171 LogRel((DRIVER_NAME ":_init_hardware() get_module(%s) failed. err=%08lx\n", B_PCI_MODULE_NAME));
172 }
173 else
174 LogRel((DRIVER_NAME ":_init_hardware() get_module(%s) failed. err=%08lx\n", VBOXGUEST_MODULE_NAME, err));
175 return B_ERROR;
176}
177
178
179status_t init_driver()
180{
181 LogFlowFunc(("init_driver\n"));
182
183 gLock.Init("VBoxVideo driver lock");
184
185 uint32 pciIndex = 0;
186
187 while (gPCI->get_nth_pci_info(pciIndex, &gDeviceInfo.pciInfo) == B_OK)
188 {
189 if (gDeviceInfo.pciInfo.vendor_id == VENDOR_ID && gDeviceInfo.pciInfo.device_id == DEVICE_ID)
190 {
191 sprintf(gDeviceInfo.name, "graphics/" DEVICE_FORMAT,
192 gDeviceInfo.pciInfo.vendor_id, gDeviceInfo.pciInfo.device_id,
193 gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function);
194 TRACE("found device %s\n", gDeviceInfo.name);
195
196 gCanHasDevice = true;
197 gDeviceInfo.openCount = 0;
198
199 size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7;
200 gDeviceInfo.sharedArea = create_area("vboxvideo shared info",
201 (void **)&gDeviceInfo.sharedInfo, B_ANY_KERNEL_ADDRESS,
202 ROUND_TO_PAGE_SIZE(sharedSize), B_FULL_LOCK,
203 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
204
205 uint16_t width, height, vwidth, bpp, flags;
206 VBoxVideoGetModeRegisters(&width, &height, &vwidth, &bpp, &flags);
207
208 gDeviceInfo.sharedInfo->currentMode.space = get_color_space_for_depth(bpp);
209 gDeviceInfo.sharedInfo->currentMode.virtual_width = width;
210 gDeviceInfo.sharedInfo->currentMode.virtual_height = height;
211 gDeviceInfo.sharedInfo->currentMode.h_display_start = 0;
212 gDeviceInfo.sharedInfo->currentMode.v_display_start = 0;
213 gDeviceInfo.sharedInfo->currentMode.flags = 0;
214 gDeviceInfo.sharedInfo->currentMode.timing.h_display = width;
215 gDeviceInfo.sharedInfo->currentMode.timing.v_display = height;
216 /* Not used, but this makes a reasonable-sounding refresh rate show in screen prefs: */
217 gDeviceInfo.sharedInfo->currentMode.timing.h_total = 1000;
218 gDeviceInfo.sharedInfo->currentMode.timing.v_total = 1;
219 gDeviceInfo.sharedInfo->currentMode.timing.pixel_clock = 850;
220
221 /* Map the PCI memory space */
222 uint32 command_reg = gPCI->read_pci_config(gDeviceInfo.pciInfo.bus,
223 gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function, PCI_command, 2);
224 command_reg |= PCI_command_io | PCI_command_memory | PCI_command_master;
225 gPCI->write_pci_config(gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device,
226 gDeviceInfo.pciInfo.function, PCI_command, 2, command_reg);
227
228 gDeviceInfo.sharedInfo->framebufferArea = map_physical_memory("vboxvideo framebuffer",
229 (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0],
230 gDeviceInfo.pciInfo.u.h0.base_register_sizes[0], B_ANY_KERNEL_BLOCK_ADDRESS,
231 B_READ_AREA | B_WRITE_AREA, &(gDeviceInfo.sharedInfo->framebuffer));
232 vm_set_area_memory_type(gDeviceInfo.sharedInfo->framebufferArea,
233 (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0], B_MTR_WC);
234 break;
235 }
236
237 pciIndex++;
238 }
239
240 return B_OK;
241}
242
243
244const char** publish_devices()
245{
246 LogFlowFunc(("publish_devices\n"));
247 if (gCanHasDevice)
248 return (const char **)gDeviceNames;
249 return NULL;
250}
251
252
253device_hooks* find_device(const char *name)
254{
255 LogFlowFunc(("find_device\n"));
256 if (gCanHasDevice && strcmp(name, gDeviceInfo.name) == 0)
257 return &gDeviceHooks;
258
259 return NULL;
260}
261
262
263void uninit_driver()
264{
265 LogFlowFunc(("uninit_driver\n"));
266 gLock.Delete();
267 put_module(VBOXGUEST_MODULE_NAME);
268}
269
270status_t device_open(const char *name, uint32 flags, void **cookie)
271{
272 LogFlowFunc(("device_open\n"));
273
274 if (!gCanHasDevice || strcmp(name, gDeviceInfo.name) != 0)
275 return B_BAD_VALUE;
276
277 /* @todo init device! */
278
279 *cookie = (void *)&gDeviceInfo;
280 return B_OK;
281}
282
283
284status_t device_close(void *dev)
285{
286 LogFlowFunc(("device_close\n"));
287 return B_ERROR;
288}
289
290
291status_t device_free(void *dev)
292{
293 LogFlowFunc(("device_free\n"));
294
295 DeviceInfo& di = *(DeviceInfo *)dev;
296 gLock.Acquire();
297
298 if (di.openCount <= 1)
299 {
300 // TODO deinit device!
301 delete_area(di.sharedArea);
302 di.sharedArea = -1;
303 di.sharedInfo = NULL;
304 }
305
306 if (di.openCount > 0)
307 di.openCount--;
308
309 gLock.Release();
310
311 return B_OK;
312}
313
314
315status_t device_read(void *dev, off_t pos, void *buf, size_t *len)
316{
317 LogFlowFunc(("device_read\n"));
318 return B_NOT_ALLOWED;
319}
320
321
322status_t device_write(void *dev, off_t pos, const void *buf, size_t *len)
323{
324 LogFlowFunc(("device_write\n"));
325 return B_NOT_ALLOWED;
326}
327
328
329status_t device_ioctl(void *cookie, uint32 msg, void *buf, size_t len)
330{
331 LogFlowFunc(("device_ioctl\n"));
332
333 DeviceInfo *dev = (DeviceInfo *)cookie;
334
335 switch (msg)
336 {
337 case B_GET_ACCELERANT_SIGNATURE:
338 {
339 strcpy((char *)buf, "vboxvideo.accelerant");
340 return B_OK;
341 }
342
343 case VBOXVIDEO_GET_PRIVATE_DATA:
344 {
345 /** @todo r=ramshankar: implement RTR0MemUserCopyFrom for haiku. */
346 return user_memcpy(buf, &dev->sharedArea, sizeof(area_id));
347 }
348
349 case VBOXVIDEO_GET_DEVICE_NAME:
350 {
351 /** @todo r=ramshankar: implement RTR0MemUserCopyFrom for haiku. */
352 if (user_strlcpy((char *)buf, gDeviceInfo.name, len) < B_OK)
353 return B_BAD_ADDRESS;
354 return B_OK;
355 }
356
357 case VBOXVIDEO_SET_DISPLAY_MODE:
358 {
359 display_mode *mode = (display_mode *)buf;
360 VBoxVideoSetModeRegisters(mode->timing.h_display, mode->timing.v_display,
361 mode->timing.h_display, get_depth_for_color_space(mode->space), 0, 0, 0);
362 gDeviceInfo.sharedInfo->currentMode = *mode;
363 return B_OK;
364 }
365 default:
366 return B_BAD_VALUE;
367 }
368}
369
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette