VirtualBox

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

Last change on this file since 85416 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.5 KB
Line 
1/* $Id: driver.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * VBoxVideo driver, Haiku Guest Additions, implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2020 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/*********************************************************************************************************************************
49* Header Files *
50*********************************************************************************************************************************/
51#include <KernelExport.h>
52#include <PCI.h>
53#include <malloc.h>
54#include <stdio.h>
55#include <string.h>
56#include <graphic_driver.h>
57#include <VBoxGuest-haiku.h>
58#include <VBoxVideoGuest.h>
59#include "../common/VBoxVideo_common.h"
60
61#define VENDOR_ID 0x80ee
62#define DEVICE_ID 0xbeef
63#define DRIVER_NAME "VBoxVideoDriver"
64#define DEVICE_FORMAT "vd_%04X_%04X_%02X%02X%02X"
65
66/** @todo r=ramshankar: pretty sure IPRT has something for page rounding,
67 * replace with IPRT version later. */
68#define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
69
70#define ENABLE_DEBUG_TRACE
71
72#undef TRACE
73#ifdef ENABLE_DEBUG_TRACE
74#define TRACE(x...) dprintf("VBoxVideo: " x)
75#else
76#define TRACE(x...) ;
77#endif
78
79int32 api_version = B_CUR_DRIVER_API_VERSION; // revision of driver API we support
80
81extern "C" status_t vm_set_area_memory_type(area_id id, phys_addr_t physicalBase, uint32 type);
82
83struct Benaphore
84{
85 sem_id sem;
86 int32 count;
87
88 status_t Init(const char *name)
89 {
90 count = 0;
91 sem = create_sem(0, name);
92 return sem < 0 ? sem : B_OK;
93 }
94
95 status_t Acquire()
96 {
97 if (atomic_add(&count, 1) > 0)
98 return acquire_sem(sem);
99 return B_OK;
100 }
101
102 status_t Release()
103 {
104 if (atomic_add(&count, -1) > 1)
105 return release_sem(sem);
106 return B_OK;
107 }
108
109 void Delete()
110 {
111 delete_sem(sem);
112 }
113};
114
115struct DeviceInfo
116{
117 uint32 openCount; /* Count of how many times device has been opened */
118 uint32 flags; /* Device flags */
119 area_id sharedArea; /* Area shared between driver and all accelerants */
120 SharedInfo *sharedInfo; /* Pointer to shared info area memory */
121 pci_info pciInfo; /* Copy of pci info for this device */
122 char name[B_OS_NAME_LENGTH]; /* Name of device */
123};
124
125
126/*********************************************************************************************************************************
127* Internal Functions *
128*********************************************************************************************************************************/
129status_t device_open(const char *name, uint32 flags, void **cookie);
130status_t device_close(void *dev);
131status_t device_free(void *dev);
132status_t device_read(void *dev, off_t pos, void *buf, size_t *len);
133status_t device_write(void *dev, off_t pos, const void *buf, size_t *len);
134status_t device_ioctl(void *dev, uint32 msg, void *buf, size_t len);
135static uint32 get_color_space_for_depth(uint32 depth);
136
137
138/*********************************************************************************************************************************
139* Globals *
140*********************************************************************************************************************************/
141/* At most one virtual video card ever appears, no reason for this to be an array */
142static DeviceInfo gDeviceInfo;
143static char *gDeviceNames[2] = { gDeviceInfo.name, NULL };
144static bool gCanHasDevice = false; /* is the device present? */
145static Benaphore gLock;
146static pci_module_info *gPCI;
147
148static device_hooks gDeviceHooks =
149{
150 device_open,
151 device_close,
152 device_free,
153 device_ioctl,
154 device_read,
155 device_write,
156 NULL, /* select */
157 NULL, /* deselect */
158 NULL, /* read_pages */
159 NULL /* write_pages */
160};
161
162
163status_t init_hardware()
164{
165 LogFlowFunc(("init_hardware\n"));
166
167 status_t err = get_module(VBOXGUEST_MODULE_NAME, (module_info **)&g_VBoxGuest);
168 if (err == B_OK)
169 {
170 err = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI);
171 if (err == B_OK)
172 return B_OK;
173
174 LogRel((DRIVER_NAME ":_init_hardware() get_module(%s) failed. err=%08lx\n", B_PCI_MODULE_NAME));
175 }
176 else
177 LogRel((DRIVER_NAME ":_init_hardware() get_module(%s) failed. err=%08lx\n", VBOXGUEST_MODULE_NAME, err));
178 return B_ERROR;
179}
180
181
182status_t init_driver()
183{
184 LogFlowFunc(("init_driver\n"));
185
186 gLock.Init("VBoxVideo driver lock");
187
188 uint32 pciIndex = 0;
189
190 while (gPCI->get_nth_pci_info(pciIndex, &gDeviceInfo.pciInfo) == B_OK)
191 {
192 if (gDeviceInfo.pciInfo.vendor_id == VENDOR_ID && gDeviceInfo.pciInfo.device_id == DEVICE_ID)
193 {
194 sprintf(gDeviceInfo.name, "graphics/" DEVICE_FORMAT,
195 gDeviceInfo.pciInfo.vendor_id, gDeviceInfo.pciInfo.device_id,
196 gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function);
197 TRACE("found device %s\n", gDeviceInfo.name);
198
199 gCanHasDevice = true;
200 gDeviceInfo.openCount = 0;
201
202 size_t sharedSize = (sizeof(SharedInfo) + 7) & ~7;
203 gDeviceInfo.sharedArea = create_area("vboxvideo shared info",
204 (void **)&gDeviceInfo.sharedInfo, B_ANY_KERNEL_ADDRESS,
205 ROUND_TO_PAGE_SIZE(sharedSize), B_FULL_LOCK,
206 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
207
208 uint16_t width, height, vwidth, bpp, flags;
209 VBoxVideoGetModeRegisters(&width, &height, &vwidth, &bpp, &flags);
210
211 gDeviceInfo.sharedInfo->currentMode.space = get_color_space_for_depth(bpp);
212 gDeviceInfo.sharedInfo->currentMode.virtual_width = width;
213 gDeviceInfo.sharedInfo->currentMode.virtual_height = height;
214 gDeviceInfo.sharedInfo->currentMode.h_display_start = 0;
215 gDeviceInfo.sharedInfo->currentMode.v_display_start = 0;
216 gDeviceInfo.sharedInfo->currentMode.flags = 0;
217 gDeviceInfo.sharedInfo->currentMode.timing.h_display = width;
218 gDeviceInfo.sharedInfo->currentMode.timing.v_display = height;
219 /* Not used, but this makes a reasonable-sounding refresh rate show in screen prefs: */
220 gDeviceInfo.sharedInfo->currentMode.timing.h_total = 1000;
221 gDeviceInfo.sharedInfo->currentMode.timing.v_total = 1;
222 gDeviceInfo.sharedInfo->currentMode.timing.pixel_clock = 850;
223
224 /* Map the PCI memory space */
225 uint32 command_reg = gPCI->read_pci_config(gDeviceInfo.pciInfo.bus,
226 gDeviceInfo.pciInfo.device, gDeviceInfo.pciInfo.function, PCI_command, 2);
227 command_reg |= PCI_command_io | PCI_command_memory | PCI_command_master;
228 gPCI->write_pci_config(gDeviceInfo.pciInfo.bus, gDeviceInfo.pciInfo.device,
229 gDeviceInfo.pciInfo.function, PCI_command, 2, command_reg);
230
231 gDeviceInfo.sharedInfo->framebufferArea = map_physical_memory("vboxvideo framebuffer",
232 (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0],
233 gDeviceInfo.pciInfo.u.h0.base_register_sizes[0], B_ANY_KERNEL_BLOCK_ADDRESS,
234 B_READ_AREA | B_WRITE_AREA, &(gDeviceInfo.sharedInfo->framebuffer));
235 vm_set_area_memory_type(gDeviceInfo.sharedInfo->framebufferArea,
236 (phys_addr_t)gDeviceInfo.pciInfo.u.h0.base_registers[0], B_MTR_WC);
237 break;
238 }
239
240 pciIndex++;
241 }
242
243 return B_OK;
244}
245
246
247const char** publish_devices()
248{
249 LogFlowFunc(("publish_devices\n"));
250 if (gCanHasDevice)
251 return (const char **)gDeviceNames;
252 return NULL;
253}
254
255
256device_hooks* find_device(const char *name)
257{
258 LogFlowFunc(("find_device\n"));
259 if (gCanHasDevice && strcmp(name, gDeviceInfo.name) == 0)
260 return &gDeviceHooks;
261
262 return NULL;
263}
264
265
266void uninit_driver()
267{
268 LogFlowFunc(("uninit_driver\n"));
269 gLock.Delete();
270 put_module(VBOXGUEST_MODULE_NAME);
271}
272
273status_t device_open(const char *name, uint32 flags, void **cookie)
274{
275 LogFlowFunc(("device_open\n"));
276
277 if (!gCanHasDevice || strcmp(name, gDeviceInfo.name) != 0)
278 return B_BAD_VALUE;
279
280 /** @todo init device! */
281
282 *cookie = (void *)&gDeviceInfo;
283 return B_OK;
284}
285
286
287status_t device_close(void *dev)
288{
289 LogFlowFunc(("device_close\n"));
290 return B_ERROR;
291}
292
293
294status_t device_free(void *dev)
295{
296 LogFlowFunc(("device_free\n"));
297
298 DeviceInfo& di = *(DeviceInfo *)dev;
299 gLock.Acquire();
300
301 if (di.openCount <= 1)
302 {
303 /// @todo deinit device!
304 delete_area(di.sharedArea);
305 di.sharedArea = -1;
306 di.sharedInfo = NULL;
307 }
308
309 if (di.openCount > 0)
310 di.openCount--;
311
312 gLock.Release();
313
314 return B_OK;
315}
316
317
318status_t device_read(void *dev, off_t pos, void *buf, size_t *len)
319{
320 LogFlowFunc(("device_read\n"));
321 return B_NOT_ALLOWED;
322}
323
324
325status_t device_write(void *dev, off_t pos, const void *buf, size_t *len)
326{
327 LogFlowFunc(("device_write\n"));
328 return B_NOT_ALLOWED;
329}
330
331
332status_t device_ioctl(void *cookie, uint32 msg, void *buf, size_t len)
333{
334 LogFlowFunc(("device_ioctl\n"));
335
336 DeviceInfo *dev = (DeviceInfo *)cookie;
337
338 switch (msg)
339 {
340 case B_GET_ACCELERANT_SIGNATURE:
341 {
342 strcpy((char *)buf, "vboxvideo.accelerant");
343 return B_OK;
344 }
345
346 case VBOXVIDEO_GET_PRIVATE_DATA:
347 {
348 /** @todo r=ramshankar: implement RTR0MemUserCopyFrom for haiku. */
349 return user_memcpy(buf, &dev->sharedArea, sizeof(area_id));
350 }
351
352 case VBOXVIDEO_GET_DEVICE_NAME:
353 {
354 /** @todo r=ramshankar: implement RTR0MemUserCopyFrom for haiku. */
355 if (user_strlcpy((char *)buf, gDeviceInfo.name, len) < B_OK)
356 return B_BAD_ADDRESS;
357 return B_OK;
358 }
359
360 case VBOXVIDEO_SET_DISPLAY_MODE:
361 {
362 display_mode *mode = (display_mode *)buf;
363 VBoxVideoSetModeRegisters(mode->timing.h_display, mode->timing.v_display,
364 mode->timing.h_display, get_depth_for_color_space(mode->space), 0, 0, 0);
365 gDeviceInfo.sharedInfo->currentMode = *mode;
366 return B_OK;
367 }
368 default:
369 return B_BAD_VALUE;
370 }
371}
372
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