VirtualBox

source: vbox/trunk/src/VBox/Devices/Serial/UartCore.h@ 77807

Last change on this file since 77807 was 77411, checked in by vboxsync, 6 years ago

Devices/UART: Properly handle loopback mode (feeding the sent data immediately back to the receive side)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1/* $Id: UartCore.h 77411 2019-02-21 15:57:31Z vboxsync $ */
2/** @file
3 * UartCore - UART (16550A up to 16950) emulation.
4 *
5 * The documentation for this device was taken from the PC16550D spec from TI.
6 */
7
8/*
9 * Copyright (C) 2018-2019 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20#ifndef VBOX_INCLUDED_SRC_Serial_UartCore_h
21#define VBOX_INCLUDED_SRC_Serial_UartCore_h
22#ifndef RT_WITHOUT_PRAGMA_ONCE
23# pragma once
24#endif
25
26#include <VBox/types.h>
27#include <VBox/vmm/pdmdev.h>
28#include <VBox/vmm/pdmserialifs.h>
29#include <VBox/vmm/ssm.h>
30#include <iprt/assert.h>
31
32RT_C_DECLS_BEGIN
33
34/*********************************************************************************************************************************
35* Defined Constants And Macros *
36*********************************************************************************************************************************/
37
38/** The current serial code saved state version. */
39#define UART_SAVED_STATE_VERSION 7
40/** Saved state version before the TX timer for the connected device case was added. */
41#define UART_SAVED_STATE_VERSION_PRE_UNCONNECTED_TX_TIMER 6
42/** Saved state version of the legacy code which got replaced after 5.2. */
43#define UART_SAVED_STATE_VERSION_LEGACY_CODE 5
44/** Includes some missing bits from the previous saved state. */
45#define UART_SAVED_STATE_VERSION_MISSING_BITS 4
46/** Saved state version when only the 16450 variant was implemented. */
47#define UART_SAVED_STATE_VERSION_16450 3
48
49/** Maximum size of a FIFO. */
50#define UART_FIFO_LENGTH_MAX 128
51
52
53/*********************************************************************************************************************************
54* Structures and Typedefs *
55*********************************************************************************************************************************/
56
57/** Pointer to the UART core state. */
58typedef struct UARTCORE *PUARTCORE;
59
60
61/**
62 * UART core IRQ request callback to let the core instance raise/clear interrupt requests.
63 *
64 * @returns nothing.
65 * @param pDevIns The owning device instance.
66 * @param pThis The UART core instance.
67 * @param iLUN The LUN associated with the UART core.
68 * @param iLvl The interrupt level.
69 */
70typedef DECLCALLBACK(void) FNUARTCOREIRQREQ(PPDMDEVINS pDevIns, PUARTCORE pThis, unsigned iLUN, int iLvl);
71/** Pointer to a UART core IRQ request callback. */
72typedef FNUARTCOREIRQREQ *PFNUARTCOREIRQREQ;
73
74
75/**
76 * UART type.
77 */
78typedef enum UARTTYPE
79{
80 /** Invalid UART type. */
81 UARTTYPE_INVALID = 0,
82 /** 16450 UART type. */
83 UARTTYPE_16450,
84 /** 16550A UART type. */
85 UARTTYPE_16550A,
86 /** 16750 UART type. */
87 UARTTYPE_16750,
88 /** 32bit hack. */
89 UARTTYPE_32BIT_HACK = 0x7fffffff
90} UARTTYPE;
91
92
93/**
94 * UART FIFO.
95 */
96typedef struct UARTFIFO
97{
98 /** Fifo size configured. */
99 uint8_t cbMax;
100 /** Current amount of bytes used. */
101 uint8_t cbUsed;
102 /** Next index to write to. */
103 uint8_t offWrite;
104 /** Next index to read from. */
105 uint8_t offRead;
106 /** The interrupt trigger level (only used for the receive FIFO). */
107 uint8_t cbItl;
108 /** The data in the FIFO. */
109 uint8_t abBuf[UART_FIFO_LENGTH_MAX];
110 /** Alignment to a 4 byte boundary. */
111 uint8_t au8Alignment0[3];
112} UARTFIFO;
113/** Pointer to a FIFO. */
114typedef UARTFIFO *PUARTFIFO;
115
116
117/**
118 * UART core device.
119 *
120 * @implements PDMIBASE
121 * @implements PDMISERIALPORT
122 */
123typedef struct UARTCORE
124{
125 /** Access critical section. */
126 PDMCRITSECT CritSect;
127 /** Pointer to the device instance - R3 Ptr. */
128 PPDMDEVINSR3 pDevInsR3;
129 /** Pointer to the device instance - R0 Ptr. */
130 PPDMDEVINSR0 pDevInsR0;
131 /** Pointer to the device instance - RC Ptr. */
132 PPDMDEVINSRC pDevInsRC;
133 /** The LUN on the owning device instance for this core. */
134 uint32_t iLUN;
135 /** LUN\#0: The base interface. */
136 PDMIBASE IBase;
137 /** LUN\#0: The serial port interface. */
138 PDMISERIALPORT ISerialPort;
139 /** Pointer to the attached base driver. */
140 R3PTRTYPE(PPDMIBASE) pDrvBase;
141 /** Pointer to the attached serial driver. */
142 R3PTRTYPE(PPDMISERIALCONNECTOR) pDrvSerial;
143 /** Configuration flags. */
144 uint32_t fFlags;
145 /** The selected UART type. */
146 UARTTYPE enmType;
147
148 /** R3 timer pointer for the character timeout indication. */
149 PTMTIMERR3 pTimerRcvFifoTimeoutR3;
150 /** R3 timer pointer for the send loop if no driver is connected/loopback mode is active. */
151 PTMTIMERR3 pTimerTxUnconnectedR3;
152 /** R3 interrupt request callback of the owning device. */
153 R3PTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqR3;
154 /** R0 timer pointer fo the character timeout indication. */
155 PTMTIMERR0 pTimerRcvFifoTimeoutR0;
156 /** R0 timer pointer for the send loop if no driver is connected/loopback mode is active. */
157 PTMTIMERR0 pTimerTxUnconnectedR0;
158 /** R0 interrupt request callback of the owning device. */
159 R0PTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqR0;
160 /** RC timer pointer fo the character timeout indication. */
161 PTMTIMERRC pTimerRcvFifoTimeoutRC;
162 /** RC timer pointer for the send loop if no driver is connected/loopback mode is active. */
163 PTMTIMERRC pTimerTxUnconnectedRC;
164 /** RC interrupt request callback of the owning device. */
165 RCPTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqRC;
166 /** Alignment */
167 uint32_t u32Alignment;
168
169 /** The divisor register (DLAB = 1). */
170 uint16_t uRegDivisor;
171 /** The Receiver Buffer Register (RBR, DLAB = 0). */
172 uint8_t uRegRbr;
173 /** The Transmitter Holding Register (THR, DLAB = 0). */
174 uint8_t uRegThr;
175 /** The Interrupt Enable Register (IER, DLAB = 0). */
176 uint8_t uRegIer;
177 /** The Interrupt Identification Register (IIR). */
178 uint8_t uRegIir;
179 /** The FIFO Control Register (FCR). */
180 uint8_t uRegFcr;
181 /** The Line Control Register (LCR). */
182 uint8_t uRegLcr;
183 /** The Modem Control Register (MCR). */
184 uint8_t uRegMcr;
185 /** The Line Status Register (LSR). */
186 uint8_t uRegLsr;
187 /** The Modem Status Register (MSR). */
188 uint8_t uRegMsr;
189 /** The Scratch Register (SCR). */
190 uint8_t uRegScr;
191
192 /** Flag whether a character timeout interrupt is pending
193 * (no symbols were inserted or removed from the receive FIFO
194 * during an 4 times the character transmit/receive period and the FIFO
195 * is not empty). */
196 bool fIrqCtiPending;
197 /** Flag whether the transmitter holding register went empty since last time the
198 * IIR register was read. This gets reset when IIR is read so the guest will get this
199 * interrupt ID only once. */
200 bool fThreEmptyPending;
201 /** Alignment. */
202 bool afAlignment[2];
203 /** The transmit FIFO. */
204 UARTFIFO FifoXmit;
205 /** The receive FIFO. */
206 UARTFIFO FifoRecv;
207
208 /** Time it takes to transmit/receive a single symbol in timer ticks. */
209 uint64_t cSymbolXferTicks;
210 /** Number of bytes available for reading from the layer below. */
211 volatile uint32_t cbAvailRdr;
212
213#if defined(IN_RC) || HC_ARCH_BITS == 32
214 uint32_t uAlignment;
215#endif
216} UARTCORE;
217
218AssertCompileSizeAlignment(UARTCORE, 8);
219
220
221#ifndef VBOX_DEVICE_STRUCT_TESTCASE
222
223/** Flag whether to yield the CPU on an LSR read. */
224#define UART_CORE_YIELD_ON_LSR_READ RT_BIT_32(0)
225
226/**
227 * Performs a register write to the given register offset.
228 *
229 * @returns VBox status code.
230 * @param pThis The UART core instance.
231 * @param uReg The register offset (byte offset) to start writing to.
232 * @param u32 The value to write.
233 * @param cb Number of bytes to write.
234 */
235DECLHIDDEN(int) uartRegWrite(PUARTCORE pThis, uint32_t uReg, uint32_t u32, size_t cb);
236
237/**
238 * Performs a register read from the given register offset.
239 *
240 * @returns VBox status code.
241 * @param pThis The UART core instance.
242 * @param uReg The register offset (byte offset) to start reading from.
243 * @param pu32 Where to store the read value.
244 * @param cb Number of bytes to read.
245 */
246DECLHIDDEN(int) uartRegRead(PUARTCORE pThis, uint32_t uReg, uint32_t *pu32, size_t cb);
247
248# ifdef IN_RING3
249/**
250 * Initializes the given UART core instance using the provided configuration.
251 *
252 * @returns VBox status code.
253 * @param pThis The UART core instance to initialize.
254 * @param pDevInsR3 The R3 device instance pointer.
255 * @param enmType The type of UART emulated.
256 * @param iLUN The LUN the UART should look for attached drivers.
257 * @param fFlags Additional flags controlling device behavior.
258 * @param pfnUartIrqReqR3 Pointer to the R3 interrupt request callback.
259 * @param pfnUartIrqReqR0 Pointer to the R0 interrupt request callback.
260 * @param pfnUartIrqReqRC Pointer to the RC interrupt request callback.
261 */
262DECLHIDDEN(int) uartR3Init(PUARTCORE pThis, PPDMDEVINS pDevInsR3, UARTTYPE enmType, unsigned iLUN, uint32_t fFlags,
263 R3PTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqR3, R0PTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqR0,
264 RCPTRTYPE(PFNUARTCOREIRQREQ) pfnUartIrqReqRC);
265
266/**
267 * Destroys the given UART core instance freeing all allocated resources.
268 *
269 * @returns nothing.
270 * @param pThis The UART core instance.
271 */
272DECLHIDDEN(void) uartR3Destruct(PUARTCORE pThis);
273
274/**
275 * Detaches any attached driver from the given UART core instance.
276 *
277 * @returns nothing.
278 * @param pThis The UART core instance.
279 */
280DECLHIDDEN(void) uartR3Detach(PUARTCORE pThis);
281
282/**
283 * Attaches the given UART core instance to the drivers at the given LUN.
284 *
285 * @returns VBox status code.
286 * @param pThis The UART core instance.
287 * @param iLUN The LUN being attached.
288 */
289DECLHIDDEN(int) uartR3Attach(PUARTCORE pThis, unsigned iLUN);
290
291/**
292 * Resets the given UART core instance.
293 *
294 * @returns nothing.
295 * @param pThis The UART core instance.
296 */
297DECLHIDDEN(void) uartR3Reset(PUARTCORE pThis);
298
299/**
300 * Relocates an RC pointers of the given UART core instance
301 *
302 * @returns nothing.
303 * @param pThis The UART core instance.
304 * @param offDelta The delta to relocate RC pointers with.
305 */
306DECLHIDDEN(void) uartR3Relocate(PUARTCORE pThis, RTGCINTPTR offDelta);
307
308/**
309 * Saves the UART state to the given SSM handle.
310 *
311 * @returns VBox status code.
312 * @param pThis The UART core instance.
313 * @param pSSM The SSM handle to save to.
314 */
315DECLHIDDEN(int) uartR3SaveExec(PUARTCORE pThis, PSSMHANDLE pSSM);
316
317/**
318 * Loads the UART state from the given SSM handle.
319 *
320 * @returns VBox status code.
321 * @param pThis The UART core instance.
322 * @param pSSM The SSM handle to load from.
323 * @param uVersion Saved state version.
324 * @param uPass The SSM pass the call is done in.
325 * @param puIrq Where to store the IRQ value for legacy
326 * saved states - optional.
327 * @param pPortBase Where to store the I/O port base for legacy
328 * saved states - optional.
329 */
330DECLHIDDEN(int) uartR3LoadExec(PUARTCORE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass,
331 uint8_t *puIrq, RTIOPORT *pPortBase);
332
333/**
334 * Called when loading the state completed, updates the parameters of any driver underneath.
335 *
336 * @returns VBox status code.
337 * @param pThis The UART core instance.
338 * @param pSSM The SSM handle.
339 */
340DECLHIDDEN(int) uartR3LoadDone(PUARTCORE pThis, PSSMHANDLE pSSM);
341
342# endif
343
344#endif
345
346RT_C_DECLS_END
347
348#endif /* !VBOX_INCLUDED_SRC_Serial_UartCore_h */
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