VirtualBox

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

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