serial.c revision 677833bc953b6cb418c701facbdcf4aa18d6c44e
#ifdef VBOX
/** @file
*
* VBox serial device:
* Serial communication port driver
*/
/*
* Copyright (C) 2006 InnoTek Systemberatung GmbH
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License as published by the Free Software Foundation,
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
* distribution. VirtualBox OSE is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY of any kind.
*
* If you received this file as part of a commercial VirtualBox
* distribution, then only the terms of your commercial VirtualBox
* license agreement apply instead of the previous paragraph.
*
* --------------------------------------------------------------------
*
* This code is based on:
*
* QEMU 16450 UART emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DEV_SERIAL
#include "Builtins.h"
#include "../vl_vbox.h"
#endif /* VBOX */
#ifndef VBOX
#include "vl.h"
#endif
//#define DEBUG_SERIAL
/*
* These are the definitions for the Modem Control Register
*/
/*
* These are the definitions for the Modem Status Register
*/
struct SerialState {
/* NOTE: this hidden state is necessary for tx irq generation as
it can be reset while reading iir */
int thr_ipending;
void *irq_opaque;
int irq;
#ifdef VBOX
/* Be careful with pointers in the structure; load just gets the whole structure from the saved state */
#else
#endif
int last_break_enable;
int it_shift;
};
static void serial_update_irq(SerialState *s)
{
s->iir = UART_IIR_RDI;
s->iir = UART_IIR_THRI;
} else {
s->iir = UART_IIR_NO_INT;
}
if (s->iir != UART_IIR_NO_INT) {
#ifdef VBOX
#else
#endif
} else {
#ifdef VBOX
#else
#endif
}
}
static void serial_update_parameters(SerialState *s)
{
if (s->lcr & 0x08) {
if (s->lcr & 0x10)
parity = 'E';
else
parity = 'O';
} else {
parity = 'N';
}
if (s->lcr & 0x04)
stop_bits = 2;
else
stop_bits = 1;
if (s->divider == 0)
return;
#ifndef VBOX
#endif
#if 0
printf("speed=%d parity=%c data=%d stop=%d\n",
#endif
}
{
SerialState *s = opaque;
unsigned char ch;
addr &= 7;
#ifdef DEBUG_SERIAL
#endif
switch(addr) {
default:
case 0:
if (s->lcr & UART_LCR_DLAB) {
} else {
s->thr_ipending = 0;
s->lsr &= ~UART_LSR_THRE;
#ifndef VBOX
#endif
s->thr_ipending = 1;
s->lsr |= UART_LSR_THRE;
s->lsr |= UART_LSR_TEMT;
}
break;
case 1:
if (s->lcr & UART_LCR_DLAB) {
} else {
if (s->lsr & UART_LSR_THRE) {
s->thr_ipending = 1;
}
}
break;
case 2:
break;
case 3:
{
int break_enable;
if (break_enable != s->last_break_enable) {
#ifndef VBOX
&break_enable);
#endif
}
}
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
}
}
{
SerialState *s = opaque;
addr &= 7;
switch(addr) {
default:
case 0:
if (s->lcr & UART_LCR_DLAB) {
} else {
}
break;
case 1:
if (s->lcr & UART_LCR_DLAB) {
} else {
}
break;
case 2:
/* reset THR pending bit */
s->thr_ipending = 0;
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
if (s->mcr & UART_MCR_LOOP) {
/* in loopback, the modem output pins are connected to the
inputs */
} else {
}
break;
case 7:
break;
}
#ifdef DEBUG_SERIAL
#endif
return ret;
}
#ifndef VBOX
static int serial_can_receive(SerialState *s)
{
return !(s->lsr & UART_LSR_DR);
}
{
s->lsr |= UART_LSR_DR;
}
static void serial_receive_break(SerialState *s)
{
s->rbr = 0;
}
static int serial_can_receive1(void *opaque)
{
SerialState *s = opaque;
return serial_can_receive(s);
}
{
SerialState *s = opaque;
serial_receive_byte(s, buf[0]);
}
{
SerialState *s = opaque;
if (event == CHR_EVENT_BREAK)
}
{
SerialState *s = opaque;
qemu_put_8s(f,&s->divider);
qemu_put_8s(f,&s->rbr);
qemu_put_8s(f,&s->ier);
qemu_put_8s(f,&s->iir);
qemu_put_8s(f,&s->lcr);
qemu_put_8s(f,&s->mcr);
qemu_put_8s(f,&s->lsr);
qemu_put_8s(f,&s->msr);
qemu_put_8s(f,&s->scr);
}
{
SerialState *s = opaque;
if(version_id != 1)
return -EINVAL;
qemu_get_8s(f,&s->divider);
qemu_get_8s(f,&s->rbr);
qemu_get_8s(f,&s->ier);
qemu_get_8s(f,&s->iir);
qemu_get_8s(f,&s->lcr);
qemu_get_8s(f,&s->mcr);
qemu_get_8s(f,&s->lsr);
qemu_get_8s(f,&s->msr);
qemu_get_8s(f,&s->scr);
return 0;
}
/* If fd is zero, it means that the serial device uses the console */
{
SerialState *s;
s = qemu_mallocz(sizeof(SerialState));
if (!s)
return NULL;
s->irq_opaque = opaque;
s->iir = UART_IIR_NO_INT;
return s;
}
/* Memory mapped interface */
{
SerialState *s = opaque;
}
static void serial_mm_writeb (void *opaque,
{
SerialState *s = opaque;
}
{
SerialState *s = opaque;
}
static void serial_mm_writew (void *opaque,
{
SerialState *s = opaque;
}
{
SerialState *s = opaque;
}
static void serial_mm_writel (void *opaque,
{
SerialState *s = opaque;
}
static CPUReadMemoryFunc *serial_mm_read[] = {
};
static CPUWriteMemoryFunc *serial_mm_write[] = {
};
{
SerialState *s;
int s_io_memory;
s = qemu_mallocz(sizeof(SerialState));
if (!s)
return NULL;
s->irq_opaque = opaque;
s->iir = UART_IIR_NO_INT;
serial_mm_write, s);
return s;
}
#else
void *pvUser,
unsigned cb)
{
if (cb == 1) {
}
else {
}
return VINF_SUCCESS;
}
void *pvUser,
unsigned cb)
{
if (cb == 1) {
return VINF_SUCCESS;
}
else {
return VERR_IOM_IOPORT_UNUSED;
}
}
{
SSMR3PutMem(pSSMHandle, s, sizeof(*s));
}
{
int rc;
if (u32Version != 1) {
}
if (VBOX_FAILURE(rc))
return rc;
if (VBOX_FAILURE(rc))
return rc;
if (u32 != ~0U) {
}
/* Be careful with pointers in the structure; load just gets the whole structure from the saved state */
return VINF_SUCCESS;
}
/**
* Construct a device instance for a VM.
*
* @returns VBox status.
* @param pDevIns The device instance data.
* If the registration structure is needed, pDevIns->pDevReg points to it.
* @param iInstance Instance number. Use this to figure out which registers and such to use.
* The device number is also found in pDevIns->iInstance, but since it's
* likely to be freqently used PDM passes it as parameter.
* @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
* of the device instance. It's also found in pDevIns->pCfgHandle, but like
* iInstance it's expected to be used a bit in this function.
*/
int iInstance,
{
int rc;
/*
* Validate configuration.
*/
}
/** @todo r=bird: Check for VERR_CFGM_VALUE_NOT_FOUND and provide sensible defaults.
* Also do AssertMsgFailed(("Configuration error:....)) in the failure cases of CFGMR3Query*()
* and CFGR3AreValuesValid() like we're doing in the other devices. */
if (VBOX_FAILURE (rc)) {
return rc;
}
if (VBOX_FAILURE (rc)) {
return rc;
}
s->iir = UART_IIR_NO_INT;
8,
s,
"SERIAL"
);
if (VBOX_FAILURE (rc)) {
return rc;
}
pDevIns, /* pDevIns */
iInstance, /* u32Instance */
1 /* u32Version */,
sizeof (*s), /* cbGuess */
NULL, /* pfnSavePrep */
SaveExec, /* pfnSaveExec */
NULL, /* pfnSaveDone */
NULL, /* pfnLoadPrep */
LoadExec, /* pfnLoadExec */
NULL /* pfnLoadDone */
);
if (VBOX_FAILURE(rc))
return rc;
return VINF_SUCCESS;
}
/**
* The device registration structure.
*/
const PDMDEVREG g_DeviceSerialPort =
{
/* u32Version */
/* szDeviceName */
"serial",
/* szGCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"Serial Communication Port",
/* fFlags */
/* fClass */
/* cMaxInstances */
1,
/* cbInstance */
sizeof(SerialState),
/* pfnConstruct */
/* pfnDestruct */
NULL,
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnQueryInterface. */
};
#endif