VirtualBox

source: vbox/trunk/src/VBox/Devices/Misc/DevPL031.cpp@ 99558

Last change on this file since 99558 was 99544, checked in by vboxsync, 2 years ago

Devices/DevPL031: Started implementing the PL031 PrimeCell RTC device, bugref:10435

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 KB
Line 
1/* $Id: DevPL031.cpp 99544 2023-04-27 08:16:31Z vboxsync $ */
2/** @file
3 * DevPL031 - ARM PL011 PrimeCell RTC.
4 *
5 * The documentation for this device was taken from
6 * https://developer.arm.com/documentation/ddi0224/c (2023-04-27).
7 */
8
9/*
10 * Copyright (C) 2023 Oracle and/or its affiliates.
11 *
12 * This file is part of VirtualBox base platform packages, as
13 * available from https://www.215389.xyz.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, in version 3 of the
18 * License.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see <https://www.gnu.org/licenses>.
27 *
28 * SPDX-License-Identifier: GPL-3.0-only
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#define LOG_GROUP LOG_GROUP_DEV_RTC
36#include <VBox/vmm/pdmdev.h>
37#include <VBox/vmm/pdmifs.h>
38#include <iprt/assert.h>
39#include <iprt/uuid.h>
40#include <iprt/string.h>
41#include <iprt/semaphore.h>
42#include <iprt/critsect.h>
43
44#include "VBoxDD.h"
45
46
47/*********************************************************************************************************************************
48* Defined Constants And Macros *
49*********************************************************************************************************************************/
50
51/** The current serial code saved state version. */
52#define PL031_SAVED_STATE_VERSION 1
53
54/** PL011 MMIO region size in bytes. */
55#define PL031_MMIO_SIZE _4K
56
57/** The offset of the RTCDR register from the beginning of the region. */
58#define PL031_REG_RTCDR_INDEX 0x0
59/** The offset of the RTCMR register from the beginning of the region. */
60#define PL031_REG_RTCMR_INDEX 0x4
61/** The offset of the RTCLR register from the beginning of the region. */
62#define PL031_REG_RTCLR_INDEX 0x8
63
64/** The offset of the RTCCR register from the beginning of the region. */
65#define PL031_REG_RTCCR_INDEX 0xc
66/** RTC start bit. */
67# define PL031_REG_RTCCR_RTC_START RT_BIT(0)
68
69/** The offset of the RTCIMSC register from the beginning of the region. */
70#define PL031_REG_RTCIMSC_INDEX 0x10
71/** Interrupt mask bit. */
72# define PL031_REG_RTCIMSC_MASK RT_BIT(0)
73
74/** The offset of the RTCRIS register from the beginning of the region. */
75#define PL031_REG_RTCRIS_INDEX 0x14
76/** Raw interrupt status bit. */
77# define PL031_REG_RTCRIS_STS RT_BIT(0)
78
79/** The offset of the RTCMIS register from the beginning of the region. */
80#define PL031_REG_RTCMIS_INDEX 0x18
81/** Masked interrupt status bit. */
82# define PL031_REG_RTCMIS_STS RT_BIT(0)
83
84/** The offset of the RTCICR register from the beginning of the region. */
85#define PL031_REG_RTCICR_INDEX 0x1c
86/** Interrupt clear bit. */
87# define PL031_REG_RTCICR_CLR RT_BIT(0)
88
89/** The offset of the UARTPeriphID0 register from the beginning of the region. */
90#define PL031_REG_RTC_PERIPH_ID0_INDEX 0xfe0
91/** The offset of the UARTPeriphID1 register from the beginning of the region. */
92#define PL031_REG_RTC_PERIPH_ID1_INDEX 0xfe4
93/** The offset of the UARTPeriphID2 register from the beginning of the region. */
94#define PL031_REG_RTC_PERIPH_ID2_INDEX 0xfe8
95/** The offset of the UARTPeriphID3 register from the beginning of the region. */
96#define PL031_REG_RTC_PERIPH_ID3_INDEX 0xfec
97/** The offset of the UARTPCellID0 register from the beginning of the region. */
98#define PL031_REG_RTC_PCELL_ID0_INDEX 0xff0
99/** The offset of the UARTPCellID1 register from the beginning of the region. */
100#define PL031_REG_RTC_PCELL_ID1_INDEX 0xff4
101/** The offset of the UARTPCellID2 register from the beginning of the region. */
102#define PL031_REG_RTC_PCELL_ID2_INDEX 0xff8
103/** The offset of the UARTPCellID3 register from the beginning of the region. */
104#define PL031_REG_RTC_PCELL_ID3_INDEX 0xffc
105
106
107/*********************************************************************************************************************************
108* Structures and Typedefs *
109*********************************************************************************************************************************/
110
111/**
112 * Shared RTC device state.
113 */
114typedef struct DEVPL031
115{
116 /** The MMIO handle. */
117 IOMMMIOHANDLE hMmio;
118 /** The second timer (pl031TimerSecond). */
119 TMTIMERHANDLE hTimerSecond;
120 /** The base MMIO address the device is registered at. */
121 RTGCPHYS GCPhysMmioBase;
122 /** The IRQ value. */
123 uint16_t u16Irq;
124
125 /** @name Registers.
126 * @{ */
127 /** Data register. */
128 uint32_t u32RtcDr;
129 /** Match register. */
130 uint32_t u32RtcMr;
131 /** Load register. */
132 uint32_t u32RtcLr;
133 /** RTC start bit from the control register. */
134 bool fRtcStarted;
135 /** RTC interrupt masked status. */
136 bool fRtcIrqMasked;
137 /** RTC raw interrupt status. */
138 bool fRtcIrqSts;
139 /** @} */
140
141} DEVPL031;
142/** Pointer to the shared RTC device state. */
143typedef DEVPL031 *PDEVPL031;
144
145
146/**
147 * Serial device state for ring-3.
148 */
149typedef struct DEVPL031R3
150{
151 uint32_t u32Dummy;
152} DEVPL031R3;
153/** Pointer to the serial device state for ring-3. */
154typedef DEVPL031R3 *PDEVPL031R3;
155
156
157/**
158 * Serial device state for ring-0.
159 */
160typedef struct DEVPL031R0
161{
162 /** Dummy .*/
163 uint8_t bDummy;
164} DEVPL031R0;
165/** Pointer to the serial device state for ring-0. */
166typedef DEVPL031R0 *PDEVPL031R0;
167
168
169/**
170 * Serial device state for raw-mode.
171 */
172typedef struct DEVPL031RC
173{
174 /** Dummy .*/
175 uint8_t bDummy;
176} DEVPL031RC;
177/** Pointer to the serial device state for raw-mode. */
178typedef DEVPL031RC *PDEVPL031RC;
179
180/** The serial device state for the current context. */
181typedef CTX_SUFF(DEVPL031) DEVPL031CC;
182/** Pointer to the serial device state for the current context. */
183typedef CTX_SUFF(PDEVPL031) PDEVPL031CC;
184
185
186/*********************************************************************************************************************************
187* Internal Functions *
188*********************************************************************************************************************************/
189
190#ifndef VBOX_DEVICE_STRUCT_TESTCASE
191
192/**
193 * Updates the IRQ state based on the current device state.
194 *
195 * @returns nothing.
196 * @param pDevIns The device instance.
197 * @param pThis The shared RTC instance data.
198 */
199DECLINLINE(void) pl031IrqUpdate(PPDMDEVINS pDevIns, PDEVPL031 pThis)
200{
201 LogFlowFunc(("pThis=%#p\n", pThis));
202 if (pThis->fRtcIrqSts && !pThis->fRtcIrqMasked) /** @todo ISA is x86 specific. */
203 PDMDevHlpISASetIrqNoWait(pDevIns, pThis->u16Irq, 1);
204 else
205 PDMDevHlpISASetIrqNoWait(pDevIns, pThis->u16Irq, 0);
206}
207
208
209/**
210 * @callback_method_impl{FNTMTIMERDEV, Second timer.}
211 */
212static DECLCALLBACK(void) pl031TimerSecond(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, void *pvUser)
213{
214 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
215
216 Assert(PDMDevHlpTimerIsLockOwner(pDevIns, hTimer));
217 Assert(PDMDevHlpCritSectIsOwner(pDevIns, pDevIns->CTX_SUFF(pCritSectRo)));
218 RT_NOREF(pvUser, hTimer);
219
220 if (pThis->fRtcStarted)
221 {
222 pThis->u32RtcDr++;
223 if (pThis->u32RtcDr + pThis->u32RtcLr == pThis->u32RtcMr)
224 {
225 /* Set interrupt. */
226 pThis->fRtcIrqSts = true;
227 pl031IrqUpdate(pDevIns, pThis);
228 }
229
230 PDMDevHlpTimerSetMillies(pDevIns, hTimer, RT_MS_1SEC);
231 }
232}
233
234
235/* -=-=-=-=-=- MMIO callbacks -=-=-=-=-=- */
236
237
238/**
239 * @callback_method_impl{FNIOMMMIONEWREAD}
240 */
241static DECLCALLBACK(VBOXSTRICTRC) pl031MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
242{
243 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
244 NOREF(pvUser);
245 Assert(cb == 4 || cb == 8);
246 Assert(!(off & (cb - 1)));
247
248 LogFlowFunc(("%RGp cb=%u\n", off, cb));
249
250 uint32_t u32Val = 0;
251 VBOXSTRICTRC rc = VINF_SUCCESS;
252 switch (off)
253 {
254 case PL031_REG_RTCDR_INDEX:
255 u32Val = pThis->u32RtcDr + pThis->u32RtcLr;
256 break;
257 case PL031_REG_RTCMR_INDEX:
258 u32Val = pThis->u32RtcMr;
259 break;
260 case PL031_REG_RTCLR_INDEX:
261 u32Val = pThis->u32RtcLr;
262 break;
263 case PL031_REG_RTCCR_INDEX:
264 u32Val = pThis->fRtcStarted ? PL031_REG_RTCCR_RTC_START : 0;
265 break;
266 case PL031_REG_RTCIMSC_INDEX:
267 u32Val = pThis->fRtcIrqMasked ? PL031_REG_RTCIMSC_MASK : 0;
268 break;
269 case PL031_REG_RTCRIS_INDEX:
270 u32Val = pThis->fRtcIrqSts ? PL031_REG_RTCRIS_STS : 0;
271 break;
272 case PL031_REG_RTCMIS_INDEX:
273 u32Val = (pThis->fRtcIrqSts && !pThis->fRtcIrqMasked) ? PL031_REG_RTCMIS_STS : 0;
274 break;
275 case PL031_REG_RTC_PERIPH_ID0_INDEX:
276 u32Val = 0x31;
277 break;
278 case PL031_REG_RTC_PERIPH_ID1_INDEX:
279 u32Val = 0x10;
280 break;
281 case PL031_REG_RTC_PERIPH_ID2_INDEX:
282 u32Val = 0x04;
283 break;
284 case PL031_REG_RTC_PERIPH_ID3_INDEX:
285 u32Val = 0x00;
286 break;
287 case PL031_REG_RTC_PCELL_ID0_INDEX:
288 u32Val = 0x0d;
289 break;
290 case PL031_REG_RTC_PCELL_ID1_INDEX:
291 u32Val = 0xf0;
292 break;
293 case PL031_REG_RTC_PCELL_ID2_INDEX:
294 u32Val = 0x05;
295 break;
296 case PL031_REG_RTC_PCELL_ID3_INDEX:
297 u32Val = 0xb1;
298 break;
299 case PL031_REG_RTCICR_INDEX: /* Writeonly */
300 default:
301 break;
302 }
303
304 if (rc == VINF_SUCCESS)
305 *(uint32_t *)pv = u32Val;
306
307 return rc;
308}
309
310
311/**
312 * @callback_method_impl{FNIOMMMIONEWWRITE}
313 */
314static DECLCALLBACK(VBOXSTRICTRC) pl031MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
315{
316 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
317 LogFlowFunc(("cb=%u reg=%RGp val=%llx\n", cb, off, cb == 4 ? *(uint32_t *)pv : cb == 8 ? *(uint64_t *)pv : 0xdeadbeef));
318 RT_NOREF(pvUser);
319 Assert(cb == 4 || cb == 8);
320 Assert(!(off & (cb - 1)));
321
322 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
323 uint32_t u32Val = *(uint32_t *)pv;
324 switch (off)
325 {
326 case PL031_REG_RTCMR_INDEX:
327 pThis->u32RtcMr = u32Val;
328 break;
329 case PL031_REG_RTCLR_INDEX:
330 pThis->u32RtcLr = u32Val;
331 break;
332 case PL031_REG_RTCCR_INDEX:
333 {
334 /* Writing this resets the data register in any case. */
335 pThis->u32RtcDr = 0;
336 bool fRtcStart = RT_BOOL(u32Val & PL031_REG_RTCCR_RTC_START);
337 if (fRtcStart ^ pThis->fRtcStarted)
338 {
339 pThis->fRtcStarted = fRtcStart;
340 if (fRtcStart)
341 {
342 PDMDevHlpTimerLockClock(pDevIns, pThis->hTimerSecond, VERR_IGNORED);
343 rcStrict = PDMDevHlpTimerSet(pDevIns, pThis->hTimerSecond, RT_MS_1SEC);
344 PDMDevHlpTimerUnlockClock(pDevIns, pThis->hTimerSecond);
345 }
346 else
347 PDMDevHlpTimerStop(pDevIns, pThis->hTimerSecond);
348 }
349 break;
350 }
351 case PL031_REG_RTCIMSC_INDEX:
352 pThis->fRtcIrqMasked = RT_BOOL(u32Val & PL031_REG_RTCIMSC_MASK);
353 pl031IrqUpdate(pDevIns, pThis);
354 break;
355 case PL031_REG_RTCDR_INDEX: /* Readonly */
356 case PL031_REG_RTCMIS_INDEX:
357 case PL031_REG_RTCRIS_INDEX:
358 default:
359 break;
360 }
361 return rcStrict;
362}
363
364
365#ifdef IN_RING3
366
367/* -=-=-=-=-=-=-=-=- Saved State -=-=-=-=-=-=-=-=- */
368
369/**
370 * @callback_method_impl{FNSSMDEVLIVEEXEC}
371 */
372static DECLCALLBACK(int) pl031R3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
373{
374 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
375 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
376 RT_NOREF(uPass);
377
378 pHlp->pfnSSMPutU16(pSSM, pThis->u16Irq);
379 pHlp->pfnSSMPutGCPhys(pSSM, pThis->GCPhysMmioBase);
380 return VINF_SSM_DONT_CALL_AGAIN;
381}
382
383
384/**
385 * @callback_method_impl{FNSSMDEVSAVEEXEC}
386 */
387static DECLCALLBACK(int) pl031R3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
388{
389 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
390 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
391
392 pHlp->pfnSSMPutU16(pSSM, pThis->u16Irq);
393 pHlp->pfnSSMPutGCPhys(pSSM, pThis->GCPhysMmioBase);
394
395 return pHlp->pfnSSMPutU32(pSSM, UINT32_MAX); /* sanity/terminator */
396}
397
398
399/**
400 * @callback_method_impl{FNSSMDEVLOADEXEC}
401 */
402static DECLCALLBACK(int) pl031R3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
403{
404 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
405 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
406 uint16_t u16Irq;
407 RTGCPHYS GCPhysMmioBase;
408 int rc;
409
410 RT_NOREF(uVersion);
411
412 pHlp->pfnSSMGetU16( pSSM, &u16Irq);
413 pHlp->pfnSSMGetGCPhys(pSSM, &GCPhysMmioBase);
414 if (uPass == SSM_PASS_FINAL)
415 {
416 rc = VERR_NOT_IMPLEMENTED;
417 AssertRCReturn(rc, rc);
418 }
419
420 if (uPass == SSM_PASS_FINAL)
421 {
422 /* The marker. */
423 uint32_t u32;
424 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
425 AssertRCReturn(rc, rc);
426 AssertMsgReturn(u32 == UINT32_MAX, ("%#x\n", u32), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
427 }
428
429 /*
430 * Check the config.
431 */
432 if ( pThis->u16Irq != u16Irq
433 || pThis->GCPhysMmioBase != GCPhysMmioBase)
434 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS,
435 N_("Config mismatch - saved Irq=%#x GCPhysMmioBase=%#RGp; configured Irq=%#x GCPhysMmioBase=%#RGp"),
436 u16Irq, GCPhysMmioBase, pThis->u16Irq, pThis->GCPhysMmioBase);
437
438 return VINF_SUCCESS;
439}
440
441
442/**
443 * @callback_method_impl{FNSSMDEVLOADDONE}
444 */
445static DECLCALLBACK(int) pl031R3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
446{
447 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
448 PDEVPL031CC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PDEVPL031CC);
449
450 RT_NOREF(pThis, pThisCC, pSSM);
451 return VERR_NOT_IMPLEMENTED;
452}
453
454
455/* -=-=-=-=-=-=-=-=- PDMDEVREG -=-=-=-=-=-=-=-=- */
456
457/**
458 * @interface_method_impl{PDMDEVREG,pfnReset}
459 */
460static DECLCALLBACK(void) pl031R3Reset(PPDMDEVINS pDevIns)
461{
462 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
463
464 pThis->u32RtcDr = 0;
465 pThis->u32RtcMr = 0;
466 pThis->u32RtcLr = 0;
467 pThis->fRtcStarted = false;
468 pThis->fRtcIrqMasked = false;
469 pThis->fRtcIrqSts = false;
470}
471
472
473/**
474 * @interface_method_impl{PDMDEVREG,pfnDestruct}
475 */
476static DECLCALLBACK(int) pl031R3Destruct(PPDMDEVINS pDevIns)
477{
478 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
479
480 /* Nothing to do. */
481 return VINF_SUCCESS;
482}
483
484
485/**
486 * @interface_method_impl{PDMDEVREG,pfnConstruct}
487 */
488static DECLCALLBACK(int) pl031R3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
489{
490 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
491 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
492 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
493 int rc;
494
495 Assert(iInstance < 4);
496
497 /*
498 * Validate and read the configuration.
499 */
500 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "Irq|MmioBase", "");
501
502 uint16_t u16Irq = 0;
503 rc = pHlp->pfnCFGMQueryU16(pCfg, "Irq", &u16Irq);
504 if (RT_FAILURE(rc))
505 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Failed to get the \"Irq\" value"));
506
507 RTGCPHYS GCPhysMmioBase = 0;
508 rc = pHlp->pfnCFGMQueryU64(pCfg, "MmioBase", &GCPhysMmioBase);
509 if (RT_FAILURE(rc))
510 return PDMDEV_SET_ERROR(pDevIns, rc,
511 N_("Configuration error: Failed to get the \"MmioBase\" value"));
512
513 pThis->u16Irq = u16Irq;
514 pThis->GCPhysMmioBase = GCPhysMmioBase;
515
516 /*
517 * Register and map the MMIO region.
518 */
519 rc = PDMDevHlpMmioCreateAndMap(pDevIns, GCPhysMmioBase, PL031_MMIO_SIZE, pl031MmioWrite, pl031MmioRead,
520 IOMMMIO_FLAGS_READ_DWORD | IOMMMIO_FLAGS_WRITE_DWORD_ZEROED, "PL031-RTC", &pThis->hMmio);
521 AssertRCReturn(rc, rc);
522
523 /* Seconds timer. */
524 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, pl031TimerSecond, pThis,
525 TMTIMER_FLAGS_DEFAULT_CRIT_SECT | TMTIMER_FLAGS_RING0,
526 "PL031 RTC Second", &pThis->hTimerSecond);
527 AssertRCReturn(rc, rc);
528
529 /*
530 * Saved state.
531 */
532 rc = PDMDevHlpSSMRegisterEx(pDevIns, PL031_SAVED_STATE_VERSION, sizeof(*pThis), NULL,
533 NULL, pl031R3LiveExec, NULL,
534 NULL, pl031R3SaveExec, NULL,
535 NULL, pl031R3LoadExec, pl031R3LoadDone);
536 AssertRCReturn(rc, rc);
537
538 pl031R3Reset(pDevIns);
539 return VINF_SUCCESS;
540}
541
542#else /* !IN_RING3 */
543
544/**
545 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
546 */
547static DECLCALLBACK(int) pl031RZConstruct(PPDMDEVINS pDevIns)
548{
549 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
550 PDEVPL031 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPL031);
551
552 int rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, pl031MmioWrite, pl031MmioRead, NULL /*pvUser*/);
553 AssertRCReturn(rc, rc);
554
555 return VINF_SUCCESS;
556}
557
558#endif /* !IN_RING3 */
559
560/**
561 * The device registration structure.
562 */
563const PDMDEVREG g_DevicePl031Rtc =
564{
565 /* .u32Version = */ PDM_DEVREG_VERSION,
566 /* .uReserved0 = */ 0,
567 /* .szName = */ "arm-pl031-rtc",
568 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
569 /* .fClass = */ PDM_DEVREG_CLASS_RTC,
570 /* .cMaxInstances = */ UINT32_MAX,
571 /* .uSharedVersion = */ 42,
572 /* .cbInstanceShared = */ sizeof(DEVPL031),
573 /* .cbInstanceCC = */ sizeof(DEVPL031CC),
574 /* .cbInstanceRC = */ sizeof(DEVPL031RC),
575 /* .cMaxPciDevices = */ 0,
576 /* .cMaxMsixVectors = */ 0,
577 /* .pszDescription = */ "ARM PL031 PrimeCell RTC",
578#if defined(IN_RING3)
579 /* .pszRCMod = */ "VBoxDDRC.rc",
580 /* .pszR0Mod = */ "VBoxDDR0.r0",
581 /* .pfnConstruct = */ pl031R3Construct,
582 /* .pfnDestruct = */ pl031R3Destruct,
583 /* .pfnRelocate = */ NULL,
584 /* .pfnMemSetup = */ NULL,
585 /* .pfnPowerOn = */ NULL,
586 /* .pfnReset = */ pl031R3Reset,
587 /* .pfnSuspend = */ NULL,
588 /* .pfnResume = */ NULL,
589 /* .pfnAttach = */ NULL,
590 /* .pfnDetach = */ NULL,
591 /* .pfnQueryInterface = */ NULL,
592 /* .pfnInitComplete = */ NULL,
593 /* .pfnPowerOff = */ NULL,
594 /* .pfnSoftReset = */ NULL,
595 /* .pfnReserved0 = */ NULL,
596 /* .pfnReserved1 = */ NULL,
597 /* .pfnReserved2 = */ NULL,
598 /* .pfnReserved3 = */ NULL,
599 /* .pfnReserved4 = */ NULL,
600 /* .pfnReserved5 = */ NULL,
601 /* .pfnReserved6 = */ NULL,
602 /* .pfnReserved7 = */ NULL,
603#elif defined(IN_RING0)
604 /* .pfnEarlyConstruct = */ NULL,
605 /* .pfnConstruct = */ pl031RZConstruct,
606 /* .pfnDestruct = */ NULL,
607 /* .pfnFinalDestruct = */ NULL,
608 /* .pfnRequest = */ NULL,
609 /* .pfnReserved0 = */ NULL,
610 /* .pfnReserved1 = */ NULL,
611 /* .pfnReserved2 = */ NULL,
612 /* .pfnReserved3 = */ NULL,
613 /* .pfnReserved4 = */ NULL,
614 /* .pfnReserved5 = */ NULL,
615 /* .pfnReserved6 = */ NULL,
616 /* .pfnReserved7 = */ NULL,
617#elif defined(IN_RC)
618 /* .pfnConstruct = */ pl031RZConstruct,
619 /* .pfnReserved0 = */ NULL,
620 /* .pfnReserved1 = */ NULL,
621 /* .pfnReserved2 = */ NULL,
622 /* .pfnReserved3 = */ NULL,
623 /* .pfnReserved4 = */ NULL,
624 /* .pfnReserved5 = */ NULL,
625 /* .pfnReserved6 = */ NULL,
626 /* .pfnReserved7 = */ NULL,
627#else
628# error "Not in IN_RING3, IN_RING0 or IN_RC!"
629#endif
630 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
631};
632
633#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
634
Note: See TracBrowser for help on using the repository browser.

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