VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/DevPcArch.cpp@ 92126

Last change on this file since 92126 was 91920, checked in by vboxsync, 3 years ago

VMM,Devices: Eliminate direct calls to VMMR3 and VMR3 APIs and introduce callbacks in the device helper callback table, bugref:10074

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 12.8 KB
Line 
1/* $Id: DevPcArch.cpp 91920 2021-10-21 06:45:26Z vboxsync $ */
2/** @file
3 * DevPcArch - PC Architecture Device.
4 */
5
6/*
7 * Copyright (C) 2006-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/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_PC_ARCH
23#include <VBox/vmm/pdmdev.h>
24#include <VBox/vmm/mm.h>
25#include <VBox/vmm/pgm.h>
26#include <VBox/log.h>
27#include <VBox/err.h>
28#include <iprt/assert.h>
29#include <iprt/string.h>
30
31#include "VBoxDD.h"
32
33
34/*********************************************************************************************************************************
35* Structures and Typedefs *
36*********************************************************************************************************************************/
37
38/**
39 * PC Bios instance data structure.
40 */
41typedef struct DEVPCARCH
42{
43 /** Pointer back to the device instance. */
44 PPDMDEVINS pDevIns;
45} DEVPCARCH, *PDEVPCARCH;
46
47
48
49/**
50 * @callback_method_impl{FNIOMIOPORTNEWIN, Math coprocessor.}
51 * @note offPort is absolute
52 */
53static DECLCALLBACK(VBOXSTRICTRC)
54pcarchIOPortFPURead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
55{
56 int rc;
57 NOREF(pvUser); NOREF(pDevIns); NOREF(pu32);
58 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d\n", offPort, cb);
59 if (rc == VINF_SUCCESS)
60 rc = VERR_IOM_IOPORT_UNUSED;
61 return rc;
62}
63
64/**
65 * @callback_method_impl{FNIOMIOPORTNEWOUT, Math coprocessor.}
66 * @note offPort is absolute
67 * @todo Add IGNNE support.
68 */
69static DECLCALLBACK(VBOXSTRICTRC)
70pcarchIOPortFPUWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
71{
72 int rc = VINF_SUCCESS;
73 NOREF(pvUser);
74 if (cb == 1)
75 {
76 switch (offPort)
77 {
78 /*
79 * Clear busy latch.
80 */
81 case 0xf0:
82 Log2(("PCARCH: FPU Clear busy latch u32=%#x\n", u32));
83/* This is triggered when booting Knoppix (3.7) */
84#if 0
85 if (!u32)
86 rc = PDMDeviceDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", offPort, cb, u32);
87#endif
88 /* pDevIns->pHlp->pfnPICSetIrq(pDevIns, 13, 0); */
89 break;
90
91 /* Reset. */
92 case 0xf1:
93 Log2(("PCARCH: FPU Reset cb=%d u32=%#x\n", cb, u32));
94 /** @todo figure out what the difference between FPU ports 0xf0 and 0xf1 are... */
95 /* pDevIns->pHlp->pfnPICSetIrq(pDevIns, 13, 0); */
96 break;
97
98 /* opcode transfers */
99 case 0xf8:
100 case 0xfa:
101 case 0xfc:
102 default:
103 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", offPort, cb, u32);
104 break;
105 }
106 /* this works better, but probably not entirely correct. */
107 PDMDevHlpISASetIrq(pDevIns, 13, 0);
108 }
109 else
110 rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", offPort, cb, u32);
111 return rc;
112}
113
114
115/**
116 * @callback_method_impl{FNIOMIOPORTIN, PS/2 system control port A.}
117 *
118 * @todo Check if the A20 enable/disable method implemented here in any way
119 * should cooperate with the one implemented in the PS/2 keyboard device.
120 * This probably belongs together in the PS/2 keyboard device (since that
121 * is where the "port B" mentioned by Ralph Brown is implemented).
122 *
123 * @remark Ralph Brown and friends have this to say about this port:
124 *
125 * @verbatim
1260092 RW PS/2 system control port A (port B is at PORT 0061h) (see #P0415)
127
128Bitfields for PS/2 system control port A:
129Bit(s) Description (Table P0415)
130 7-6 any bit set to 1 turns activity light on
131 5 unused
132 4 watchdog timout occurred
133 3 =0 RTC/CMOS security lock (on password area) unlocked
134 =1 CMOS locked (done by POST)
135 2 unused
136 1 A20 is active
137 0 =0 system reset or write
138 =1 pulse alternate reset pin (high-speed alternate CPU reset)
139Notes: once set, bit 3 may only be cleared by a power-on reset
140 on at least the C&T 82C235, bit 0 remains set through a CPU reset to
141 allow the BIOS to determine the reset method
142 on the PS/2 30-286 & "Tortuga" the INT 15h/87h memory copy does
143 not use this port for A20 control, but instead uses the keyboard
144 controller (8042). Reportedly this may cause the system to crash
145 when access to the 8042 is disabled in password server mode
146 (see #P0398).
147SeeAlso: #P0416,#P0417,MSR 00001000h
148 * @endverbatim
149 * @note offPort is absolute
150 */
151static DECLCALLBACK(VBOXSTRICTRC)
152pcarchIOPortPS2SysControlPortARead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
153{
154 RT_NOREF1(pvUser);
155 if (cb == 1)
156 {
157 *pu32 = PDMDevHlpA20IsEnabled(pDevIns) << 1;
158 return VINF_SUCCESS;
159 }
160 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d\n", offPort, cb);
161}
162
163
164/**
165 * @callback_method_impl{FNIOMIOPORTOUT, PS/2 system control port A.}
166 * @see Remark and todo of pcarchIOPortPS2SysControlPortARead().
167 * @note offPort is absolute
168 */
169static DECLCALLBACK(VBOXSTRICTRC)
170pcarchIOPortPS2SysControlPortAWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
171{
172 NOREF(pvUser);
173 if (cb == 1)
174 {
175 /*
176 * Fast reset?
177 */
178 if (u32 & 1)
179 {
180 LogRel(("Reset initiated by system port A\n"));
181 return PDMDevHlpVMReset(pDevIns, PDMVMRESET_F_PORT_A);
182 }
183
184 /*
185 * A20 is the only thing we care about of the other stuff.
186 */
187 PDMDevHlpA20Set(pDevIns, !!(u32 & 2));
188 return VINF_SUCCESS;
189 }
190 return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Port=%#x cb=%d u32=%#x\n", offPort, cb, u32);
191}
192
193
194/**
195 * @callback_method_impl{FNIOMMMIONEWWRITE, Ignores writes to the reserved memory.}
196 * @note off is an absolute address.
197 */
198static DECLCALLBACK(VBOXSTRICTRC)
199pcarchReservedMemoryWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb)
200{
201 Log2(("pcarchReservedMemoryRead: %#RGp LB %#x %.*Rhxs\n", off, cb, RT_MIN(cb, 16), pv));
202 RT_NOREF(pDevIns, pvUser, off, pv, cb);
203 return VINF_SUCCESS;
204}
205
206
207/**
208 * @callback_method_impl{FNIOMMMIONEWREAD, The reserved memory reads as 0xff.}
209 * @note off is an absolute address.
210 */
211static DECLCALLBACK(VBOXSTRICTRC)
212pcarchReservedMemoryRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb)
213{
214 Log2(("pcarchReservedMemoryRead: %#RGp LB %#x\n", off, cb));
215 RT_NOREF(pDevIns, pvUser, off);
216 memset(pv, 0xff, cb);
217 return VINF_SUCCESS;
218}
219
220
221/**
222 * @interface_method_impl{PDMDEVREG,pfnInitComplete,
223 * Turn RAM pages between 0xa0000 and 0xfffff into reserved memory.}
224 */
225static DECLCALLBACK(int) pcarchInitComplete(PPDMDEVINS pDevIns)
226{
227 int iRegion = 0;
228 RTGCPHYS const GCPhysEnd = 0x100000;
229 RTGCPHYS GCPhysCur = 0x0a0000;
230 do
231 {
232 if (!PDMDevHlpPhysIsGCPhysNormal(pDevIns, GCPhysCur))
233 GCPhysCur += X86_PAGE_SIZE;
234 else
235 {
236 RTGCPHYS const GCPhysStart = GCPhysCur;
237 do
238 GCPhysCur += X86_PAGE_SIZE;
239 while (GCPhysCur < GCPhysEnd && PDMDevHlpPhysIsGCPhysNormal(pDevIns, GCPhysCur));
240
241 IOMMMIOHANDLE hMmioRegion;
242 int rc = PDMDevHlpMmioCreateAndMap(pDevIns, GCPhysStart, GCPhysCur - GCPhysStart,
243 pcarchReservedMemoryWrite, pcarchReservedMemoryRead,
244 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU | IOMMMIO_FLAGS_ABS,
245 PDMDevHlpMMHeapAPrintf(pDevIns, MM_TAG_PGM_PHYS /* bad bird*/, "PC Arch Reserved #%u", iRegion),
246 &hMmioRegion);
247 AssertLogRelRCReturn(rc, rc);
248 iRegion++;
249 }
250 } while (GCPhysCur < GCPhysEnd);
251
252 return VINF_SUCCESS;
253}
254
255
256/**
257 * @interface_method_impl{PDMDEVREG,pfnConstruct}
258 */
259static DECLCALLBACK(int) pcarchConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
260{
261 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
262 PDEVPCARCH pThis = PDMDEVINS_2_DATA(pDevIns, PDEVPCARCH);
263 int rc;
264 RT_NOREF(iInstance, pCfg);
265 Assert(iInstance == 0);
266
267 /*
268 * Validate configuration.
269 */
270 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "", "");
271
272 /*
273 * Init the data.
274 */
275 pThis->pDevIns = pDevIns;
276
277 /*
278 * Register I/O Ports
279 */
280 IOMIOPORTHANDLE hIoPorts;
281 rc = PDMDevHlpIoPortCreateFlagsAndMap(pDevIns, 0xf0 /*uPort*/, 0x10 /*cPorts*/, IOM_IOPORT_F_ABS,
282 pcarchIOPortFPUWrite, pcarchIOPortFPURead,
283 "Math Co-Processor (DOS/OS2 mode)", NULL /*paExtDescs*/, &hIoPorts);
284 AssertRCReturn(rc, rc);
285 rc = PDMDevHlpIoPortCreateFlagsAndMap(pDevIns, 0x92 /*uPort*/, 1 /*cPorts*/, IOM_IOPORT_F_ABS,
286 pcarchIOPortPS2SysControlPortAWrite, pcarchIOPortPS2SysControlPortARead,
287 "PS/2 system control port A (A20 and more)", NULL /*paExtDescs*/, &hIoPorts);
288 AssertRCReturn(rc, rc);
289
290 return VINF_SUCCESS;
291}
292
293
294/**
295 * The device registration structure.
296 */
297const PDMDEVREG g_DevicePcArch =
298{
299 /* .u32Version = */ PDM_DEVREG_VERSION,
300 /* .uReserved0 = */ 0,
301 /* .szName = */ "pcarch",
302 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_NEW_STYLE,
303 /* .fClass = */ PDM_DEVREG_CLASS_ARCH,
304 /* .cMaxInstances = */ 1,
305 /* .uSharedVersion = */ 42,
306 /* .cbInstanceShared = */ sizeof(DEVPCARCH),
307 /* .cbInstanceCC = */ 0,
308 /* .cbInstanceRC = */ 0,
309 /* .cMaxPciDevices = */ 0,
310 /* .cMaxMsixVectors = */ 0,
311 /* .pszDescription = */ "PC Architecture Device",
312#if defined(IN_RING3)
313 /* .pszRCMod = */ "",
314 /* .pszR0Mod = */ "",
315 /* .pfnConstruct = */ pcarchConstruct,
316 /* .pfnDestruct = */ NULL,
317 /* .pfnRelocate = */ NULL,
318 /* .pfnMemSetup = */ NULL,
319 /* .pfnPowerOn = */ NULL,
320 /* .pfnReset = */ NULL,
321 /* .pfnSuspend = */ NULL,
322 /* .pfnResume = */ NULL,
323 /* .pfnAttach = */ NULL,
324 /* .pfnDetach = */ NULL,
325 /* .pfnQueryInterface = */ NULL,
326 /* .pfnInitComplete = */ pcarchInitComplete,
327 /* .pfnPowerOff = */ NULL,
328 /* .pfnSoftReset = */ NULL,
329 /* .pfnReserved0 = */ NULL,
330 /* .pfnReserved1 = */ NULL,
331 /* .pfnReserved2 = */ NULL,
332 /* .pfnReserved3 = */ NULL,
333 /* .pfnReserved4 = */ NULL,
334 /* .pfnReserved5 = */ NULL,
335 /* .pfnReserved6 = */ NULL,
336 /* .pfnReserved7 = */ NULL,
337#elif defined(IN_RING0)
338 /* .pfnEarlyConstruct = */ NULL,
339 /* .pfnConstruct = */ NULL,
340 /* .pfnDestruct = */ NULL,
341 /* .pfnFinalDestruct = */ NULL,
342 /* .pfnRequest = */ NULL,
343 /* .pfnReserved0 = */ NULL,
344 /* .pfnReserved1 = */ NULL,
345 /* .pfnReserved2 = */ NULL,
346 /* .pfnReserved3 = */ NULL,
347 /* .pfnReserved4 = */ NULL,
348 /* .pfnReserved5 = */ NULL,
349 /* .pfnReserved6 = */ NULL,
350 /* .pfnReserved7 = */ NULL,
351#elif defined(IN_RC)
352 /* .pfnConstruct = */ NULL,
353 /* .pfnReserved0 = */ NULL,
354 /* .pfnReserved1 = */ NULL,
355 /* .pfnReserved2 = */ NULL,
356 /* .pfnReserved3 = */ NULL,
357 /* .pfnReserved4 = */ NULL,
358 /* .pfnReserved5 = */ NULL,
359 /* .pfnReserved6 = */ NULL,
360 /* .pfnReserved7 = */ NULL,
361#else
362# error "Not in IN_RING3, IN_RING0 or IN_RC!"
363#endif
364 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
365};
366
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