VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

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