DevSerial.cpp revision 30adc6dd25ed9fef4d800a6d9f1ab7e765b4c340
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VBox serial device:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Serial communication port driver
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Copyright (C) 2006-2007 innotek GmbH
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * available from http://www.virtualbox.org. This file is free software;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * General Public License (GPL) as published by the Free Software
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This code is based on:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * QEMU 16450 UART emulation
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Copyright (c) 2003-2004 Fabrice Bellard
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Permission is hereby granted, free of charge, to any person obtaining a copy
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * of this software and associated documentation files (the "Software"), to deal
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * in the Software without restriction, including without limitation the rights
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * copies of the Software, and to permit persons to whom the Software is
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * furnished to do so, subject to the following conditions:
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The above copyright notice and this permission notice shall be included in
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * all copies or substantial portions of the Software.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * THE SOFTWARE.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/*******************************************************************************
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync* Header Files *
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync*******************************************************************************/
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#undef VBOX_SERIAL_PCI /* The PCI variant has lots of problems: wrong IRQ line and wrong IO base assigned. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif /* VBOX_SERIAL_PCI */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IIR_MSI 0x00 /* Modem status interrupt */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * These are the definitions for the Modem Control Register
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * These are the definitions for the Modem Status Register
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_LSR_BI 0x10 /* Break interrupt indicator */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_LSR_FE 0x08 /* Frame error indicator */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_LSR_PE 0x04 /* Parity error indicator */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define UART_LSR_OE 0x02 /* Overrun error indicator */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Access critical section. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Pointer to the device instance. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Pointer to the device instance. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** The base interface. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** The character port interface. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Pointer to the attached base driver. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /** Pointer to the attached character driver. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* NOTE: this hidden state is necessary for tx irq generation as
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync it can be reset while reading iir */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif /* VBOX_SERIAL_PCI */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define PCIDEV_2_SERIALSTATE(pPciDev) ( (SerialState *)((uintptr_t)(pPciDev) - RT_OFFSETOF(SerialState, dev)) )
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif /* VBOX_SERIAL_PCI */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define PDMIBASE_2_SERIALSTATE(pInstance) ( (SerialState *)((uintptr_t)(pInterface) - RT_OFFSETOF(SerialState, IBase)) )
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#define PDMICHARPORT_2_SERIALSTATE(pInstance) ( (SerialState *)((uintptr_t)(pInterface) - RT_OFFSETOF(SerialState, ICharPort)) )
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncPDMBOTHCBDECL(int) serialIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncPDMBOTHCBDECL(int) serialIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
83d61602c6968041692aa7203ee51c4085c7e460vboxsync if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync } else if (s->msr_changed && (s->ier & UART_IER_RLSI)) {
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMDevHlpPCISetIrqNoWait(CTXSUFF(s->pDevIns), 0, 1);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#else /* !VBOX_SERIAL_PCI */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 1);
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync#endif /* !VBOX_SERIAL_PCI */
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync PDMDevHlpPCISetIrqNoWait(CTXSUFF(s->pDevIns), 0, 0);
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync#else /* !VBOX_SERIAL_PCI */
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync PDMDevHlpISASetIrqNoWait(CTXSUFF(s->pDevIns), s->irq, 0);
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync#endif /* !VBOX_SERIAL_PCI */
6a0359b8230a1b91fe49967c124a75191c3dfbf9vboxsyncstatic void serial_update_parameters(SerialState *s)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (s->divider == 0)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Log(("speed=%d parity=%c data=%d stop=%d\n", speed, parity, data_bits, stop_bits));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync s->pDrvChar->pfnSetParameters(s->pDrvChar, speed, parity, data_bits, stop_bits);
a9d98aa17ecb241bc2c79b67dc044f0af2eb7448vboxsyncstatic int serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
83d61602c6968041692aa7203ee51c4085c7e460vboxsync unsigned char ch;
1e0e13b23ace43d2fe93d45953b123f63b7e547cvboxsync LogFlow(("serial: write addr=0x%02x val=0x%02x\n", addr, val));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = s->pDrvChar->pfnWrite(s->pDrvChar, &ch, 1);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync int rc = s->pDrvChar->pfnSetModemLines(s->pDrvChar, !!(s->mcr & UART_MCR_RTS), !!(s->mcr & UART_MCR_DTR));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic uint32_t serial_ioport_read(void *opaque, uint32_t addr, int *pRC)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* reset THR pending bit */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* reset msr changed bit */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* in loopback, the modem output pins are connected to the
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Reset delta bits. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogFlow(("serial: read addr=0x%02x val=0x%02x\n", addr, ret));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) serialNotifyRead(PPDMICHARPORT pInterface, const void *pvBuf, size_t *pcbRead)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PDMICHARPORT_2_SERIALSTATE(pInterface);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMCritSectEnter(&pData->CritSect, VERR_PERMISSION_DENIED);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* If a character is still in the read queue, then wait for it to be emptied. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMCritSectEnter(&pData->CritSect, VERR_PERMISSION_DENIED);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) serialNotifyStatusLinesChanged(PPDMICHARPORT pInterface, uint32_t newStatusLines)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PDMICHARPORT_2_SERIALSTATE(pInterface);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync Log(("%s: pInterface=%p newStatusLines=%u\n", __FUNCTION__, pInterface, newStatusLines));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync PDMCritSectEnter(&pData->CritSect, VERR_PERMISSION_DENIED);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Set new states. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Compare the old and the new states and set the delta bits accordingly. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if ((newMsr & UART_MSR_DCD) != (pData->msr & UART_MSR_DCD))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if ((newMsr & UART_MSR_RI) == 1 && (pData->msr & UART_MSR_RI) == 0)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if ((newMsr & UART_MSR_DSR) != (pData->msr & UART_MSR_DSR))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if ((newMsr & UART_MSR_CTS) != (pData->msr & UART_MSR_CTS))
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync#endif /* IN_RING3 */
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * Port I/O Handler for OUT operations.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @returns VBox status code.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param pDevIns The device instance.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param pvUser User argument.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param Port Port number used for the IN operation.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param u32 The value to output.
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync * @param cb The value size in bytes.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsyncPDMBOTHCBDECL(int) serialIOPortWrite(PPDMDEVINS pDevIns, void *pvUser,
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync SerialState *pData = PDMINS2DATA(pDevIns, SerialState *);
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync rc = PDMCritSectEnter(&pData->CritSect, VINF_IOM_HC_IOPORT_WRITE);
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, u32));
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", Port, cb, u32));
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * Port I/O Handler for IN operations.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * @returns VBox status code.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * @param pDevIns The device instance.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * @param pvUser User argument.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * @param Port Port number used for the IN operation.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * @param u32 The value to output.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync * @param cb The value size in bytes.
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsyncPDMBOTHCBDECL(int) serialIOPortRead(PPDMDEVINS pDevIns, void *pvUser,
6ea079037b825359aab1ba56bb4b9e202ecea648vboxsync SerialState *pData = PDMINS2DATA(pDevIns, SerialState *);
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync rc = PDMCritSectEnter(&pData->CritSect, VINF_IOM_HC_IOPORT_READ);
9d7b020d79101e5c23c1f58a0ce5fa49488ccf73vboxsync Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, Port, *pu32));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Saves a state of the serial port device.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pDevIns The device instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pSSMHandle The handle to save the state to.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) serialSaveExec(PPDMDEVINS pDevIns,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PDMINS2DATA(pDevIns, SerialState *);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync return SSMR3PutU32(pSSMHandle, ~0); /* sanity/terminator */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Loads a saved serial port device state.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status code.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pDevIns The device instance.
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync * @param pSSMHandle The handle to the saved state.
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync * @param u32Version The data unit version number.
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsyncstatic DECLCALLBACK(int) serialLoadExec(PPDMDEVINS pDevIns,
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync SerialState *pData = PDMINS2DATA(pDevIns, SerialState *);
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync SSMR3GetS32(pSSMHandle, &pData->last_break_enable);
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync if (u32 != ~0U)
90ce7af4052f25f4a94d18c0ef86181971396cd3vboxsync /* Be careful with pointers in the structure; they are not preserved
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * in the saved state. */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @copydoc FNPDMDEVRELOCATE
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void) serialRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PDMINS2DATA(pDevIns, SerialState *);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) serialIOPortRegionMap(PPCIDEVICE pPciDev, /* unsigned */ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PCIDEV_2_SERIALSTATE(pPciDev);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertMsg(RT_ALIGN(GCPhysAddress, 8) == GCPhysAddress, ("Expected 8 byte alignment. GCPhysAddress=%#x\n", GCPhysAddress));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync LogRel(("Serial#%d: mapping I/O at %#06x\n", pData->pDevIns->iInstance, pData->base));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Register our port IO handlers.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns, (RTIOPORT)GCPhysAddress, 8, (void *)pData,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync serial_io_write, serial_io_read, NULL, NULL, "SERIAL");
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync#endif /* VBOX_SERIAL_PCI */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync/** @copyfrom PIBASE::pfnqueryInterface */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(void *) serialQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PDMIBASE_2_SERIALSTATE(pInterface);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Destruct a device instance.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Most VM resources are freed by the VM. This callback is provided so that any non-VM
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * resources can be freed correctly.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pDevIns The device instance data.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) serialDestruct(PPDMDEVINS pDevIns)
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PDMINS2DATA(pDevIns, SerialState *);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Construct a device instance for a VM.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @returns VBox status.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pDevIns The device instance data.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * If the registration structure is needed, pDevIns->pDevReg points to it.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param iInstance Instance number. Use this to figure out which registers and such to use.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * The device number is also found in pDevIns->iInstance, but since it's
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * likely to be freqently used PDM passes it as parameter.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * of the device instance. It's also found in pDevIns->pCfgHandle, but like
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * iInstance it's expected to be used a bit in this function.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsyncstatic DECLCALLBACK(int) serialConstruct(PPDMDEVINS pDevIns,
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync SerialState *pData = PDMINS2DATA(pDevIns, SerialState*);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Validate configuration.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync if (!CFGMR3AreValuesValid(pCfgHandle, "IRQ\0IOBase\0"))
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync AssertMsgFailed(("serialConstruct Invalid configuration values\n"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = CFGMR3QueryBool(pCfgHandle, "GCEnabled", &pData->fGCEnabled);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Failed to get the \"GCEnabled\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = CFGMR3QueryBool(pCfgHandle, "R0Enabled", &pData->fR0Enabled);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync N_("Configuration error: Failed to get the \"R0Enabled\" value"));
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* IBase */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pData->IBase.pfnQueryInterface = serialQueryInterface;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* ICharPort */
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync pData->ICharPort.pfnNotifyStatusLinesChanged = serialNotifyStatusLinesChanged;
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * Initialize critical section.
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync * This must of course be done before attaching drivers or anything else which can call us back..
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync RTStrPrintf(szName, sizeof(szName), "Serial#%d", iInstance);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync rc = PDMDevHlpCritSectInit(pDevIns, &pData->CritSect, szName);
41d680dd6eb0287afc200adc5b0d61b07a32b72dvboxsync /* Provide sensible defaults. */
if (iInstance == 0)
#ifdef VBOX_SERIAL_PCI
return rc;
return rc;
return rc;
pData->pDrvChar = (PDMICHAR *)pData->pDrvBase->pfnQueryInterface(pData->pDrvBase, PDMINTERFACE_CHAR);
return VERR_PDM_MISSING_INTERFACE;
return rc;
return rc;
return VINF_SUCCESS;
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0,
sizeof(SerialState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,